SimpleNeuralNetwork 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 46f5556f65b4606a5e8314e7ba7791f73ba314fd
4
+ data.tar.gz: 72fdae81f4c25de9f57bf4295f064d414dcd5380
5
+ SHA512:
6
+ metadata.gz: 7149124f6817e608bba4ad2f9ca8419bbf50c27991fc1565b59f0f42cb8b2d1bdfa17fb4ad3bfeb4c41055eb19b7bec0b22e30361ead91c4c3251c4fb9a2c92a
7
+ data.tar.gz: 73e138bd6e0b474fcf57e576a884a407fe6512f2e0ae66ed8ab8ae2c22143247ac6b24aae5c2c409d3e19a83d3ea41075d71745b96c2ed34f9d5b5a31b4f9d35
@@ -0,0 +1,71 @@
1
+ require_relative "neuron"
2
+
3
+ class SimpleNeuralNetwork
4
+ class Layer
5
+ # Number of neurons
6
+ attr_accessor :size
7
+
8
+ attr_accessor :prev_layer
9
+ attr_accessor :next_layer
10
+
11
+ # List of #{size} neurons
12
+ attr_accessor :neurons
13
+
14
+ attr_accessor :network
15
+
16
+ def initialize(size, network)
17
+ @size = size
18
+ @neurons = []
19
+ @network = network
20
+
21
+ populate_neurons
22
+ end
23
+
24
+ # The method that drives network output resolution.
25
+ # get_output calculates the array of node values for this layer.
26
+ # This is calculated by recursively fetching the output from the previous layer, then applying edge/node weight rules.
27
+ # The first layer will fetch it's values from @network.inputs
28
+ def get_output
29
+ if !prev_layer
30
+ # This is the first layer, so the output set is simply the network input set
31
+ @network.inputs
32
+ else
33
+ # Each neuron output value is calculated by:
34
+ # output[i] = (
35
+ # (prev_layer.neurons[0] * prev_layer.neurons[0].edges[i])
36
+ # + (prev_layer.neurons[1] * prev_layer.neurons[1].edges[i])
37
+ # + ...
38
+ # ) + self.neurons[i].bias
39
+
40
+ prev_layer_output = prev_layer.get_output
41
+
42
+ # Generate the output values for the layer
43
+ (0..@size-1).map do |i|
44
+ value = 0
45
+
46
+ prev_layer_output.each_with_index do |output, index|
47
+ value += (output * prev_layer.neurons[index].edges[i])
48
+ end
49
+
50
+ value + @neurons[i].bias
51
+ end
52
+ end
53
+ end
54
+
55
+ def initialize_neuron_edges
56
+ return unless @next_layer
57
+
58
+ @neurons.each do |neuron|
59
+ neuron.initialize_edges(@next_layer.size)
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def populate_neurons
66
+ @size.times do
67
+ @neurons << Neuron.new(layer: self)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,78 @@
1
+ require_relative "layer"
2
+
3
+ # To properly initialze a network:
4
+ # - Initialize the new Network object
5
+ # - Create layers using Network#create_layer
6
+ # (This creates layers from left to right, input -> hidden layers -> output layer)
7
+ # - Call Network#initialize_edges to populate neuron edges in the network.
8
+ # This has to be done after creating all layers because the number of edges depends
9
+ # on the number on neurons in the next layer
10
+ class SimpleNeuralNetwork
11
+ class Network
12
+ class InvalidInputError < StandardError; end
13
+ # An array of layers
14
+ attr_accessor :layers
15
+
16
+ attr_accessor :inputs
17
+
18
+ def initialize
19
+ @layers = []
20
+ @inputs = []
21
+ end
22
+
23
+ # Run an input set against the neural network.
24
+ # Accepts an array of input integers between 0 and 1 of length #input_size
25
+ # Returns
26
+ def run(inputs)
27
+ unless inputs.size == input_size && inputs.all? { |input| input >= 0 && input <= 1 }
28
+ raise InvalidInputError.new("Invalid input passed to Network#run")
29
+ end
30
+
31
+ @inputs = inputs
32
+
33
+ # Get output from last layer. It recursively depends on layers before it.
34
+ @layers[-1].get_output
35
+ end
36
+
37
+ # Returns the number of input nodes
38
+ def input_size
39
+ @layers[0].size
40
+ end
41
+
42
+ # Returns the number of output nodes
43
+ def output_size
44
+ @layers[-1].size
45
+ end
46
+
47
+ def create_layer(neurons:)
48
+ unless @layers.empty?
49
+ new_layer = Layer.new(neurons, self)
50
+ prev_layer = @layers.last
51
+
52
+ @layers << new_layer
53
+
54
+ new_layer.prev_layer = prev_layer
55
+ prev_layer.next_layer = new_layer
56
+ else
57
+ @layers << Layer.new(neurons, self)
58
+ end
59
+ end
60
+
61
+ # This traverses the network and initializes all neurons with edges
62
+ # Initializes with random weights between -5 and 5
63
+ def initialize_edges
64
+ @layers.each(&:initialize_neuron_edges)
65
+ end
66
+ end
67
+ end
68
+
69
+ # Sample usage:
70
+ #
71
+ # network = Network.new
72
+ #
73
+ # network.create_layer(neurons: 10)
74
+ # network.create_layer(neurons: 2)
75
+
76
+ # network.initialize_edges
77
+
78
+ # network.run([0.5]*10)
@@ -0,0 +1,28 @@
1
+ class SimpleNeuralNetwork
2
+ class Neuron
3
+ # Define the minimum and maximum edge weight
4
+ EDGE_RANGE = -5..5
5
+
6
+ attr_accessor :bias
7
+
8
+ # The neuron parent layer
9
+ attr_accessor :layer
10
+
11
+ # A neuron's edges connect it to the #{layer.next_layer.size} neurons of the next layer
12
+ attr_accessor :edges
13
+
14
+ def initialize(layer)
15
+ @layer = layer
16
+ @bias = 0
17
+ @edges = []
18
+ @value = nil
19
+ end
20
+
21
+ # A neuron should have one edge per neuron in the next layer
22
+ def initialize_edges(next_layer_size)
23
+ next_layer_size.times do
24
+ @edges << rand(EDGE_RANGE)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ class SimpleNeuralNetwork
2
+ require "network"
3
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: SimpleNeuralNetwork
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nathaniel Woodthorpe
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-20 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A very simple neural network implementation in Ruby.
14
+ email: njwoodthorpe@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/layer.rb
20
+ - lib/network.rb
21
+ - lib/neuron.rb
22
+ - lib/simple_neural_network.rb
23
+ homepage: https://github.com/d12/SimpleNeuralNetwork
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 2.5.2
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: A very simple neural network implementation in Ruby.
47
+ test_files: []