Sfoglia il codice sorgente

Add Reset method to NeuralNetwork to reset it to random state with
specified layers configuration
Use sync locker for most methods of nueral network
Minor code cleanup

Alexey Edelev 5 anni fa
parent
commit
a6374f1562
1 ha cambiato i file con 46 aggiunte e 4 eliminazioni
  1. 46 4
      neuralnetwork/neuralnetwork/neuralnetwork.go

+ 46 - 4
neuralnetwork/neuralnetwork/neuralnetwork.go

@@ -149,6 +149,8 @@ func NewNeuralNetwork(sizes []int, gradientDescentInitializer GradientDescentIni
 }
 
 func (nn *NeuralNetwork) Copy() (outNN *NeuralNetwork) {
+	nn.syncMutex.Lock()
+	defer nn.syncMutex.Unlock()
 	outNN = &NeuralNetwork{
 		Sizes:                      nn.Sizes,
 		LayerCount:                 len(nn.Sizes),
@@ -171,6 +173,42 @@ func (nn *NeuralNetwork) Copy() (outNN *NeuralNetwork) {
 	return
 }
 
+func (nn *NeuralNetwork) Reset(sizes []int) (err error) {
+	nn.syncMutex.Lock()
+	defer nn.syncMutex.Unlock()
+	err = nil
+	if len(sizes) < 3 {
+		fmt.Printf("Invalid network configuration: %v\n", sizes)
+		return errors.New("Invalid network configuration: %v\n")
+	}
+
+	for i := 0; i < len(sizes); i++ {
+		if sizes[i] < 2 {
+			fmt.Printf("Invalid network configuration: %v\n", sizes)
+			return errors.New("Invalid network configuration: %v\n")
+		}
+	}
+
+	lenSizes := len(sizes)
+	nn.Sizes = sizes
+	nn.LayerCount = len(sizes)
+	nn.Biases = make([]*mat.Dense, lenSizes)
+	nn.Weights = make([]*mat.Dense, lenSizes)
+	nn.BGradient = make([]interface{}, lenSizes)
+	nn.WGradient = make([]interface{}, lenSizes)
+
+	for l := 1; l < nn.LayerCount; l++ {
+		nn.Biases[l] = generateRandomDense(nn.Sizes[l], 1)
+		nn.Weights[l] = generateRandomDense(nn.Sizes[l], nn.Sizes[l-1])
+		if nn.gradientDescentInitializer != nil {
+			nn.BGradient[l] = nn.gradientDescentInitializer(nn, l, BiasGradient)
+			nn.WGradient[l] = nn.gradientDescentInitializer(nn, l, WeightGradient)
+		}
+	}
+
+	return
+}
+
 func (nn *NeuralNetwork) SetStateWatcher(watcher StateWatcher) {
 	nn.watcher = watcher
 	if watcher != nil {
@@ -207,6 +245,8 @@ func (nn *NeuralNetwork) Predict(aIn mat.Matrix) (maxIndex int, max float64) {
 }
 
 func (nn *NeuralNetwork) Validate(trainer training.Trainer) (failCount, total int) {
+	nn.syncMutex.Lock()
+	defer nn.syncMutex.Unlock()
 	failCount = 0
 	total = 0
 	trainer.Reset()
@@ -313,13 +353,15 @@ func (nn *NeuralNetwork) runBatchWorkers(threadCount int, trainer training.Train
 }
 
 func (nn *NeuralNetwork) SaveState(writer io.Writer) {
+	nn.syncMutex.Lock()
+	defer nn.syncMutex.Unlock()
 	//save input array count
 	bufferSize := make([]byte, 4)
 	binary.LittleEndian.PutUint32(bufferSize[0:], uint32(nn.LayerCount))
 	_, err := writer.Write(bufferSize)
 
 	check(err)
-	fmt.Printf("wrote value %d\n", uint32(nn.LayerCount))
+	//fmt.Printf("wrote value %d\n", uint32(nn.LayerCount))
 
 	// save an input array
 	buffer := make([]byte, nn.LayerCount*4)
@@ -332,13 +374,11 @@ func (nn *NeuralNetwork) SaveState(writer io.Writer) {
 	// fmt.Printf("wrote buffer %d bytes\n", n2)
 
 	//save biases
-	////////////////////////
 	for i := 1; i < nn.LayerCount; i++ {
 		saveDense(writer, nn.Biases[i])
 	}
 
 	//save weights
-	////////////////////////
 	for i := 1; i < nn.LayerCount; i++ {
 		saveDense(writer, nn.Weights[i])
 	}
@@ -352,6 +392,8 @@ func (nn *NeuralNetwork) SaveStateToFile(filePath string) {
 }
 
 func (nn *NeuralNetwork) LoadState(reader io.Reader) {
+	nn.syncMutex.Lock()
+	defer nn.syncMutex.Unlock()
 	// Reade count
 	nn.LayerCount = readInt(reader)
 
@@ -374,9 +416,9 @@ func (nn *NeuralNetwork) LoadState(reader io.Reader) {
 		nn.Biases[l] = readDense(reader, nn.Biases[l])
 	}
 
+	// read Weights and initialize gradient descents
 	nn.BGradient = make([]interface{}, nn.LayerCount)
 	nn.WGradient = make([]interface{}, nn.LayerCount)
-	// read Weights and initialize gradient descents
 	nn.Weights[0] = &mat.Dense{}
 	for l := 1; l < nn.LayerCount; l++ {
 		nn.Weights = append(nn.Weights, &mat.Dense{})