我正在使用Keras(Theano后端)构建基于chacter的rnn模型。需要注意的一点是,我不想使用预建的损失功能。相反,我想计算一些数据点的损失。这就是我的意思。
Vectoried训练集及其标签如下所示: X_train = np.array([[0,1,2,3,4]]) y_train = np.array([[1,2,3,4,5]])
但是由于某种原因,我将y_train中的第一个k元素替换为0。所以,例如,新的y_train是
y_train = np.array([[0,0,3,4,5]])
我将前两个元素设置为0的原因是我不想在计算丢失时包含它们。换句话说,我想计算X_train [2:]和y_train [2:]之间的损失。
这是我的尝试。
import numpy as np
np.random.seed(0) # for reproducibility
from keras.preprocessing import sequence
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Embedding
from keras.layers import LSTM
from keras.layers.wrappers import TimeDistributed
X_train = np.array([[0,1,2,3,4]])
y_train = np.array([[0,0,3,4,5]])
y_3d = np.zeros((y_train.shape[0], y_train.shape[1], 6))
for i in range(y_train.shape[0]):
for j in range(y_train.shape[1]):
y_3d[i, j, y_train[i,j]] = 1
model = Sequential()
model.add(Embedding(6, 5, input_length=5, dropout=0.2))
model.add(LSTM(5, input_shape=(5, 12), return_sequences=True) )
model.add(TimeDistributed(Dense(6))) #output classes =6
model.add(Activation('softmax'))
from keras import backend as K
import theano.tensor as T
def custom_objective(y_true,y_pred):
# Find the last index of minimum value in y_true, axis=-1
# For example, y_train = np.array([[0,0,3,4,5]]) in my example, and
# I'd like to calculate the loss only between X_train[3:] and y_train[3:] because the values
# in y_train[:3] (i.e.0) are dummies. The following is pseudo code if y_true is 1-d numpy array, which is not true.
def rindex(y_true):
for i in range(len(y_true), -1, -1):
if y_true(i) == 0:
return i
starting_point = rindex(y_true)
return K.categorical_crossentropy(y_pred[starting_point:], y_true[starting_point:])
model.compile(loss=custom_objective,
optimizer='adam',
metrics=['accuracy'])
model.fit(X_train, y_t, batch_size=batch_size, nb_epoch=1)
答案 0 :(得分:0)
来自第35行中错误的paranthesis和最后一行中错误的变量名称之类的小错误,您的代码存在两个问题。
首先,您定义的模型将返回每个时间步的类的概率分布矩阵(由于softmax激活)。
但是在custom_objective
中,您将输出视为向量。您已经正确地将y_train
转换为上面的矩阵。
因此,您首先必须得到实际的预测,最简单的情况是分配具有最高概率的类,即:
y_pred = y_pred.argmax(axis=2)
y_true = y_true.argmax(axis=2) # this reconstructs y_train resp. a subset thereof
第二个问题是你将这些视为真正的变量(numpy数组)。
但是,y_true
和y_pred
是符号张量。您得到的错误清楚地说明了由此产生的问题之一:
TypeError: object of type 'TensorVariable' has no len()
TensorVariable
没有长度,因为在插入实际值之前根本就不知道!这也使迭代成为你实现它的方式不可能。
顺便说一句,如果你迭代真正的向量,你可能想要这样做:#{1}}向后迭代,不要越界,甚至range(len(y_true)-1, -1, -1)
要实现您的目标,您需要将相应的变量视为它们的含义,并使用为张量提供的方法。
此计算的中心是找到最小值的for val in y_true[::-1]
函数。默认情况下,它返回此最小值的第一个匹配项。
由于您要查找此最小值的最后一次出现,我们需要将其应用于反向张量并将其计算回原始向量的索引。
argmin
可能,您的问题可能会有一个更简单的解决方案,因为您似乎正在尝试实现屏蔽等功能。
您可能需要查看嵌入图层的starting_point = y_true.shape[0] - y_true[::-1].argmin() - 1
标记。不过,这可以在输入端工作。