如何监控Theano / Keras的张量值?
我知道这个问题已经以各种形式提出,但我无法找到任何我能理解和使用的答案。 所以如果这是一个基本问题,请原谅我,因为我是这些工具的新手(theano / keras)
解决问题
监视神经网络中的变量(例如LSTM中的输入/忘记/输出门值)
我目前正在获得什么
无论我在哪个阶段获得这些价值观,我都会得到如下的东西:
Elemwise{mul,no_inplace}.0
Elemwise{mul,no_inplace}.0
[for{cpu,scan_fn}.2, Subtensor{int64::}.0, Subtensor{int64::}.0]
[for{cpu,scan_fn}.2, Subtensor{int64::}.0, Subtensor{int64::}.0]
Subtensor{int64}.0
Subtensor{int64}.0
有什么办法我不能监视(例如打印到标准输出,写入文件等)他们?
可能的方案
似乎Keras中的回调可以完成这项工作,但它对我来说不起作用。 我得到了和上面一样的东西
我猜
好像我犯了非常简单的错误。
大家提前非常感谢你。
添加
具体来说,我试图监视LSTM中的输入/忘记/输出门控值。 我发现LSTM.step()用于计算这些值:
def step(self, x, states):
h_tm1 = states[0] # hidden state of the previous time step
c_tm1 = states[1] # cell state from the previous time step
B_U = states[2] # dropout matrices for recurrent units?
B_W = states[3] # dropout matrices for input units?
if self.consume_less == 'cpu': # just cut x into 4 pieces in columns
x_i = x[:, :self.output_dim]
x_f = x[:, self.output_dim: 2 * self.output_dim]
x_c = x[:, 2 * self.output_dim: 3 * self.output_dim]
x_o = x[:, 3 * self.output_dim:]
else:
x_i = K.dot(x * B_W[0], self.W_i) + self.b_i
x_f = K.dot(x * B_W[1], self.W_f) + self.b_f
x_c = K.dot(x * B_W[2], self.W_c) + self.b_c
x_o = K.dot(x * B_W[3], self.W_o) + self.b_o
i = self.inner_activation(x_i + K.dot(h_tm1 * B_U[0], self.U_i))
f = self.inner_activation(x_f + K.dot(h_tm1 * B_U[1], self.U_f))
c = f * c_tm1 + i * self.activation(x_c + K.dot(h_tm1 * B_U[2], self.U_c))
o = self.inner_activation(x_o + K.dot(h_tm1 * B_U[3], self.U_o))
with open("test_visualization.txt", "a") as myfile:
myfile.write(str(i)+"n")
h = o * self.activation(c)
return h, [h, c]
因为它在上面的代码中,我试图将我的值写入文件,但它只给了我这样的值:
Elemwise{mul,no_inplace}.0
[for{cpu,scan_fn}.2, Subtensor{int64::}.0, Subtensor{int64::}.0]
Subtensor{int64}.0
所以我尝试了deceval()或i.get_value(),但都没有给我价值。
.eval()给了我这个:
theano.gof.fg.MissingInputError: An input of the graph, used to compute Subtensor{::, :int64:}(<TensorType(float32, matrix)>, Constant{10}), was not provided and not given a value.Use the Theano flag exception_verbosity='high',for more information on this error.
和.get_value()给了我这个:
AttributeError: 'TensorVariable' object has no attribute 'get_value'
所以我回溯了那些连锁店(这些连锁店呼吁哪些功能......),并试图在我发现的每一个步骤都获得价值,但徒劳无功。
感觉像我在一些基本的陷阱。
我使用Keras FAQ中描述的解决方案:
http://keras.io/getting-started/faq/#how-can-i-visualize-the-output-of-an-intermediate-layer
详细:
from keras import backend as K
intermediate_tensor_function = K.function([model.layers[0].input],[model.layers[layer_of_interest].output])
intermediate_tensor = intermediate_tensor_function([thisInput])[0]
收益率:
array([[ 3., 17.]], dtype=float32)
不过,我想使用功能API,但我似乎无法得到实际的张量,只有符号表示。 例如:
model.layers[1].output
收益率:
<tf.Tensor 'add:0' shape=(?, 2) dtype=float32>
我错过了Keras和Tensorflow的交互,但我不确定是什么。 任何洞察力非常感谢。
一种解决方案是创建一个网络版本,该版本在要监视其门值的LSTM层处截断,然后用一个自定义图层替换原始图层,在该图层中修改了stepfunction,以便不仅返回隐藏图层值,但也是门值。
例如,假设您想要访问GRU的门限值。 创建一个自定义图层GRU2,该图层继承GRU类的所有内容,但要调整step函数,使其返回要监视的状态的级联,然后在计算下一次激活时只取得包含以前隐藏层激活的部分。 即:
def step(self, x, states):
# get prev hidden layer from input that is concatenation of
# prev hidden layer + reset gate + update gate
x = x[:self.output_dim, :]
###############################################
# This is the original code from the GRU layer
#
h_tm1 = states[0] # previous memory
B_U = states[1] # dropout matrices for recurrent units
B_W = states[2]
if self.consume_less == 'gpu':
matrix_x = K.dot(x * B_W[0], self.W) + self.b
matrix_inner = K.dot(h_tm1 * B_U[0], self.U[:, :2 * self.output_dim])
x_z = matrix_x[:, :self.output_dim]
x_r = matrix_x[:, self.output_dim: 2 * self.output_dim]
inner_z = matrix_inner[:, :self.output_dim]
inner_r = matrix_inner[:, self.output_dim: 2 * self.output_dim]
z = self.inner_activation(x_z + inner_z)
r = self.inner_activation(x_r + inner_r)
x_h = matrix_x[:, 2 * self.output_dim:]
inner_h = K.dot(r * h_tm1 * B_U[0], self.U[:, 2 * self.output_dim:])
hh = self.activation(x_h + inner_h)
else:
if self.consume_less == 'cpu':
x_z = x[:, :self.output_dim]
x_r = x[:, self.output_dim: 2 * self.output_dim]
x_h = x[:, 2 * self.output_dim:]
elif self.consume_less == 'mem':
x_z = K.dot(x * B_W[0], self.W_z) + self.b_z
x_r = K.dot(x * B_W[1], self.W_r) + self.b_r
x_h = K.dot(x * B_W[2], self.W_h) + self.b_h
else:
raise Exception('Unknown `consume_less` mode.')
z = self.inner_activation(x_z + K.dot(h_tm1 * B_U[0], self.U_z))
r = self.inner_activation(x_r + K.dot(h_tm1 * B_U[1], self.U_r))
hh = self.activation(x_h + K.dot(r * h_tm1 * B_U[2], self.U_h))
h = z * h_tm1 + (1 - z) * hh
#
# End of original code
###########################################################
# concatenate states you want to monitor, in this case the
# hidden layer activations and gates z and r
all = K.concatenate([h, z, r])
# return everything
return all, [h]
(请注意,我添加的唯一行在函数的开头和结尾)。
如果你使用GRU2作为最后一层而不是GRU运行你的网络(对于GRU2层,return_sequences = True),你可以在你的网络上调用预测,这会给你所有隐藏的层和门的值。
同样的事情对于LSTM也是一样,尽管你可能需要弄清楚如何在一个向量中存储你想要的所有输出并在之后再次检索它们。
希望有所帮助!
您可以在执行期间使用theano的打印模块进行打印(而不是在定义期间,这就是您正在做的以及您没有获取值的原因,但是它们的抽象定义)。
打印
只需使用Print
功能。 不要忘记使用Print
的输出来继续您的图形 ,否则输出将断开连接,并且在优化期间很可能会删除Print。 你什么也看不到。
from keras import backend as K
from theano.printing import Print
def someLossFunction(x, ref):
loss = K.square(x - ref)
loss = Print('Loss tensor (before sum)')(loss)
loss = K.sum(loss)
loss = Print('Loss scalar (after sum)')(loss)
return loss
情节
你可能会喜欢的一点奖励。
Print类具有global_fn
参数,以覆盖要打印的默认回调。 您可以提供自己的功能并直接访问数据,以构建一个图例。
from keras import backend as K
from theano.printing import Print
import matplotlib.pyplot as plt
curve = []
# the callback function
def myPlottingFn(printObj, data):
global curve
# Store scalar data
curve.append(data)
# Plot it
fig, ax = plt.subplots()
ax.plot(curve, label=printObj.message)
ax.legend(loc='best')
plt.show()
def someLossFunction(x, ref):
loss = K.sum(K.square(x - ref))
# Callback is defined line below
loss = Print('Loss scalar (after sum)', global_fn=myplottingFn)(loss)
return loss
顺便说一句,您传递给Print('...')的字符串存储在属性名称message
下的打印对象中(请参阅函数myPlottingFn
)。 这对自动构建多曲线图很有用
上一篇: How to monitor tensor values in Theano/Keras?
下一篇: IDF of a query?