ruby-cntk 0.1.0.pre1 → 0.1.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/cntk/cntk_wrap.cxx +32669 -37956
- data/ext/cntk/extconf.rb +2 -10
- data/lib/cntk/axis.rb +18 -0
- data/lib/cntk/dictionary.rb +62 -0
- data/lib/cntk/function.rb +89 -37
- data/lib/cntk/initializer.rb +67 -0
- data/lib/cntk/inspect.rb +57 -0
- data/lib/cntk/io.rb +50 -0
- data/lib/cntk/layers.rb +17 -0
- data/lib/cntk/learner.rb +197 -0
- data/lib/cntk/ndarrayview.rb +23 -12
- data/lib/cntk/ndmask.rb +8 -0
- data/lib/cntk/ndshape.rb +9 -4
- data/lib/cntk/ops.rb +552 -0
- data/lib/cntk/trainer.rb +59 -0
- data/lib/cntk/value.rb +9 -3
- data/lib/cntk/variable.rb +109 -0
- data/lib/cntk.rb +15 -0
- data/{LICENSE → licenses/LICENSE} +0 -0
- data/licenses/LICENSE_cntk.md +65 -0
- metadata +16 -4
data/ext/cntk/extconf.rb
CHANGED
@@ -1,21 +1,13 @@
|
|
1
|
-
require "rbconfig"
|
2
|
-
|
3
|
-
#RbConfig::MAKEFILE_CONFIG["CXX"] = "clang++-3.8"
|
4
|
-
|
5
1
|
require 'mkmf'
|
6
2
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
3
|
have_library("c++") or have_library("stdc++")
|
11
4
|
|
12
|
-
# have_library("cntklibrary-2.0", nil, nil, " -L /cntk/build/cpu/release/lib/ ")
|
13
5
|
dir_config("cntklibrary-2.0")
|
14
6
|
have_library("cntklibrary-2.0")
|
15
7
|
|
16
8
|
# rake2.3 compile -- --with-cntklibrary-2.0-lib=/cntk/build/cpu/release/lib/ --with-cntklibrary-2.0-include=/cntk/Source/CNTKv2LibraryDll/API/
|
17
9
|
# rake2.3 compile -- --with-cntklibrary-2.0-lib=/cntk/cntk/lib/ --with-cntklibrary-2.0-include=/cntk/Include/
|
18
|
-
|
19
|
-
|
10
|
+
|
11
|
+
$CXXFLAGS = ($CXXFLAGS || "") + " -std=c++11 -O2 -DSWIG -Wl,--whole-archive "
|
20
12
|
|
21
13
|
create_makefile('cntk/CNTK')
|
data/lib/cntk/axis.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
module CNTK
|
2
|
+
|
3
|
+
class DictionaryValue
|
4
|
+
|
5
|
+
def self.create(val)
|
6
|
+
case val
|
7
|
+
when Hash
|
8
|
+
new Dictionary.create(val)
|
9
|
+
when Array
|
10
|
+
v = StdVectorDictionaryValue.new
|
11
|
+
val.each_with_index{|e, idx|
|
12
|
+
v[idx] = create(e)
|
13
|
+
}
|
14
|
+
new( v )
|
15
|
+
else
|
16
|
+
new val
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def value
|
21
|
+
case value_type
|
22
|
+
when Type_Bool
|
23
|
+
value_bool__
|
24
|
+
when Type_Int
|
25
|
+
value_int__
|
26
|
+
when Type_SizeT
|
27
|
+
value_size_t__
|
28
|
+
when Type_Float
|
29
|
+
value_float__
|
30
|
+
when Type_Double
|
31
|
+
value_double__
|
32
|
+
when Type_String
|
33
|
+
value_string__
|
34
|
+
when Type_NDShape
|
35
|
+
value_ndshape__
|
36
|
+
when Type_Axis
|
37
|
+
value_axis__
|
38
|
+
when Type_Vector
|
39
|
+
value_vec_dict_value__
|
40
|
+
when Type_Dictionary
|
41
|
+
value_dict__
|
42
|
+
when Type_NDArrayView
|
43
|
+
value_ndarrayview__
|
44
|
+
else
|
45
|
+
raise "unknown type"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class Dictionary
|
52
|
+
def self.create(h)
|
53
|
+
dict = new()
|
54
|
+
h.each_pair{|k, v|
|
55
|
+
k = k.to_s if k.is_a?(Symbol)
|
56
|
+
dict[k] = DictionaryValue.create(v)
|
57
|
+
}
|
58
|
+
return dict
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
data/lib/cntk/function.rb
CHANGED
@@ -1,61 +1,113 @@
|
|
1
1
|
module CNTK
|
2
|
+
|
2
3
|
class Function
|
3
4
|
|
4
|
-
def
|
5
|
-
|
6
|
-
|
5
|
+
def dot(other)
|
6
|
+
output.dot(other)
|
7
|
+
end
|
8
|
+
|
9
|
+
def -@
|
10
|
+
- output
|
11
|
+
end
|
12
|
+
|
13
|
+
def +(other)
|
14
|
+
output + other
|
15
|
+
end
|
16
|
+
|
17
|
+
def -(other)
|
18
|
+
output - other
|
19
|
+
end
|
20
|
+
|
21
|
+
def *(other)
|
22
|
+
output * other
|
23
|
+
end
|
24
|
+
|
25
|
+
def /(other)
|
26
|
+
output / other
|
27
|
+
end
|
28
|
+
|
29
|
+
# FIXME
|
30
|
+
def coerce(other)
|
31
|
+
if other.is_a?(Numeric)
|
32
|
+
[Constant::scalar(output.get_data_type, other), self]
|
33
|
+
else
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def call(func)
|
39
|
+
if func.respond_to?(:output)
|
40
|
+
val = func.output
|
7
41
|
else
|
8
|
-
|
42
|
+
val = func
|
9
43
|
end
|
44
|
+
if placeholders().length == 1
|
45
|
+
replace_placeholders({placeholders[0] => val})
|
46
|
+
else
|
47
|
+
raise "the number of placeholders is not 1."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# forward function composition self(func(...))
|
52
|
+
def >>(func)
|
53
|
+
func.call(self)
|
54
|
+
end
|
55
|
+
|
56
|
+
def <<(func)
|
57
|
+
call(func)
|
58
|
+
end
|
59
|
+
|
60
|
+
def forward(argsmap, outputs = [], keep_for_backward: [], device: DeviceDescriptor.use_default_device(), remove_dynamic_axes: true)
|
61
|
+
input = convert_to_value(argsmap)
|
62
|
+
out = StdUMapVariableValue.new()
|
63
|
+
outputs.each{|out_var|
|
64
|
+
# By setting nullptr, Forward function implemented in C++ will allocate Value object with required storage.
|
65
|
+
out.__set_nullptr__(out_var)
|
66
|
+
}
|
67
|
+
b = __forward__(input, out, device, keep_for_backward)
|
68
|
+
# FIXME. we will remove this line.
|
69
|
+
out = remove_dynamic_axes(out) if remove_dynamic_axes
|
70
|
+
return [b, out]
|
10
71
|
end
|
11
72
|
|
12
|
-
def
|
13
|
-
if
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
v = NDArrayView.new(CNTK::DataType_Double,
|
20
|
-
required_output_shape(o),
|
21
|
-
required_output_buf(o),
|
22
|
-
CNTK::DeviceDescriptor.default_device(),
|
23
|
-
true)
|
24
|
-
out[o] = Value.new(v)
|
25
|
-
}
|
26
|
-
b = __forward__(input, out)
|
27
|
-
out = remove_dynamic_axes(out)
|
28
|
-
return [out, b]
|
73
|
+
def eval(argsmap=nil, device: DeviceDescriptor.use_default_device(), remove_dynamic_axes: true)
|
74
|
+
argsmap = {} if argsmap == nil
|
75
|
+
_, outmap = forward(argsmap, outputs(), device: device, remove_dynamic_axes: remove_dynamic_axes)
|
76
|
+
if outmap.size > 1
|
77
|
+
outmap
|
78
|
+
else
|
79
|
+
outmap.values[0]
|
29
80
|
end
|
30
81
|
end
|
31
82
|
|
83
|
+
def backward(state, root_gradients, variables, remove_dynamic_axes: true)
|
84
|
+
root_gradients = convert_to_value(root_gradients)
|
85
|
+
out = StdUMapVariableValue.new()
|
86
|
+
variables.each{|var|
|
87
|
+
out.__set_nullptr__(var)
|
88
|
+
}
|
89
|
+
__backward__(state, root_gradients, out)
|
90
|
+
out = remove_dynamic_axes(out)
|
91
|
+
end
|
92
|
+
|
32
93
|
def convert_to_value(h)
|
33
|
-
|
94
|
+
ret = {}
|
34
95
|
h.each_pair{|k,val|
|
35
96
|
if val.respond_to?(:row_major?)
|
36
|
-
|
97
|
+
ret[k] = Value.new(NDArrayView.create(val))
|
37
98
|
else
|
38
|
-
|
99
|
+
ret[k] = val
|
39
100
|
end
|
40
101
|
}
|
41
|
-
return
|
42
|
-
end
|
43
|
-
|
44
|
-
#FIXME
|
45
|
-
# we must add dynamic axes?
|
46
|
-
def required_output_shape(ov)
|
47
|
-
ov.shape().to_a + [1,1]
|
48
|
-
end
|
49
|
-
|
50
|
-
def required_output_buf(ov)
|
51
|
-
[1.0] * ov.shape.total_size
|
102
|
+
return ret
|
52
103
|
end
|
53
104
|
|
54
105
|
def remove_dynamic_axes(out)
|
55
106
|
out1 = {}
|
56
107
|
out.each{|o,ov|
|
57
|
-
|
58
|
-
|
108
|
+
sz = o.dynamic_axes.size
|
109
|
+
if sz > 0 and sz < ov.shape.rank and ov.shape.to_a[0..1] == [1,1]
|
110
|
+
out1[o] = ov.reshape( ov.shape.to_a[sz..-1] )
|
59
111
|
else
|
60
112
|
out1[o] = ov
|
61
113
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module CNTK
|
2
|
+
module Initializer
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def constant
|
6
|
+
CNTK.__constant_initializer__
|
7
|
+
end
|
8
|
+
|
9
|
+
def uniform(scale, seed = CNTK.SentinelValueForAutoSelectRandomSeed)
|
10
|
+
CNTK.__uniform_initializer__(scale, seed)
|
11
|
+
end
|
12
|
+
|
13
|
+
def normal(scale,
|
14
|
+
output_rank: CNTK.SentinelValueForInferParamInitRank,
|
15
|
+
filter_rank: CNTK.SentinelValueForInferParamInitRank,
|
16
|
+
seed: CNTK.SentinelValueForAutoSelectRandomSeed)
|
17
|
+
CNTK.__normal_initializer__(scale, output_rank, filter_rank, seed)
|
18
|
+
end
|
19
|
+
|
20
|
+
def glorot_uniform(scale = CNTK.DefaultParamInitScale,
|
21
|
+
output_rank: CNTK.SentinelValueForInferParamInitRank,
|
22
|
+
filter_rank: CNTK.SentinelValueForInferParamInitRank,
|
23
|
+
seed: CNTK.SentinelValueForAutoSelectRandomSeed)
|
24
|
+
CNTK.__glorot_uniform_initializer__(scale, output_rank, filter_rank, seed)
|
25
|
+
end
|
26
|
+
|
27
|
+
def glorot_normal(scale = CNTK.DefaultParamInitScale,
|
28
|
+
output_rank: CNTK.SentinelValueForInferParamInitRank,
|
29
|
+
filter_rank: CNTK.SentinelValueForInferParamInitRank,
|
30
|
+
seed: CNTK.SentinelValueForAutoSelectRandomSeed)
|
31
|
+
CNTK.__glorot_normal_initializer__(scale, output_rank, filter_rank, seed)
|
32
|
+
end
|
33
|
+
|
34
|
+
def xavier(scale,
|
35
|
+
output_rank: CNTK.SentinelValueForInferParamInitRank,
|
36
|
+
filter_rank: CNTK.SentinelValueForInferParamInitRank,
|
37
|
+
seed: CNTK.SentinelValueForAutoSelectRandomSeed)
|
38
|
+
CNTK.__xavier_initializer__(scale, output_rank, filter_rank, seed)
|
39
|
+
end
|
40
|
+
|
41
|
+
def he_uniform(scale = CNTK.DefaultParamInitScale,
|
42
|
+
output_rank: CNTK.SentinelValueForInferParamInitRank,
|
43
|
+
filter_rank: CNTK.SentinelValueForInferParamInitRank,
|
44
|
+
seed: CNTK.SentinelValueForAutoSelectRandomSeed)
|
45
|
+
CNTK.__he_uniform_initializer__(scale, output_rank, filter_rank, seed)
|
46
|
+
end
|
47
|
+
|
48
|
+
def he_normal(scale = CNTK.DefaultParamInitScale,
|
49
|
+
output_rank: CNTK.SentinelValueForInferParamInitRank,
|
50
|
+
filter_rank: CNTK.SentinelValueForInferParamInitRank,
|
51
|
+
seed: CNTK.SentinelValueForAutoSelectRandomSeed)
|
52
|
+
CNTK.__he_normal_initializer__(scale, output_rank, filter_rank, seed)
|
53
|
+
end
|
54
|
+
|
55
|
+
def bilinear(kernel_width, kernel_height)
|
56
|
+
CNTK.__bilinear_initializer__(kernel_width, kernel_height)
|
57
|
+
end
|
58
|
+
|
59
|
+
def initializer_with_rank(initializer,
|
60
|
+
output_rank: CNTK.SentinelValueForInferParamInitRank,
|
61
|
+
filter_rank: CNTK.SentinelValueForInferParamInitRank)
|
62
|
+
CNTK.__random_initializer_with_rank__(initializer, output_rank, filter_rank)
|
63
|
+
end
|
64
|
+
|
65
|
+
end # class << self
|
66
|
+
end # module Initializer
|
67
|
+
end # module CNT
|
data/lib/cntk/inspect.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module CNTK
|
2
|
+
module InspectUtil
|
3
|
+
def inspect_methods_p(mthds)
|
4
|
+
mthds.map{|mth| "#{mth}=" + send(mth).inspect }.join(", ")
|
5
|
+
end
|
6
|
+
|
7
|
+
def inspect_methods(mthds)
|
8
|
+
s = inspect_methods_p(mthds)
|
9
|
+
"#<#{self.class} #{s}>"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class StdUMapStreamInfoMinibatchData
|
14
|
+
include InspectUtil
|
15
|
+
def inspect
|
16
|
+
s = "{" + map{|k, v| k.inspect + " => " + v.inspect }.join(", ") + "}"
|
17
|
+
"#<#{self.class}: #{s}>"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Axis
|
22
|
+
include InspectUtil
|
23
|
+
def inspect
|
24
|
+
inspect_methods([:name, :is_dynamic_axis])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class NDShape
|
29
|
+
def inspect
|
30
|
+
to_a.inspect
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Value
|
35
|
+
include InspectUtil
|
36
|
+
def inspect
|
37
|
+
inspect_methods([:shape])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class StreamInformation
|
42
|
+
include InspectUtil
|
43
|
+
|
44
|
+
def inspect
|
45
|
+
inspect_methods([:name, :id])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class MinibatchData
|
50
|
+
include InspectUtil
|
51
|
+
|
52
|
+
def inspect
|
53
|
+
inspect_methods([:data, :number_of_samples])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
data/lib/cntk/io.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module CNTK
|
2
|
+
|
3
|
+
def self.create_composite_minibatch_source(dict)
|
4
|
+
if dict.respond_to?(:to_hash)
|
5
|
+
h = {}
|
6
|
+
dict.to_hash.each_pair{|k, v|
|
7
|
+
k = k.to_s if k.is_a?(Symbol)
|
8
|
+
h[k] = v
|
9
|
+
}
|
10
|
+
des = h["deserializers"]
|
11
|
+
unless des.respond_to?(:to_ary)
|
12
|
+
h["deserializers"] = [des]
|
13
|
+
end
|
14
|
+
dict = Dictionary.create(h)
|
15
|
+
end
|
16
|
+
CNTK.__create_composite_minibatch_source__(dict)
|
17
|
+
end
|
18
|
+
|
19
|
+
class MinibatchSource
|
20
|
+
|
21
|
+
# @param minibatch_size_in_samples [Integer]
|
22
|
+
# @param device [DeviceDescriptor]
|
23
|
+
# @param num_data_partitions [Integer]
|
24
|
+
# @param partition_index [Integer]
|
25
|
+
# @return [MinibatchData]
|
26
|
+
def next_minibatch(minibatch_size_in_samples, device: DeviceDescriptor.use_default_device,
|
27
|
+
num_data_partitions: 1, partition_index: 0)
|
28
|
+
get_next_minibatch(0, minibatch_size_in_samples, num_data_partitions, partition_index, device)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
# std::unordered_map<StreamInfo, MinibatchData>
|
34
|
+
class MinibatchTable
|
35
|
+
alias __get__ :[]
|
36
|
+
def [](key)
|
37
|
+
if key.respond_to?(:to_str)
|
38
|
+
key = key.to_str
|
39
|
+
a = self.keys.find_all{|k| k.name == key }
|
40
|
+
if a.size > 1
|
41
|
+
raise "The number of input data having the name is not 1."
|
42
|
+
end
|
43
|
+
__get__(a[0])
|
44
|
+
else
|
45
|
+
__get__(key)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/lib/cntk/layers.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module CNTK
|
2
|
+
module Layers
|
3
|
+
|
4
|
+
module_function
|
5
|
+
|
6
|
+
# @return [Function]
|
7
|
+
def dense(output_shape, init: Initializer.glorot_uniform,
|
8
|
+
input_shape: [CNTK::NDShape::InferredDimension],
|
9
|
+
use_bias: true, init_bias: 0, name: "")
|
10
|
+
_W = Ops.parameter(shape: input_shape + output_shape, init: init, name: "W")
|
11
|
+
b = Ops.parameter(shape: output_shape, init: init_bias, name: "b")
|
12
|
+
x = Ops.placeholder_variable(name: "x")
|
13
|
+
Ops.times(x, _W, output_rank: output_shape.size, infer_input_rank_to_map: 0) + b
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
data/lib/cntk/learner.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
module CNTK
|
2
|
+
|
3
|
+
class Learner
|
4
|
+
LearningRateSchedule = MomentumSchedule
|
5
|
+
MinibatchSizeSchedule = TrainingParameterPerSampleSchedule
|
6
|
+
|
7
|
+
# TrainingParameterPerSampleSchedule == MinibatchSizeSchedule
|
8
|
+
# TrainingParameterPerMinibatchSchedule
|
9
|
+
#
|
10
|
+
class << self
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def create_opt(l1_weight, l2_weight, ga, threshold, truncation)
|
15
|
+
opt = AdditionalLearningOptions.new
|
16
|
+
opt.l1_regularization_weight = l1_weight
|
17
|
+
opt.l2_regularization_weight = l2_weight
|
18
|
+
opt.gaussian_noise_injection_std_dev = ga
|
19
|
+
opt.gradient_clipping_threshold_per_sample = threshold
|
20
|
+
opt.gradient_clipping_with_truncation = truncation
|
21
|
+
|
22
|
+
return opt
|
23
|
+
end
|
24
|
+
|
25
|
+
public
|
26
|
+
|
27
|
+
# @param schedule [Numeric, Array<Numeric>]
|
28
|
+
# @param unit [:sample, :minibatch]
|
29
|
+
# @param epoch_size [Numeric]
|
30
|
+
# @return [TrainingParameterPerSampleSchedule, TrainingParameterPerMinibatchSchedule]
|
31
|
+
def training_parameter_schedule(schedule, unit, epoch_size = nil)
|
32
|
+
case unit
|
33
|
+
when :sample
|
34
|
+
klass = TrainingParameterPerSampleSchedule
|
35
|
+
when :minibatch
|
36
|
+
klass = TrainingParameterPerMinibatchSchedule
|
37
|
+
else
|
38
|
+
raise "unknown unit"
|
39
|
+
end
|
40
|
+
|
41
|
+
if schedule.is_a?(Numeric)
|
42
|
+
unless epoch_size.nil?
|
43
|
+
raise "epoch_size can't be given when schedule is Numeric."
|
44
|
+
else
|
45
|
+
klass.new(schedule)
|
46
|
+
end
|
47
|
+
else
|
48
|
+
if epoch_size.nil?
|
49
|
+
klass.new(schedule)
|
50
|
+
else
|
51
|
+
klass.new(schedule, epoch_size)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param schedule [Numeric, Array<Numeric>]
|
58
|
+
# @param unit [:sample, :minibatch]
|
59
|
+
# @param epoch_size [Numeric]
|
60
|
+
# @return [TrainingParameterPerSampleSchedule, TrainingParameterPerMinibatchSchedule]
|
61
|
+
def momentum_schedule(schedule, unit = :minibatch, epoch_size = nil)
|
62
|
+
training_parameter_schedule(schedule, unit, epoch_size)
|
63
|
+
end
|
64
|
+
|
65
|
+
# @param schedule [Numeric, Array<Numeric>]
|
66
|
+
# @param epoch_size [Numeric]
|
67
|
+
# @return [MomentumAsTimeConstantSchedule]
|
68
|
+
def momentum_as_time_constant_schedule(schedule, epoch_size)
|
69
|
+
klass = MomentumAsTimeConstantSchedule
|
70
|
+
if schedule.is_a?(Numeric)
|
71
|
+
if epoch_size.nil?
|
72
|
+
raise "epoch_size can't be given when schedule is Numeric."
|
73
|
+
else
|
74
|
+
klass.new(schedule)
|
75
|
+
end
|
76
|
+
else
|
77
|
+
if epoch_size.nil?
|
78
|
+
klass.new(schedule)
|
79
|
+
else
|
80
|
+
klass.new(schedule, epoch_size)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @param parameters [Array<Parameter>]
|
86
|
+
# @param lr [TrainingParameterPerSampleSchedule, TrainingParameterPerMinibatchSchedule]
|
87
|
+
# @option opt [Float] :l1_weight
|
88
|
+
# @option opt [Float] :l2_weight
|
89
|
+
# @option opt [Float] :std_dev
|
90
|
+
# @option opt [Float] :threshold
|
91
|
+
# @option opt [Boolean] :truncation
|
92
|
+
# @return [Learner]
|
93
|
+
def sgd(parameters, lr, l1_weight: 0.0, l2_weight: 0.0,
|
94
|
+
std_dev: 0.0, threshold: Float::INFINITY, truncation: true)
|
95
|
+
ga = training_parameter_schedule(std_dev, :minibatch)
|
96
|
+
opt = create_opt(l1_weight, l2_weight, ga, threshold, truncation)
|
97
|
+
CNTK.__sgdlearner__(parameters, lr, opt)
|
98
|
+
end
|
99
|
+
|
100
|
+
# @param parameters [Array<Parameter>]
|
101
|
+
# @param lr [TrainingParameterPerSampleSchedule, TrainingParameterPerMinibatchSchedule]
|
102
|
+
# @param momentum [MomentumSchedule]
|
103
|
+
# @param unit_gain [Boolean]
|
104
|
+
# @option opt [Float] :l1_weight
|
105
|
+
# @option opt [Float] :l2_weight
|
106
|
+
# @option opt [Float] :std_dev
|
107
|
+
# @option opt [Boolean] :truncation
|
108
|
+
# @return [Learner]
|
109
|
+
def momentum_sgd(parameters, lr, momentum, unit_gain: CNTK.default_unit_gain_value(),
|
110
|
+
l1_weight: 0.0, l2_weight: 0.0,
|
111
|
+
std_dev: 0.0, threshold: Float::INFINITY, truncation: true)
|
112
|
+
ga = training_parameter_schedule(std_dev, :minibatch)
|
113
|
+
opt = create_opt(l1_weight, l2_weight, ga, threshold, truncation)
|
114
|
+
CNTK.__momentum_sgd_learner__(parameters, lr, momentum, unit_gain, opt)
|
115
|
+
end
|
116
|
+
|
117
|
+
# @param parameters [Array<Parameter>]
|
118
|
+
# @param lr [TrainingParameterPerSampleSchedule, TrainingParameterPerMinibatchSchedule]
|
119
|
+
# @param momentum [MomentumSchedule]
|
120
|
+
# @param unit_gain [Boolean]
|
121
|
+
# @option opt [Float] :l1_weight
|
122
|
+
# @option opt [Float] :l2_weight
|
123
|
+
# @option opt [Float] :std_dev
|
124
|
+
# @option opt [Boolean] :truncation
|
125
|
+
# @return [Learner]
|
126
|
+
def nesterov(parameters, lr, momentum, unit_gain: CNTK.default_unit_gain_value(),
|
127
|
+
l1_weight: 0.0, l2_weight: 0.0,
|
128
|
+
std_dev: 0.0, threshold: Float::INFINITY, truncation: true)
|
129
|
+
ga = training_parameter_schedule(std_dev, :minibatch)
|
130
|
+
opt = create_opt(l1_weight, l2_weight, ga, threshold, truncation)
|
131
|
+
CNTK.__nesterov_learner__(parameters, lr, momentum, unit_gain, opt)
|
132
|
+
end
|
133
|
+
|
134
|
+
# @param parameters [Array<Parameter>]
|
135
|
+
# @param lr [TrainingParameterPerSampleSchedule, TrainingParameterPerMinibatchSchedule]
|
136
|
+
# @param momentum [MomentumSchedule]
|
137
|
+
# @param unit_gain [Boolean]
|
138
|
+
# @option opt [Float] :l1_weight
|
139
|
+
# @option opt [Float] :l2_weight
|
140
|
+
# @option opt [Float] :std_dev
|
141
|
+
# @option opt [Boolean] :truncation
|
142
|
+
# @return [Learner]
|
143
|
+
def adagrad(parameters, lr, multiplier: true, unit_gain: CNTK.default_unit_gain_value(),
|
144
|
+
l1_weight: 0.0, l2_weight: 0.0,
|
145
|
+
std_dev: 0.0, threshold: Float::INFINITY, truncation: true)
|
146
|
+
ga = training_parameter_schedule(std_dev, :minibatch)
|
147
|
+
opt = create_opt(l1_weight, l2_weight, ga, threshold, truncation)
|
148
|
+
CNTK.__ada_grad_learner__(parameters, lr, multiplier, unit_gain, opt)
|
149
|
+
end
|
150
|
+
|
151
|
+
# @param parameters [Array<Parameter>]
|
152
|
+
# @param lr [TrainingParameterPerSampleSchedule, TrainingParameterPerMinibatchSchedule]
|
153
|
+
# @param momentum [MomentumSchedule]
|
154
|
+
# @param unit_gain [Boolean]
|
155
|
+
# @param variance_momentum [MomentumAsTimeConstantSchedule]
|
156
|
+
# @param low_memory [Boolean]
|
157
|
+
# @option opt [Float] :l1_weight
|
158
|
+
# @option opt [Float] :l2_weight
|
159
|
+
# @option opt [Float] :std_dev
|
160
|
+
# @option opt [Boolean] :truncation
|
161
|
+
# @return [Learner]
|
162
|
+
def adam_sgd(parameters, lr, momentum, unit_gain: CNTK.default_unit_gain_value(),
|
163
|
+
variance_momentum: momentum_as_time_constant_schedule(720000),
|
164
|
+
low_memory: true,
|
165
|
+
l1_weight: 0.0, l2_weight: 0.0,
|
166
|
+
std_dev: 0.0, threshold: Float::INFINITY, truncation: true)
|
167
|
+
ga = training_parameter_schedule(std_dev, :minibatch)
|
168
|
+
opt = create_opt(l1_weight, l2_weight, ga, threshold, truncation)
|
169
|
+
CNTK.__adam_learner__(parameters, lr, momentum, unit_gain, variance_momentum, low_memory, opt)
|
170
|
+
end
|
171
|
+
|
172
|
+
# @param parameters [Array<Parameter>]
|
173
|
+
# @param lr [TrainingParameterPerSampleSchedule, TrainingParameterPerMinibatchSchedule]
|
174
|
+
# @param gamma [Float]
|
175
|
+
# @param inc [Float]
|
176
|
+
# @param dec [Float]
|
177
|
+
# @param max [Float]
|
178
|
+
# @param min [Float]
|
179
|
+
# @param multiplier [Boolean]
|
180
|
+
# @option opt [Float] :l1_weight
|
181
|
+
# @option opt [Float] :l2_weight
|
182
|
+
# @option opt [Float] :std_dev
|
183
|
+
# @option opt [Boolean] :truncation
|
184
|
+
# @return [Learner]
|
185
|
+
def rmsprop(parameters, lr, gamma, inc, dec, max, min,
|
186
|
+
multiplier: true, l1_weight: 0.0, l2_weight: 0.0,
|
187
|
+
std_dev: 0.0, threshold: Float::INFINITY, truncation: true)
|
188
|
+
ga = training_parameter_schedule(std_dev, :minibatch)
|
189
|
+
opt = create_opt(l1_weight, l2_weight, ga, threshold, truncation)
|
190
|
+
CNTK.__rmsprop_learner__(parameters, lr, gamma, inc, dec, max, min, multiplier, opt)
|
191
|
+
end
|
192
|
+
|
193
|
+
end # class << self
|
194
|
+
|
195
|
+
end # class Learner
|
196
|
+
|
197
|
+
end # module CNTK
|
data/lib/cntk/ndarrayview.rb
CHANGED
@@ -2,25 +2,36 @@ module CNTK
|
|
2
2
|
class NDArrayView
|
3
3
|
|
4
4
|
def self.create(a)
|
5
|
-
if a.respond_to?(:shape)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
if a.respond_to?(:shape)
|
6
|
+
case a
|
7
|
+
when NDArrayView
|
8
|
+
return a
|
9
|
+
when Numo::DFloat
|
10
|
+
dtype = DataType_Double
|
11
|
+
when Numo::SFloat
|
12
|
+
dtype = DataType_Float
|
13
|
+
else
|
14
|
+
raise ArgumentError, "Numo::NArray or NDArrayView expected"
|
10
15
|
end
|
11
|
-
return self.new(
|
16
|
+
return self.new(dtype, a.shape, a.flatten.to_a,
|
12
17
|
CNTK::DeviceDescriptor.default_device(), false)
|
13
18
|
else
|
14
|
-
raise "not
|
19
|
+
raise ArgumentError, "not responds to :shape"
|
15
20
|
end
|
16
21
|
end
|
17
22
|
|
18
23
|
def to_narray
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
case get_data_type
|
25
|
+
when DataType_Float
|
26
|
+
klass = Numo::SFloat
|
27
|
+
when DataType_Double
|
28
|
+
klass = Numo::DFloat
|
29
|
+
else
|
30
|
+
raise "unknown data type"
|
31
|
+
end
|
32
|
+
ret = klass[*to_vec()]
|
33
|
+
ret = ret.reshape(*shape().to_a)
|
34
|
+
return ret
|
24
35
|
end
|
25
36
|
|
26
37
|
end
|