CooCoo 0.1.0

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.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/CooCoo.gemspec +47 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +88 -0
  6. data/README.md +123 -0
  7. data/Rakefile +81 -0
  8. data/bin/cuda-dev-info +25 -0
  9. data/bin/cuda-free +28 -0
  10. data/bin/cuda-free-trend +7 -0
  11. data/bin/ffi-gen +267 -0
  12. data/bin/spec_runner_html.sh +42 -0
  13. data/bin/trainer +198 -0
  14. data/bin/trend-cost +13 -0
  15. data/examples/char-rnn.rb +405 -0
  16. data/examples/cifar/cifar.rb +94 -0
  17. data/examples/img-similarity.rb +201 -0
  18. data/examples/math_ops.rb +57 -0
  19. data/examples/mnist.rb +365 -0
  20. data/examples/mnist_classifier.rb +293 -0
  21. data/examples/mnist_dream.rb +214 -0
  22. data/examples/seeds.rb +268 -0
  23. data/examples/seeds_dataset.txt +210 -0
  24. data/examples/t10k-images-idx3-ubyte +0 -0
  25. data/examples/t10k-labels-idx1-ubyte +0 -0
  26. data/examples/train-images-idx3-ubyte +0 -0
  27. data/examples/train-labels-idx1-ubyte +0 -0
  28. data/ext/buffer/Rakefile +50 -0
  29. data/ext/buffer/buffer.pre.cu +727 -0
  30. data/ext/buffer/matrix.pre.cu +49 -0
  31. data/lib/CooCoo.rb +1 -0
  32. data/lib/coo-coo.rb +18 -0
  33. data/lib/coo-coo/activation_functions.rb +344 -0
  34. data/lib/coo-coo/consts.rb +5 -0
  35. data/lib/coo-coo/convolution.rb +298 -0
  36. data/lib/coo-coo/core_ext.rb +75 -0
  37. data/lib/coo-coo/cost_functions.rb +91 -0
  38. data/lib/coo-coo/cuda.rb +116 -0
  39. data/lib/coo-coo/cuda/device_buffer.rb +240 -0
  40. data/lib/coo-coo/cuda/device_buffer/ffi.rb +109 -0
  41. data/lib/coo-coo/cuda/error.rb +51 -0
  42. data/lib/coo-coo/cuda/host_buffer.rb +117 -0
  43. data/lib/coo-coo/cuda/runtime.rb +157 -0
  44. data/lib/coo-coo/cuda/vector.rb +315 -0
  45. data/lib/coo-coo/data_sources.rb +2 -0
  46. data/lib/coo-coo/data_sources/xournal.rb +25 -0
  47. data/lib/coo-coo/data_sources/xournal/bitmap_stream.rb +197 -0
  48. data/lib/coo-coo/data_sources/xournal/document.rb +377 -0
  49. data/lib/coo-coo/data_sources/xournal/loader.rb +144 -0
  50. data/lib/coo-coo/data_sources/xournal/renderer.rb +101 -0
  51. data/lib/coo-coo/data_sources/xournal/saver.rb +99 -0
  52. data/lib/coo-coo/data_sources/xournal/training_document.rb +78 -0
  53. data/lib/coo-coo/data_sources/xournal/training_document/constants.rb +15 -0
  54. data/lib/coo-coo/data_sources/xournal/training_document/document_maker.rb +89 -0
  55. data/lib/coo-coo/data_sources/xournal/training_document/document_reader.rb +105 -0
  56. data/lib/coo-coo/data_sources/xournal/training_document/example.rb +37 -0
  57. data/lib/coo-coo/data_sources/xournal/training_document/sets.rb +76 -0
  58. data/lib/coo-coo/debug.rb +8 -0
  59. data/lib/coo-coo/dot.rb +129 -0
  60. data/lib/coo-coo/drawing.rb +4 -0
  61. data/lib/coo-coo/drawing/cairo_canvas.rb +100 -0
  62. data/lib/coo-coo/drawing/canvas.rb +68 -0
  63. data/lib/coo-coo/drawing/chunky_canvas.rb +101 -0
  64. data/lib/coo-coo/drawing/sixel.rb +214 -0
  65. data/lib/coo-coo/enum.rb +17 -0
  66. data/lib/coo-coo/from_name.rb +58 -0
  67. data/lib/coo-coo/fully_connected_layer.rb +205 -0
  68. data/lib/coo-coo/generation_script.rb +38 -0
  69. data/lib/coo-coo/grapher.rb +140 -0
  70. data/lib/coo-coo/image.rb +286 -0
  71. data/lib/coo-coo/layer.rb +67 -0
  72. data/lib/coo-coo/layer_factory.rb +26 -0
  73. data/lib/coo-coo/linear_layer.rb +59 -0
  74. data/lib/coo-coo/math.rb +607 -0
  75. data/lib/coo-coo/math/abstract_vector.rb +121 -0
  76. data/lib/coo-coo/math/functions.rb +39 -0
  77. data/lib/coo-coo/math/interpolation.rb +7 -0
  78. data/lib/coo-coo/network.rb +264 -0
  79. data/lib/coo-coo/neuron.rb +112 -0
  80. data/lib/coo-coo/neuron_layer.rb +168 -0
  81. data/lib/coo-coo/option_parser.rb +18 -0
  82. data/lib/coo-coo/platform.rb +17 -0
  83. data/lib/coo-coo/progress_bar.rb +11 -0
  84. data/lib/coo-coo/recurrence/backend.rb +99 -0
  85. data/lib/coo-coo/recurrence/frontend.rb +101 -0
  86. data/lib/coo-coo/sequence.rb +187 -0
  87. data/lib/coo-coo/shell.rb +2 -0
  88. data/lib/coo-coo/temporal_network.rb +291 -0
  89. data/lib/coo-coo/trainer.rb +21 -0
  90. data/lib/coo-coo/trainer/base.rb +67 -0
  91. data/lib/coo-coo/trainer/batch.rb +82 -0
  92. data/lib/coo-coo/trainer/batch_stats.rb +27 -0
  93. data/lib/coo-coo/trainer/momentum_stochastic.rb +59 -0
  94. data/lib/coo-coo/trainer/stochastic.rb +47 -0
  95. data/lib/coo-coo/transformer.rb +272 -0
  96. data/lib/coo-coo/vector_layer.rb +194 -0
  97. data/lib/coo-coo/version.rb +3 -0
  98. data/lib/coo-coo/weight_deltas.rb +23 -0
  99. data/prototypes/convolution.rb +116 -0
  100. data/prototypes/linear_drop.rb +51 -0
  101. data/prototypes/recurrent_layers.rb +79 -0
  102. data/www/images/screamer.png +0 -0
  103. data/www/images/screamer.xcf +0 -0
  104. data/www/index.html +82 -0
  105. metadata +373 -0
