【问题标题】:Using Keras LSTM to predict a single example after using batch training使用批量训练后使用 Keras LSTM 预测单个示例
【发布时间】:2017-08-15 03:20:21
【问题描述】:

我有一个使用批量训练进行训练的网络模型。训练完成后,我想预测单个示例的输出。

这是我的型号代码:

model = Sequential()
model.add(Dense(32, batch_input_shape=(5, 1, 1)))
model.add(LSTM(16, stateful=True))
model.add(Dense(1, activation='linear'))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])

我有一系列单个输入到单个输出。我正在做一些测试代码来将字符映射到下一个字符(A->B、B->C 等)。

我创建一个形状为 (15,1,1) 的输入数据和一个形状为 (15, 1) 的输出数据并调用函数:

model.fit(x, y, nb_epoch=epochs, batch_size=5, shuffle=False, verbose=0)

模型训练,现在我想取一个字符并预测下一个字符(输入 A,它预测 B)。我创建一个形状 (1, 1, 1) 的输入并调用:

pred = model.predict(x, batch_size=1, verbose=0)

这给出了:

ValueError: Shape mismatch: x has 5 rows but z has 1 rows

我看到一种解决方案是将“虚拟数据”添加到您的预测值中,因此预测的输入形状将是 (5,1,1) 和数据 [x 0 0 0 0],您只需采用输出的第一个元素作为您的值。但是,在处理较大的批次时,这似乎效率低下。

我还尝试从模型创建中删除批量大小,但收到以下消息:

ValueError: If a RNN is stateful, a complete input_shape must be provided (including batch size).

还有其他方法吗?感谢您的帮助。

【问题讨论】:

    标签: neural-network keras lstm recurrent-neural-network


    【解决方案1】:

    目前(Keras v2.0.8)在批量训练后获得单行预测需要更多的努力。

    基本上,batch_size 在训练时是固定的,在预测时必须相同。

    目前的解决方法是从经过训练的模型中获取权重,并将其用作您刚刚创建的新模型中的权重,该模型的 batch_size 为 1。

    快速代码是

    model = create_model(batch_size=64)
    mode.fit(X, y)
    weights = model.get_weights()
    single_item_model = create_model(batch_size=1)
    single_item_model.set_weights(weights)
    single_item_model.compile(compile_params)
    

    这是一篇更深入的博文: https://machinelearningmastery.com/use-different-batch-sizes-training-predicting-python-keras/

    我过去曾使用这种方法在预测时拥有多个模型——一个对大批量进行预测,一个对小批量进行预测,一个对单个项目进行预测。由于批量预测效率更高,这使我们可以灵活地接受任意数量的预测行(不仅仅是可以被 batch_size 整除的数字),同时仍然可以非常快速地获得预测。

    【讨论】:

    • 我知道这已经过时了,但你知道在此期间是否发生了一些变化吗?
    【解决方案2】:

    @ClimbsRocks 展示了一个很好的解决方法。从“这就是 Keras 打算如何完成”的意义上,我无法提供“正确”的答案,但我可以分享另一种解决方法,这可能会根据用例对某人有所帮助。

    在这个解决方法中,我使用predict_on_batch()。此方法允许从批次中传递单个样本而不会引发错误。不幸的是,它根据训练设置返回目标形状的向量。但是,目标中的每个样本都会产生单个样本的预测。

    你可以这样访问它:

    to_predict = #Some single sample that would be part of a batch (has to have the right shape)#
    model.predict_on_batch(to_predict)[0].flatten() #Flatten is optional
    

    预测结果与将整个批次传递给predict() 完全相同。


    这里有一些鳕鱼示例。 代码来自my question,它也处理这个问题(但方式略有不同)。

    sequence_size      = 5
    number_of_features = 1
    input              = (sequence_size, number_of_features)
    batch_size         = 2
    
    model = Sequential()
    
    #Of course you can replace the Gated Recurrent Unit with a LSTM-layer
    model.add(GRU(100, return_sequences=True, activation='relu', input_shape=input, batch_size=2, name="GRU"))
    model.add(GRU(1, return_sequences=True, activation='relu', input_shape=input, batch_size=batch_size, name="GRU2"))
    model.compile(optimizer='adam', loss='mse')
    
    model.summary()
    
    #Summary-output:
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    GRU (GRU)                    (2, 5, 100)               30600     
    _________________________________________________________________
    GRU2 (GRU)                   (2, 5, 1)                 306       
    =================================================================
    Total params: 30,906
    Trainable params: 30,906
    Non-trainable params: 0
    
    
    def generator(data, batch_size, sequence_size, num_features):
        """Simple generator"""
        while True:
            for i in range(len(data) - (sequence_size * batch_size + sequence_size) + 1):
                start = i
                end   = i + (sequence_size * batch_size)
    
                yield data[start : end].reshape(batch_size, sequence_size, num_features), \
                        data[end - ((sequence_size * batch_size) - sequence_size) : end + sequence_size].reshape(batch_size, sequence_size, num_features)
    
    #Task: Predict the continuation of a linear range
    data = np.arange(100)
    hist = model.fit_generator(
                    generator=generator(data, batch_size, sequence_size, num_features),
                    steps_per_epoch=total_batches,
                    epochs=200,
                    shuffle=False
                )
    
    to_predict = np.asarray([[np.asarray([x]) for x in range(95,100,1)]]) #Only single element of a batch
    correct    = np.asarray([100,101,102,103,104])
    print( model.predict_on_batch(to_predict)[0].flatten() )
    
    #Output:
    [ 99.92908 100.95854 102.32129 103.28584 104.20213 ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 2019-11-25
      • 2018-01-30
      • 1970-01-01
      • 1970-01-01
      • 2020-12-16
      相关资源
      最近更新 更多