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,105 @@
1
+ require 'coo-coo/data_sources/xournal/training_document/constants'
2
+ require 'coo-coo/data_sources/xournal/training_document/example'
3
+
4
+ module CooCoo
5
+ module DataSources
6
+ module Xournal
7
+ class TrainingDocument
8
+ class DocumentReader
9
+ def initialize
10
+ end
11
+
12
+ def load(xournal)
13
+ version, columns, rows, cells_per_example = read_meta_label(xournal)
14
+
15
+ if columns == nil || rows == nil
16
+ raise ArgumentError.new("Xournal lacks a Text element with '#{META_LABEL} VERSION: COLS ROWS CELLS_PER_EXAMPLE'")
17
+ end
18
+
19
+ doc = TrainingDocument.new
20
+
21
+ xournal.each_page do |page|
22
+ page.each_layer do |layer|
23
+ process_layer(doc, page, layer, columns, rows)
24
+ end
25
+ end
26
+
27
+ doc
28
+ end
29
+
30
+ def read_meta_label(xournal)
31
+ version = nil
32
+ columns = nil
33
+ rows = nil
34
+ meta = nil
35
+
36
+ xournal.each_page do |page|
37
+ page.each_layer do |layer|
38
+ layer.each_text do |txt|
39
+ if txt.text =~ /^#{META_LABEL}/
40
+ meta = txt.text
41
+ break
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ if meta
48
+ m = meta.match(META_LABEL_REGEX)
49
+ version = m[1].to_f
50
+ columns = m[2].to_i
51
+ rows = m[3].to_i
52
+ cells_per_example = (m[4] || 1).to_i
53
+ end
54
+
55
+ return version, columns, rows, cells_per_example
56
+ end
57
+
58
+ def process_layer(doc, page, layer, columns, rows)
59
+ grid_w = page.width / columns.to_f
60
+ grid_h = page.height / rows.to_f
61
+
62
+ labels = Hash.new { |h, k| h[k] = Hash.new { |a, b| a[b] = Array.new } }
63
+ strokes = Hash.new { |h, k| h[k] = Hash.new { |a, b| a[b] = Array.new } }
64
+
65
+ layer.each_text do |txt|
66
+ next if txt.text =~ /^#{META_LABEL}/
67
+ row = (txt.y / grid_h).round
68
+ column = (txt.x / grid_w).round
69
+ labels[row.to_i][column.to_i] << txt
70
+ end
71
+
72
+ layer.each_stroke do |stroke|
73
+ color = ChunkyPNG::Color.parse(stroke.color)
74
+ next if ChunkyPNG::Color.euclidean_distance_rgba(color, PARSED_GRID_COLOR) == 0.0
75
+ min, max = stroke.minmax
76
+ row = (min[1] / grid_h)
77
+ column = (min[0] / grid_w)
78
+
79
+ strokes[row.to_i][column.to_i] << stroke
80
+ end
81
+
82
+
83
+ rows.times do |row|
84
+ grid_min_y = (row * grid_h).floor
85
+
86
+ columns.times do |column|
87
+ grid_min_x = (column * grid_w).floor
88
+ ex_label = labels[row][column].first
89
+ ex_strokes = strokes[row][column]
90
+ unless ex_strokes.empty? && ex_label == nil
91
+ doc.add_example(ex_label && ex_label.text,
92
+ ex_strokes.collect { |s|
93
+ s.
94
+ translate(-grid_min_x, -grid_min_y).
95
+ scale(1.0 / grid_w, 1.0 / grid_h, 1.0 / grid_w)
96
+ })
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,37 @@
1
+ module CooCoo
2
+ module DataSources
3
+ module Xournal
4
+ class TrainingDocument
5
+ class Example
6
+ attr_accessor :label
7
+ attr_reader :stroke_sets
8
+
9
+ def initialize(label, *sets)
10
+ @label = label
11
+ @stroke_sets = Array.new
12
+ sets.each do |points|
13
+ @stroke_sets << points
14
+ end
15
+ end
16
+
17
+ def add_set(strokes)
18
+ @stroke_sets << strokes
19
+ self
20
+ end
21
+
22
+ def each_set(&block)
23
+ @stroke_sets.each(&block)
24
+ end
25
+
26
+ def empty?
27
+ @stroke_sets.empty?
28
+ end
29
+
30
+ def size
31
+ @stroke_sets.size
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,76 @@
1
+ module CooCoo
2
+ module DataSources
3
+ module Xournal
4
+ class TrainingDocument
5
+ # Create a {TrainingDocument} for ASCII characters.
6
+ # @param doc [Document] Optional Document used to extract examples.
7
+ # @return [TrainingDocument]
8
+ def self.ascii_trainer(doc = self.new)
9
+ (32...127).each do |c|
10
+ c = c.chr[0]
11
+ doc.add_example(c, [])
12
+ end
13
+
14
+ doc
15
+ end
16
+
17
+ # Create a {TrainingDocument} for an arbitrary Unicode block.
18
+ # @param starting_offset [Integer] Which Unicode character to start the examples
19
+ # @param number [Integer] The number of characters to place in the document.
20
+ # @param doc [Document] Optional Document used to extract examples.
21
+ # @return [TrainingDocument]
22
+ def self.unicode_trainer(starting_offset, number, doc = self.new)
23
+ number.times do |i|
24
+ doc.add_example("" << (starting_offset + i), [])
25
+ end
26
+
27
+ doc
28
+ end
29
+
30
+ # Create a {TrainingDocument} for Japanese Hiragana, Katakana, and punctuation.
31
+ # @param doc [Document] Optional Document used to extract examples.
32
+ # @return [TrainingDocument]
33
+ def self.jp_trainer(doc = self.new)
34
+ unicode_trainer(0x3000, 64, doc)
35
+ unicode_trainer(0x3040, 96, doc)
36
+ unicode_trainer(0x30A0, 96, doc)
37
+ unicode_trainer(0xff00, 16 * 15, doc)
38
+ doc
39
+ end
40
+
41
+ # Create a {TrainingDocument} for the CJK block.
42
+ # @param limit [Integer] Optional limit on how many characters to include.
43
+ # @param doc [Document] Optional Document used to extract examples.
44
+ # @return [TrainingDocument]
45
+ def self.cjk_trainer(limit = 2000, doc = self.new)
46
+ unicode_trainer(0x4e00, limit)
47
+ end
48
+
49
+ # Create a {TrainingDocument} for emoji.
50
+ # @param doc [Document] Optional Document used to extract examples.
51
+ # @return [TrainingDocument]
52
+ def self.emoji_trainer(doc = self.new)
53
+ unicode_trainer(0x1F600, 16 * 5, doc)
54
+ unicode_trainer(0x2700, 16 * 12, doc)
55
+ end
56
+
57
+ # Create a {TrainingDocument} for math symbols.
58
+ # @param doc [Document] Optional Document used to extract examples.
59
+ # @return [TrainingDocument]
60
+ def self.math_trainer(doc = self.new)
61
+ unicode_trainer(0x2200, 16 * 16, doc)
62
+ unicode_trainer(0x2A00, 16 * 16, doc)
63
+ unicode_trainer(0x2100, 16 * 5, doc)
64
+ unicode_trainer(0x27C0, 16 * 3, doc)
65
+ unicode_trainer(0x2980, 16 * 8, doc)
66
+ unicode_trainer(0x2300, 16 * 16, doc)
67
+ unicode_trainer(0x25A0, 16 * 6, doc)
68
+ unicode_trainer(0x2B00, 16 * 16, doc)
69
+ unicode_trainer(0x2190, 16 * 7, doc)
70
+ unicode_trainer(0x2900, 16 * 8, doc)
71
+ unicode_trainer(0x1D400, 16 * 16 * 4, doc)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,8 @@
1
+ module CooCoo
2
+ def self.debug(msg, *args)
3
+ $stderr.puts(msg)
4
+ args.each do |a|
5
+ $stderr.puts("\t" + a.to_s)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,129 @@
1
+ module CooCoo
2
+ module Dot
3
+ class Block
4
+ attr_reader :options
5
+ attr_reader :kind
6
+
7
+ def initialize(kind, options)
8
+ @kind = kind
9
+ @options = options
10
+ end
11
+ end
12
+
13
+ class Graph < Block
14
+ class Node
15
+ attr_reader :options
16
+ attr_reader :name
17
+
18
+ def initialize(name, options)
19
+ @name = name
20
+ @options = options
21
+ end
22
+ end
23
+
24
+ class Edge
25
+ attr_reader :options
26
+ attr_reader :nodes
27
+
28
+ def initialize(nodes, options = {})
29
+ @options = options
30
+ @nodes = nodes.dup
31
+ end
32
+
33
+ def add_node(node)
34
+ @nodes << node
35
+ self
36
+ end
37
+ end
38
+
39
+ attr_reader :nodes, :edges, :blocks
40
+
41
+ def initialize(kind, options)
42
+ super(kind, options)
43
+ @nodes = []
44
+ @edges = []
45
+ @blocks = []
46
+ yield(self) if block_given?
47
+ end
48
+
49
+ def add_node(name, options = {})
50
+ @nodes << Node.new(name, options)
51
+ self
52
+ end
53
+
54
+ def add_edge(nodes, options = {})
55
+ @edges << Edge.new(nodes, options)
56
+ self
57
+ end
58
+
59
+ def add_subgraph(name, options = {}, &block)
60
+ @blocks << Graph.new("subgraph #{name}", options, &block)
61
+ self
62
+ end
63
+
64
+ def add_block(type, options = {}, &block)
65
+ @blocks << Graph.new(type, options, &block)
66
+ self
67
+ end
68
+ end
69
+
70
+ class Writer
71
+ def initialize
72
+ end
73
+
74
+ def write(graph, io)
75
+ io.write(write_graph(graph).join("\n"))
76
+ self
77
+ end
78
+
79
+ def write_graph(g, depth = 0)
80
+ start_block("#{g.kind}", depth) do |d|
81
+ lines = []
82
+ lines += write_graph_options(g, d)
83
+ g.blocks.each do |kid|
84
+ lines += write_graph(kid, d)
85
+ end
86
+ lines += write_nodes(g.nodes, d)
87
+ lines += write_edges(g.edges, d)
88
+ lines
89
+ end
90
+ end
91
+
92
+ def indent(size)
93
+ " " * size
94
+ end
95
+
96
+ def write_graph_options(graph, depth)
97
+ graph.options.collect do |key, value|
98
+ indent(depth) + "#{key}=\"#{value}\";"
99
+ end
100
+ end
101
+
102
+ def start_block(kind, depth)
103
+ [ indent(depth) + "#{kind} {",
104
+ *yield(depth + 1),
105
+ indent(depth) + "}"
106
+ ]
107
+ end
108
+
109
+ def write_nodes(nodes, depth)
110
+ nodes.collect do |node|
111
+ indent(depth) + "#{node.name}[#{write_options(node.options)}];"
112
+ end
113
+ end
114
+
115
+ def write_edges(edges, depth)
116
+ edges.collect do |edge|
117
+ nodes = edge.nodes.join(" -> ")
118
+ indent(depth) + "#{nodes}[#{write_options(edge.options)}];"
119
+ end
120
+ end
121
+
122
+ def write_options(options)
123
+ options.collect do |key, value|
124
+ "#{key}=\"#{value}\""
125
+ end.join(",")
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,4 @@
1
+ require 'coo-coo/drawing/canvas'
2
+ require 'coo-coo/drawing/chunky_canvas'
3
+ require 'coo-coo/drawing/cairo_canvas'
4
+ require 'coo-coo/drawing/sixel'
@@ -0,0 +1,100 @@
1
+ require 'chunky_png'
2
+ require 'cairo'
3
+
4
+ module CooCoo
5
+ module Drawing
6
+ class CairoCanvas < Canvas
7
+ attr_reader :surface, :context
8
+
9
+ def initialize(surface_or_width, height = nil)
10
+ if height
11
+ surface = Cairo::ImageSurface.new(surface_or_width, height)
12
+ else
13
+ surface = surface_or_width
14
+ end
15
+
16
+ @surface = surface
17
+ @context = Cairo::Context.new(@surface)
18
+ end
19
+
20
+ def flush
21
+ @surface.flush
22
+ self
23
+ end
24
+
25
+ def line(x1, y1, x2, y2)
26
+ @context.set_source_rgba(ChunkyPNG::Color.to_truecolor_alpha_bytes(stroke_color))
27
+ @context.move_to(x1, y1)
28
+ @context.line_to(x2, y2)
29
+ @context.stroke
30
+ self
31
+ end
32
+
33
+ def stroke(points)
34
+ @context.set_source_rgba(*ChunkyPNG::Color.to_truecolor_alpha_bytes(stroke_color))
35
+ @context.set_line_width(points[0][2])
36
+ @context.move_to(points[0][0], points[0][1])
37
+ @context.line_cap = Cairo::LINE_CAP_ROUND
38
+ @context.line_join = Cairo::LINE_JOIN_ROUND
39
+
40
+ points.each.drop(1).each do |(x, y, w, color)|
41
+ @context.set_line_width(w)
42
+ if color
43
+ @context.set_source_rgba(*ChunkyPNG::Color.to_truecolor_alpha_bytes(color))
44
+ end
45
+ @context.line_to(x, y)
46
+ end
47
+
48
+ @context.stroke
49
+
50
+ self
51
+ end
52
+
53
+ def rect(x, y, w, h)
54
+ @context.rectangle(x, y, w, h)
55
+ @context.set_source_rgba(*ChunkyPNG::Color.to_truecolor_alpha_bytes(fill_color))
56
+ @context.fill
57
+ self
58
+ end
59
+
60
+ def circle(x, y, r)
61
+ @context.circle(x, y, r)
62
+ @context.set_source_rgba(*ChunkyPNG::Color.to_truecolor_alpha_bytes(fill_color))
63
+ @context.fill
64
+ self
65
+ end
66
+
67
+ def blit(img, x, y, w, h)
68
+ surface = Cairo::ImageSurface.from_png(StringIO.new(img))
69
+ zx = w / surface.width.to_f
70
+ zy = h / surface.height.to_f
71
+ @context.set_source(surface, x / zx, y / zy)
72
+ @context.scale(zx, zy)
73
+ @context.paint
74
+
75
+ self
76
+ end
77
+
78
+ def text(txt, x, y, font, font_size, style = Cairo::FONT_SLANT_NORMAL)
79
+ @context.move_to(x, y + font_size)
80
+ @context.set_source_rgba(*ChunkyPNG::Color.to_truecolor_alpha_bytes(fill_color))
81
+ @context.select_font_face(font, style)
82
+ @context.font_size = font_size
83
+ @context.show_text(txt)
84
+ self
85
+ end
86
+
87
+ def to_blob
88
+ data = StringIO.new
89
+ @surface.write_to_png(data)
90
+ data.rewind
91
+ data.read
92
+ end
93
+
94
+ def to_vector(grayscale = false)
95
+ @surface.flush
96
+ chunky_to_vector(ChunkyPNG::Image.from_blob(to_blob), grayscale)
97
+ end
98
+ end
99
+ end
100
+ end