首先,需要明确一点,Keras只提供了计算loss对权重的导数的接口,并没有直接打印导数的方法。
要打印loss对权重的导数,需要使用Keras中的回调函数(Callback)。回调函数可以在每个epoch结束或每个batch结束时调用。我们需要自定义一个回调函数,在回调函数中打印loss对权重的导数。
下面是打印loss对权重的梯度的完整攻略。
定义回调函数
import numpy as np
import keras.backend as K
from keras.callbacks import Callback
class PrintWeightsGradient(Callback):
def __init__(self, model):
super(PrintWeightsGradient, self).__init__()
self.model = model
def on_batch_end(self, batch, logs=None):
weights = self.model.trainable_weights
gradients = self.model.optimizer.get_gradients(self.model.total_loss, weights)
weights_names = [w.name for w in weights]
gradient_values = self.model.sess.run(gradients, feed_dict=self.model._feed_dict)
for name, value in zip(weights_names, gradient_values):
print('weight name: {}, gradient: {}'.format(name, value))
上面的代码定义了一个名为PrintWeightsGradient的回调函数,继承了Keras的Callback类。在on_batch_end函数中,计算了loss对所有可训练权重的导数,然后打印出权重名称和对应的导数值。
需要注意的是,获取导数值需要调用session的run方法,需要在fit之前需要将model的session属性赋值为K.get_session()。
在训练过程中使用回调函数
创建模型后,可以使用定义好的回调函数进行训练。例如:
from keras.models import Sequential
from keras.layers import Dense
X = np.random.rand(1000, 10)
y = np.random.rand(1000, 1)
model = Sequential()
model.add(Dense(16, input_dim=10, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print_weights_gradient_callback = PrintWeightsGradient(model)
history = model.fit(X, y, epochs=10, batch_size=32, callbacks=[print_weights_gradient_callback])
在fit函数中,将定义好的回调函数传入callbacks参数中,即可在训练过程中调用回调函数。
示例说明
示例1
对于一个简单的线性回归模型,例如:
from keras.models import Sequential
from keras.layers import Dense
X = np.array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
y = np.array([[3], [7], [11], [15]])
model = Sequential()
model.add(Dense(1, input_dim=2))
model.compile(loss='mean_squared_error', optimizer='adam')
print_weights_gradient_callback = PrintWeightsGradient(model)
history = model.fit(X, y, epochs=10, batch_size=1, callbacks=[print_weights_gradient_callback])
运行训练的过程中,回调函数将会打印出模型中所有参数的梯度信息。
示例2
对于一个简单的分类任务,例如:
from keras.models import Sequential
from keras.layers import Dense
X = np.random.rand(100, 10)
y = np.random.randint(0, 2, size=(100, 1))
model = Sequential()
model.add(Dense(16, input_dim=10, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print_weights_gradient_callback = PrintWeightsGradient(model)
history = model.fit(X, y, epochs=10, batch_size=32, callbacks=[print_weights_gradient_callback])
运行训练的过程中,回调函数将会打印出模型中所有参数的梯度信息。