brainy 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3e533ffeb3db5e19cc90f955e4943a2be6860e31
4
- data.tar.gz: e2076373a36e253e85138507e9fb29fb31e8cff8
3
+ metadata.gz: fd89c615bcbb935df0b74079d0a9d966e3ee7a1b
4
+ data.tar.gz: cfb4ba364fbb4e22988ea52ad1a009a7a409921b
5
5
  SHA512:
6
- metadata.gz: 7c31a98936e9621497f0f7ef786b083abdf37dee0951072fb41c7f77ff063c9f3cd60db16013e6a8d3b8d4db0b95fd5f13689298a7c13c0eb774d328709e804c
7
- data.tar.gz: e2873d97e5829b53e11cc15e8069a9093de133a0dc21c72e4df674616bf0d4f55481bc569474a339478a636a5b77b4cefea152bbfdd141a22189186e292d0dec
6
+ metadata.gz: 44ddc7ca29fa248784df73e8b843427a7b31876f6372013e634cfa6383bfadf0aace3008b77340d9d50854cae61e602444ad5ffbed2ad8b87a0c5d128226015e
7
+ data.tar.gz: fb22aab27dc09690df51a40d121c6eb6b4285fa3cb3f1f4cc32f634e504786828c4bf57eaeaa913f2275b360c837162e97f7a26350539d4016645d5fb2c4cfb9
data/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2016 Robert Scott Reis
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Brainy - An Artificial Neural Network [![Build Status](https://travis-ci.org/EvilScott/brainy.svg?branch=master)](https://travis-ci.org/EvilScott/brainy)
2
+
3
+ Brainy is an [Artificial Neural Network (ANN)](https://en.wikipedia.org/wiki/Artificial_neural_network) using the
4
+ [Backpropagation](https://en.wikipedia.org/wiki/Backpropagation) algorithm. It was originally created as part of
5
+ the Neural NFL project [here](https://github.com/EvilScott/neuralnfl), but was broken out into a gem to be more reusable.
6
+
7
+ ### Usage
8
+ From [examples/sin.rb](https://github.com/EvilScott/brainy/blob/master/examples/sin.rb):
9
+ ```ruby
10
+ # Example using sin wave function
11
+ require_relative '../lib/brainy'
12
+ net = Brainy::Network.new(1, 3, 1, 0.25)
13
+
14
+ # training
15
+ 4000.times do
16
+ i = rand(0..(Math::PI/2))
17
+ o = Math.sin(i)
18
+ net.train!([i], [o])
19
+ end
20
+
21
+ # testing
22
+ mse = 1000.times.map do
23
+ i = rand(0..(Math::PI/2))
24
+ o = Math.sin(i)
25
+ (o - net.evaluate([i]).first) ** 2
26
+ end.reduce(:+) / 1000
27
+
28
+ puts "your MSE: #{ mse.round(3) }" # smaller is better
29
+ ```
@@ -0,0 +1,66 @@
1
+ module Brainy
2
+ class Network
3
+ attr_accessor :hidden_layer, :output_layer
4
+
5
+ def initialize(input_count, hidden_count, output_count, learning_rate)
6
+ @layers = [
7
+ Array.new(hidden_count, Vector.elements(Array.new(input_count + 1, rand(-1.0..1.0)))),
8
+ Array.new(output_count, Vector.elements(Array.new(hidden_count + 1, rand(-1.0..1.0))))
9
+ ]
10
+ @learning_rate = learning_rate
11
+ @activate = lambda { |x| 1 / (1 + Math.exp(-1 * x)) }
12
+ @activate_prime = lambda { |x| x * (1 - x) }
13
+ end
14
+
15
+ def evaluate(inputs)
16
+ @layers.reduce(Vector.elements(inputs)) do |input, layer|
17
+ input = Vector.elements(input.to_a + [1])
18
+ output = layer.map { |node| @activate.call(node.inner_product(input)) }
19
+ Vector.elements(output)
20
+ end
21
+ end
22
+
23
+ def train!(inputs, expected)
24
+ inputs = Vector.elements(inputs + [1])
25
+ hidden_outs = Vector.elements(@layers.first.map { |node| @activate.call(node.inner_product(inputs)) } + [1])
26
+ output_outs = Vector.elements(@layers.last.map { |node| @activate.call(node.inner_product(hidden_outs)) })
27
+ output_deltas = get_output_deltas(expected, output_outs)
28
+ hidden_deltas = get_hidden_deltas(hidden_outs, @layers.last, output_deltas)
29
+ @layers[1] = get_updated_weights(@layers.last, hidden_outs, output_deltas)
30
+ @layers[0] = get_updated_weights(@layers.first, inputs, hidden_deltas)
31
+ end
32
+
33
+ def get_output_deltas(expected, output)
34
+ expected.zip(output.to_a).map do |expect, out|
35
+ (out - expect) * @activate_prime.call(out)
36
+ end
37
+ end
38
+
39
+ def get_hidden_deltas(hidden_outs, output_nodes, output_deltas)
40
+ hidden_outs.each_with_index.map do |out, index|
41
+ error = output_nodes.zip(output_deltas).map { |weights, delta| weights[index] * delta }.reduce(:+)
42
+ error * @activate_prime.call(out)
43
+ end
44
+ end
45
+
46
+ def get_updated_weights(layer, inputs, deltas)
47
+ layer.each_with_index.map do |weights, node_index|
48
+ weights = weights.each_with_index.map do |weight, weight_index|
49
+ weight - (@learning_rate * inputs[weight_index] * deltas[node_index])
50
+ end
51
+ Vector.elements(weights)
52
+ end
53
+ end
54
+
55
+ def serialize
56
+ YAML.dump(self)
57
+ end
58
+
59
+ def self.from_serialized(dump)
60
+ net = YAML.load(dump)
61
+ net.instance_variable_set(:@activate, lambda { |x| 1 / (1 + Math.exp(-1 * x)) })
62
+ net.instance_variable_set(:@activate_prime, lambda { |x| x * (1 - x) })
63
+ net
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,3 @@
1
+ module Brainy
2
+ VERSION = '1.0.1'
3
+ end
@@ -0,0 +1,62 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ module Brainy
4
+ describe Network do
5
+ let (:net) { Network.new(4, 3, 2, 0.25) }
6
+
7
+ describe '#evaluate' do
8
+ it 'evaluates the network for a set of inputs' do
9
+ net.instance_variable_set(:@layers, [
10
+ [
11
+ Vector[0.1, 0.2, 0.3, 0.4, 0.5],
12
+ Vector[0.5, 0.6, 0.7, 0.8, 0.9],
13
+ Vector[0.9, 0.1, 0.2, 0.3, 0.4]
14
+ ],
15
+ [
16
+ Vector[0.1, 0.2, 0.3, 0.4],
17
+ Vector[0.4, 0.5, 0.6, 0.5]
18
+ ]
19
+ ])
20
+ output = net.evaluate([0.1, 0.3, 0.5, 0.7]).to_a.map { |x| x.round(6) }
21
+ expect(output).to eq [0.702451, 0.839256]
22
+ end
23
+ end
24
+
25
+ describe '#get_output_deltas' do
26
+ it 'provides deltas for the output layer' do
27
+ expected, output = [0.4, 0.6], [0.3, 0.8]
28
+ deltas = net.get_output_deltas(expected, output)
29
+ expect(deltas.map { |x| x.round(6) }).to eq [-0.021, 0.032]
30
+ end
31
+ end
32
+
33
+ describe '#get_hidden_deltas' do
34
+ it 'provides deltas for the hidden layer' do
35
+ hidden_outs, output_deltas = [0.9, 0.8, 0.7], [0.6, 0.4]
36
+ output_nodes = [Vector[0.2, 0.3, 0.4], Vector[0.4, 0.3, 0.2]]
37
+ deltas = net.get_hidden_deltas(hidden_outs, output_nodes, output_deltas)
38
+ expect(deltas.map { |x| x.round(6) }).to eq [0.0252, 0.048, 0.0672]
39
+ end
40
+ end
41
+
42
+ describe '#get_updated_weights' do
43
+ it 'updates the hidden weights' do
44
+ layer = [
45
+ Vector[0.3, 0.4, 0.5, 0.6],
46
+ Vector[0.1, 0.2, 0.4, 0.8],
47
+ Vector[0.9, 0.6, 0.3, 0.0]
48
+ ]
49
+ inputs, deltas = [0.2, 0.3, 0.4, 0.5], [0.7, 0.6, 0.5]
50
+ new_layer = net.get_updated_weights(layer, inputs, deltas)
51
+ expected_layer = [
52
+ [0.265, 0.3475, 0.43, 0.5125],
53
+ [0.07, 0.155, 0.34, 0.725],
54
+ [0.875, 0.5625, 0.25, -0.0625]
55
+ ]
56
+ new_layer.zip(expected_layer).each do |actual, expected|
57
+ expect(actual.to_a.map { |x| x.round(6) }).to eq expected
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,3 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup(:test)
3
+ require_relative '../lib/brainy'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brainy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Scott Reis
@@ -9,7 +9,35 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2016-02-07 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 10.4.2
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 10.4.2
13
41
  description: Brainy is an Artificial Neural Network (ANN) using the Backpropagation
14
42
  algorithm.
15
43
  email: reis.robert.s@gmail.com
@@ -17,7 +45,13 @@ executables: []
17
45
  extensions: []
18
46
  extra_rdoc_files: []
19
47
  files:
48
+ - LICENSE
49
+ - README.md
20
50
  - lib/brainy.rb
51
+ - lib/brainy/network.rb
52
+ - lib/brainy/version.rb
53
+ - spec/lib/brainy/network_spec.rb
54
+ - spec/spec_helper.rb
21
55
  homepage: https://github.com/EvilScott/brainy
22
56
  licenses:
23
57
  - MIT
@@ -30,7 +64,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
30
64
  requirements:
31
65
  - - ">="
32
66
  - !ruby/object:Gem::Version
33
- version: '0'
67
+ version: 1.9.3
34
68
  required_rubygems_version: !ruby/object:Gem::Requirement
35
69
  requirements:
36
70
  - - ">="