ruby-dnn 0.12.4 → 0.13.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.
- checksums.yaml +4 -4
- data/examples/cifar100_example.rb +1 -1
- data/examples/cifar10_example.rb +1 -1
- data/examples/dcgan/dcgan.rb +7 -3
- data/examples/dcgan/imgen.rb +1 -1
- data/examples/dcgan/train.rb +5 -2
- data/examples/iris_example.rb +1 -1
- data/examples/mnist_conv2d_example.rb +1 -1
- data/examples/mnist_define_by_run.rb +1 -1
- data/examples/mnist_example.rb +1 -1
- data/examples/mnist_lstm_example.rb +1 -1
- data/lib/dnn.rb +2 -0
- data/lib/dnn/core/embedding.rb +1 -2
- data/lib/dnn/core/error.rb +2 -0
- data/lib/dnn/core/global.rb +9 -0
- data/lib/dnn/core/initializers.rb +1 -1
- data/lib/dnn/core/iterator.rb +11 -3
- data/lib/dnn/core/layers.rb +13 -15
- data/lib/dnn/core/link.rb +11 -0
- data/lib/dnn/core/losses.rb +52 -63
- data/lib/dnn/core/merge_layers.rb +3 -3
- data/lib/dnn/core/models.rb +130 -140
- data/lib/dnn/core/normalizations.rb +2 -10
- data/lib/dnn/core/optimizers.rb +62 -57
- data/lib/dnn/core/param.rb +2 -0
- data/lib/dnn/core/savers.rb +138 -0
- data/lib/dnn/{cifar10.rb → datasets/cifar10.rb} +1 -1
- data/lib/dnn/{cifar100.rb → datasets/cifar100.rb} +1 -1
- data/lib/dnn/{downloader.rb → datasets/downloader.rb} +0 -0
- data/lib/dnn/{fashion-mnist.rb → datasets/fashion-mnist.rb} +1 -1
- data/lib/dnn/{iris.rb → datasets/iris.rb} +0 -0
- data/lib/dnn/{mnist.rb → datasets/mnist.rb} +1 -1
- data/lib/dnn/version.rb +1 -1
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a0f021b01f03d45c51e52a1147b05703f8da8895380560d4add4fd3f2fc3d90
|
4
|
+
data.tar.gz: 2c5b3b04d23b0285a0acd1fbde3ca4f774948645d016c471264484f45230fa6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33758acb29f83b8523accd213293c84d4b887591926de256e38bd41895f86358c80ee64f2876cd4fb679a9a2c71a64929780149a324dd80020f5b6d397c9a608
|
7
|
+
data.tar.gz: 6a8e95ca8c57a968a846562ad4fa921e382cef83c0839599651ab93ad2d7f6d6cb0c36ada945fb125c0b13e10aa1333030ce019b138146b00e19ed9882237ae7
|
data/examples/cifar10_example.rb
CHANGED
data/examples/dcgan/dcgan.rb
CHANGED
@@ -68,9 +68,13 @@ class Discriminator < Model
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def call(x, trainable = true)
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
@l1.trainable = trainable
|
72
|
+
@l2.trainable = trainable
|
73
|
+
@l3.trainable = trainable
|
74
|
+
@l4.trainable = trainable
|
75
|
+
@l5.trainable = trainable
|
76
|
+
@l6.trainable = trainable
|
77
|
+
|
74
78
|
x = InputLayer.new([28, 28, 1]).(x)
|
75
79
|
x = @l1.(x)
|
76
80
|
x = LeakyReLU.(x, 0.2)
|
data/examples/dcgan/imgen.rb
CHANGED
data/examples/dcgan/train.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require "dnn"
|
2
|
-
require "dnn/mnist"
|
2
|
+
require "dnn/datasets/mnist"
|
3
3
|
require "numo/linalg/autoloader"
|
4
4
|
require_relative "dcgan"
|
5
5
|
|
@@ -22,9 +22,11 @@ x_train = Numo::SFloat.cast(x_train)
|
|
22
22
|
x_train = x_train / 127.5 - 1
|
23
23
|
|
24
24
|
iter = DNN::Iterator.new(x_train, y_train)
|
25
|
+
num_batchs = x_train.shape[0] / batch_size
|
25
26
|
(1..epochs).each do |epoch|
|
26
27
|
puts "epoch: #{epoch}"
|
27
|
-
|
28
|
+
num_batchs.times do |index|
|
29
|
+
x_batch, y_batch = iter.next_batch(batch_size)
|
28
30
|
noise = Numo::SFloat.new(batch_size, 20).rand(-1, 1)
|
29
31
|
images = gen.predict(noise)
|
30
32
|
x = x_batch.concatenate(images)
|
@@ -37,5 +39,6 @@ iter = DNN::Iterator.new(x_train, y_train)
|
|
37
39
|
|
38
40
|
puts "index: #{index}, dis_loss: #{dis_loss.mean}, dcgan_loss: #{dcgan_loss.mean}"
|
39
41
|
end
|
42
|
+
iter.reset
|
40
43
|
dcgan.save("trained/dcgan_model_epoch#{epoch}.marshal")
|
41
44
|
end
|
data/examples/iris_example.rb
CHANGED
data/examples/mnist_example.rb
CHANGED
data/lib/dnn.rb
CHANGED
@@ -9,6 +9,7 @@ end
|
|
9
9
|
|
10
10
|
require_relative "dnn/version"
|
11
11
|
require_relative "dnn/core/error"
|
12
|
+
require_relative "dnn/core/global"
|
12
13
|
require_relative "dnn/core/models"
|
13
14
|
require_relative "dnn/core/param"
|
14
15
|
require_relative "dnn/core/link"
|
@@ -24,4 +25,5 @@ require_relative "dnn/core/cnn_layers"
|
|
24
25
|
require_relative "dnn/core/embedding"
|
25
26
|
require_relative "dnn/core/rnn_layers"
|
26
27
|
require_relative "dnn/core/optimizers"
|
28
|
+
require_relative "dnn/core/savers"
|
27
29
|
require_relative "dnn/core/utils"
|
data/lib/dnn/core/embedding.rb
CHANGED
data/lib/dnn/core/error.rb
CHANGED
@@ -2,7 +2,7 @@ module DNN
|
|
2
2
|
module Initializers
|
3
3
|
|
4
4
|
class Initializer
|
5
|
-
# @param [Boolean | Integer] seed Seed of random number used for
|
5
|
+
# @param [Boolean | Integer] seed Seed of random number used for initialize parameter.
|
6
6
|
# Set true to determine seed as random.
|
7
7
|
def initialize(seed: false)
|
8
8
|
@seed = seed == true ? rand(1 << 31) : seed
|
data/lib/dnn/core/iterator.rb
CHANGED
@@ -8,7 +8,7 @@ module DNN
|
|
8
8
|
@x_datas = x_datas
|
9
9
|
@y_datas = y_datas
|
10
10
|
@random = random
|
11
|
-
@num_datas = x_datas.shape[0]
|
11
|
+
@num_datas = x_datas.is_a?(Array) ? x_datas[0].shape[0] : x_datas.shape[0]
|
12
12
|
reset
|
13
13
|
end
|
14
14
|
|
@@ -22,8 +22,16 @@ module DNN
|
|
22
22
|
else
|
23
23
|
batch_indexes = @indexes.shift(batch_size)
|
24
24
|
end
|
25
|
-
x_batch = @x_datas
|
26
|
-
|
25
|
+
x_batch = if @x_datas.is_a?(Array)
|
26
|
+
@x_datas.map { |datas| datas[batch_indexes, false] }
|
27
|
+
else
|
28
|
+
@x_datas[batch_indexes, false]
|
29
|
+
end
|
30
|
+
y_batch = if @y_datas.is_a?(Array)
|
31
|
+
@y_datas.map { |datas| datas[batch_indexes, false] }
|
32
|
+
else
|
33
|
+
@y_datas[batch_indexes, false]
|
34
|
+
end
|
27
35
|
[x_batch, y_batch]
|
28
36
|
end
|
29
37
|
|
data/lib/dnn/core/layers.rb
CHANGED
@@ -3,6 +3,7 @@ module DNN
|
|
3
3
|
|
4
4
|
# Super class of all layer classes.
|
5
5
|
class Layer
|
6
|
+
attr_accessor :name
|
6
7
|
attr_reader :input_shape
|
7
8
|
|
8
9
|
def self.call(x, *args)
|
@@ -14,13 +15,13 @@ module DNN
|
|
14
15
|
end
|
15
16
|
|
16
17
|
# Forward propagation and create a link.
|
17
|
-
# @param [Array] input Array of the form [x_input_data, prev_link
|
18
|
+
# @param [Array] input Array of the form [x_input_data, prev_link].
|
18
19
|
def call(input)
|
19
|
-
x, prev_link
|
20
|
+
x, prev_link = *input
|
20
21
|
build(x.shape[1..-1]) unless built?
|
21
22
|
y = forward(x)
|
22
23
|
link = Link.new(prev_link, self)
|
23
|
-
[y, link
|
24
|
+
[y, link]
|
24
25
|
end
|
25
26
|
|
26
27
|
# Build the layer.
|
@@ -98,9 +99,14 @@ module DNN
|
|
98
99
|
|
99
100
|
def call(input)
|
100
101
|
build unless built?
|
101
|
-
|
102
|
+
if input.is_a?(Array)
|
103
|
+
x, prev_link = *input
|
104
|
+
else
|
105
|
+
x = input
|
106
|
+
prev_link = nil
|
107
|
+
end
|
102
108
|
link = prev_link ? Link.new(prev_link, self) : Link.new(nil, self)
|
103
|
-
[forward(x), link
|
109
|
+
[forward(x), link]
|
104
110
|
end
|
105
111
|
|
106
112
|
def build
|
@@ -310,16 +316,8 @@ module DNN
|
|
310
316
|
@rnd = Random.new(@seed)
|
311
317
|
end
|
312
318
|
|
313
|
-
def
|
314
|
-
|
315
|
-
build(x.shape[1..-1]) unless built?
|
316
|
-
y = forward(x, learning_phase)
|
317
|
-
link = Link.new(prev_link, self)
|
318
|
-
[y, link, learning_phase]
|
319
|
-
end
|
320
|
-
|
321
|
-
def forward(x, learning_phase)
|
322
|
-
if learning_phase
|
319
|
+
def forward(x)
|
320
|
+
if DNN.learning_phase
|
323
321
|
Xumo::SFloat.srand(@rnd.rand(1 << 31))
|
324
322
|
@mask = Xumo::SFloat.ones(*x.shape).rand < @dropout_ratio
|
325
323
|
x[@mask] = 0
|
data/lib/dnn/core/link.rb
CHANGED
@@ -7,6 +7,11 @@ module DNN
|
|
7
7
|
@prev = prev
|
8
8
|
@layer = layer
|
9
9
|
end
|
10
|
+
|
11
|
+
def backward(dy)
|
12
|
+
dy = @layer.backward(dy)
|
13
|
+
@prev&.backward(dy)
|
14
|
+
end
|
10
15
|
end
|
11
16
|
|
12
17
|
|
@@ -20,5 +25,11 @@ module DNN
|
|
20
25
|
@prev2 = prev2
|
21
26
|
@layer = layer
|
22
27
|
end
|
28
|
+
|
29
|
+
def backward(dy)
|
30
|
+
dy1, dy2 =* @layer.backward(dy)
|
31
|
+
@prev1&.backward(dy1)
|
32
|
+
@prev2&.backward(dy2)
|
33
|
+
end
|
23
34
|
end
|
24
35
|
end
|
data/lib/dnn/core/losses.rb
CHANGED
@@ -2,25 +2,37 @@ module DNN
|
|
2
2
|
module Losses
|
3
3
|
|
4
4
|
class Loss
|
5
|
-
def
|
5
|
+
def loss(y, t, layers = nil)
|
6
6
|
unless y.shape == t.shape
|
7
7
|
raise DNN_ShapeError.new("The shape of y does not match the t shape. y shape is #{y.shape}, but t shape is #{t.shape}.")
|
8
8
|
end
|
9
|
-
loss_value =
|
10
|
-
|
11
|
-
|
9
|
+
loss_value = forward(y, t)
|
10
|
+
loss_value += regularizers_forward(layers) if layers
|
11
|
+
loss_value
|
12
|
+
end
|
13
|
+
|
14
|
+
def forward(y, t)
|
15
|
+
raise NotImplementedError.new("Class '#{self.class.name}' has implement method 'forward'")
|
16
|
+
end
|
12
17
|
|
18
|
+
def backward(y, t)
|
19
|
+
raise NotImplementedError.new("Class '#{self.class.name}' has implement method 'backward'")
|
20
|
+
end
|
21
|
+
|
22
|
+
def regularizers_forward(layers)
|
23
|
+
loss_value = 0
|
24
|
+
regularizers = layers.select { |layer| layer.respond_to?(:regularizers) }
|
25
|
+
.map(&:regularizers).flatten
|
13
26
|
regularizers.each do |regularizer|
|
14
27
|
loss_value = regularizer.forward(loss_value)
|
15
28
|
end
|
16
29
|
loss_value
|
17
30
|
end
|
18
31
|
|
19
|
-
def
|
32
|
+
def regularizers_backward(layers)
|
20
33
|
layers.select { |layer| layer.respond_to?(:regularizers) }.each do |layer|
|
21
34
|
layer.regularizers.each(&:backward)
|
22
35
|
end
|
23
|
-
backward_loss(t)
|
24
36
|
end
|
25
37
|
|
26
38
|
def to_hash(merge_hash = nil)
|
@@ -28,44 +40,28 @@ module DNN
|
|
28
40
|
hash.merge!(merge_hash) if merge_hash
|
29
41
|
hash
|
30
42
|
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def forward_loss(y, t)
|
35
|
-
raise NotImplementedError.new("Class '#{self.class.name}' has implement method 'forward_loss'")
|
36
|
-
end
|
37
|
-
|
38
|
-
def backward_loss(t)
|
39
|
-
raise NotImplementedError.new("Class '#{self.class.name}' has implement method 'backward_loss'")
|
40
|
-
end
|
41
43
|
end
|
42
44
|
|
43
45
|
class MeanSquaredError < Loss
|
44
|
-
|
45
|
-
|
46
|
-
def forward_loss(y, t)
|
47
|
-
@y = y
|
46
|
+
def forward(y, t)
|
48
47
|
batch_size = t.shape[0]
|
49
48
|
0.5 * ((y - t) ** 2).sum / batch_size
|
50
49
|
end
|
51
50
|
|
52
|
-
def
|
53
|
-
|
51
|
+
def backward(y, t)
|
52
|
+
y - t
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
57
56
|
|
58
57
|
class MeanAbsoluteError < Loss
|
59
|
-
|
60
|
-
|
61
|
-
def forward_loss(y, t)
|
62
|
-
@y = y
|
58
|
+
def forward(y, t)
|
63
59
|
batch_size = t.shape[0]
|
64
60
|
(y - t).abs.sum / batch_size
|
65
61
|
end
|
66
62
|
|
67
|
-
def
|
68
|
-
dy =
|
63
|
+
def backward(y, t)
|
64
|
+
dy = y - t
|
69
65
|
dy[dy >= 0] = 1
|
70
66
|
dy[dy < 0] = -1
|
71
67
|
dy
|
@@ -74,14 +70,12 @@ module DNN
|
|
74
70
|
|
75
71
|
|
76
72
|
class Hinge < Loss
|
77
|
-
|
78
|
-
|
79
|
-
def forward_loss(y, t)
|
73
|
+
def forward(y, t)
|
80
74
|
@a = 1 - y * t
|
81
75
|
Xumo::SFloat.maximum(0, @a)
|
82
76
|
end
|
83
77
|
|
84
|
-
def
|
78
|
+
def backward(y, t)
|
85
79
|
a = Xumo::SFloat.ones(*@a.shape)
|
86
80
|
a[@a <= 0] = 0
|
87
81
|
a * -t
|
@@ -90,16 +84,13 @@ module DNN
|
|
90
84
|
|
91
85
|
|
92
86
|
class HuberLoss < Loss
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
@y = y
|
97
|
-
loss_l1_value = loss_l1(t)
|
98
|
-
@loss_value = loss_l1_value > 1 ? loss_l1_value : loss_l2(t)
|
87
|
+
def forward(y, t)
|
88
|
+
loss_l1_value = loss_l1(y, t)
|
89
|
+
@loss_value = loss_l1_value > 1 ? loss_l1_value : loss_l2(y, t)
|
99
90
|
end
|
100
91
|
|
101
|
-
def
|
102
|
-
dy =
|
92
|
+
def backward(y, t)
|
93
|
+
dy = y - t
|
103
94
|
if @loss_value > 1
|
104
95
|
dy[dy >= 0] = 1
|
105
96
|
dy[dy < 0] = -1
|
@@ -107,14 +98,16 @@ module DNN
|
|
107
98
|
dy
|
108
99
|
end
|
109
100
|
|
110
|
-
|
101
|
+
private
|
102
|
+
|
103
|
+
def loss_l1(y, t)
|
111
104
|
batch_size = t.shape[0]
|
112
|
-
(
|
105
|
+
(y - t).abs.sum / batch_size
|
113
106
|
end
|
114
107
|
|
115
|
-
def loss_l2(t)
|
108
|
+
def loss_l2(y, t)
|
116
109
|
batch_size = t.shape[0]
|
117
|
-
0.5 * ((
|
110
|
+
0.5 * ((y - t) ** 2).sum / batch_size
|
118
111
|
end
|
119
112
|
end
|
120
113
|
|
@@ -135,20 +128,18 @@ module DNN
|
|
135
128
|
@eps = eps
|
136
129
|
end
|
137
130
|
|
138
|
-
def
|
139
|
-
|
131
|
+
def forward(y, t)
|
132
|
+
@x = SoftmaxCrossEntropy.softmax(y)
|
133
|
+
batch_size = t.shape[0]
|
134
|
+
-(t * Xumo::NMath.log(@x + @eps)).sum / batch_size
|
140
135
|
end
|
141
136
|
|
142
|
-
|
143
|
-
|
144
|
-
def forward_loss(y, t)
|
145
|
-
@y = SoftmaxCrossEntropy.softmax(y)
|
146
|
-
batch_size = t.shape[0]
|
147
|
-
-(t * Xumo::NMath.log(@y + @eps)).sum / batch_size
|
137
|
+
def backward(y, t)
|
138
|
+
@x - t
|
148
139
|
end
|
149
140
|
|
150
|
-
def
|
151
|
-
@
|
141
|
+
def to_hash
|
142
|
+
super(eps: @eps)
|
152
143
|
end
|
153
144
|
end
|
154
145
|
|
@@ -165,19 +156,17 @@ module DNN
|
|
165
156
|
@eps = eps
|
166
157
|
end
|
167
158
|
|
168
|
-
def
|
169
|
-
|
159
|
+
def forward(y, t)
|
160
|
+
@x = Activations::Sigmoid.new.forward(y)
|
161
|
+
-(t * Xumo::NMath.log(@x) + (1 - t) * Xumo::NMath.log(1 - @x))
|
170
162
|
end
|
171
163
|
|
172
|
-
|
173
|
-
|
174
|
-
def forward_loss(y, t)
|
175
|
-
@y = Activations::Sigmoid.new.forward(y)
|
176
|
-
-(t * Xumo::NMath.log(@y) + (1 - t) * Xumo::NMath.log(1 - @y))
|
164
|
+
def backward(y, t)
|
165
|
+
@x - t
|
177
166
|
end
|
178
167
|
|
179
|
-
def
|
180
|
-
@
|
168
|
+
def to_hash
|
169
|
+
super(eps: @eps)
|
181
170
|
end
|
182
171
|
end
|
183
172
|
|