Kerasを使用してLSTMを構築し、外部コスト関数を使用して勾配降下法を実行することでLSTMを調整しています。したがって、重みは次のように更新されます。
_weights := weights + alpha* gradient(cost)
_
keras.getweights()
を使用して重みを取得できることはわかっていますが、勾配降下を実行してすべての重みを更新し、それに応じて重みを更新するにはどうすればよいですか。 initializer
を使用しようとしましたが、まだわかりませんでした。 tensorflowで関連するコードをいくつか見つけただけですが、それをKerasに変換する方法がわかりません。
ヘルプ、ヒント、アドバイスはありがたいです!
keras.layer.set_weights()
はあなたが探しているものです:
import numpy as np
from keras.layers import Dense
from keras.models import Sequential
model = Sequential()
model.add(Dense(10, activation='relu', input_shape=(10,)))
model.add(Dense(5, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='categorical_crossentropy')
a = np.array(model.get_weights()) # save weights in a np.array of np.arrays
model.set_weights(a + 1) # add 1 to all weights in the neural network
b = np.array(model.get_weights()) # save weights a second time in a np.array of np.arrays
print(b - a) # print changes in weights
Kerasドキュメンテーションの各ページ here をご覧ください。
シンボリック勾配を計算するには、TensorFlowが必要です。これはKerasを使用したおもちゃの例で、TensorFlowで段階的な降下を手動で実行するために少し掘り下げます。
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras import backend as k
from keras import losses
import numpy as np
import tensorflow as tf
from sklearn.metrics import mean_squared_error
from math import sqrt
model = Sequential()
model.add(Dense(12, input_dim=8, kernel_initializer='uniform', activation='relu'))
model.add(Dense(8, kernel_initializer='uniform', activation='relu'))
model.add(Dense(8, kernel_initializer='uniform', activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
inputs = np.random.random((1, 8))
outputs = model.predict(inputs)
targets = np.random.random((1, 8))
rmse = sqrt(mean_squared_error(targets, outputs))
print("===BEFORE WALKING DOWN GRADIENT===")
print("outputs:\n", outputs)
print("targets:\n", targets)
print("RMSE:", rmse)
def descend(steps=40, learning_rate=100.0, learning_decay=0.95):
for s in range(steps):
# If your target changes, you need to update the loss
loss = losses.mean_squared_error(targets, model.output)
# ===== Symbolic Gradient =====
# Tensorflow Tensor Object
gradients = k.gradients(loss, model.trainable_weights)
# ===== Numerical gradient =====
# Numpy ndarray Objcet
evaluated_gradients = sess.run(gradients, feed_dict={model.input: inputs})
# For every trainable layer in the network
for i in range(len(model.trainable_weights)):
layer = model.trainable_weights[i] # Select the layer
# And modify it explicitly in TensorFlow
sess.run(tf.assign_sub(layer, learning_rate * evaluated_gradients[i]))
# decrease the learning rate
learning_rate *= learning_decay
outputs = model.predict(inputs)
rmse = sqrt(mean_squared_error(targets, outputs))
print("RMSE:", rmse)
if __name__ == "__main__":
# Begin TensorFlow
sess = tf.InteractiveSession()
sess.run(tf.initialize_all_variables())
descend(steps=5)
final_outputs = model.predict(inputs)
final_rmse = sqrt(mean_squared_error(targets, final_outputs))
print("===AFTER STEPPING DOWN GRADIENT===")
print("outputs:\n", final_outputs)
print("targets:\n", targets)
結果:
===BEFORE WALKING DOWN GRADIENT===
outputs:
[[0.49995303 0.5000101 0.50001436 0.50001544 0.49998832 0.49991882
0.49994195 0.4999649 ]]
targets:
[[0.60111501 0.70807258 0.02058449 0.96990985 0.83244264 0.21233911
0.18182497 0.18340451]]
RMSE: 0.33518919408969455
RMSE: 0.05748867468895
RMSE: 0.03369414290610595
RMSE: 0.021872132066183464
RMSE: 0.015070048653579693
RMSE: 0.01164369828903875
===AFTER STEPPING DOWN GRADIENT===
outputs:
[[0.601743 0.707857 0.04268148 0.9536494 0.8448022 0.20864952
0.17241994 0.17464897]]
targets:
[[0.60111501 0.70807258 0.02058449 0.96990985 0.83244264 0.21233911
0.18182497 0.18340451]]