|
@@ -8,25 +8,27 @@ import (
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
const (
|
|
|
- Input int = 1433
|
|
|
|
|
- Hidden int = 50
|
|
|
|
|
- Output int = 7
|
|
|
|
|
- Sample int = 1000
|
|
|
|
|
- Batch int = 10
|
|
|
|
|
- RateWo float64 = 0.06
|
|
|
|
|
- RateWi float64 = 0.08
|
|
|
|
|
- RateB float64 = 0.1
|
|
|
|
|
|
|
+ Input int = 1433
|
|
|
|
|
+ Hidden int = 64
|
|
|
|
|
+ Output int = 7
|
|
|
|
|
+ Sample int = 10000
|
|
|
|
|
+ Batch int = 5
|
|
|
|
|
+ Dropout float64 = 0.5
|
|
|
|
|
+ RateWo float64 = 0.1
|
|
|
|
|
+ RateWi float64 = 0.1
|
|
|
|
|
+ RateB float64 = 0.1
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
type (
|
|
|
Parameter struct {
|
|
Parameter struct {
|
|
|
- Wo, Wi, B Matrix
|
|
|
|
|
|
|
+ Wo, Wi, B, A Matrix
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Layer struct {
|
|
Layer struct {
|
|
|
d int
|
|
d int
|
|
|
f func(Matrix) Matrix
|
|
f func(Matrix) Matrix
|
|
|
p Parameter
|
|
p Parameter
|
|
|
|
|
+ D Vector
|
|
|
O, I, E Matrix
|
|
O, I, E Matrix
|
|
|
}
|
|
}
|
|
|
)
|
|
)
|
|
@@ -42,10 +44,8 @@ func ReLU(A Matrix) Matrix {
|
|
|
|
|
|
|
|
func Softmax(A Matrix) Matrix {
|
|
func Softmax(A Matrix) Matrix {
|
|
|
for i := 0; i < A.N(); i++ {
|
|
for i := 0; i < A.N(); i++ {
|
|
|
- max, sum := 0., 0.
|
|
|
|
|
- for j := 0; j < A.M(); j++ {
|
|
|
|
|
- max = math.Max(max, A[i][j])
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ _, max := A[i].Max()
|
|
|
|
|
+ sum := 0.
|
|
|
for j := 0; j < A.M(); j++ {
|
|
for j := 0; j < A.M(); j++ {
|
|
|
A[i][j] = math.Exp(A[i][j] - max)
|
|
A[i][j] = math.Exp(A[i][j] - max)
|
|
|
sum += A[i][j]
|
|
sum += A[i][j]
|
|
@@ -57,90 +57,95 @@ func Softmax(A Matrix) Matrix {
|
|
|
return A
|
|
return A
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func GetEmbedding(G Graph, u, k int, l []Layer) Vector {
|
|
|
|
|
|
|
+func GetEmbedding(G Graph, u, k int, l []Layer, train bool) Matrix {
|
|
|
if k == 0 {
|
|
if k == 0 {
|
|
|
- return G.X[u]
|
|
|
|
|
|
|
+ l[k].E = MakeMatrix(1, l[k].d).Add(Matrix{G.X[u]})
|
|
|
|
|
+ if train && l[k].D != nil {
|
|
|
|
|
+ l[k].E.Dropout(l[k].D)
|
|
|
|
|
+ }
|
|
|
|
|
+ return l[k].E
|
|
|
}
|
|
}
|
|
|
l[k-1].O, l[k-1].I, l[k].E = MakeMatrix(1, l[k-1].d), MakeMatrix(1, l[k-1].d), MakeMatrix(1, l[k].d)
|
|
l[k-1].O, l[k-1].I, l[k].E = MakeMatrix(1, l[k-1].d), MakeMatrix(1, l[k-1].d), MakeMatrix(1, l[k].d)
|
|
|
Do, Di := 0, 0
|
|
Do, Di := 0, 0
|
|
|
for v, w := range G.A[u] {
|
|
for v, w := range G.A[u] {
|
|
|
if w == 1 {
|
|
if w == 1 {
|
|
|
- l[k-1].O.Add(Matrix{GetEmbedding(G, v, k-1, l)})
|
|
|
|
|
|
|
+ l[k-1].O.Add(GetEmbedding(G, v, k-1, l, train))
|
|
|
Do++
|
|
Do++
|
|
|
} else {
|
|
} else {
|
|
|
- l[k-1].I.Add(Matrix{GetEmbedding(G, v, k-1, l)})
|
|
|
|
|
|
|
+ l[k-1].I.Add(GetEmbedding(G, v, k-1, l, train))
|
|
|
Di++
|
|
Di++
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if Do > 0 {
|
|
if Do > 0 {
|
|
|
- l[k].E.Add(Multiply(l[k-1].O.Divide(float64(Do)), l[k].p.Wo))
|
|
|
|
|
|
|
+ l[k].E.Add(l[k-1].O.Divide(float64(Do)).Multiply(l[k].p.Wo))
|
|
|
}
|
|
}
|
|
|
if Di > 0 {
|
|
if Di > 0 {
|
|
|
- l[k].E.Add(Multiply(l[k-1].I.Divide(float64(Di)), l[k].p.Wi))
|
|
|
|
|
|
|
+ l[k].E.Add(l[k-1].I.Divide(float64(Di)).Multiply(l[k].p.Wi))
|
|
|
}
|
|
}
|
|
|
- l[k].E.Add(Multiply(Matrix{GetEmbedding(G, u, k-1, l)}, l[k].p.B))
|
|
|
|
|
- return l[k].f(l[k].E)[0]
|
|
|
|
|
|
|
+ l[k].E.Add(GetEmbedding(G, u, k-1, l, train).Multiply(l[k].p.B))
|
|
|
|
|
+ if train && l[k].D != nil {
|
|
|
|
|
+ l[k].E.Dropout(l[k].D)
|
|
|
|
|
+ }
|
|
|
|
|
+ return l[k].f(l[k].E)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// A += B * C / d
|
|
|
|
|
-func StartCalc(wg *sync.WaitGroup, A, B, C Matrix, d float64) {
|
|
|
|
|
|
|
+// A += B * C
|
|
|
|
|
+func StartCalc(wg *sync.WaitGroup, A, B, C Matrix) {
|
|
|
wg.Add(1)
|
|
wg.Add(1)
|
|
|
go func() {
|
|
go func() {
|
|
|
- A.Add(Multiply(B.Transpose(), C).Divide(d))
|
|
|
|
|
|
|
+ A.Add(B.Transpose().Multiply(C))
|
|
|
wg.Done()
|
|
wg.Done()
|
|
|
}()
|
|
}()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// A += B
|
|
|
|
|
-func StartRefine(wg *sync.WaitGroup, A, B Matrix) {
|
|
|
|
|
|
|
+// A += B / c
|
|
|
|
|
+func StartRefine(wg *sync.WaitGroup, A, B Matrix, c float64) {
|
|
|
wg.Add(1)
|
|
wg.Add(1)
|
|
|
go func() {
|
|
go func() {
|
|
|
- A.Add(B)
|
|
|
|
|
|
|
+ A.Add(B.Divide(c))
|
|
|
wg.Done()
|
|
wg.Done()
|
|
|
}()
|
|
}()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func Train(G Graph) []Layer {
|
|
func Train(G Graph) []Layer {
|
|
|
- p1 := Parameter{MakeRandomMatrix(Input, Hidden), MakeRandomMatrix(Input, Hidden), MakeRandomMatrix(Input, Hidden)}
|
|
|
|
|
- p2 := Parameter{MakeRandomMatrix(Hidden, Output), MakeRandomMatrix(Hidden, Output), MakeRandomMatrix(Hidden, Output)}
|
|
|
|
|
|
|
+ p1 := Parameter{MakeRandomMatrix(Input, Hidden), MakeRandomMatrix(Input, Hidden), MakeRandomMatrix(Input, Hidden), MakeRandomMatrix(Input*2, 1)}
|
|
|
|
|
+ p2 := Parameter{MakeRandomMatrix(Hidden, Output), MakeRandomMatrix(Hidden, Output), MakeRandomMatrix(Hidden, Output), MakeRandomMatrix(Hidden*2, 1)}
|
|
|
l := []Layer{{d: Input}, {d: Hidden, f: ReLU, p: p1}, {d: Output, f: Softmax, p: p2}}
|
|
l := []Layer{{d: Input}, {d: Hidden, f: ReLU, p: p1}, {d: Output, f: Softmax, p: p2}}
|
|
|
for i := 0; i < Sample; i++ {
|
|
for i := 0; i < Sample; i++ {
|
|
|
- if i%10 == 0 {
|
|
|
|
|
|
|
+ if i%100 == 0 {
|
|
|
fmt.Println("sampling", i)
|
|
fmt.Println("sampling", i)
|
|
|
}
|
|
}
|
|
|
var wg sync.WaitGroup
|
|
var wg sync.WaitGroup
|
|
|
|
|
+ l[0].D, l[1].D = MakeDropoutVector(Input), MakeDropoutVector(Hidden)
|
|
|
DWo2, DWi2, DB2 := MakeMatrix(Hidden, Output), MakeMatrix(Hidden, Output), MakeMatrix(Hidden, Output)
|
|
DWo2, DWi2, DB2 := MakeMatrix(Hidden, Output), MakeMatrix(Hidden, Output), MakeMatrix(Hidden, Output)
|
|
|
DWo1, DWi1, DB1 := MakeMatrix(Input, Hidden), MakeMatrix(Input, Hidden), MakeMatrix(Input, Hidden)
|
|
DWo1, DWi1, DB1 := MakeMatrix(Input, Hidden), MakeMatrix(Input, Hidden), MakeMatrix(Input, Hidden)
|
|
|
- for u, j := nodeId[rand.Intn(len(nodeId))], 0; j < Batch; j++ {
|
|
|
|
|
- GetEmbedding(G, u, 2, l)
|
|
|
|
|
- delta := MakeMatrix(1, Output)
|
|
|
|
|
- delta[0][G.L[u]] = 1
|
|
|
|
|
- delta.Sub(l[2].E)
|
|
|
|
|
- StartCalc(&wg, DWo2, l[1].O, delta, float64(Batch)/RateWo)
|
|
|
|
|
- StartCalc(&wg, DWi2, l[1].I, delta, float64(Batch)/RateWi)
|
|
|
|
|
- StartCalc(&wg, DB2, l[1].E, delta, float64(Batch)/RateB)
|
|
|
|
|
- delta = Multiply(delta, l[2].p.B.Transpose())
|
|
|
|
|
|
|
+ for j := 0; j < Batch; j++ {
|
|
|
|
|
+ u := nodeId[rand.Intn(len(nodeId))]
|
|
|
|
|
+ GetEmbedding(G, u, 2, l, true)
|
|
|
|
|
+ // GCN
|
|
|
|
|
+ delta := MakeMatrix(1, Output).Sub(l[2].E)
|
|
|
|
|
+ delta[0][G.L[u]] += 1
|
|
|
|
|
+ StartCalc(&wg, DWo2, l[1].O, delta)
|
|
|
|
|
+ StartCalc(&wg, DWi2, l[1].I, delta)
|
|
|
|
|
+ StartCalc(&wg, DB2, l[1].E, delta)
|
|
|
|
|
+ delta = delta.Multiply(l[2].p.B.Transpose())
|
|
|
for k := 0; k < Hidden; k++ {
|
|
for k := 0; k < Hidden; k++ {
|
|
|
if l[1].E[0][k] == 0 {
|
|
if l[1].E[0][k] == 0 {
|
|
|
delta[0][k] = 0
|
|
delta[0][k] = 0
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- StartCalc(&wg, DWo1, l[0].O, delta, float64(Batch)/RateWo)
|
|
|
|
|
- StartCalc(&wg, DWi1, l[0].I, delta, float64(Batch)/RateWi)
|
|
|
|
|
- StartCalc(&wg, DB1, Matrix{G.X[u]}, delta, float64(Batch)/RateB)
|
|
|
|
|
- neighbor := make([]int, 0)
|
|
|
|
|
- for v := range G.A[u] {
|
|
|
|
|
- neighbor = append(neighbor, v)
|
|
|
|
|
- }
|
|
|
|
|
- u = neighbor[rand.Intn(len(neighbor))]
|
|
|
|
|
|
|
+ StartCalc(&wg, DWo1, l[0].O, delta)
|
|
|
|
|
+ StartCalc(&wg, DWi1, l[0].I, delta)
|
|
|
|
|
+ StartCalc(&wg, DB1, l[0].E, delta)
|
|
|
|
|
+ // GAT
|
|
|
wg.Wait()
|
|
wg.Wait()
|
|
|
}
|
|
}
|
|
|
- StartRefine(&wg, l[2].p.Wo, DWo2)
|
|
|
|
|
- StartRefine(&wg, l[2].p.Wi, DWi2)
|
|
|
|
|
- StartRefine(&wg, l[2].p.B, DB2)
|
|
|
|
|
- StartRefine(&wg, l[1].p.Wo, DWo1)
|
|
|
|
|
- StartRefine(&wg, l[1].p.Wi, DWi1)
|
|
|
|
|
- StartRefine(&wg, l[1].p.B, DB1)
|
|
|
|
|
|
|
+ StartRefine(&wg, l[2].p.Wo, DWo2, float64(Batch)/RateWo)
|
|
|
|
|
+ StartRefine(&wg, l[2].p.Wi, DWi2, float64(Batch)/RateWi)
|
|
|
|
|
+ StartRefine(&wg, l[2].p.B, DB2, float64(Batch)/RateB)
|
|
|
|
|
+ StartRefine(&wg, l[1].p.Wo, DWo1, float64(Batch)/RateWo)
|
|
|
|
|
+ StartRefine(&wg, l[1].p.Wi, DWi1, float64(Batch)/RateWi)
|
|
|
|
|
+ StartRefine(&wg, l[1].p.B, DB1, float64(Batch)/RateB)
|
|
|
wg.Wait()
|
|
wg.Wait()
|
|
|
}
|
|
}
|
|
|
return l
|
|
return l
|