-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
120 lines (93 loc) · 3.07 KB
/
main.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package main
import (
"fmt"
"math/rand"
"reflect"
"strings"
"time"
"github.com/tsholmes/go-dl/calc"
"github.com/tsholmes/go-dl/dataset"
"github.com/tsholmes/go-dl/model"
"github.com/tsholmes/go-dl/tensor"
)
func main() {
rand.Seed(time.Now().UnixNano())
batchSize := 100
X, Y, Xtest, Ytest := dataset.LoadMNIST()
trainBatches := 60
testBatches := 10
trainSamples := batchSize * trainBatches
testSamples := batchSize * testBatches
X, Y, Xtest, Ytest = X.SliceRoot(0, trainSamples), Y.SliceRoot(0, trainSamples), Xtest.SliceRoot(0, testSamples), Ytest.SliceRoot(0, testSamples)
l1Size := 16
l2Size := 32
l3Size := 64
x := tensor.Input(batchSize, 28, 28, 1)
y := tensor.Input(batchSize, 10)
m := model.NewModel()
var t tensor.Tensor = tensor.Reshape(x, batchSize, 28, 28, 1)
t = model.Conv2D(m, t, 3, 3, l1Size)
t = model.BatchNormalization(m, t)
t = tensor.ReLU(t)
t = model.MaxPooling2D(m, t, 2, 2)
t = model.Conv2D(m, t, 3, 3, l2Size)
t = model.BatchNormalization(m, t)
t = tensor.ReLU(t)
t = model.MaxPooling2D(m, t, 2, 2)
t = model.Conv2D(m, t, 3, 3, l3Size)
t = model.BatchNormalization(m, t)
t = tensor.ReLU(t)
t = tensor.Flatten(t, 1)
t = model.Dense(m, t, 10, true)
pred := tensor.Softmax(t)
loss := tensor.CategoricalCrossEntropy(y, pred)
const lr = 1e-2
opt := model.SGDMomentumOptimizer{LR: lr, Momentum: 0.1, Nesterov: true}
m.Compile(&opt, x, y, pred, loss, tensor.CategoricalAccuracy(y, pred))
const epochs = 10
index := make([]int, trainSamples)
for i := range index {
index[i] = i
}
for epoch := 0; epoch < epochs; epoch++ {
rand.Shuffle(len(index), func(i, j int) { index[i], index[j] = index[j], index[i] })
X = X.ReindexRoot(index)
Y = Y.ReindexRoot(index)
workingLoss := 0.0
workingAcc := 0.0
for i := 0; i < trainBatches; i++ {
bX, bY := X.SliceRoot(i*batchSize, batchSize), Y.SliceRoot(i*batchSize, batchSize)
start := time.Now()
bloss, bmet := m.Train(bX, bY)
workingLoss += bloss
workingAcc += bmet[0]
end := time.Now()
fmt.Printf("epoch %d/%d train batch %d/%d train loss %f train acc %f duration %s\n", epoch, epochs, i, trainBatches, workingLoss/float64(i+1), workingAcc/float64(i+1), end.Sub(start).String())
}
// m.DebugTrain()
workingLoss = 0.0
workingAcc = 0.0
for i := 0; i < testBatches; i++ {
bX, bY := Xtest.SliceRoot(i*batchSize, batchSize), Ytest.SliceRoot(i*batchSize, batchSize)
bloss, bmet := m.Test(bX, bY)
workingLoss += bloss
workingAcc += bmet[0]
fmt.Printf("epoch %d/%d test batch %d/%d test loss %f test acc %f\n", epoch, epochs, i, testBatches, workingLoss/float64(i+1), workingAcc/float64(i+1))
}
}
}
func mag(w calc.NDArray) float64 {
ax := make([]int, len(w.Shape()))
for i := range ax {
ax[i] = i
}
return w.PowConstant(2.0).Sum(ax...).PowConstant(0.5).Get(make([]int, len(w.Shape())))
}
func display(t tensor.Tensor) string {
typ := reflect.TypeOf(t).String()
var idStrs []string
for _, it := range t.Inputs() {
idStrs = append(idStrs, fmt.Sprintf("%d", it.ID()))
}
return fmt.Sprintf("%s(%s)%v", typ, strings.Join(idStrs, ","), t.Shape())
}