@@ -0,0 +1,68 @@
1
+ require 'chunky_png'
2
+ require 'coo-coo/math'
3
+
4
+ module CooCoo
5
+ module Drawing
6
+ class Canvas
7
+ attr_accessor :fill_color, :stroke_color
8
+
9
+ def fill_color=(c)
10
+ @fill_color = ChunkyPNG::Color.parse(c)
11
+ end
12
+
13
+ def stroke_color=(c)
14
+ @stroke_color = ChunkyPNG::Color.parse(c)
15
+ end
16
+
17
+ def flush
18
+ self
19
+ end
20
+
21
+ def line(x1, y1, x2, y2)
22
+ self
23
+ end
24
+
25
+ def stroke(points)
26
+ self
27
+ end
28
+
29
+ def rect(x, y, w, h)
30
+ self
31
+ end
32
+
33
+ def circle(x, y, r)
34
+ self
35
+ end
36
+
37
+ def blit(img, x, y)
38
+ self
39
+ end
40
+
41
+ def text(txt, x, y, font, size, style = nil)
42
+ self
43
+ end
44
+
45
+ protected
46
+ def color_components(c)
47
+ [ ChunkyPNG::Color.r(c),
48
+ ChunkyPNG::Color.g(c),
49
+ ChunkyPNG::Color.b(c)
50
+ ]
51
+ end
52
+
53
+ def to_grayscale(c)
54
+ ChunkyPNG::Color.r(ChunkyPNG::Color.to_grayscale(c))
55
+ end
56
+
57
+ def chunky_to_vector(img, grayscale)
58
+ f = if grayscale
59
+ method(:to_grayscale)
60
+ else
61
+ method(:color_components)
62
+ end
63
+
64
+ Vector[img.pixels.collect(&f).flatten]
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,101 @@
1
+ require 'chunky_png'
2
+ require 'coo-coo/math'
3
+
4
+ module CooCoo
5
+ module Drawing
6
+ class ChunkyCanvas < Canvas
7
+ attr_reader :image
8
+
9
+ def initialize(img_or_width, height = nil)
10
+ if height
11
+ img = ChunkyPNG::Image.new(img_or_width, height)
12
+ else
13
+ img = img_or_width
14
+ end
15
+
16
+ @image = img
17
+ end
18
+
19
+ def line(x1, y1, x2, y2)
20
+ @image.line(x1, y1, x2, y2, stroke_color)
21
+ self
22
+ end
23
+
24
+ def stroke(points)
25
+ last_x = points[0][0]
26
+ last_y = points[0][1]
27
+ last_w = points[0][2] || 1.0
28
+ last_color = points[0][3]
29
+
30
+ points.each.drop(1).each do |(x, y, w, color)|
31
+ w ||= 1.0
32
+
33
+ if color
34
+ self.stroke_color = color
35
+ self.fill_color = color
36
+ end
37
+
38
+ if w <= 1.0
39
+ line(last_x.to_i, last_y.to_i, x.to_i, y.to_i)
40
+ else
41
+ step_x = (x / w).abs.round
42
+ step_y = (y / w).abs.round
43
+ steps = Math.max(step_x, step_y)
44
+ steps = 4.0 if steps < 4.0
45
+
46
+ (steps + 1).to_i.times do |n|
47
+ t = n / steps.to_f
48
+ if color
49
+ self.stroke_color = lerp_color(last_color, color, t)
50
+ self.fill_color = lerp_color(last_color, color, t)
51
+ end
52
+
53
+ circle(Math.lerp(last_x, x, t).to_i,
54
+ Math.lerp(last_y, y, t).to_i,
55
+ (Math.lerp(last_w, w, t)/2.0).ceil.to_i)
56
+ end
57
+ end
58
+
59
+ last_x = x
60
+ last_y = y
61
+ last_w = w
62
+ last_color = color
63
+ end
64
+
65
+ self
66
+ end
67
+
68
+ def lerp_color(a, b, t)
69
+ ChunkyPNG::Color.interpolate_quick(a, b, (t * 256).to_i)
70
+ end
71
+
72
+ def rect(x, y, w, h)
73
+ @image.rect(x, y, w, h, stroke_color, fill_color)
74
+ self
75
+ end
76
+
77
+ def circle(x, y, r)
78
+ @image.circle(x, y, r, stroke_color, fill_color)
79
+ self
80
+ end
81
+
82
+ def blit(other, x, y, w, h)
83
+ img = ChunkyPNG::Image.from_blob(other)
84
+ if w != img.width || h != img.height
85
+ img.resample_bilinear!(w.to_i, h.to_i)
86
+ end
87
+ @image.compose!(img, x.to_i, y.to_i)
88
+ self
89
+ end
90
+
91
+ def text(txt, x, y, font, font_size, font_style = nil)
92
+ self
93
+ end
94
+
95
+ def to_vector(grayscale = false)
96
+ chunky_to_vector(@image, grayscale)
97
+ end
98
+ end
99
+ end
100
+ end
101
+
@@ -0,0 +1,214 @@
1
+ require 'stringio'
2
+
3
+ module CooCoo
4
+ module Drawing
5
+ module Sixel
6
+ def self.from_array(a, width, height = nil)
7
+ s = Stringer.new
8
+ s.begin_sixel + s.from_array(a, width, height) + s.newline + s.finish_sixel
9
+ end
10
+
11
+ def self.with_sixel(io = $stdout, &block)
12
+ Streamer.new(io) do |s|
13
+ block.call(s)
14
+ end
15
+ end
16
+
17
+ def self.to_string(&block)
18
+ stream = StringIO.new
19
+ Streamer.new(stream, &block)
20
+ stream.string
21
+ end
22
+
23
+ class Streamer
24
+ def initialize(io = $stdout, stringer = Stringer.new, &block)
25
+ @io = io
26
+ @stringer = stringer
27
+ with_sixel(&block)
28
+ end
29
+
30
+ def method_missing(mid, *args, &block)
31
+ @io.write(@stringer.send(mid, *args, &block))
32
+ end
33
+
34
+ def with_sixel(&block)
35
+ begin_sixel
36
+ block.call(self)
37
+ ensure
38
+ finish_sixel
39
+ end
40
+ end
41
+
42
+ class Stringer
43
+ RGB = Struct.new(:r, :g, :b)
44
+ HSL = Struct.new(:h, :s, :l)
45
+
46
+ def initialize(options = Hash.new)
47
+ @max_colors = options.fetch(:max_colors, 256)
48
+ @colors = Array.new(@max_colors)
49
+ @background = options.fetch(:background, 0)
50
+ end
51
+
52
+ def from_array(a, width, height = nil)
53
+ height ||= (a.size / width.to_f).ceil
54
+ max_color = a.max.ceil
55
+
56
+ (height / 6.0).ceil.times.collect do |y|
57
+ (max_color + 1).times.collect do |c|
58
+ #next if c == 0
59
+ in_color(c) + width.times.collect do |x|
60
+ sixel_line(c, *6.times.collect { |i|
61
+ a[(y*6+i) * width + x] rescue @background
62
+ })
63
+ end.join
64
+ end.join(cr)
65
+ end.join(newline)
66
+ end
67
+
68
+ def sixel_line(c, *pixels)
69
+ line = 6.times.inject(0) { |acc, i|
70
+ if pixels[i].to_i == c
71
+ (acc | (1 << i))
72
+ else
73
+ acc
74
+ end
75
+ }
76
+ [ 63 + line ].pack('c')
77
+ end
78
+
79
+ def move_to(x, y)
80
+ finish_sixel + "\e[#{y.to_i};#{x.to_i}H" + begin_sixel
81
+ end
82
+
83
+ def set_color(c, r, g, b)
84
+ @colors[c] = RGB.new(r, g, b)
85
+ emit_color(c)
86
+ end
87
+
88
+ def set_color_hsl(c, h, s, l)
89
+ @colors[c] = HSL.new(h, s, l)
90
+ emit_color(c)
91
+ end
92
+
93
+ def emit_color(n, c = nil)
94
+ case c
95
+ when RGB then "\##{n.to_i};2;#{c.r.to_i};#{c.g.to_i};#{c.b.to_i}"
96
+ when HSL then "\##{n.to_i};1;#{c.h.to_i};#{c.s.to_i};#{c.l.to_i}"
97
+ else @colors[n] && emit_color(n, @colors[n])
98
+ end
99
+ end
100
+
101
+ def emit_all_colors
102
+ @colors.each.with_index.collect do |c, i|
103
+ emit_color(i, c) if c
104
+ end.join
105
+ end
106
+
107
+ def in_color(c)
108
+ "\##{c}"
109
+ end
110
+
111
+ def start_sixel
112
+ "\ePq"
113
+ end
114
+
115
+ def begin_sixel
116
+ start_sixel + emit_all_colors
117
+ end
118
+
119
+ def finish_sixel
120
+ "\e\\"
121
+ end
122
+
123
+ def cr
124
+ "$"
125
+ end
126
+
127
+ def lf
128
+ "-\n"
129
+ end
130
+
131
+ def newline
132
+ cr + lf
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ if __FILE__ == $0
140
+ require 'coo-coo/math'
141
+
142
+ HI = <<-EOT
143
+ \ePq
144
+ \#0;2;0;0;0\#1;2;100;0;0\#2;2;0;100;0
145
+ \#1~~@@vv@@~~@@~~$
146
+ \#2??}}GG}}??}}??-
147
+ \#1!14@
148
+ \e\\
149
+ EOT
150
+
151
+ arr = 100.times.collect { |y|
152
+ 100.times.collect { |x|
153
+ 8 + (8 * (Math.cos(y / 100.0 * 6.28) * Math.sin(x / 100.0 * 6.28))).to_i
154
+ }
155
+ }.flatten
156
+ line = 100.times.collect { |y| 40.times.collect { |i| (i < 2 || i > 37) ? 15 : 0 } }.flatten
157
+ stringer = CooCoo::Drawing::Sixel::Stringer.new
158
+
159
+ puts(HI)
160
+
161
+ puts
162
+ puts("In sixel")
163
+ puts(stringer.begin_sixel)
164
+ puts("\#0;2;100;0;0\#1;2;0;100;0\#2;2;0;0;100")
165
+ 16.times {
166
+ $stdout.write(stringer.sixel_line(1, 1, 1, 0, 0, 1, 1))
167
+ }
168
+ puts
169
+ puts(stringer.sixel_line(1, 0, 0, 1, 1, 0, 0))
170
+ puts(stringer.sixel_line(1, 0, 0, 1, 1, 0, 0))
171
+ puts(stringer.sixel_line(2, 1, 1, 2, 2, 1, 1))
172
+ puts(stringer.sixel_line(2, 1, 1, 2, 2, 1, 1))
173
+ puts(stringer.sixel_line(1, 1, 1, 1, 1, 1, 1))
174
+ puts(stringer.sixel_line(1, 1, 1, 1, 1, 1, 1))
175
+ puts(stringer.sixel_line(1, 1, 1, 1, 1, 1, 1))
176
+ puts(stringer.finish_sixel)
177
+
178
+ puts("And the big one:")
179
+ puts
180
+ puts(stringer.begin_sixel)
181
+ #puts("\#0;2;100;0;0\#1;2;0;100;0\#2;2;0;0;100\#3;2;100,100,100")
182
+ 16.times { |i| puts(stringer.set_color(i, i * 100 / 16.0, i * 100 / 16.0, i * 100 / 16.0)) }
183
+ # puts(stringer.set_color(0, 100, 0, 0) +
184
+ # stringer.set_color(1, 0, 100, 0) +
185
+ # stringer.set_color(2, 0, 0, 100) +
186
+ # stringer.set_color(3, 100, 100, 100))
187
+ puts(stringer.from_array(arr, 100, 100))
188
+ puts(stringer.cr)
189
+ puts(stringer.from_array(arr.collect { |a| arr.max - a }, 100, 100))
190
+ puts(stringer.newline)
191
+ puts(stringer.newline)
192
+ puts(stringer.from_array(line, 40, 100))
193
+ puts(stringer.finish_sixel)
194
+
195
+ v = CooCoo::Vector.new(28 * 28, 2)
196
+ CooCoo::Drawing::Sixel.with_sixel do |s|
197
+ s.set_color(0, 0, 0, 0)
198
+ s.set_color(1, 100, 0, 0)
199
+ s.set_color(2, 100, 100, 100)
200
+ s.set_color(3, 100, 0, 100)
201
+ s.set_color(3, 50, 50, 50)
202
+ s.from_array(CooCoo::Vector[64.times] / 16, 64, 1)
203
+ s.from_array(CooCoo::Vector[64.times] / 16, 1, 64)
204
+ s.from_array(CooCoo::Vector[64.times] / 16, 8, 8)
205
+ s.newline
206
+ s.from_array(v, 28)
207
+ s.newline
208
+ s.from_array(CooCoo::Vector.new(28 * 28, 3), 28)
209
+ s.newline
210
+ s.from_array(CooCoo::Vector.rand(28 * 28, 4), 28)
211
+ end
212
+
213
+ puts("Good bye.")
214
+ end
@@ -0,0 +1,17 @@
1
+ require 'coo-coo/core_ext'
2
+
3
+ class Enumerator
4
+ define_once(:zero) do
5
+ Array.new(size, self.first.zero)
6
+ end
7
+
8
+ define_once(:sum) do
9
+ inject(0) do |acc, e|
10
+ acc += e
11
+ end
12
+ end
13
+
14
+ define_once(:average) do
15
+ sum / (size || count)
16
+ end
17
+ end
@@ -0,0 +1,58 @@
1
+ module CooCoo
2
+ # Adds class methods to register classes that can be instantiated
3
+ # using strings.
4
+ #
5
+ # To get an instance, use {#from_name}.
6
+ #
7
+ # To add classes to the registry, call {#register}, preferably
8
+ # inside the class definition.
9
+ module FromName
10
+ # Adds a class to the registry using the given name.
11
+ # @param klass [Class] the class to instantiate
12
+ # @param name [String] name to use when calling #from_name
13
+ # @return [self]
14
+ def register(klass, name = nil)
15
+ @klasses ||= Hash.new
16
+ @klasses[(name || klass.name).split('::').last] = klass
17
+ self
18
+ end
19
+
20
+ # @return [Array] of names of all the registered classes.
21
+ def named_classes
22
+ @klasses.keys.sort
23
+ end
24
+
25
+ # @return [Enumerator] of all the registered classes.
26
+ def each(&block)
27
+ @klasses.each(&block)
28
+ end
29
+
30
+ # Returns an instance of the class registered with the given name.
31
+ # @param name [String] Registered name of the class with optional arguments in parenthesis.
32
+ # @param args Additional arguments to pass to the constructor. Overrides any given in the string.
33
+ # @return An instance of the registered class.
34
+ def from_name(name, *args)
35
+ name, params = parse_name(name)
36
+ klass = @klasses.fetch(name)
37
+ params = args unless args == nil || args.empty?
38
+
39
+ if params && klass.respond_to?(:new)
40
+ klass.new(*params)
41
+ elsif klass.respond_to?(:instance)
42
+ klass.instance
43
+ else
44
+ klass
45
+ end
46
+ end
47
+
48
+ private
49
+ def parse_name(name)
50
+ m = name.match(/(\w+)\((.*)\)/)
51
+ if m
52
+ return m[1], m[2].split(',').collect(&:chomp)
53
+ else
54
+ return name, nil
55
+ end
56
+ end
57
+ end
58
+ end