我尝试使用LSTM单元和Tensorflow创建文本生成神经网络。我用时间主要格式[time_steps,batch_size,input_size]训练网络,我希望每一步都能预测一个序列中的下一个单词。序列用空值填充,直至时间步长,单独的占位符包含批次中每个序列的长度。
关于随时间的反向传播的概念有很多信息,但是我无法找到关于可变长度序列成本计算的张量流中的实际实现的任何信息。由于序列的结尾是填充的,我假设我不想计算填充部分的成本。所以我需要一种方法来将输出从第一个输出剪辑到序列的末尾。
这是我目前拥有的代码:
outputs = []
states = []
cost = 0
for i in range(time_steps+1):
output, state = cell(X[i], state)
z1 = tf.matmul(output, dec_W1) + dec_b1
a1 = tf.nn.sigmoid(z1)
z2 = tf.matmul(a1, dec_W2) + dec_b2
a2 = tf.nn.softmax(z2)
outputs.append(a2)
states.append(state)
#== calculate cost
cost = cost + tf.nn.softmax_cross_entropy_with_logits(logits=z2, labels=y[i])
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
此代码不使用可变长度序列。但是,如果我在末尾添加了填充值,那么它也会计算填充部分的成本,这也没有多大意义。
如何才能在序列长度上限之前计算输出的成本?
答案 0 :(得分:0)
解决了!
在深入研究了很多例子(大多数都是在Keras的高级框架中,这是一种痛苦)我发现你必须创建一个面具!回想起来似乎很简单。
这里是创建1&0和0的掩码然后以元素方式将其与矩阵相乘的代码(这将是成本值)
x = tf.placeholder(tf.float32)
seq = tf.placeholder(tf.int32)
def mask_by_length(input_matrix, length):
'''
Input matrix is a 2d tensor [batch_size, time_steps]
length is a 1d tensor
length refers to the length of input matrix axis 1
'''
length_transposed = tf.expand_dims(length, 1)
# Create range in order to compare length to
range = tf.range(tf.shape(input_matrix)[1])
range_row = tf.expand_dims(range, 0)
# Use the logical operations to create a mask
mask = tf.less(range_row, length_transposed)
# cast boolean to int to finalize mask
mask_result = tf.cast(mask, dtype=tf.float32)
# Element-wise multiplication to cancel out values in the mask
result = tf.multiply(mask_result, input_matrix)
return result
mask_values = mask_by_length(x, seq)
输入值(时间 - 主要)[time_steps,batch_size]
[[0.71,0.22,1.42,-0.28,0.99] [0.41,2.24,0.09,0.74,0.65]]
序列值[batch_size]
[2,3]
输出(time-major)[time_steps,batch_size]
[[0.71,0.22,0,0,0,] [0.41,2.24,0.09,0,0,]]