Skip to content

Commit

Permalink
basic evaluate method working
Browse files Browse the repository at this point in the history
  • Loading branch information
dorkrawk committed Apr 23, 2017
1 parent 40c84f9 commit 9f2312a
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 15 deletions.
4 changes: 2 additions & 2 deletions spec/grey_matter/edge_spec.cr
Expand Up @@ -7,8 +7,8 @@ describe GreyMatter::Edge do
it "sets an initial_weight" do
node1 = GreyMatter::Node.new
node2 = GreyMatter::Node.new
edge = GreyMatter::Edge.new(node1, node2, 0.3)
edge.weight.should eq(0.3)
edge = GreyMatter::Edge.new(node1, node2)
edge.weight.should_not be_nil
end
end
end
31 changes: 31 additions & 0 deletions spec/grey_matter/neural_network_spec.cr
@@ -1,4 +1,35 @@
require "../../spec_helper"

describe GreyMatter::NeuralNetwork do
input_size = 5
hidden_sizes = [4, 3]
output_size = 2

describe ".initialize" do

it "builds layers of the given size" do
nn = GreyMatter::NeuralNetwork.new(input_size, hidden_sizes, output_size)
nn.input_layer.size.should eq input_size
nn.hidden_layers.map { |l| l.size }.should eq hidden_sizes
nn.output_layer.size.should eq output_size
end
end

describe "#evaluate" do

it "takes input and produces output based on current weights" do
nn = GreyMatter::NeuralNetwork.new(input_size, hidden_sizes, output_size)
nn.edges.flatten.each { |e| e.weight = 0.5}
input = [1.0, 1.0, 1.0, 1.0, 1.0]
nn.evaluate(input).should eq [7.5, 7.5]
end

it "raises an ArgumentError if the input doesn't match the size of the input layer" do
nn = GreyMatter::NeuralNetwork.new(input_size, hidden_sizes, output_size)
input = [1.0, 1.0]
expect_raises(ArgumentError) do
nn.evaluate(input)
end
end
end
end
8 changes: 6 additions & 2 deletions src/grey_matter/edge.cr
Expand Up @@ -2,7 +2,11 @@ class GreyMatter::Edge

property input, output, weight

def initialize(@input : GreyMatter::Node, @output : GreyMatter::Node, initial_weight : Float64 = nil)
@weight = initial_weight || Random.rand
def initialize(@input : GreyMatter::Node, @output : GreyMatter::Node)
@weight = Random.rand
end

def reset
@weight = Random.rand
end
end
40 changes: 30 additions & 10 deletions src/grey_matter/neural_network.cr
@@ -1,19 +1,26 @@
class GreyMatter::NeuralNetwork

@input_layer : Array(Node)
@hidden_layers : Array(Array(Node))
@output_layer : Array(Node)
@edges = [] of Array(Edge)

getter input_layer, hidden_layers, output_layer, edges

def initialize(input_size : Int32, hidden_layer_sizes : Array(Int32), output_size : Int32)
@input_layer = build_layer(input_size)
@hidden_layers = hidden_layer_sizes.map { |layer_size| build_layer(layer_size) }
@output_layer = build_layer(output_size)
build_edges
# build network, set edge weights to random values
end

def train(input, output)

raise ArgumentError.new("input must be the same size as the input layer") unless input.size == @input_layer.size
raise ArgumentError.new("output must be the same size as the output layer") unless output.size == @output_layer.size
end

def reset
# reset all edge weights to random values
def reset!
@edges.flatten.each { |e| e.reset }
end

def import(file)
Expand All @@ -24,6 +31,20 @@ class GreyMatter::NeuralNetwork
#export weights to file
end

def evaluate(input : Array(Float64))
raise ArgumentError.new("input must be the same size as the input layer") unless input.size == @input_layer.size
@input_layer.each_with_index { |node, i| node.value = input[i] }
@hidden_layers.each { |layer| forward_propigate(layer) }
forward_propigate(@output_layer)
@output_layer.map { |node| node.value }
end

def forward_propigate(layer : Array(Node))
layer.each do |node|
node.value = @edges.flatten.select { |e| e.output == node }.map { |e| e.input.value * e.weight }.sum
end
end

def all_nodes
[@input_layer] + @hidden_layers + [@output_layer]
end
Expand All @@ -37,14 +58,13 @@ class GreyMatter::NeuralNetwork
end

def build_edges
@edges = [] of Array(GreyMatter::Edge)
all_nodes.each_with_index do |layer, i|
@edges << connect_layers(layer, all_nodes[i+1]) if i -1 < all_nodes.size
all_nodes.each_cons(2) do |layers|
@edges << connect_layers(layers.first, layers.last)
end
end

def connect_layers(layer1 : Array(GreyMatter::Node), layer2 : Array(GreyMatter::Node))
edges = [] of GreyMatter::Edge
def connect_layers(layer1 : Array(Node), layer2 : Array(Node))
edges = [] of Edge
layer1.each do |input_node|
layer2.each do |output_node|
edges << Edge.new(input_node, output_node)
Expand All @@ -54,7 +74,7 @@ class GreyMatter::NeuralNetwork
end

def build_layer(size : Int32)
layer = [] of Float64
layer = [] of Node
size.times do
layer << Node.new
end
Expand Down
3 changes: 2 additions & 1 deletion src/grey_matter/node.cr
@@ -1,6 +1,7 @@
class GreyMatter::Node

def initialize
property value

def initialize(@value : Float64 = 0.0)
end
end

0 comments on commit 9f2312a

Please sign in to comment.