phren 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6a36bbbd6ba022487b4efab719fe04f00f4155c2
4
+ data.tar.gz: 20e811f45f8fe96a561c99a645d868e89b504563
5
+ SHA512:
6
+ metadata.gz: dfcf6737c205c14ec1c275a68873d90b84dd2300c0541b2c6e2318bec6e09d9db5858b3918d312659e338987c630dab51b2c992afcf5325b468c6ed3f16eeb4b
7
+ data.tar.gz: 853e584e3449abc2a67f2644df6302b4bdd7c82d7943d68a64b8775d82d7f498b171011bc4336ab4c7aee76b37977d569b50995805367778b49e24dd78044df9
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :spec
data/lib/layer.rb ADDED
@@ -0,0 +1,17 @@
1
+ module Phren
2
+
3
+ class Layer
4
+
5
+ attr_reader :id, :neurons, :length
6
+
7
+ def initialize(length, id)
8
+ @length = length
9
+ @id = id # num of layer starting from 0. if it's negative neurons are bias
10
+ @neurons = Array.new(@length) { |i|
11
+ Neuron.new(@id < 0 ? 1 : 0,[@id, i])
12
+ }
13
+ end
14
+
15
+ end
16
+
17
+ end
data/lib/moldmaker.rb ADDED
@@ -0,0 +1,131 @@
1
+ module Phren
2
+ class Moldmaker
3
+
4
+ # @option opts [Float] :molding_rate
5
+ # @option opts [Float] :momentum
6
+ # @option opts [Integer] :max_iterations
7
+ def initialize(opts = {})
8
+ @molding_rate = opts[:molding_rate]
9
+ @momentum = opts[:momentum]
10
+ @max_iterations = opts[:max_iterations]
11
+ end
12
+
13
+ # @param [Phren::Network] an architecture of network
14
+ # @param [Array] with elements array of inputs
15
+ # @param [Array] with elements array of outputs
16
+ def mold(network, stimulus, expected_responses)
17
+ @network = network
18
+
19
+ 1.upto(@max_iterations) { |iter|
20
+ stimulus.each_index { |i|
21
+ self.irritate(stimulus[i])
22
+ self.learn(expected_responses[i])
23
+ }
24
+ }
25
+
26
+ end
27
+
28
+ def irritate(stimuli)
29
+
30
+ 0.upto(@network.num_of_inputs-1) { |i|
31
+ @network.layers[0].neurons[i].value = stimuli[i]
32
+ }
33
+
34
+
35
+
36
+ 1.upto(@network.num_of_layers-1) { |l|
37
+ @network.layers[l].neurons.each { |n|
38
+ n.value = net_input(n)
39
+ n.value = sig(n.value)
40
+ }
41
+ }
42
+
43
+ end
44
+
45
+ def test(inputs)
46
+ outputs = []
47
+ irritate(inputs)
48
+ @network.layers[@network.num_of_layers-1].neurons.each { |n|
49
+ outputs << n.value
50
+ }
51
+
52
+ return outputs
53
+
54
+ end
55
+
56
+
57
+ def learn(expected_response)
58
+
59
+ @network.layers[@network.num_of_layers-1].neurons.each_with_index { |n, i|
60
+ expected_value = expected_response[i]
61
+ n.error_signal = n.value * (1 - n.value) * (n.value - expected_value)
62
+ }
63
+
64
+ # compute deltas - error_signal
65
+
66
+
67
+ (@network.num_of_layers-2).downto(0) { |l|
68
+ @network.layers[l].neurons.each { |n|
69
+ n.error_signal = n.value * (1 - n.value) * net_output(n)
70
+ }
71
+ }
72
+
73
+ # TODO reduce it to one forloop
74
+ 1.upto(@network.num_of_layers-1) { |l|
75
+ @network.layers[l].neurons.each { |n|
76
+ @network.synapses.keys.each { |k|
77
+ if k[1] == n.id[0]
78
+ @network.synapses[k].each { |s|
79
+ if (s.to == n)
80
+ w = s.weight
81
+ s.weight = s.weight - (@molding_rate * n.error_signal * s.from.value)
82
+ #puts "Just updated synapse from Neuron(Layer:#{s.from.id[0]},#{s.from.id[1]} to Neuron(Layer:#{s.to.id[0]},#{s.to.id[1]}) !!"
83
+ # puts "From #{w} became #{s.weight} with error signal #{n.error_signal} \n"
84
+ # puts "\n\n"
85
+ end
86
+ }
87
+ end
88
+ }
89
+ }
90
+ }
91
+
92
+ end
93
+
94
+ def sig(x)
95
+ return (1 / (1 + Math.exp(-x)))
96
+ end
97
+
98
+
99
+ def net_input(neuron)
100
+ net_j = 0
101
+ @network.synapses.keys.each { |k|
102
+ if k[1] == neuron.id[0]
103
+ @network.synapses[k].each { |s|
104
+ if (s.to == neuron)
105
+ # from_synapses << s
106
+ net_j += (s.from.value * s.weight)
107
+ end
108
+ }
109
+ end
110
+ }
111
+ return net_j
112
+ end
113
+
114
+ # να καλείται ως προς το δίκτυο
115
+ def net_output(neuron)
116
+ net_o = 0
117
+ @network.synapses.keys.each { |k|
118
+ if k[0] == neuron.id[0]
119
+ @network.synapses[k].each { |s|
120
+ if (s.from == neuron)
121
+ net_o += (s.to.error_signal * s.weight)
122
+ end
123
+ }
124
+ end
125
+ }
126
+ return net_o
127
+ end
128
+
129
+
130
+ end
131
+ end
data/lib/network.rb ADDED
@@ -0,0 +1,48 @@
1
+ module Phren
2
+
3
+ class Network
4
+
5
+ attr_reader :synapses, :layers, :num_of_layers
6
+ attr_reader :num_of_inputs, :num_of_outputs
7
+ # @param [Array] architecture of network
8
+ # @opts options
9
+ def initialize(architecture, opts = {})
10
+
11
+ @synapses = {}
12
+ @layers = {}
13
+
14
+ @num_of_inputs = architecture.first
15
+ @num_of_outputs = architecture.last
16
+
17
+ @num_of_layers = architecture.length
18
+
19
+ # TODO try to implemet it with map
20
+ @layers[0] = Layer.new(architecture.first, 0)
21
+ 1.upto(@num_of_layers-1) { |i| # create layers
22
+ @layers[-i] = Layer.new(1, -i) # bias layer
23
+ @layers[i] = Layer.new(architecture[i], i)
24
+ }
25
+
26
+ @layers.keys.each { |k| # connect layers
27
+ if( k < 0) # is bias
28
+ connect_layers(@layers[k], @layers[-k])
29
+ elsif( k > 0) # is hidden or output layer
30
+ connect_layers(@layers[k-1], @layers[k])
31
+ end
32
+ }
33
+
34
+ end
35
+
36
+ # According to dontveter.com/bpr/basics.html is faster for xor problem
37
+ def connect_input_to_output_layer
38
+ connect_layers(@layers[0], @layers[@num_of_layers-1])
39
+ end
40
+
41
+ def connect_layers(from, to)
42
+ @synapses[[from.id, to.id]] = Array.new(from.length * to.length){ |index|
43
+ Synapse.new(from.neurons[index % from.length], to.neurons[index % to.length], 0) # 0 could be replace with random
44
+ }
45
+ end
46
+
47
+ end
48
+ end
data/lib/neuron.rb ADDED
@@ -0,0 +1,17 @@
1
+ module Phren
2
+
3
+ class Neuron
4
+
5
+ attr_accessor :value, :error_signal
6
+ attr_reader :id
7
+ # @param [Float] value for neuron
8
+ # @param [Array] [layer id,index]
9
+ def initialize(value, id)
10
+ @value = value
11
+ @id = id
12
+ @error_signal = 0
13
+ end
14
+
15
+ end
16
+
17
+ end
data/lib/synapse.rb ADDED
@@ -0,0 +1,19 @@
1
+ module Phren
2
+
3
+ class Synapse
4
+
5
+ attr_accessor :weight
6
+ attr_reader :from, :to
7
+
8
+ # @param [Phren::Neuron] where synapse starting
9
+ # @param [Phren::Neuron] where synapse is ending
10
+ # @param [Phren::Neuron] synapse wheight
11
+ def initialize(from, to, weight)
12
+ @from = from
13
+ @to = to
14
+ @weight = weight
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Phren, "#network" do
4
+ context "with parameters" do
5
+ it "the network is initialized" do
6
+ inputs = [[0,0],[0,1],[1,0],[1,1]]
7
+ outputs = [0,1,1,0]
8
+
9
+ net = Network.new()
10
+ net.forward
11
+ expect(net.my_variable).to eq true
12
+ end
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: phren
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Savvas Alexandrou
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple neural network gem
14
+ email: salexa@member.fsf.org
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - Rakefile
20
+ - lib/layer.rb
21
+ - lib/moldmaker.rb
22
+ - lib/network.rb
23
+ - lib/neuron.rb
24
+ - lib/synapse.rb
25
+ - spec/network_spec.rb
26
+ homepage: https://github.com/Savinos90/phren
27
+ licenses:
28
+ - GPL-3.0
29
+ metadata: {}
30
+ post_install_message: Thanks for installing!
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 2.5.1
47
+ signing_key:
48
+ specification_version: 3
49
+ summary: An Artificial Neural Network gem
50
+ test_files:
51
+ - spec/network_spec.rb