|
@@ -1,7 +1,7 @@
|
|
|
|
|
|
* MIT License
|
|
|
*
|
|
|
- * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>
|
|
|
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
|
|
|
*
|
|
|
* This file is part of NeuralNetwork project https:
|
|
|
*
|
|
@@ -29,8 +29,7 @@ import (
|
|
|
"encoding/binary"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
- "log"
|
|
|
- "os"
|
|
|
+ "io"
|
|
|
|
|
|
teach "../teach"
|
|
|
mat "gonum.org/v1/gonum/mat"
|
|
@@ -95,7 +94,7 @@ import (
|
|
|
|
|
|
|
|
|
|
|
|
-type NeuralNetwork struct {
|
|
|
+type BackProp struct {
|
|
|
Count int
|
|
|
Sizes []int
|
|
|
Biases []*mat.Dense
|
|
@@ -106,7 +105,7 @@ type NeuralNetwork struct {
|
|
|
trainingCycles int
|
|
|
}
|
|
|
|
|
|
-func NewNeuralNetwork(sizes []int, nu float64, trainingCycles int) (nn *NeuralNetwork, err error) {
|
|
|
+func NewBackProp(sizes []int, nu float64, trainingCycles int) (nn *BackProp, err error) {
|
|
|
err = nil
|
|
|
if len(sizes) < 3 {
|
|
|
fmt.Printf("Invalid network configuration: %v\n", sizes)
|
|
@@ -134,7 +133,7 @@ func NewNeuralNetwork(sizes []int, nu float64, trainingCycles int) (nn *NeuralNe
|
|
|
fmt.Println("Training cycles number probably is too small")
|
|
|
}
|
|
|
|
|
|
- nn = &NeuralNetwork{}
|
|
|
+ nn = &BackProp{}
|
|
|
nn.Sizes = sizes
|
|
|
nn.Count = len(sizes)
|
|
|
nn.Weights = make([]*mat.Dense, nn.Count)
|
|
@@ -151,8 +150,8 @@ func NewNeuralNetwork(sizes []int, nu float64, trainingCycles int) (nn *NeuralNe
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-func (nn *NeuralNetwork) Copy() (out *NeuralNetwork) {
|
|
|
- out = &NeuralNetwork{}
|
|
|
+func (nn *BackProp) Copy() (out *BackProp) {
|
|
|
+ out = &BackProp{}
|
|
|
out.Sizes = nn.Sizes
|
|
|
out.Count = nn.Count
|
|
|
out.Weights = make([]*mat.Dense, nn.Count)
|
|
@@ -169,7 +168,7 @@ func (nn *NeuralNetwork) Copy() (out *NeuralNetwork) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-func (nn *NeuralNetwork) Predict(aIn mat.Matrix) (maxIndex int, max float64) {
|
|
|
+func (nn *BackProp) Predict(aIn mat.Matrix) (maxIndex int, max float64) {
|
|
|
r, _ := aIn.Dims()
|
|
|
if r != nn.Sizes[0] {
|
|
|
fmt.Printf("Invalid rows number of input matrix size: %v\n", r)
|
|
@@ -190,7 +189,7 @@ func (nn *NeuralNetwork) Predict(aIn mat.Matrix) (maxIndex int, max float64) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-func (nn *NeuralNetwork) Teach(teacher teach.Teacher) {
|
|
|
+func (nn *BackProp) Teach(teacher teach.Teacher) {
|
|
|
for i := 0; i < nn.trainingCycles; i++ {
|
|
|
for teacher.NextData() {
|
|
|
nn.backward(teacher.GetData())
|
|
@@ -198,25 +197,11 @@ func (nn *NeuralNetwork) Teach(teacher teach.Teacher) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func check(e error) {
|
|
|
- if e != nil {
|
|
|
- panic(e)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (nn *NeuralNetwork) SaveState(filename string) {
|
|
|
-
|
|
|
- inputFile, err := os.Create(filename)
|
|
|
- if err != nil {
|
|
|
- log.Fatal(err)
|
|
|
- }
|
|
|
-
|
|
|
- defer inputFile.Close()
|
|
|
-
|
|
|
+func (nn *BackProp) SaveState(writer io.Writer) {
|
|
|
|
|
|
bufferSize := make([]byte, 4)
|
|
|
binary.LittleEndian.PutUint32(bufferSize[0:], uint32(nn.Count))
|
|
|
- n2, err := inputFile.Write(bufferSize)
|
|
|
+ _, err := writer.Write(bufferSize)
|
|
|
|
|
|
check(err)
|
|
|
fmt.Printf("wrote value %d\n", uint32(nn.Count))
|
|
@@ -227,88 +212,34 @@ func (nn *NeuralNetwork) SaveState(filename string) {
|
|
|
binary.LittleEndian.PutUint32(buffer[i*4:], uint32(nn.Sizes[i]))
|
|
|
}
|
|
|
|
|
|
- n2, err = inputFile.Write(buffer)
|
|
|
+ _, err = writer.Write(buffer)
|
|
|
check(err)
|
|
|
- fmt.Printf("wrote buffer %d bytes\n", n2)
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
|
for i := 1; i < nn.Count; i++ {
|
|
|
- saveDense(inputFile, nn.Biases[i])
|
|
|
+ saveDense(writer, nn.Biases[i])
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for i := 1; i < nn.Count; i++ {
|
|
|
- saveDense(inputFile, nn.Weights[i])
|
|
|
+ saveDense(writer, nn.Weights[i])
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func saveDense(inputFile *os.File, matrix *mat.Dense) {
|
|
|
- buffer, _ := matrix.MarshalBinary()
|
|
|
-
|
|
|
- bufferSize := make([]byte, 4)
|
|
|
- binary.LittleEndian.PutUint32(bufferSize, uint32(len(buffer)))
|
|
|
- inputFile.Write(bufferSize)
|
|
|
- bufferCount, err := inputFile.Write(buffer)
|
|
|
- check(err)
|
|
|
- fmt.Printf("wrote array size %d count of bytes %d \n", len(buffer), bufferCount)
|
|
|
- printMatDense(matrix)
|
|
|
-}
|
|
|
-
|
|
|
-func printMatDense(matrix *mat.Dense) {
|
|
|
-
|
|
|
- fc := mat.Formatted(matrix, mat.Prefix(" "), mat.Squeeze())
|
|
|
- fmt.Printf("c = %v \n\n", fc)
|
|
|
-}
|
|
|
-
|
|
|
-func readDense(inputFile *os.File, matrix *mat.Dense) *mat.Dense {
|
|
|
- count := readInt(inputFile)
|
|
|
- fmt.Printf("%d \n\n", count)
|
|
|
- matrix = &mat.Dense{}
|
|
|
- matrix.UnmarshalBinary(readByteArray(inputFile, count))
|
|
|
- printMatDense(matrix)
|
|
|
- return matrix
|
|
|
-}
|
|
|
-
|
|
|
-func readByteArray(inputFile *os.File, size int) []byte {
|
|
|
-
|
|
|
- sizeBuffer := make([]byte, size)
|
|
|
- n1, err := inputFile.Read(sizeBuffer)
|
|
|
- check(err)
|
|
|
-
|
|
|
- fmt.Printf("readByteArray: size = %d \n", n1)
|
|
|
-
|
|
|
- return sizeBuffer
|
|
|
-}
|
|
|
-
|
|
|
-func readInt(inputFile *os.File) int {
|
|
|
-
|
|
|
- count := make([]byte, 4)
|
|
|
- _, err := inputFile.Read(count)
|
|
|
- check(err)
|
|
|
-
|
|
|
- return int(binary.LittleEndian.Uint32(count))
|
|
|
-}
|
|
|
-
|
|
|
-func (nn *NeuralNetwork) LoadState(filename string) {
|
|
|
- inputFile, err := os.Open(filename)
|
|
|
- if err != nil {
|
|
|
- log.Fatal(err)
|
|
|
- }
|
|
|
-
|
|
|
- defer inputFile.Close()
|
|
|
-
|
|
|
+func (nn *BackProp) LoadState(reader io.Reader) {
|
|
|
|
|
|
- nn.Count = readInt(inputFile)
|
|
|
+ nn.Count = readInt(reader)
|
|
|
|
|
|
|
|
|
- sizeBuffer := readByteArray(inputFile, nn.Count*4)
|
|
|
+ sizeBuffer := readByteArray(reader, nn.Count*4)
|
|
|
nn.Sizes = make([]int, nn.Count)
|
|
|
|
|
|
for i := 0; i < nn.Count; i++ {
|
|
|
nn.Sizes[i] = int(binary.LittleEndian.Uint32(sizeBuffer[i*4:]))
|
|
|
- fmt.Printf("LoadState: nn.Sizes[%d] %d \n", i, nn.Sizes[i])
|
|
|
+
|
|
|
}
|
|
|
|
|
|
nn.Weights = []*mat.Dense{&mat.Dense{}}
|
|
@@ -318,19 +249,23 @@ func (nn *NeuralNetwork) LoadState(filename string) {
|
|
|
nn.Biases[0] = &mat.Dense{}
|
|
|
for i := 1; i < nn.Count; i++ {
|
|
|
nn.Biases = append(nn.Biases, &mat.Dense{})
|
|
|
- nn.Biases[i] = readDense(inputFile, nn.Biases[i])
|
|
|
+ nn.Biases[i] = readDense(reader, nn.Biases[i])
|
|
|
}
|
|
|
|
|
|
|
|
|
nn.Weights[0] = &mat.Dense{}
|
|
|
for i := 1; i < nn.Count; i++ {
|
|
|
nn.Weights = append(nn.Weights, &mat.Dense{})
|
|
|
- nn.Weights[i] = readDense(inputFile, nn.Weights[i])
|
|
|
+ nn.Weights[i] = readDense(reader, nn.Weights[i])
|
|
|
}
|
|
|
- fmt.Printf("\nLoadState end\n")
|
|
|
+
|
|
|
+ nn.A = make([]*mat.Dense, nn.Count)
|
|
|
+ nn.Z = make([]*mat.Dense, nn.Count)
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
-func (nn *NeuralNetwork) forward(aIn mat.Matrix) {
|
|
|
+func (nn *BackProp) forward(aIn mat.Matrix) {
|
|
|
nn.A[0] = mat.DenseCopyOf(aIn)
|
|
|
|
|
|
for i := 1; i < nn.Count; i++ {
|
|
@@ -355,7 +290,7 @@ func (nn *NeuralNetwork) forward(aIn mat.Matrix) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (nn *NeuralNetwork) backward(aIn, aOut mat.Matrix) {
|
|
|
+func (nn *BackProp) backward(aIn, aOut mat.Matrix) {
|
|
|
nn.forward(aIn)
|
|
|
|
|
|
lastLayerNum := nn.Count - 1
|
|
@@ -468,10 +403,6 @@ func (nn *NeuralNetwork) backward(aIn, aOut mat.Matrix) {
|
|
|
nn.Weights = newWeights
|
|
|
}
|
|
|
|
|
|
-func (nn *NeuralNetwork) result() *mat.Dense {
|
|
|
+func (nn *BackProp) result() *mat.Dense {
|
|
|
return nn.A[nn.Count-1]
|
|
|
}
|
|
|
-
|
|
|
-func (nn *NeuralNetwork) TeachResilient(aIn, aOut mat.Matrix, nuP, nuM float64, deltaMin, deltaMax float64) {
|
|
|
-
|
|
|
-}
|