keras打印loss对权重的导数方式

  • Post category:Python

首先,需要明确一点,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])

运行训练的过程中,回调函数将会打印出模型中所有参数的梯度信息。