首页 > 解决方案 > 批量大小 = 1 和可变时间步长误差的 LSTM

问题描述

大家好,我正在尝试使用 batch_size = 1 训练我的 LSTM 模型。输入是一个二维数组列表,每个数组都包含可变时间步长,因为每个音频都有不同的长度和固定数量的特征,所以列表的每个元素看起来像这样(Tx,Number_of 特征)。例如(随机):

X=[]
for i in range(0,420):
   X.append(np.random.rand(np.random.randint(1,10),12))

y = np.random.rand(420)
y = to_categorical(Y,num_classes=5)

我尝试按如下方式传递输入:

def rnn(X,y):

model = Sequential()
model.add(LSTM(128, input_shape=(None, X[0].shape[1])))
model.add(Dense(32, activation='relu'))
model.add(Dense(5, activation='softmax'))
opt = tf.keras.optimizers.Adam(lr=1e-3, decay=1e-5)
model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])

model.fit(X, y, epochs=3,batch_size=1,validation_split=0.3)

但是我收到以下错误:

 File "C:\Users\mp95\PycharmProjects\Thesis\venv\lib\site-packages\tensorflow_core\python\keras\engine\training_utils.py", line 573, in standardize_input_data
    'with shape ' + str(data_shape))
ValueError: Error when checking input: expected lstm_input to have 3 dimensions, but got array with shape (86, 12)

我认为我必须按如下方式重塑列表的每个元素(1,Tx,number_of_features),所以我这样做了:

def rnn(X,y):
for s,x in enumerate(X):
    seq_len = x.shape[0]
    X[s]=np.reshape(X[s],(1,seq_len,x.shape[1]))

model = Sequential()
model.add(LSTM(128, input_shape=(None, X[0].shape[2])))
model.add(Dense(32, activation='relu'))
model.add(Dense(5, activation='softmax'))
opt = tf.keras.optimizers.Adam(lr=1e-3, decay=1e-5)
model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])

model.fit(X, y, epochs=3,batch_size=1,validation_split=0.3)

但我似乎无法让它发挥作用:

File "C:\Users\mp95\PycharmProjects\Thesis\venv\lib\site-packages\tensorflow_core\python\keras\engine\training_utils.py", line 744, in check_array_lengths
    'and ' + str(list(set_y)[0]) + ' target samples.')
ValueError: Input arrays should have the same number of samples as target arrays. Found 1 input samples and 420 target samples.

如何以可变时间步长提供样本?我发现了一些类似的问题,但无法真正让它发挥作用。

编辑:添加了随机参数初始化以实现最小的可重复性,如评论中指出的那样

标签: pythontensorflowkerasdeep-learningneural-network

解决方案


您应该使用train_on_batch而不是fit.

fit将尝试创建一个具有一致维度的 numpy 数组,这在您的情况下将是一个问题。

fit您可以使用train_on_bacthpredict_on_batch和编写自己的自定义test_on_batch

def train_task(simple_conv, X, y_ohe, EPOCH, train_split=1.0):
    # single zero padding for NULL datas


    report_acc = 0.0
    for epoch in range(EPOCH):
        print(f'Training epoch {epoch} ...')
        avg_loss = 0.0
        avg_acc = 0.0
        avg_mae = 0.0

        for sample_i in tqdm(range(int(len(X)*train_split))):
            [train_loss, acc, mae]   =  simple_conv.train_on_batch(X[sample_i].reshape(1,X[sample_i].shape[0], X[sample_i].shape[1]), 
 , 
                                        y_ohe[sample_i].reshape(1,5))
            avg_loss += train_loss/(len(X)*train_split)
            avg_acc += acc/(len(X)*train_split)
            avg_mae += mae/(len(X)*train_split)
        report_acc = avg_acc
        print(f'f1: {avg_acc} mae: {avg_mae} loss: {avg_loss}')
        #print('Running validation ...')
        avg_loss = 0.0
        avg_acc = 0.0
        avg_mae = 0.0

    return simple_conv, report_acc

这是一个做类似事情的仓库(也包括一篇论文):https ://github.com/zabir-nabil/activity-recognition-abc


推荐阅读