Keras顺序时间分布模型在2和3个序列之间的极端结果差异

时间:2017-03-02 15:09:10

标签: python deep-learning keras recurrent-neural-network sequential

我有2个模型,我在2个基本相同的自制数据集上进行训练。一个序列长度为1,一个序列长度为2.在第一种情况下,它像一个魅力一样进行传播,并且实际上计算出我的生成过程,第二种情况它比机会好一点。我做错了什么?任何事情都可能有所帮助。

数据生成代码

def make_other_date(samples = 720,sequence = 1, features =100):
    y_train = np.zeros((samples,sequence, 2))
    x_train = np.random.randint(2, size=(samples, sequence, features))
    for  i_sample in range(samples):
        for i_sequence in range(sequence):

                if np.sum(x_train[i_sample,i_sequence,:]) > 50:

                    y_train[i_sample,:,:] = np.array([0,1])
                else:
                    y_train[i_sample,:,:] = np.array([1,0])


    return x_train-0.5,y_train #-0.5 to make mean = 0 

nsequence = 1
x_train, y_train = make_other_date(36000,sequence = nsequence)
x_val, y_val = make_other_date(360,sequence = nsequence)
print(x_train.shape,y_train.shape)#(36000, 1, 100) (36000, 1, 2)

模型

model = Sequential()
model.add(TimeDistributed(Dense(10), batch_input_shape=(None,nsequence,100)))
model.add(TimeDistributed(Dense(10))) #unnessacery 
model.add(TimeDistributed(Dense(2)))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
print (model.output_shape) #(None, 1, 2)

结果nsequence = 1

Epoch 10/10
28800/28800 [==============================] - 3s - loss: 3.4264e-05 - val_loss: 2.4744e-05

结果nsequence = 2

Epoch 10/10
28800/28800 [==============================] - 3s - loss: 0.6053 - val_loss: 0.6042

1 个答案:

答案 0 :(得分:1)

问题的形成有问题。我将尝试向您解释为什么您的示例无法正常工作,如果您愿意,您可以再制作另一个示例。

在数据部分,生成数据集时:

for i_sequence in range(sequence):
    if np.sum(x_train[i_sample,i_sequence,:]) > 50:
        y_train[i_sample,:,:] = np.array([0,1])
    else:
        y_train[i_sample,:,:] = np.array([1,0])

仅根据此序列的最后一个元素定义整个序列的目标。 y_train[i_sample,0,:]将被循环的最后一个操作覆盖,因为每次按顺序前进时都会更新y_train[i_sample,:,:]

所以:你有一个整个序列的目标,它只取决于这个序列的最后一个元素。

现在在模型部分:

您的模型仅由TimeDistributed(Dense())层组成。根据{{​​3}},这是一个包装器,它在序列的每个元素上应用相同的密集层。那些密集的图层共享权重,因此将应用于序列的第一个元素的图层与应用于最后一个元素的图层完全相同。

现在,如果您考虑一下:要确定要应用于序列的第一个元素的目标,您的网络需要知道最后一个元素发生了什么,因为您以这种方式定义了数据集。

想象一下你的一个序列 - 调用它seq_i-就是这样

np.sum(x_train[seq_i,0,:]) = 52
np.sum(x_train[seq_i,1,:]) = 49

那么这个序列的目标是

y_train[seq_i,0] = [1,0]
y_train[seq_i,1] = [1,0]

假设密集层能够预测目标[1,0],如果输入是< 50,就像你想要它作为序列的第二个元素一样。由于您将相同的图层应用于序列的第一个元素,因此它将为该元素预测[0,1]并在训练阶段对其进行惩罚。它会来回走动,不会学到任何东西。

清楚吗?