-
Notifications
You must be signed in to change notification settings - Fork 0
/
nn.go
88 lines (77 loc) · 2.4 KB
/
nn.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package main
import (
"math"
"gonum.org/v1/gonum/mat"
"gonum.org/v1/gonum/stat/distuv"
)
//Network structure for NN
type Network struct {
inputs int
hiddens int
outputs int
hiddenWeights *mat.Dense
outputWeights *mat.Dense
rate float64
}
//CreateNet creates network n to be trained
func CreateNet(input, hidden, output int, rate float64) (net Network) {
net = Network{
inputs: input,
hiddens: hidden,
outputs: output,
rate: rate,
}
randHidden := randArray(net.inputs*net.hiddens, float64(net.inputs))
randOutputs := randArray(net.outputs*net.hiddens, float64(net.hiddens))
net.hiddenWeights = mat.NewDense(net.hiddens, net.inputs, randHidden)
net.outputWeights = mat.NewDense(net.outputs, net.hiddens, randOutputs)
return
}
func randArray(size int, v float64) (weights []float64) {
dist := distuv.Uniform{
Min: -1 / math.Sqrt(v),
Max: 1 / math.Sqrt(v),
}
weights = make([]float64, size)
for i := 0; i < size; i++ {
weights[i] = dist.Rand()
}
return
}
//Predict forward propagation
func (net Network) Predict(inputData []float64) (mat.Matrix, mat.Matrix) {
inputMat := mat.NewDense(len(inputData), 1, inputData)
hiddenInputs := Dot(net.hiddenWeights, inputMat)
hiddenOutputs := Apply(sigmoid, hiddenInputs)
finalInputs := Dot(net.outputWeights, hiddenOutputs)
finalOutputs := Apply(sigmoid, finalInputs)
return finalOutputs, hiddenOutputs
}
func sigmoid(r, c int, z float64) float64 {
return 1.0 / (1 + math.Exp(-1*z))
}
//Train forward propagate -> find errors -> back propagate
func (net *Network) Train(inputData []float64, targetData []float64) mat.Matrix {
finalOutputs, hiddenOutputs := net.Predict(inputData)
inputMat := mat.NewDense(len(inputData), 1, inputData)
targetMat := mat.NewDense(len(targetData), 1, targetData)
outputErrors := Sub(targetMat, finalOutputs)
hiddenErrors := Dot(net.outputWeights.T(), outputErrors)
net.outputWeights = Add(net.outputWeights,
Scale(net.rate,
Dot(Multiply(outputErrors, sigmoidPrime(finalOutputs)),
hiddenOutputs.T()))).(*mat.Dense)
net.hiddenWeights = Add(net.hiddenWeights,
Scale(net.rate, Dot(Multiply(hiddenErrors, sigmoidPrime(hiddenOutputs)),
inputMat.T()))).(*mat.Dense)
return finalOutputs
}
func sigmoidPrime(m mat.Matrix) mat.Matrix {
rows, _ := m.Dims()
o := make([]float64, rows)
for i := range o {
o[i] = 1
}
oneMat := mat.NewDense(rows, 1, o)
return Multiply(m, Sub(oneMat, m))
}