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 +7 -0
- data/Rakefile +8 -0
- data/lib/layer.rb +17 -0
- data/lib/moldmaker.rb +131 -0
- data/lib/network.rb +48 -0
- data/lib/neuron.rb +17 -0
- data/lib/synapse.rb +19 -0
- data/spec/network_spec.rb +14 -0
- metadata +51 -0
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
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
|