ruby_brain 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 243add4b6f64c99d4bc2de70f69ff74f8fe439fd
4
+ data.tar.gz: 979c86696fd11c0892031495e57e7f3746b8df2f
5
+ SHA512:
6
+ metadata.gz: a4d8118899133f660ebfb9a64dd1cd068bb7501dff0cf371b6a8937a51fb9d9c0949b45f76176e71404dc745aa766fd9d3853ef34b6015f1d9bc33025df00b48
7
+ data.tar.gz: e0aec12b42540e424555f50e3bd7784d136fd7d831ee01486967198461d2940d63f174cdcb4a6b7583bb0b5ffdd0aae8968879a45d137d03a07c02b725d13e49
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ *~
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ruby_brain.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 TODO: Write your name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # RubyBrain
2
+
3
+ RubyBrain is a library of neural net, deep learning for Ruby.
4
+ You can install/use this library easily because the core is created by using only Ruby standard library.
5
+
6
+ The code of RubyBrain is the neuron oriented style.
7
+ This means that a class which represents a neuraon exists and each neurons are instances of the class.
8
+ So, you can treat neurons flexibly in a network.
9
+ Instead, the speed is very slow and it might not be reasonable for applications to use this library in the core.
10
+ However this library may help you get more deep knowledge around neuralnet/deep learning.
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'ruby_brain'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install ruby_brain
27
+
28
+ ## Usage
29
+
30
+ Please refer to
31
+ [github.com/elgoog/ruby_brain/README.org](https://github.com/elgoog/ruby_brain/blob/master/README.org)
32
+ for detail.
33
+
34
+ ## Development
35
+
36
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
37
+
38
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
39
+
40
+ ## Contributing
41
+
42
+ Bug reports and pull requests are welcome on GitHub at https://github.com/elgoog/ruby_brain.
43
+
44
+
45
+ ## License
46
+
47
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
48
+
data/README.org ADDED
@@ -0,0 +1,237 @@
1
+ * Introduction
2
+
3
+ RubyBrain is a library of neural net, deep learning for Ruby.
4
+ You can install/use this library easily because the core is created by using only Ruby standard library.
5
+
6
+ The code of RubyBrain is the neuron oriented style.
7
+ This means that a class which represents a neuraon exists and each neurons are instances of the class.
8
+ So, you can treat neurons flexibly in a network.
9
+ Instead, the speed is very slow and it might not be reasonable for applications to use this library in the core.
10
+ However this library may help you get more deep knowledge around neuralnet/deep learning.
11
+
12
+ * Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ #+BEGIN_SRC ruby
17
+ gem 'ruby_brain'
18
+ #+END_SRC
19
+
20
+ And then execute:
21
+
22
+ #+BEGIN_SRC shell
23
+ $ bundle
24
+ #+END_SRC
25
+
26
+ Or install it yourself as:
27
+
28
+ #+BEGIN_SRC shell
29
+ $ gem install ruby_brain
30
+ #+END_SRC
31
+
32
+ * Usage
33
+
34
+ ** dataset
35
+
36
+ All dataset used for training/test/predicate must be 2 dimension array structure.
37
+ 1st dimension indicates samples and 2nd dimension is used for features.
38
+
39
+ *** example "AND"
40
+ Now we assume that we train a network to operate as "AND operator"
41
+ The true table of "AND operator" is as below.
42
+ In short, when both "in 1" and "in 2" are 1, the "out" should be 1
43
+ and 0 should be output for other input combinations.
44
+
45
+ | in 1 | in 2 | out |
46
+ |------+------+-----|
47
+ | 0 | 0 | 0 |
48
+ | 0 | 1 | 0 |
49
+ | 1 | 0 | 0 |
50
+ | 1 | 1 | 1 |
51
+
52
+ In this situation, you can prepare the dataset lake following Ruby array.
53
+ #+BEGIN_SRC ruby
54
+ training_input_set = [
55
+ [0, 0],
56
+ [0, 1],
57
+ [1, 0],
58
+ [1, 1],
59
+ ]
60
+
61
+ training_supervisor_set = [
62
+ [0],
63
+ [0],
64
+ [0],
65
+ [1],
66
+ ]
67
+ #+END_SRC
68
+
69
+ ** constructing a network
70
+
71
+ RubyBrain::Network class represents a network. The constructor accepts an array which specifies the network structure.
72
+ If we use 1 hidden layer which has 3 neurons for above "AND operator" example, following array indicates the structure.
73
+ #+BEGIN_SRC ruby
74
+ # 2 inputs
75
+ # 3 units in a hidden layer
76
+ # 1 output
77
+ [2, 3, 1]
78
+ #+END_SRC
79
+
80
+ You can use 2 hidden layers with following code.
81
+ #+BEGIN_SRC ruby
82
+ # 2 inputs
83
+ # 4 units in 1st hidden layer
84
+ # 3 units in 2nd hidden layer
85
+ # 1 output
86
+ [2, 4, 2, 1]
87
+ #+END_SRC
88
+
89
+ So, a netowrk is created by
90
+ #+BEGIN_SRC ruby
91
+ a_network = RubyBrain::Network.new([2, 3, 1])
92
+
93
+ # learning_rate can be set
94
+ a_network.learning_rate = 0.5
95
+
96
+ # the networks must be initialized before it is used
97
+ a_network.init_network
98
+ #+END_SRC
99
+
100
+ There are other options for the constructor.
101
+ Please refer to the code. Sorry for missing document.
102
+
103
+ ** training
104
+
105
+ An instance method =learn= is used for training the network.
106
+ You can specify not only dataset but also other options for training.
107
+ #+BEGIN_SRC ruby
108
+ # max_training_cout : max epoch
109
+ # tolerance : stop training if RMS error become smaller than this value.
110
+ a_network.learn(training_input_set, training_supervisor_set, max_training_count=100, tolerance=0.0004, monitoring_channels=[:best_params_training])
111
+ #+END_SRC
112
+
113
+ ** predicate
114
+
115
+ Use =get_forward_outputs= with input data for predicating something.
116
+ Input data should be 1 sample.
117
+ #+BEGIN_SRC ruby
118
+ a_network.get_forward_outputs([1, 0])
119
+ #+END_SRC
120
+
121
+ ** save weights to a file
122
+
123
+ You can save optimized weights into a file.
124
+ Weights are saved as YAML format.
125
+
126
+ #+BEGIN_SRC ruby
127
+ a_network.dump_weights_to_yaml('/path/to/saved/weights/file.yml')
128
+ #+END_SRC
129
+
130
+ ** restore weights from a file
131
+
132
+ Optimized weights can be saved into a YAML file and you can use it for initializing weights when you create a new network.
133
+ #+BEGIN_SRC ruby
134
+ a_network = RubyBrain::Network.new([2, 3, 1])
135
+ a_network.init_network
136
+ a_network.load_weights_from_yaml_file('/path/to/saved/weights/file.yml')
137
+ #+END_SRC
138
+
139
+ * Examples
140
+
141
+ ** MNIST
142
+ Following code is included in [[https://github.com/elgoog/ruby_brain/blob/master/examples/mnist.rb][examples/mnist.rb]]
143
+
144
+ This module dependos on [[https://rubygems.org/gems/mnist][mnist]] gem to load mnist data into ruby array.
145
+
146
+ #+BEGIN_SRC ruby
147
+ require 'ruby_brain'
148
+ require 'ruby_brain/dataset/mnist/data'
149
+ #+END_SRC
150
+
151
+ Get MNIST dataset from [[http://yann.lecun.com/exdb/mnist/][THE MNIST DATABASE of handwritten digits]] if the dataset files don't exist in the working directory.
152
+ And load them into Ruby array =dataset=.
153
+
154
+ #+BEGIN_SRC ruby
155
+ dataset = RubyBrain::DataSet::Mnist::data
156
+ #+END_SRC
157
+
158
+ Divide =dataset= into training and test data.
159
+ NUM_TRAIN_DATA means how many first images are used as training data.
160
+ We use first 5000 images for training here.
161
+
162
+ #+BEGIN_SRC ruby
163
+ NUM_TRAIN_DATA = 5000
164
+ training_input = dataset[:input][0..(NUM_TRAIN_DATA-1)]
165
+ training_supervisor = dataset[:output][0..(NUM_TRAIN_DATA-1)]
166
+ #+END_SRC
167
+
168
+ Then construct the network and initialize.
169
+ In this case, an image has 784(28x28) pixcels and 10 classes(0..9).
170
+ So, the network structure should be [784, 50, 10] with 1 hidden layer which has 50 units.
171
+ You can construct the structure with following code.
172
+
173
+ #+BEGIN_SRC ruby
174
+ # network structure [784, 50, 10]
175
+ network = RubyBrain::Network.new([dataset[:input].first.size, 50, dataset[:output].first.size])
176
+ # learning rate is 0.7
177
+ network.learning_rate = 0.7
178
+ # initialize network
179
+ network.init_network
180
+ #+END_SRC
181
+
182
+ Run training.
183
+ #+BEGIN_SRC ruby
184
+ network.learn(training_input, training_supervisor, max_training_count=100, tolerance=0.0004, monitoring_channels=[:best_params_training])
185
+ #+END_SRC
186
+
187
+ Now, An optimized network was completed.
188
+ You can check it.
189
+
190
+ First, add =argmax= function into Array class.
191
+ This method finds the index of the array position the max value exists.
192
+ We use this method for finding the class(label 0~9) whose probability is the highest.
193
+
194
+ #+BEGIN_SRC ruby
195
+ class Array
196
+ def argmax
197
+ max_i, max_val = 0, self.first
198
+ self.each_with_index do |v, i|
199
+ max_val, max_i = v, i if v > max_val
200
+ end
201
+ max_i
202
+ end
203
+ end
204
+ #+END_SRC
205
+
206
+ Then, you can review each classes(labels) predicated by the model with following code.
207
+
208
+ #+BEGIN_SRC ruby
209
+ results = []
210
+ test_input.each_with_index do |input, i|
211
+ input.each_with_index do |e, j|
212
+ print(e > 0.3 ? 'x' : ' ')
213
+ puts if (j % 28) == 0
214
+ end
215
+ puts
216
+ supervisor_label = test_supervisor[i].argmax
217
+ predicated_label = network.get_forward_outputs(test_input[i]).argmax
218
+ puts "test_supervisor: #{supervisor_label}"
219
+ puts "predicate: #{predicated_label}"
220
+ results << (supervisor_label == predicated_label)
221
+ puts "------------------------------------------------------------"
222
+ end
223
+
224
+ puts "accuracy: #{results.count(true).to_f/results.size}"
225
+ #+END_SRC
226
+
227
+ I tried to train wioth above conditions.
228
+ The accuracy of trained model was 92.3%.
229
+ The weights file is [[https://github.com/elgoog/weights_ruby_brain/blob/master/weights_782_50_10_1.yml][here]].
230
+
231
+ * Contributing
232
+
233
+ 1. Fork it ( https://github.com/elgoog/ruby_brain/fork )
234
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
235
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
236
+ 4. Push to the branch (`git push origin my-new-feature`)
237
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ruby_brain"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/examples/mnist.rb ADDED
@@ -0,0 +1,79 @@
1
+ require 'ruby_brain'
2
+ require 'ruby_brain/dataset/mnist/data'
3
+
4
+ # NUM_TEST_DATA = 50000
5
+
6
+ dataset = RubyBrain::DataSet::Mnist::data
7
+
8
+ NUM_TRAIN_DATA = 5000
9
+
10
+ training_input = dataset[:input][0..(NUM_TRAIN_DATA-1)]
11
+ training_supervisor = dataset[:output][0..(NUM_TRAIN_DATA-1)]
12
+
13
+ # test_input = dataset[:input][NUM_TRAIN_DATA..(NUM_TRAIN_DATA+NUM_TEST_DATA-1)]
14
+ # test_supervisor = dataset[:output][NUM_TRAIN_DATA..(NUM_TRAIN_DATA+NUM_TEST_DATA-1)]
15
+ test_input = dataset[:input][NUM_TRAIN_DATA..-1]
16
+ test_supervisor = dataset[:output][NUM_TRAIN_DATA..-1]
17
+
18
+ network = RubyBrain::Network.new([dataset[:input].first.size, 50, dataset[:output].first.size])
19
+ network.learning_rate = 0.7
20
+ network.init_network
21
+ ### You can load weights from file in this timing if you want.
22
+ # network.load_weights_from_yaml_file(File.dirname(__FILE__) + '/../best_weights_1469044985.yml')
23
+
24
+ ### You can initializes weights by loading weights from file if you want.
25
+ # network.load_weights_from_yaml_file('path/to/weights.yml.file')
26
+
27
+ network.learn(training_input, training_supervisor, max_training_count=100, tolerance=0.0004, monitoring_channels=[:best_params_training])
28
+
29
+ ### You can save weights into a yml file if you want.
30
+ # network.dump_weights_to_yaml('path/to/weights.yml.file')
31
+
32
+
33
+ class Array
34
+ def argmax
35
+ max_i, max_val = 0, self.first
36
+ self.each_with_index do |v, i|
37
+ max_val, max_i = v, i if v > max_val
38
+ end
39
+ max_i
40
+ end
41
+ end
42
+
43
+ results = []
44
+ test_input.each_with_index do |input, i|
45
+ ### You can see test input, label and predicated lable in standard out if you uncomment in this block
46
+ # input.each_with_index do |e, j|
47
+ # print(e > 0.3 ? 'x' : ' ')
48
+ # puts if (j % 28) == 0
49
+ # end
50
+ # puts
51
+ supervisor_label = test_supervisor[i].argmax
52
+ predicated_label = network.get_forward_outputs(test_input[i]).argmax
53
+ # puts "test_supervisor: #{supervisor_label}"
54
+ # puts "predicate: #{predicated_label}"
55
+ results << (supervisor_label == predicated_label)
56
+ # puts "------------------------------------------------------------"
57
+ end
58
+
59
+ puts "accuracy: #{results.count(true).to_f/results.size}"
60
+
61
+
62
+
63
+ ### you can do above procedure simply by using Trainer
64
+
65
+ # training_option = {
66
+ # learning_rate: 0.5,
67
+ # max_training_count: 50,
68
+ # tolerance: 0.0004,
69
+ # # initial_weights_file: 'weights_3_30_10_1429166740.yml',
70
+ # # initial_weights_file: 'best_weights_1429544001.yml',
71
+ # monitoring_channels: [:best_params_training]
72
+ # }
73
+
74
+ # RubyBrain::Trainer.normal_learning([dataset[:input].first.size, 50, dataset[:output].first.size],
75
+ # training_input, training_supervisor,
76
+ # training_option)
77
+
78
+
79
+