2017-10-27 13 views
1

Kerasカスタムレイヤーの仕組みを理解しようとしていました。スカラーの入力を受け取り、それを被乗数で乗算する乗算層を作成しようとしています。ランダムなデータを生成し、被乗数を知りたい。私は10の数字で試してみると、うまく動作します。しかし、私が20の数字で試してみると、その損失は爆発するだけです。Kerasカスタムレイヤーが異常な結果をもたらす

from keras import backend as K 
from keras.engine.topology import Layer 
from keras import initializers 

class MultiplicationLayer(Layer): 
    def __init__(self, **kwargs): 
     super(MultiplicationLayer, self).__init__(**kwargs) 

    def build(self, input_shape): 
     # Create a trainable weight variable for this layer. 
     self.kernel = self.add_weight(name='multiplicand', 
            shape=(1,), 
            initializer='glorot_uniform', 
            trainable=True) 
     self.built = True 

    def call(self, x): 
     return self.kernel*x 

    def compute_output_shape(self, input_shape): 
     return input_shape 

TensorFlowバックエンドの使用。 10の数字

from keras.layers import Input 
from keras.models import Model 

# input is a single scalar 
input = Input(shape=(1,)) 
multiply = MultiplicationLayer()(input) 

model = Model(input, multiply) 
model.compile(optimizer='sgd', loss='mse') 

import numpy as np 
input_data = np.arange(10) 
output_data = 2 * input_data 

model.fit(input_data, output_data, epochs=10) 
#print(model.layers[1].multiplicand.get_value()) 
print(model.layers[1].get_weights()) 

試験モデル1エポック1/10 10/10 [======================= =======] - 7秒 - 損失:257.6145 エポック2/10 10/10 [============ ====] - 0秒 - 損失:47.6329 エポック3/10 10/10 [=============== =] - 0 - 損失:8.8073 エポック4/10 10/10 [===============] 0秒 - 損失:1.6285 エポック5/10 10/10 [===============] - 0秒 - 損失: 0.3011 エポック6/10 10/10 [==============] - 0秒 - 損失:0.0557 エポック7/10 10/10 [================] - 0秒 - 損失:0.0103 エポック8/10 10/10 [==============] - 0秒 - 損失:0.0019 エポック9/10 10/10 [===============] - 0秒 - 損失:3.5193e-04 エポック10/10 10/10 [=================== 0 - 損失:6.5076e-05

[array([ 1.99935019]、dtype = float32)]

モデル2を20個テストするS

from keras.layers import Input 
from keras.models import Model 

# input is a single scalar 
input = Input(shape=(1,)) 
multiply = MultiplicationLayer()(input) 

model = Model(input, multiply) 
model.compile(optimizer='sgd', loss='mse') 

import numpy as np 
input_data = np.arange(20) 
output_data = 2 * input_data 

model.fit(input_data, output_data, epochs=10) 
#print(model.layers[1].multiplicand.get_value()) 
print(model.layers[1].get_weights()) 

エポック1/10 20/20 [==============================] - 0 - 損失:278.2014 エポック2/10 20/20 [==============] - 0秒 - 損失: 601.1653 エポック3/10 20/20 [==============] - 0秒 - 損失:1299.0583 エポック4/10 20/20 [===============] - 0秒 - 損失:2807.1353 エポック5/10 20/20 [=============] - 0秒 - 損失:6065.9375 エポック6/10 20/20 [===============] - 0 - 損失:1310 7.8828 エポック7/10 20/20 [==============] - 0秒 - 損失:28324.8320 エポック8/10 20/20 [==============] - 0秒 - 損失:61207.1250 エポック9/10 20/20 [=============] - 0秒 - 損失:132262.4375 エポック10/10 20/20 [===============] - 0秒 - 損失:285805.9688

[配列([ - 68.71629333] 、dtype = float32)]

これはなぜ起こるのか?

+0

が面白いですね....しかし、あなたは( 'superを呼び出していません。.. ..)。ビルド() '....それは、いくつかの奇妙な振る舞いの原因になる可能性がありますか? –

+1

@DanielMöller私はself.built = Trueは同じことだと思います。私はsuper(...)。build()を使ってみましたが、同じ動作をしました。 – SidML

答えて

1

これは、Adam(lr=0.1)などの別のオプティマイザを使用して解決できます。これは残念なことに100エポックを必要とします....またはSGD(lr = 0.001)のようにSGDの学習率を小さくすることで実現します。

from keras.optimizers import * 

# input is a single scalar 
inp = Input(shape=(1,)) 
multiply = MultiplicationLayer()(inp) 

model = Model(inp, multiply) 
model.compile(optimizer=Adam(lr=0.1), loss='mse') 

import numpy as np 
input_data = np.arange(20) 
output_data = 2 * input_data 

model.fit(input_data, output_data, epochs=100) 
#print(model.layers[1].multiplicand.get_value()) 
print(model.layers[1].get_weights()) 

SGD(lr = 0.01)が噴出しながら、テストはさらに、私は、SGD(lr = 0.001)も働くことに気づきました。

あなたの学習率は、あなたの更新は、それが以前よりも長い距離でポイントを過ぎて行かせるには十分であるならば、次のステップは、さらに大きな勾配を取得します、あなたが過去に行く作る:私があると仮定し何

もう一度、より大きな距離でポイント。唯一の番号と

例:下の学習率と

inputNumber = 20 
x = currentMultiplicand = 1 
targetValue = 40 
lr = 0.01 

#first step (x=1): 
mse = (40-20x)² = 400 
gradient = -2*(40-20x)*20 = -800 
update = - lr * gradient = 8 
new x = 9 

#second step (x=9): 
mse = (40-20x)² = 19600 #(!!!!!) 
gradient = -2*(40-20x)*20 = 5600 
update = - lr * gradient = -56 
new x = -47 
    #you can see from here that this is not going to be contained anymore... 

同じ例、:

inputNumber = 20 
x = currentMultiplicand = 1 
targetValue = 40 
lr = 0.001 

#first step (x=1): 
mse = (40-20x)² = 400 
gradient = -2*(40-20x)*20 = -800 
update = - lr * gradient = 0.8 
new x = 1.8 

#second step (x=1.8): 
mse = (40-20x)² = 16 #(now this is better) 
gradient = -2*(40-20x)*20 = -160 
update = - lr * gradient = 0.16 #(decreasing update sizes....) 
new x = 1.96 
    #you can see from here that this converging... 
+0

大胆な説明@ダニエル・モラーに感謝します。今は理にかなっています! – SidML

関連する問題