Skip to content

Commit

Permalink
Add support for loading and saving Neural Network
Browse files Browse the repository at this point in the history
  • Loading branch information
Zomis committed Jan 11, 2016
1 parent 6dbc8b3 commit 572d4b5
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/main/groovy/net/zomis/machlearn/neural/NeuralNetwork.groovy
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.zomis.machlearn.neural

import java.nio.file.Path
import java.util.stream.Stream

class NeuralNetwork {
Expand Down Expand Up @@ -44,6 +45,53 @@ class NeuralNetwork {
println()
}

void save(OutputStream output) {
new DataOutputStream(output).withCloseable {
it.writeInt(layerCount)
for (NeuronLayer layer : layers) {
it.writeInt(layer.size())
it.writeInt(layer.name.length())
it.writeBytes(layer.name)
}
for (NeuronLayer layer : layers) {
for (Neuron neuron : layer) {
for (NeuronLink link : neuron.inputs) {
it.writeDouble(link.weight)
}
}
}
}
}

static NeuralNetwork load(InputStream input) {
def network = new NeuralNetwork()
new DataInputStream(input).withCloseable {
int layers = it.readInt()
for (int i = 0; i < layers; i++) {
int size = it.readInt()
int nameLength = it.readInt()
StringBuilder name = new StringBuilder()
for (int nameIndex = 0; nameIndex < nameLength; nameIndex++) {
name.append((char) it.readByte())
}
NeuronLayer layer = network.createLayer(name.toString())
size.times { layer.createNeuron() }
}
for (int i = 0; i < layers; i++) {
NeuronLayer layer = network.getLayer(i)
if (i > 0) {
layer.neurons.each {it.addInputs(network.getLayer(i - 1))}
}
for (Neuron neuron : layer) {
for (NeuronLink link : neuron.inputs) {
link.weight = it.readDouble()
}
}
}
}
network
}

double[] run(double[] input) {
double[] output = new double[outputLayer.size()]
assert input.length == inputLayer.size()
Expand Down
56 changes: 56 additions & 0 deletions src/test/groovy/net/zomis/machlearn/neural/LoadSaveTest.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package net.zomis.machlearn.neural

import org.junit.Test

class LoadSaveTest {

@Test
void simpleLoadSave() {
List<LearningData> examples = Arrays.asList(
new LearningData([0, 0] as double[], [0] as double[]),
new LearningData([0, 1] as double[], [1] as double[]),
new LearningData([1, 0] as double[], [1] as double[]),
new LearningData([1, 1] as double[], [0] as double[]),
)
def network = new NeuralNetwork()
def inputLayer = network.createLayer('IN')
inputLayer.createNeuron()
inputLayer.createNeuron()

def middleLayer = network.createLayer('MIDDLE')
middleLayer.createNeuron().addInputs(inputLayer)
middleLayer.createNeuron().addInputs(inputLayer)

def outputLayer = network.createLayer('OUT')
outputLayer.createNeuron().addInputs(middleLayer)
new BackPropagation(0.2, 100000).backPropagationLearning(examples, network, new Random(42))

def savedNetwork = new ByteArrayOutputStream()
network.save(savedNetwork)

assert savedNetwork.toByteArray() == LoadSaveTest.class.getClassLoader()
.getResource('simplenetwork.network').bytes
}

@Test
void loadTest() {
def network = NeuralNetwork.load(LoadSaveTest.class.getClassLoader()
.getResourceAsStream('simplenetwork.network'))
assert network.layerCount == 3
assert network.getLayer(0).size() == 2
assert network.getLayer(1).size() == 2
assert network.getLayer(2).size() == 1

assert network.getLayer(0).name == 'IN'
assert network.getLayer(1).name == 'MIDDLE'
assert network.getLayer(2).name == 'OUT'
def loadedNetwork = new ByteArrayOutputStream()
network.save(loadedNetwork)

def runResult = network.run([1, 0] as double[])
println runResult
assert loadedNetwork.toByteArray() == LoadSaveTest.class.getClassLoader()
.getResource('simplenetwork.network').bytes
}

}
Binary file added src/test/resources/simplenetwork.network
Binary file not shown.

0 comments on commit 572d4b5

Please sign in to comment.