caffe 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.
@@ -0,0 +1,6 @@
1
+ module Caffe
2
+ TRAIN = Phase::TRAIN
3
+ TEST = Phase::TEST
4
+ CPU = SolverParameter::SolverMode::CPU
5
+ GPU = SolverParameter::SolverMode::GPU
6
+ end
@@ -0,0 +1,3 @@
1
+ module Caffe
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,104 @@
1
+ RSpec.describe Caffe::Blob do
2
+ before :example do
3
+ @blob = Caffe::Blob.new [1, 2, 3, 4]
4
+ end
5
+
6
+ it 'returns its shape as an array' do
7
+ expect(@blob.shape).to eq([1, 2, 3, 4])
8
+ end
9
+
10
+ it 'can only have at most 4 dimensions' do
11
+ expect { Caffe::Blob.new [1, 2, 3, 4, 5] }.to raise_error(ArgumentError)
12
+ end
13
+
14
+ it 'can have shape dimension other than 4' do
15
+ @blob = Caffe::Blob.new [1, 10]
16
+ expect(@blob[0][5]).to eq(0.0)
17
+ end
18
+
19
+ it 'can reshape' do
20
+ @blob.shape = [1, 2, 2, 2]
21
+ expect(@blob.shape).to eq([1, 2, 2, 2])
22
+ end
23
+
24
+ def random_indices
25
+ @blob.shape.map do |x|
26
+ Random.rand x
27
+ end
28
+ end
29
+
30
+ shared_examples :memory do
31
+ it 'can access to next dimension via []' do
32
+ indices = random_indices
33
+ 3.times do |i|
34
+ @data = @data[indices[i]]
35
+ expect(@data).to be_a(Caffe::Blob::Cursor)
36
+ end
37
+ end
38
+
39
+ it 'can be read via []' do
40
+ i, j, k, l = random_indices
41
+ expect(@data[i][j][k][l]).to eq(0.0)
42
+ end
43
+
44
+ it 'can be write via []=' do
45
+ i, j, k, l = random_indices
46
+ @data[i][j][k][l] = 1.0
47
+ expect(@data[i][j][k][l]).to eq(1.0)
48
+ end
49
+
50
+ it 'returns the size of its memory' do
51
+ i, j = random_indices
52
+ expect(@data.size).to eq(1 * 2 * 3 * 4)
53
+ expect(@data[i][j].size).to eq(3 * 4)
54
+ end
55
+
56
+ it 'raise error when the index is out of range' do
57
+ expect { @data[10] }.to raise_error(RangeError)
58
+ expect { @data[0][0][0][10] }.to raise_error(RangeError)
59
+ end
60
+
61
+ it 'can be enumerated' do
62
+ i, j = random_indices
63
+
64
+ @data[i].each do |x|
65
+ expect(x).to be(0.0)
66
+ end
67
+
68
+ arr = Array.new @data[i][j].size, 0.0
69
+ expect(@data[i][j].to_a).to eq(arr)
70
+ end
71
+
72
+ it 'can be copied from Array' do
73
+ arr = Array.new @data.size do
74
+ Random.rand 2
75
+ end
76
+ @data.copy_from! arr
77
+ expect(@data.to_a).to eq(arr)
78
+ end
79
+ end
80
+
81
+ context '#data' do
82
+ before :example do
83
+ @data = @blob.data
84
+ end
85
+
86
+ include_examples :memory
87
+ end
88
+
89
+ context '#diff' do
90
+ before :example do
91
+ @data = @blob.diff
92
+ end
93
+
94
+ include_examples :memory
95
+ end
96
+
97
+ context 'itself' do
98
+ before :example do
99
+ @data = @blob
100
+ end
101
+
102
+ include_examples :memory
103
+ end
104
+ end
@@ -0,0 +1,26 @@
1
+ RSpec.describe Caffe do
2
+ it 'contains constant shortcuts of enum' do
3
+ expect(Caffe::TRAIN).to eq(Caffe::Phase::TRAIN)
4
+ expect(Caffe::TEST).to eq(Caffe::Phase::TEST)
5
+ expect(Caffe::CPU).to eq(Caffe::SolverParameter::SolverMode::CPU)
6
+ expect(Caffe::GPU).to eq(Caffe::SolverParameter::SolverMode::GPU)
7
+ end
8
+
9
+ it 'can change mode' do
10
+ expect(Caffe.mode).to eq(Caffe::CPU)
11
+ Caffe.mode = Caffe::GPU
12
+ expect(Caffe.mode).to eq(Caffe::GPU)
13
+ end
14
+
15
+ it 'can get / set parallel settings' do
16
+ expect(Caffe.solver_count).to eq(1)
17
+ expect(Caffe.solver_rank).to eq(0)
18
+ expect(Caffe.multiprocess).to eq(false)
19
+ Caffe.solver_count = 2
20
+ Caffe.solver_rank = 1
21
+ Caffe.multiprocess = true
22
+ expect(Caffe.solver_count).to eq(2)
23
+ expect(Caffe.solver_rank).to eq(1)
24
+ expect(Caffe.multiprocess).to eq(true)
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ $LOAD_PATH << File.expand_path('../../../lib', __FILE__)
2
+
3
+ require 'lmdb'
4
+ require 'caffe'
5
+
6
+ def gen
7
+ data = Array.new 32 do
8
+ Random.rand 2
9
+ end
10
+
11
+ num = data.inject(0) do |i, x|
12
+ 2 * i + x
13
+ end
14
+
15
+ label = num % 1024 > 1024 / 2 ? 1 : 0
16
+
17
+ datum = Caffe::Datum.new channels: 32, height: 1, width: 1, label: label
18
+ datum.data = data.pack 'C*'
19
+
20
+ datum.serialize_to_string
21
+ end
22
+
23
+ env = LMDB.new File.expand_path('../test_data', __FILE__)
24
+ env.mapsize = 1 * 1024 * 1024 * 1024
25
+ db = env.database
26
+
27
+ 25600.times do |i|
28
+ db[format('%08d', i)] = gen
29
+ end
Binary file
@@ -0,0 +1,71 @@
1
+ name: "test"
2
+
3
+ layer {
4
+ name: "data"
5
+ type: "Input"
6
+ top: "data"
7
+ input_param {
8
+ shape: {
9
+ dim: 1
10
+ dim: 32
11
+ }
12
+ }
13
+ }
14
+
15
+ layer {
16
+ name: "ip1"
17
+ type: "InnerProduct"
18
+ bottom: "data"
19
+ top: "ip1"
20
+ param {
21
+ lr_mult: 1
22
+ }
23
+ param {
24
+ lr_mult: 2
25
+ }
26
+ inner_product_param {
27
+ num_output: 100
28
+ weight_filler {
29
+ type: "gaussian"
30
+ }
31
+ bias_filler {
32
+ type: "constant"
33
+ }
34
+ }
35
+ }
36
+
37
+ layer {
38
+ name: "sigmoid"
39
+ type: "Sigmoid"
40
+ bottom: "ip1"
41
+ top: "ip1"
42
+ }
43
+
44
+ layer {
45
+ name: "ip2"
46
+ type: "InnerProduct"
47
+ bottom: "ip1"
48
+ top: "ip2"
49
+ param {
50
+ lr_mult: 1
51
+ }
52
+ param {
53
+ lr_mult: 2
54
+ }
55
+ inner_product_param {
56
+ num_output: 2
57
+ weight_filler {
58
+ type: "gaussian"
59
+ }
60
+ bias_filler {
61
+ type: "constant"
62
+ }
63
+ }
64
+ }
65
+
66
+ layer {
67
+ name: "prob"
68
+ type: "Softmax"
69
+ bottom: "ip2"
70
+ top: "prob"
71
+ }
@@ -0,0 +1,14 @@
1
+ net: "test_train.prototxt"
2
+ test_iter: 100
3
+ test_interval: 800
4
+ base_lr: 0.1
5
+ momentum: 0.9
6
+ weight_decay: 0.0005
7
+ lr_policy: "inv"
8
+ gamma: 0.0001
9
+ power: 0.75
10
+ display: 800
11
+ max_iter: 25600
12
+ snapshot: 25600
13
+ snapshot_prefix: "test"
14
+ solver_mode: CPU
@@ -0,0 +1,83 @@
1
+ name: "test"
2
+
3
+ layer {
4
+ name: "data"
5
+ type: "Data"
6
+ top: "data"
7
+ top: "label"
8
+ data_param {
9
+ source: "test_data"
10
+ batch_size: 256
11
+ backend: LMDB
12
+ }
13
+ }
14
+
15
+ layer {
16
+ name: "ip1"
17
+ type: "InnerProduct"
18
+ bottom: "data"
19
+ top: "ip1"
20
+ param {
21
+ lr_mult: 1
22
+ }
23
+ param {
24
+ lr_mult: 2
25
+ }
26
+ inner_product_param {
27
+ num_output: 100
28
+ weight_filler {
29
+ type: "gaussian"
30
+ }
31
+ bias_filler {
32
+ type: "constant"
33
+ }
34
+ }
35
+ }
36
+
37
+ layer {
38
+ name: "sigmoid"
39
+ type: "Sigmoid"
40
+ bottom: "ip1"
41
+ top: "ip1"
42
+ }
43
+
44
+ layer {
45
+ name: "ip2"
46
+ type: "InnerProduct"
47
+ bottom: "ip1"
48
+ top: "ip2"
49
+ param {
50
+ lr_mult: 1
51
+ }
52
+ param {
53
+ lr_mult: 2
54
+ }
55
+ inner_product_param {
56
+ num_output: 2
57
+ weight_filler {
58
+ type: "gaussian"
59
+ }
60
+ bias_filler {
61
+ type: "constant"
62
+ }
63
+ }
64
+ }
65
+
66
+ layer {
67
+ name: "accuracy"
68
+ type: "Accuracy"
69
+ bottom: "ip2"
70
+ bottom: "label"
71
+ top: "accuracy"
72
+ include {
73
+ phase: TEST
74
+ }
75
+ }
76
+
77
+ layer {
78
+ name: "loss"
79
+ type: "SoftmaxWithLoss"
80
+ bottom: "ip2"
81
+ bottom: "label"
82
+ top: "loss"
83
+ }
@@ -0,0 +1,71 @@
1
+ RSpec.describe Caffe::Net do
2
+ before :example do
3
+ Caffe.mode = Caffe::CPU
4
+ path = File.expand_path '../net/test.prototxt', __FILE__
5
+ @net = Caffe::Net.new path, Caffe::TEST
6
+ end
7
+
8
+ it 'can get the input' do
9
+ expect(@net.inputs).to be_an(Array)
10
+ expect(@net.inputs.size).to eq(1)
11
+ input = @net.inputs[0]
12
+ expect(input).to be_a(Caffe::Blob)
13
+ expect(input.shape).to eq([1, 32])
14
+ end
15
+
16
+ it 'can get blob by name' do
17
+ blob = @net.blob('ip1')
18
+ expect(blob).to be_a(Caffe::Blob)
19
+ expect(blob.shape).to eq([1, 100])
20
+
21
+ blob = @net.blob('prob')
22
+ expect(blob.shape).to eq([1, 2])
23
+ end
24
+
25
+ it 'can get output' do
26
+ expect(@net.outputs).to be_an(Array)
27
+ expect(@net.outputs.size).to eq(1)
28
+ output = @net.outputs[0]
29
+ expect(output).to be_a(Caffe::Blob)
30
+ expect(output.shape).to eq([1, 2])
31
+ end
32
+
33
+ it 'can reshape according to the input size' do
34
+ input = @net.inputs[0]
35
+ input.shape = [64, 32]
36
+ @net.reshape!
37
+ expect(@net.outputs[0].shape).to eq([64, 2])
38
+ end
39
+
40
+ context 'trained net' do
41
+ before :example do
42
+ path = File.expand_path '../net/test.caffemodel', __FILE__
43
+ @net.load_trained! path
44
+ end
45
+
46
+ it 'can read from trained model' do
47
+ input = @net.inputs[0]
48
+ expect(input.shape).to eq([1, 32])
49
+ end
50
+
51
+ it 'can forward' do
52
+ data = Array.new 32 do
53
+ Random.rand 2
54
+ end
55
+ input = @net.inputs[0]
56
+ input.copy_from! data
57
+
58
+ expect(@net.forward!).to eq(0.0)
59
+ output = @net.outputs[0]
60
+ expect(output[0][0] + output[0][1]).to be_within(1e-6).of(1.0)
61
+
62
+ label = output[0][1] > output[0][0] ? 1 : 0
63
+ num = data.inject(0) do |i, x|
64
+ 2 * i + x
65
+ end
66
+ expected = num % 1024 > 1024 / 2 ? 1 : 0
67
+
68
+ expect(label).to eq(expected)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,16 @@
1
+ RSpec.configure do |config|
2
+ config.expect_with :rspec do |expectations|
3
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
4
+ end
5
+
6
+ config.mock_with :rspec do |mocks|
7
+ mocks.verify_partial_doubles = true
8
+ end
9
+
10
+ config.shared_context_metadata_behavior = :apply_to_host_groups
11
+ end
12
+
13
+ lib = File.expand_path '../../lib', __FILE__
14
+ $LOAD_PATH << lib
15
+
16
+ require 'caffe'
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: caffe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tiny Tiny
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rice
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: protobuf
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake-compiler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: A ruby wrapper of the deep leaning framework
84
+ email:
85
+ - gyf1214@gmail.com
86
+ executables: []
87
+ extensions:
88
+ - ext/caffe/extconf.rb
89
+ extra_rdoc_files:
90
+ - README.md
91
+ - LICENSE
92
+ files:
93
+ - LICENSE
94
+ - README.md
95
+ - ext/caffe/blob.cc
96
+ - ext/caffe/blob.hpp
97
+ - ext/caffe/caffe.cc
98
+ - ext/caffe/common.cc
99
+ - ext/caffe/common.hpp
100
+ - ext/caffe/extconf.rb
101
+ - ext/caffe/mkmf_cxx.rb
102
+ - ext/caffe/net.cc
103
+ - ext/caffe/net.hpp
104
+ - ext/caffe/util.hpp
105
+ - lib/caffe.rb
106
+ - lib/caffe/blob.rb
107
+ - lib/caffe/caffe.pb.rb
108
+ - lib/caffe/common.rb
109
+ - lib/caffe/version.rb
110
+ - spec/blob_spec.rb
111
+ - spec/common_spec.rb
112
+ - spec/net/gen_data.rb
113
+ - spec/net/test.caffemodel
114
+ - spec/net/test.prototxt
115
+ - spec/net/test_solver.prototxt
116
+ - spec/net/test_train.prototxt
117
+ - spec/net_spec.rb
118
+ - spec/spec_helper.rb
119
+ homepage: https://github.com/gyf1214/ruby-caffe
120
+ licenses:
121
+ - MIT
122
+ metadata: {}
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 2.5.2
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: A ruby wrapper of the deep leaning framework
143
+ test_files:
144
+ - spec/blob_spec.rb
145
+ - spec/common_spec.rb
146
+ - spec/net/gen_data.rb
147
+ - spec/net/test.caffemodel
148
+ - spec/net/test.prototxt
149
+ - spec/net/test_solver.prototxt
150
+ - spec/net/test_train.prototxt
151
+ - spec/net_spec.rb
152
+ - spec/spec_helper.rb