소스 검색

feat: add random walk sampling

RegMs If 3 년 전
부모
커밋
8d84d1e86d
3개의 변경된 파일66개의 추가작업 그리고 43개의 파일을 삭제
  1. 35 24
      gnn.go
  2. 25 16
      main.go
  3. 6 3
      matrix.go

+ 35 - 24
gnn.go

@@ -2,10 +2,15 @@ package main
 
 
 import (
 import (
 	"math"
 	"math"
+	"math/rand"
 )
 )
 
 
 const (
 const (
+	Input  int     = 1433
 	Hidden int     = 50
 	Hidden int     = 50
+	Output int     = 7
+	Sample int     = 5000
+	Batch  int     = 20
 	RateWo float64 = 0.02
 	RateWo float64 = 0.02
 	RateWi float64 = 0.04
 	RateWi float64 = 0.04
 	RateB  float64 = 0.05
 	RateB  float64 = 0.05
@@ -67,39 +72,45 @@ func GetEmbedding(G Graph, u, k int, l []Layer) Vector {
 		}
 		}
 	}
 	}
 	if Do > 0 {
 	if Do > 0 {
-		l[k-1].O.Divide(float64(Do))
-		l[k].E.Add(Multiply(l[k-1].O, l[k].p.Wo))
+		l[k].E.Add(Multiply(l[k-1].O.Divide(float64(Do)), l[k].p.Wo))
 	}
 	}
 	if Di > 0 {
 	if Di > 0 {
-		l[k-1].I.Divide(float64(Di))
-		l[k].E.Add(Multiply(l[k-1].I, l[k].p.Wi))
+		l[k].E.Add(Multiply(l[k-1].I.Divide(float64(Di)), l[k].p.Wi))
 	}
 	}
 	return l[k].f(l[k].E)[0]
 	return l[k].f(l[k].E)[0]
 }
 }
 
 
 func Train(G Graph) []Layer {
 func Train(G Graph) []Layer {
-	p1 := Parameter{MakeRandomMatrix(1433, Hidden), MakeRandomMatrix(1433, Hidden), MakeRandomMatrix(1433, Hidden)}
-	p2 := Parameter{MakeRandomMatrix(Hidden, 7), MakeRandomMatrix(Hidden, 7), MakeRandomMatrix(Hidden, 7)}
-	l := []Layer{{d: 1433}, {d: Hidden, f: ReLU, p: p1}, {d: 7, f: Softmax, p: p2}}
-	for u, X := range G.X {
-		GetEmbedding(G, u, 2, l)
-		delta := MakeMatrix(1, 7)
-		delta[0][nodeLabel[u]] = 1
-		delta.Sub(l[2].E)
-		DWo2, DWi2, DB2 := Multiply(l[1].O.Transpose(), delta), Multiply(l[1].I.Transpose(), delta), Multiply(l[1].E.Transpose(), delta)
-		DWo2.Divide(1 / RateWo)
-		DWi2.Divide(1 / RateWi)
-		DB2.Divide(1 / RateB)
-		delta = Multiply(delta, l[2].p.B.Transpose())
-		for i := 0; i < Hidden; i++ {
-			if l[1].E[0][i] == 0 {
-				delta[0][i] = 0
+	p1 := Parameter{MakeRandomMatrix(Input, Hidden), MakeRandomMatrix(Input, Hidden), MakeRandomMatrix(Input, Hidden)}
+	p2 := Parameter{MakeRandomMatrix(Hidden, Output), MakeRandomMatrix(Hidden, Output), MakeRandomMatrix(Hidden, Output)}
+	l := []Layer{{d: Input}, {d: Hidden, f: ReLU, p: p1}, {d: Output, f: Softmax, p: p2}}
+	for i := 0; i < Sample; i++ {
+		DWo2, DWi2, DB2 := MakeMatrix(Hidden, Output), MakeMatrix(Hidden, Output), MakeMatrix(Hidden, Output)
+		DWo1, DWi1, DB1 := MakeMatrix(Input, Hidden), MakeMatrix(Input, Hidden), MakeMatrix(Input, Hidden)
+		u := nodeId[rand.Intn(len(nodeId))]
+		for j := 0; j < Batch; j++ {
+			GetEmbedding(G, u, 2, l)
+			delta := MakeMatrix(1, Output)
+			delta[0][nodeLabel[u]] = 1
+			delta.Sub(l[2].E)
+			DWo2.Add(Multiply(l[1].O.Transpose(), delta).Divide(float64(Batch) / RateWo))
+			DWi2.Add(Multiply(l[1].I.Transpose(), delta).Divide(float64(Batch) / RateWi))
+			DB2.Add(Multiply(l[1].E.Transpose(), delta).Divide(float64(Batch) / RateB))
+			delta = Multiply(delta, l[2].p.B.Transpose())
+			for k := 0; k < Hidden; k++ {
+				if l[1].E[0][k] == 0 {
+					delta[0][k] = 0
+				}
 			}
 			}
+			DWo1.Add(Multiply(l[0].O.Transpose(), delta).Divide(float64(Batch) / RateWo))
+			DWi1.Add(Multiply(l[0].I.Transpose(), delta).Divide(float64(Batch) / RateWi))
+			DB1.Add(Multiply(Matrix{G.X[u]}.Transpose(), delta).Divide(float64(Batch) / RateB))
+			neighbor := make([]int, 0)
+			for v := range G.A[u] {
+				neighbor = append(neighbor, v)
+			}
+			u = neighbor[rand.Intn(len(neighbor))]
 		}
 		}
-		DWo1, DWi1, DB1 := Multiply(l[0].O.Transpose(), delta), Multiply(l[0].I.Transpose(), delta), Multiply(Matrix{X}.Transpose(), delta)
-		DWo1.Divide(1 / RateWo)
-		DWi1.Divide(1 / RateWi)
-		DB1.Divide(1 / RateB)
 		l[2].p.Wo.Add(DWo2)
 		l[2].p.Wo.Add(DWo2)
 		l[2].p.Wi.Add(DWi2)
 		l[2].p.Wi.Add(DWi2)
 		l[2].p.B.Add(DB2)
 		l[2].p.B.Add(DB2)

+ 25 - 16
main.go

@@ -5,17 +5,25 @@ import (
 	"os"
 	"os"
 )
 )
 
 
-var labelName = []string{
-	"Case_Based",
-	"Genetic_Algorithms",
-	"Neural_Networks",
-	"Probabilistic_Methods",
-	"Reinforcement_Learning",
-	"Rule_Learning",
-	"Theory",
-}
+const (
+	Node = 2708
+	Edge = 5429
+)
 
 
-var nodeLabel = make(map[int]int)
+var (
+	labelName = []string{
+		"Case_Based",
+		"Genetic_Algorithms",
+		"Neural_Networks",
+		"Probabilistic_Methods",
+		"Reinforcement_Learning",
+		"Rule_Learning",
+		"Theory",
+	}
+
+	nodeId    = make([]int, 0)
+	nodeLabel = make(map[int]int)
+)
 
 
 func main() {
 func main() {
 	file, err := os.Open("cora/cora.content")
 	file, err := os.Open("cora/cora.content")
@@ -23,17 +31,18 @@ func main() {
 		panic(err)
 		panic(err)
 	}
 	}
 	G := MakeGraph()
 	G := MakeGraph()
-	for i := 0; i < 2708; i++ {
+	for i := 0; i < Node; i++ {
 		var u int
 		var u int
 		fmt.Fscan(file, &u)
 		fmt.Fscan(file, &u)
-		V := MakeVector(1433)
-		for j := 0; j < 1433; j++ {
+		nodeId = append(nodeId, u)
+		V := MakeVector(Input)
+		for j := 0; j < Input; j++ {
 			fmt.Fscan(file, &V[j])
 			fmt.Fscan(file, &V[j])
 		}
 		}
 		G.AddNode(u, V)
 		G.AddNode(u, V)
 		var label string
 		var label string
 		fmt.Fscan(file, &label)
 		fmt.Fscan(file, &label)
-		for j := 0; j < 7; j++ {
+		for j := 0; j < Output; j++ {
 			if labelName[j] == label {
 			if labelName[j] == label {
 				nodeLabel[u] = j
 				nodeLabel[u] = j
 				break
 				break
@@ -48,7 +57,7 @@ func main() {
 	if err != nil {
 	if err != nil {
 		panic(err)
 		panic(err)
 	}
 	}
-	for i := 0; i < 5429; i++ {
+	for i := 0; i < Edge; i++ {
 		var u, v int
 		var u, v int
 		fmt.Fscan(file, &u, &v)
 		fmt.Fscan(file, &u, &v)
 		G.AddEdge(u, v)
 		G.AddEdge(u, v)
@@ -59,7 +68,7 @@ func main() {
 	for u := range G.X {
 	for u := range G.X {
 		GetEmbedding(G, u, 2, l)
 		GetEmbedding(G, u, 2, l)
 		id, max := 0, 0.
 		id, max := 0, 0.
-		for i := 0; i < 7; i++ {
+		for i := 0; i < Output; i++ {
 			if l[2].E[0][i] > max {
 			if l[2].E[0][i] > max {
 				id, max = i, l[2].E[0][i]
 				id, max = i, l[2].E[0][i]
 			}
 			}

+ 6 - 3
matrix.go

@@ -36,7 +36,7 @@ func (A Matrix) Transpose() Matrix {
 	return B
 	return B
 }
 }
 
 
-func (A Matrix) Add(B Matrix) {
+func (A Matrix) Add(B Matrix) Matrix {
 	if A.N() != B.N() || A.M() != B.M() {
 	if A.N() != B.N() || A.M() != B.M() {
 		panic("Incompatible Dimensions")
 		panic("Incompatible Dimensions")
 	}
 	}
@@ -45,9 +45,10 @@ func (A Matrix) Add(B Matrix) {
 			A[i][j] += B[i][j]
 			A[i][j] += B[i][j]
 		}
 		}
 	}
 	}
+	return A
 }
 }
 
 
-func (A Matrix) Sub(B Matrix) {
+func (A Matrix) Sub(B Matrix) Matrix {
 	if A.N() != B.N() || A.M() != B.M() {
 	if A.N() != B.N() || A.M() != B.M() {
 		panic("Incompatible Dimensions")
 		panic("Incompatible Dimensions")
 	}
 	}
@@ -56,14 +57,16 @@ func (A Matrix) Sub(B Matrix) {
 			A[i][j] -= B[i][j]
 			A[i][j] -= B[i][j]
 		}
 		}
 	}
 	}
+	return A
 }
 }
 
 
-func (A Matrix) Divide(b float64) {
+func (A Matrix) Divide(b float64) Matrix {
 	for i := 0; i < A.N(); i++ {
 	for i := 0; i < A.N(); i++ {
 		for j := 0; j < A.M(); j++ {
 		for j := 0; j < A.M(); j++ {
 			A[i][j] /= b
 			A[i][j] /= b
 		}
 		}
 	}
 	}
+	return A
 }
 }
 
 
 func Multiply(A, B Matrix) Matrix {
 func Multiply(A, B Matrix) Matrix {