ruby-dnn 0.14.3 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -3
- data/Rakefile +4 -2
- data/examples/api-examples/save_example.rb +7 -5
- data/examples/dcgan/imgen.rb +2 -7
- data/examples/dcgan/train.rb +0 -1
- data/lib/dnn.rb +10 -10
- data/lib/dnn/core/callbacks.rb +6 -2
- data/lib/dnn/core/iterator.rb +10 -2
- data/lib/dnn/core/{activations.rb → layers/activations.rb} +0 -0
- data/lib/dnn/core/{layers.rb → layers/basic_layers.rb} +31 -8
- data/lib/dnn/core/{cnn_layers.rb → layers/cnn_layers.rb} +0 -0
- data/lib/dnn/core/{embedding.rb → layers/embedding.rb} +5 -4
- data/lib/dnn/core/{merge_layers.rb → layers/merge_layers.rb} +1 -1
- data/lib/dnn/core/{normalizations.rb → layers/normalizations.rb} +9 -5
- data/lib/dnn/core/{rnn_layers.rb → layers/rnn_layers.rb} +25 -16
- data/lib/dnn/core/losses.rb +8 -0
- data/lib/dnn/core/models.rb +164 -68
- data/lib/dnn/core/optimizers.rb +49 -72
- data/lib/dnn/core/param.rb +0 -2
- data/lib/dnn/core/savers.rb +40 -49
- data/lib/dnn/datasets/stl-10.rb +65 -0
- data/lib/dnn/version.rb +1 -1
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6be46c1c89fbb1f1f2091c95f15ccab21473d52571ee47953a4c07446ea8544c
|
4
|
+
data.tar.gz: e01eb929c13b2a33a350ee42b8bb8584446722ac3ba3dc7e163f7f3429ec068a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc5bd6608d17a90cb97f6f5530877e5441a2dc73fc18e7b821c33d606469d6a15c22d519570b8c8821282915de84b677b3527221b1eb076a145a85997a58d2d9
|
7
|
+
data.tar.gz: 721c578f41a7648dfc5c462a1b9a81f6b9604b50540e8fa4a58bb801adc8059ee7cff9f27d3c1b1a710ce0857e426ca2087f4902bf46d9c621870e3ae7cb664a
|
data/README.md
CHANGED
@@ -2,8 +2,9 @@
|
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/ruby-dnn.svg)](https://badge.fury.io/rb/ruby-dnn)
|
3
3
|
[![Build Status](https://travis-ci.org/unagiootoro/ruby-dnn.svg?branch=master)](https://travis-ci.org/unagiootoro/ruby-dnn)
|
4
4
|
|
5
|
-
ruby-dnn is a ruby deep learning library. This library supports full connected neural network and convolution neural network
|
6
|
-
|
5
|
+
ruby-dnn is a ruby deep learning library. This library supports full connected neural network and convolution neural network
|
6
|
+
and recurrent neural network.
|
7
|
+
Currently, you can get 99% accuracy with MNIST and 78% with CIFAR 10.
|
7
8
|
|
8
9
|
## Installation
|
9
10
|
|
@@ -79,8 +80,9 @@ If you want to know more detailed information, please refer to the source code.
|
|
79
80
|
|| Implemented classes |
|
80
81
|
|:-----------|------------:|
|
81
82
|
| Connections | Dense, Conv2D, Conv2DTranspose, Embedding, SimpleRNN, LSTM, GRU |
|
82
|
-
| Layers | Flatten, Reshape, Dropout, BatchNormalization, MaxPool2D, AvgPool2D, UnPool2D |
|
83
83
|
| Activations | Sigmoid, Tanh, Softsign, Softplus, Swish, ReLU, LeakyReLU, ELU |
|
84
|
+
| Basic | Flatten, Reshape, Dropout, BatchNormalization |
|
85
|
+
| Pooling | MaxPool2D, AvgPool2D, GlobalAvgPool2D, UnPool2D |
|
84
86
|
| Optimizers | SGD, Nesterov, AdaGrad, RMSProp, AdaDelta, RMSPropGraves, Adam, AdaBound |
|
85
87
|
| Losses | MeanSquaredError, MeanAbsoluteError, Hinge, HuberLoss, SoftmaxCrossEntropy, SigmoidCrossEntropy |
|
86
88
|
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ Rake::TestTask.new(:test) do |t|
|
|
5
5
|
t.libs << "test"
|
6
6
|
t.libs << "ext"
|
7
7
|
t.libs << "lib"
|
8
|
-
t.test_files = FileList["test/*_test.rb"]
|
8
|
+
t.test_files = FileList["test/*_test.rb", "test/layers_test/*_test.rb"]
|
9
9
|
end
|
10
10
|
|
11
11
|
task :build_cifar_loader do
|
@@ -27,7 +27,9 @@ end
|
|
27
27
|
task :default => [:test, :build_cifar_loader, :build_rb_stb_image]
|
28
28
|
|
29
29
|
task :doc do
|
30
|
-
src_list = Dir["lib/dnn
|
30
|
+
src_list = Dir["lib/dnn.rb"]
|
31
|
+
src_list += Dir["lib/dnn/core/*.rb"]
|
32
|
+
src_list += Dir["lib/dnn/core/layers/*.rb"]
|
31
33
|
src_list += Dir["lib/dnn/*.rb"]
|
32
34
|
sh "yardoc #{src_list.join(' ')}"
|
33
35
|
end
|
@@ -20,9 +20,9 @@ BATCH_SIZE = 128
|
|
20
20
|
# Select save style from USE_MARSHAL or USE_JSON.
|
21
21
|
SAVE_STYLE = USE_MARSHAL
|
22
22
|
|
23
|
-
# When set a true, save data included
|
23
|
+
# When set a true, save data included model structure.
|
24
24
|
# This setting is enabled when SAVE_STYLE is USE_MARSHAL.
|
25
|
-
|
25
|
+
INCLUDE_MODEL = true
|
26
26
|
|
27
27
|
x_train, y_train = MNIST.load_train
|
28
28
|
x_test, y_test = MNIST.load_test
|
@@ -47,7 +47,7 @@ class MLP < Model
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def call(x)
|
50
|
-
x = InputLayer.(x)
|
50
|
+
x = InputLayer.new(784).(x)
|
51
51
|
x = @l1.(x)
|
52
52
|
x = @bn1.(x)
|
53
53
|
x = ReLU.(x)
|
@@ -64,7 +64,7 @@ model.setup(Adam.new, SoftmaxCrossEntropy.new)
|
|
64
64
|
model.train(x_train, y_train, EPOCHS, batch_size: BATCH_SIZE, test: [x_test, y_test])
|
65
65
|
|
66
66
|
if SAVE_STYLE == USE_MARSHAL
|
67
|
-
saver = MarshalSaver.new(model,
|
67
|
+
saver = MarshalSaver.new(model, include_model: INCLUDE_MODEL)
|
68
68
|
saver.save("trained_mnist.marshal")
|
69
69
|
# model.save("trained_mnist.marshal") # This code is equivalent to the code above.
|
70
70
|
elsif SAVE_STYLE == USE_JSON
|
@@ -73,6 +73,8 @@ elsif SAVE_STYLE == USE_JSON
|
|
73
73
|
end
|
74
74
|
|
75
75
|
model2 = MLP.new
|
76
|
+
model2.setup(Adam.new, SoftmaxCrossEntropy.new)
|
77
|
+
model2.predict1(Numo::SFloat.zeros(784))
|
76
78
|
if SAVE_STYLE == USE_MARSHAL
|
77
79
|
loader = MarshalLoader.new(model2)
|
78
80
|
loader.load("trained_mnist.marshal")
|
@@ -82,4 +84,4 @@ elsif SAVE_STYLE == USE_JSON
|
|
82
84
|
loader.load("trained_mnist.json")
|
83
85
|
end
|
84
86
|
|
85
|
-
puts model2.
|
87
|
+
puts model2.evaluate(x_test, y_test)
|
data/examples/dcgan/imgen.rb
CHANGED
@@ -8,13 +8,8 @@ Image = DNN::Image
|
|
8
8
|
|
9
9
|
batch_size = 100
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
dcgan = DCGAN.new(gen, dis)
|
14
|
-
dcgan.predict1(Numo::SFloat.zeros(20))
|
15
|
-
|
16
|
-
loader = MarshalLoader.new(dcgan)
|
17
|
-
loader.load("trained/dcgan_model_epoch20.marshal")
|
11
|
+
dcgan = DCGAN.load("trained/dcgan_model_epoch20.marshal")
|
12
|
+
gen = dcgan.gen
|
18
13
|
|
19
14
|
Numo::SFloat.srand(rand(1 << 31))
|
20
15
|
noise = Numo::SFloat.new(batch_size, 20).rand(-1, 1)
|
data/examples/dcgan/train.rb
CHANGED
@@ -20,7 +20,6 @@ dcgan = DCGAN.new(gen, dis)
|
|
20
20
|
dis.setup(Adam.new(alpha: 0.00001, beta1: 0.1), SigmoidCrossEntropy.new)
|
21
21
|
dcgan.setup(Adam.new(alpha: 0.0002, beta1: 0.5), SigmoidCrossEntropy.new)
|
22
22
|
dcgan.add_callback(CheckPoint.new("trained/dcgan_model"))
|
23
|
-
dcgan.predict1(Numo::SFloat.zeros(20))
|
24
23
|
|
25
24
|
x_train, * = MNIST.load_train
|
26
25
|
x_train = Numo::SFloat.cast(x_train)
|
data/lib/dnn.rb
CHANGED
@@ -11,21 +11,21 @@ require_relative "dnn/version"
|
|
11
11
|
require_relative "dnn/core/error"
|
12
12
|
require_relative "dnn/core/global"
|
13
13
|
require_relative "dnn/core/tensor"
|
14
|
-
require_relative "dnn/core/models"
|
15
14
|
require_relative "dnn/core/param"
|
16
15
|
require_relative "dnn/core/link"
|
17
16
|
require_relative "dnn/core/iterator"
|
18
|
-
require_relative "dnn/core/
|
19
|
-
require_relative "dnn/core/layers"
|
20
|
-
require_relative "dnn/core/normalizations"
|
21
|
-
require_relative "dnn/core/activations"
|
22
|
-
require_relative "dnn/core/merge_layers"
|
17
|
+
require_relative "dnn/core/models"
|
18
|
+
require_relative "dnn/core/layers/basic_layers"
|
19
|
+
require_relative "dnn/core/layers/normalizations"
|
20
|
+
require_relative "dnn/core/layers/activations"
|
21
|
+
require_relative "dnn/core/layers/merge_layers"
|
22
|
+
require_relative "dnn/core/layers/cnn_layers"
|
23
|
+
require_relative "dnn/core/layers/embedding"
|
24
|
+
require_relative "dnn/core/layers/rnn_layers"
|
25
|
+
require_relative "dnn/core/optimizers"
|
23
26
|
require_relative "dnn/core/losses"
|
27
|
+
require_relative "dnn/core/initializers"
|
24
28
|
require_relative "dnn/core/regularizers"
|
25
|
-
require_relative "dnn/core/cnn_layers"
|
26
|
-
require_relative "dnn/core/embedding"
|
27
|
-
require_relative "dnn/core/rnn_layers"
|
28
|
-
require_relative "dnn/core/optimizers"
|
29
29
|
require_relative "dnn/core/callbacks"
|
30
30
|
require_relative "dnn/core/savers"
|
31
31
|
require_relative "dnn/core/utils"
|
data/lib/dnn/core/callbacks.rb
CHANGED
@@ -35,13 +35,17 @@ module DNN
|
|
35
35
|
end
|
36
36
|
|
37
37
|
# A callback that save the model at the after of the epoch.
|
38
|
+
# @param [String] base_file_name Base file name for saving.
|
39
|
+
# @param [Boolean] include_model When set a true, save data included model structure.
|
38
40
|
class CheckPoint < Callback
|
39
|
-
def initialize(base_file_name)
|
41
|
+
def initialize(base_file_name, include_model: true)
|
40
42
|
@base_file_name = base_file_name
|
43
|
+
@include_model = include_model
|
41
44
|
end
|
42
45
|
|
43
46
|
def after_epoch
|
44
|
-
|
47
|
+
saver = Savers::MarshalSaver.new(@model, include_model: @include_model)
|
48
|
+
saver.save(@base_file_name + "_epoch#{model.last_log[:epoch]}.marshal")
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
data/lib/dnn/core/iterator.rb
CHANGED
@@ -4,8 +4,8 @@ module DNN
|
|
4
4
|
attr_reader :num_datas
|
5
5
|
attr_reader :last_round_down
|
6
6
|
|
7
|
-
# @param [Numo::SFloat] x_datas input datas.
|
8
|
-
# @param [Numo::SFloat] y_datas output datas.
|
7
|
+
# @param [Numo::SFloat | Array] x_datas input datas.
|
8
|
+
# @param [Numo::SFloat | Array] y_datas output datas.
|
9
9
|
# @param [Boolean] random Set true to return batches randomly. Setting false returns batches in order of index.
|
10
10
|
# @param [Boolean] last_round_down Set true to round down for last batch data when call foreach.
|
11
11
|
def initialize(x_datas, y_datas, random: true, last_round_down: false)
|
@@ -19,6 +19,7 @@ module DNN
|
|
19
19
|
|
20
20
|
# Return the next batch.
|
21
21
|
# @param [Integer] batch_size Required batch size.
|
22
|
+
# @return [Array] Returns the mini batch in the form [x_batch, y_batch].
|
22
23
|
def next_batch(batch_size)
|
23
24
|
raise DNN_Error, "This iterator has not next batch. Please call reset." unless has_next?
|
24
25
|
if @indexes.length <= batch_size
|
@@ -27,6 +28,13 @@ module DNN
|
|
27
28
|
else
|
28
29
|
batch_indexes = @indexes.shift(batch_size)
|
29
30
|
end
|
31
|
+
get_batch(batch_indexes)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Implement a process to get mini batch.
|
35
|
+
# @param [Array] batch_indexes Index of batch to get.
|
36
|
+
# @return [Array] Returns the mini batch in the form [x_batch, y_batch].
|
37
|
+
private def get_batch(batch_indexes)
|
30
38
|
x_batch = if @x_datas.is_a?(Array)
|
31
39
|
@x_datas.map { |datas| datas[batch_indexes, false] }
|
32
40
|
else
|
File without changes
|
@@ -3,7 +3,6 @@ module DNN
|
|
3
3
|
|
4
4
|
# Super class of all layer classes.
|
5
5
|
class Layer
|
6
|
-
attr_accessor :name
|
7
6
|
attr_reader :input_shape
|
8
7
|
|
9
8
|
def self.call(x, *args)
|
@@ -16,13 +15,11 @@ module DNN
|
|
16
15
|
layer = layer_class.allocate
|
17
16
|
raise DNN_Error, "#{layer.class} is not an instance of #{self} class." unless layer.is_a?(self)
|
18
17
|
layer.load_hash(hash)
|
19
|
-
layer.name = hash[:name]&.to_sym
|
20
18
|
layer
|
21
19
|
end
|
22
20
|
|
23
21
|
def initialize
|
24
22
|
@built = false
|
25
|
-
@name = nil
|
26
23
|
end
|
27
24
|
|
28
25
|
# Forward propagation and create a link.
|
@@ -70,7 +67,7 @@ module DNN
|
|
70
67
|
|
71
68
|
# Layer to a hash.
|
72
69
|
def to_hash(merge_hash = nil)
|
73
|
-
hash = { class: self.class.name
|
70
|
+
hash = { class: self.class.name }
|
74
71
|
hash.merge!(merge_hash) if merge_hash
|
75
72
|
hash
|
76
73
|
end
|
@@ -78,10 +75,20 @@ module DNN
|
|
78
75
|
def load_hash(hash)
|
79
76
|
initialize
|
80
77
|
end
|
78
|
+
|
79
|
+
def clean
|
80
|
+
input_shape = @input_shape
|
81
|
+
hash = to_hash
|
82
|
+
instance_variables.each do |ivar|
|
83
|
+
instance_variable_set(ivar, nil)
|
84
|
+
end
|
85
|
+
load_hash(hash)
|
86
|
+
build(input_shape)
|
87
|
+
end
|
81
88
|
end
|
82
89
|
|
83
90
|
# This class is a superclass of all classes with learning parameters.
|
84
|
-
class
|
91
|
+
class TrainableLayer < Layer
|
85
92
|
# @return [Boolean] Setting false prevents learning of parameters.
|
86
93
|
attr_accessor :trainable
|
87
94
|
|
@@ -94,6 +101,22 @@ module DNN
|
|
94
101
|
def get_params
|
95
102
|
raise NotImplementedError, "Class '#{self.class.name}' has implement method 'get_params'"
|
96
103
|
end
|
104
|
+
|
105
|
+
def clean
|
106
|
+
input_shape = @input_shape
|
107
|
+
hash = to_hash
|
108
|
+
params = get_params
|
109
|
+
instance_variables.each do |ivar|
|
110
|
+
instance_variable_set(ivar, nil)
|
111
|
+
end
|
112
|
+
load_hash(hash)
|
113
|
+
build(input_shape)
|
114
|
+
params.each do |(key, param)|
|
115
|
+
param.data = nil
|
116
|
+
param.grad = Xumo::SFloat[0] if param.grad
|
117
|
+
instance_variable_set("@#{key}", param)
|
118
|
+
end
|
119
|
+
end
|
97
120
|
end
|
98
121
|
|
99
122
|
class InputLayer < Layer
|
@@ -109,7 +132,7 @@ module DNN
|
|
109
132
|
end
|
110
133
|
|
111
134
|
def call(input)
|
112
|
-
build unless built?
|
135
|
+
build(@input_shape) unless built?
|
113
136
|
if input.is_a?(Tensor)
|
114
137
|
x = input.data
|
115
138
|
prev_link = input&.link
|
@@ -120,7 +143,7 @@ module DNN
|
|
120
143
|
Tensor.new(forward(x), Link.new(prev_link, self))
|
121
144
|
end
|
122
145
|
|
123
|
-
def build
|
146
|
+
def build(input_shape)
|
124
147
|
@built = true
|
125
148
|
end
|
126
149
|
|
@@ -163,7 +186,7 @@ module DNN
|
|
163
186
|
end
|
164
187
|
|
165
188
|
# It is a superclass of all connection layers.
|
166
|
-
class Connection <
|
189
|
+
class Connection < TrainableLayer
|
167
190
|
attr_reader :weight
|
168
191
|
attr_reader :bias
|
169
192
|
attr_reader :weight_initializer
|
File without changes
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module DNN
|
2
2
|
module Layers
|
3
3
|
|
4
|
-
class Embedding <
|
4
|
+
class Embedding < TrainableLayer
|
5
5
|
attr_reader :input_length
|
6
6
|
attr_reader :weight
|
7
7
|
attr_reader :weight_initializer
|
@@ -19,16 +19,17 @@ module DNN
|
|
19
19
|
@input_length = input_length
|
20
20
|
@weight_initializer = weight_initializer
|
21
21
|
@weight_regularizer = weight_regularizer
|
22
|
+
@weight = Param.new(nil, Xumo::SFloat[0])
|
22
23
|
end
|
23
24
|
|
24
25
|
def call(input_tensor)
|
25
|
-
build unless built?
|
26
|
+
build(@input_shape) unless built?
|
26
27
|
Tensor.new(forward(input_tensor.data), Link.new(nil, self))
|
27
28
|
end
|
28
29
|
|
29
|
-
def build
|
30
|
+
def build(input_shape)
|
30
31
|
@built = true
|
31
|
-
@weight =
|
32
|
+
@weight.data = Xumo::SFloat.new(@input_length)
|
32
33
|
@weight_initializer.init_param(self, @weight)
|
33
34
|
@weight_regularizer.param = @weight if @weight_regularizer
|
34
35
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module DNN
|
2
2
|
module Layers
|
3
3
|
|
4
|
-
class BatchNormalization <
|
4
|
+
class BatchNormalization < TrainableLayer
|
5
5
|
attr_reader :gamma
|
6
6
|
attr_reader :beta
|
7
7
|
attr_reader :running_mean
|
@@ -18,14 +18,18 @@ module DNN
|
|
18
18
|
@axis = axis
|
19
19
|
@momentum = momentum
|
20
20
|
@eps = eps
|
21
|
+
@gamma = Param.new(nil, Xumo::SFloat[0])
|
22
|
+
@beta = Param.new(nil, Xumo::SFloat[0])
|
23
|
+
@running_mean = Param.new
|
24
|
+
@running_var = Param.new
|
21
25
|
end
|
22
26
|
|
23
27
|
def build(input_shape)
|
24
28
|
super
|
25
|
-
@gamma =
|
26
|
-
@beta =
|
27
|
-
@running_mean =
|
28
|
-
@running_var =
|
29
|
+
@gamma.data = Xumo::SFloat.ones(*output_shape)
|
30
|
+
@beta.data = Xumo::SFloat.zeros(*output_shape)
|
31
|
+
@running_mean.data = Xumo::SFloat.zeros(*output_shape)
|
32
|
+
@running_var.data = Xumo::SFloat.zeros(*output_shape)
|
29
33
|
end
|
30
34
|
|
31
35
|
def forward(x)
|
@@ -31,7 +31,7 @@ module DNN
|
|
31
31
|
@num_nodes = num_nodes
|
32
32
|
@stateful = stateful
|
33
33
|
@return_sequences = return_sequences
|
34
|
-
@
|
34
|
+
@hidden_layers = []
|
35
35
|
@hidden = Param.new
|
36
36
|
@recurrent_weight = Param.new(nil, Xumo::SFloat[0])
|
37
37
|
@recurrent_weight_initializer = recurrent_weight_initializer
|
@@ -46,14 +46,19 @@ module DNN
|
|
46
46
|
@time_length = @input_shape[0]
|
47
47
|
end
|
48
48
|
|
49
|
+
private def create_hidden_layer
|
50
|
+
raise NotImplementedError, "Class '#{self.class.name}' has implement method 'create_hidden_layer'"
|
51
|
+
end
|
52
|
+
|
49
53
|
def forward(xs)
|
54
|
+
create_hidden_layer
|
50
55
|
@xs_shape = xs.shape
|
51
56
|
hs = Xumo::SFloat.zeros(xs.shape[0], @time_length, @num_nodes)
|
52
57
|
h = @stateful && @hidden.data ? @hidden.data : Xumo::SFloat.zeros(xs.shape[0], @num_nodes)
|
53
58
|
xs.shape[1].times do |t|
|
54
59
|
x = xs[true, t, false]
|
55
|
-
@
|
56
|
-
h = @
|
60
|
+
@hidden_layers[t].trainable = @trainable
|
61
|
+
h = @hidden_layers[t].forward(x, h)
|
57
62
|
hs[true, t, false] = h
|
58
63
|
end
|
59
64
|
@hidden.data = h
|
@@ -70,7 +75,7 @@ module DNN
|
|
70
75
|
dh = 0
|
71
76
|
(dh2s.shape[1] - 1).downto(0) do |t|
|
72
77
|
dh2 = dh2s[true, t, false]
|
73
|
-
dx, dh = @
|
78
|
+
dx, dh = @hidden_layers[t].backward(dh2 + dh)
|
74
79
|
dxs[true, t, false] = dx
|
75
80
|
end
|
76
81
|
dxs
|
@@ -196,9 +201,10 @@ module DNN
|
|
196
201
|
@recurrent_weight.data = Xumo::SFloat.new(@num_nodes, @num_nodes)
|
197
202
|
@bias.data = Xumo::SFloat.new(@num_nodes) if @bias
|
198
203
|
init_weight_and_bias
|
199
|
-
|
200
|
-
|
201
|
-
|
204
|
+
end
|
205
|
+
|
206
|
+
def create_hidden_layer
|
207
|
+
@hidden_layers = Array.new(@time_length) { SimpleRNNDense.new(@weight, @recurrent_weight, @bias, @activation) }
|
202
208
|
end
|
203
209
|
|
204
210
|
def to_hash
|
@@ -301,12 +307,14 @@ module DNN
|
|
301
307
|
@recurrent_weight.data = Xumo::SFloat.new(@num_nodes, @num_nodes * 4)
|
302
308
|
@bias.data = Xumo::SFloat.new(@num_nodes * 4) if @bias
|
303
309
|
init_weight_and_bias
|
304
|
-
|
305
|
-
|
306
|
-
|
310
|
+
end
|
311
|
+
|
312
|
+
def create_hidden_layer
|
313
|
+
@hidden_layers = Array.new(@time_length) { LSTMDense.new(@weight, @recurrent_weight, @bias) }
|
307
314
|
end
|
308
315
|
|
309
316
|
def forward(xs)
|
317
|
+
create_hidden_layer
|
310
318
|
@xs_shape = xs.shape
|
311
319
|
hs = Xumo::SFloat.zeros(xs.shape[0], @time_length, @num_nodes)
|
312
320
|
h = nil
|
@@ -319,8 +327,8 @@ module DNN
|
|
319
327
|
c ||= Xumo::SFloat.zeros(xs.shape[0], @num_nodes)
|
320
328
|
xs.shape[1].times do |t|
|
321
329
|
x = xs[true, t, false]
|
322
|
-
@
|
323
|
-
h, c = @
|
330
|
+
@hidden_layers[t].trainable = @trainable
|
331
|
+
h, c = @hidden_layers[t].forward(x, h, c)
|
324
332
|
hs[true, t, false] = h
|
325
333
|
end
|
326
334
|
@hidden.data = h
|
@@ -339,7 +347,7 @@ module DNN
|
|
339
347
|
dc = 0
|
340
348
|
(dh2s.shape[1] - 1).downto(0) do |t|
|
341
349
|
dh2 = dh2s[true, t, false]
|
342
|
-
dx, dh, dc = @
|
350
|
+
dx, dh, dc = @hidden_layers[t].backward(dh2 + dh, dc)
|
343
351
|
dxs[true, t, false] = dx
|
344
352
|
end
|
345
353
|
dxs
|
@@ -444,9 +452,10 @@ module DNN
|
|
444
452
|
@recurrent_weight.data = Xumo::SFloat.new(@num_nodes, @num_nodes * 3)
|
445
453
|
@bias.data = Xumo::SFloat.new(@num_nodes * 3) if @bias
|
446
454
|
init_weight_and_bias
|
447
|
-
|
448
|
-
|
449
|
-
|
455
|
+
end
|
456
|
+
|
457
|
+
def create_hidden_layer
|
458
|
+
@hidden_layers = Array.new(@time_length) { GRUDense.new(@weight, @recurrent_weight, @bias) }
|
450
459
|
end
|
451
460
|
end
|
452
461
|
|