我正在尝试调试keras我已经构建的模型.似乎我的渐变是爆炸性的,或者有0或者其他类似的除法.当它们通过网络反向传播时能够检查各种梯度将是方便的.像下面这样的东西是理想的:
model.evaluate(np.array([[1,2]]), np.array([[1]])) #gives the loss
model.evaluate_gradient(np.array([[1,2]]), np.array([[1]]), layer=2) #gives the doutput/dloss at layer 2 for the given input
model.evaluate_weight_gradient(np.array([[1,2]]), np.array([[1]]), layer=2) #gives the dweight/dloss at layer 2 for the given input
Run Code Online (Sandbox Code Playgroud) 我有一个完全连接的多层感知器在Keras训练.我给它一个N维特征向量,它预测输入向量的M类中的一个.培训和预测运作良好.现在我想分析输入特征向量的哪个部分实际负责特定类.
例如,让我们说,有两个类A和B,以及输入向量f.向量f属于类A,网络正确地预测它 - 网络的输出是A=1 B=0.因为我有一些领域知识,我知道整个f实际上不负责f归属A,只有内部的某个部分f负责.我想知道神经网络是否捕获了那个.绘制与图像的对应关系,如果图像中I有图像cat(具有一些草背景)并且训练有素的网络正确预测,则网络必须知道整个图像实际上不是图像cat; 网络内部知道cat图像中的位置.同样,在我的情况下,网络知道f它属于哪个部分A.我想知道那是什么部分.
我四处搜索,并相信我想要做的是为我的网络寻找Saliency Maps,以获得给定的输入.那是对的吗?
如果我已经正确理解它,Saliency Maps就是简单的(change in output)/(change in input),只需1个反向传播操作即可找到,其中我找到输出相对于输入的导数.
我在Keras找到了以下代码片段,但我不确定它是否正确:
inp = model.layers[0].get_input()
outp = model.layers[-1].get_output()
max_outp = T.max(outp, axis=1)
saliency = theano.grad(max_outp.sum(), wrt=inp)
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,当计算梯度时,反向传播实际上是在发生吗?输出是输入的非线性函数,因此找到梯度的唯一方法是做backprop.但是在上面的代码中,没有什么可以连接theano和网络,theano如何"了解"网络?据我所知,在使用Theano计算渐变时,我们首先根据输入和输出定义函数.所以theano必须知道非线性函数是什么.我不认为在上面的片段中是真的..
更新:上面的代码不起作用,因为我有一个完全连接的MLP.它给出了一个错误,说"密集对象没有get_output()".我有以下Keras函数,它计算给定输入的网络输出.我想现在找到输入的这个函数的渐变:
get_output = K.function([self.model.layers[0].input],[self.model.layers[-1].output])
Run Code Online (Sandbox Code Playgroud) 作为入门练习,我在Keras中制作了一个非常简单的NN模型为我做一些非线性回归。我在这里上传了我的jupyter notebookit作为要点(在github上正确渲染),这很短而且很关键。
它只适合一维函数y =(x-5)^ 2/25。
我知道Theano和Tensorflow的核心是基于图的派生(渐变)传递框架。利用损失函数相对于权重的梯度进行基于梯度步长的优化是其主要目的。
但是,我想了解的是,如果我得到的东西,在经过训练的模型下,可以为我近似输入相对于输出层的导数(而不是权重或损失函数)。因此,在这种情况下,我希望通过网络的导数图为我确定y'= 2(x-5)/25.0,用于在网络当前训练状态下输入x的指示值。
我在Keras或Theano / TF后端API中是否有任何选择可以做到这一点,还是我需要以某种方式对权重进行自己的链裁(或者可能添加我自己的不可训练的“身份”层或其他东西)?在我的笔记本中,您可以看到我尝试了一些基于到目前为止所能找到的方法,但是并没有取得成功。
具体来说,我有一个具有以下结构的可运行的keras模型:
model = Sequential()
# 1d input
model.add(Dense(64, input_dim=1, activation='relu'))
model.add(Activation("linear"))
model.add(Dense(32, activation='relu'))
model.add(Activation("linear"))
model.add(Dense(32, activation='relu'))
# 1d output
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam', metrics=["accuracy"])
model.fit(x, y,
batch_size=10,
epochs=25,
verbose=0,
validation_data=(x_test, y_test))
Run Code Online (Sandbox Code Playgroud)
我想估计相对于输入x的输出y的导数,例如x = 0.5。
我所有基于搜索过去的答案来提取梯度值的尝试都导致了语法错误。从较高的角度来看,这是Keras的受支持功能,还是任何解决方案都将特定于后端?
我训练了一个神经网络来对正弦函数进行回归,并希望计算相对于输入的一阶和二阶导数。我尝试使用这样的 tf.gradients() 函数(neural_net 是 tf.keras.Sequential 的实例):
prediction = neural_net(x_value)
dx_f = tf.gradients(prediction, x_value)
dx_dx_f = tf.gradients(dx_f, x_value)
Run Code Online (Sandbox Code Playgroud)
x_value 是一个长度为测试大小的数组。然而,这会产生预测和导数。网络的预测(蓝色曲线)基本上准确地捕获了正弦函数,但我必须将一阶导数(橙色)除以 10 倍,将二阶导数(绿色)除以 100 倍,才能得到在同一数量级。因此,一阶导数看起来(重新缩放后)没问题,但二阶导数完全不稳定。由于正弦函数的预测效果非常好,所以这里显然发生了一些有趣的事情。