【问题标题】:Keras: Predicting New Values using predict_generatorKeras:使用 predict_generator 预测新值
【发布时间】:2020-04-30 09:00:15
【问题描述】:

目前,我正在尝试使用 Keras 中的温度预测示例(如 F. Chollet 的“Python 深度学习”一书的第 6.3 章中所述)。我在使用指定的生成器进行预测时遇到了一些问题。我的理解是我应该使用model.predict_generator 进行预测,但我不确定如何为该方法使用steps 参数,以及如何获取原始数据正确“形状”的预测。

理想情况下,我希望能够绘制测试集(索引 300001 直到结束)并绘制我对该测试集的预测(即具有预测值的相同长度的数组)。

示例(此处提供数据集:https://s3.amazonaws.com/keras-datasets/jena_climate_2009_2016.csv.zip)如下:

import numpy as np

# Read in data
fname = ('jena_climate_2009_2016.csv')
f = open(fname)
data = f.read()
f.close()
lines = data.split('\n')
col_names = lines[0].split(',')
col_names = [i.replace('"', "") for i in col_names]

# Normalize the data
float_data = np.array(df.iloc[:, 1:])
temp = float_data[:, 1]
mean = float_data[:200000].mean(axis=0)
float_data -= mean
std = float_data[:200000].std(axis=0)
float_data /= std

def generator(data, lookback, delay, min_index, max_index, shuffle=False, batch_size=128, step=6):
    if max_index is None:
        max_index = len(data) - delay - 1
    i = min_index + lookback
    while 1:
        if shuffle:
            rows = np.random.randint(
                min_index + lookback, max_index, size=batch_size)
        else:
            if i + batch_size >= max_index:
                i = min_index + lookback
            rows = np.arange(i, min(i + batch_size, max_index))
            i += len(rows)
        samples = np.zeros((len(rows), 
                            lookback // step,
                            data.shape[-1]))
        targets = np.zeros((len(rows),))
        for j, row in enumerate(rows):
            indices = range(rows[j] - lookback, rows[j], step)
            samples[j] = data[indices]
            targets[j] = data[rows[j] + delay][1]
        yield(samples, targets)

lookback = 720
step = 6
delay = 144

train_gen = generator(float_data, lookback=lookback, delay=delay, 
                      min_index=0, max_index=200000, shuffle=True,
                      step=step, batch_size=batch_size)

val_gen = generator(float_data, lookback=lookback, delay=delay, 
                    min_index=200001, max_index=300000, step=step,
                    batch_size=batch_size)

test_gen = generator(float_data, lookback=lookback, delay=delay, 
                     min_index=300001, max_index=None, step=step, 
                     batch_size=batch_size)

val_steps = (300000 - 200001 - lookback)
test_steps = (len(float_data) - 300001 - lookback)

from keras.models import Sequential
from keras import layers
from keras.optimizers import RMSprop

model = Sequential()
model.add(layers.Flatten(input_shape=(lookback // step, float_data.shape[-1])))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(1))

model.compile(optimizer=RMSprop(), loss='mae')
model.fit_generator(train_gen, steps_per_epoch=500,
                              epochs=20, validation_data=val_gen,
                              validation_steps=val_steps)

在网上搜索了一番后,我尝试了一些类似于以下的技术:

pred = model.predict_generator(test_gen, steps=test_steps // batch_size)

但是,我返回的预测数组太长了,根本与我的原始数据不匹配。有人有什么建议吗?

【问题讨论】:

    标签: python machine-learning keras prediction


    【解决方案1】:

    对于现在正在查看该问题的任何人,当使用 predict_generator 用于较新版本的 keras 时,我们不需要指定 steps 参数。参考:https://github.com/keras-team/keras/issues/11902

    如果提供了一个值,将生成step*batch_size 示例的预测。如 OP 所述,这可能会导致排除 len(test)%batch_size 行。 另外,在我看来,设置batch_size=1 违背了使用生成器的目的,因为它相当于一个一个地迭代测试数据。 同样设置steps=1(当test_generator中没有设置batch_size时)会一次性读取整个测试数据,对于大的测试数据并不理想。

    【讨论】:

      【解决方案2】:

      predict_generator 中,steps 将测试路径中的图像数量除以test_gen 中提供的任何批量大小
      例如:我有50 图像,我提供的批量大小为10,而不是步骤5

      #first seperate the `test images` and `test labels`
       test_images,test_labels = next(test_gen)
      
      #get the class indices
       test_labels = test_labels[:,0]  #this should give you array of labels
      
      predictions = model.predict_generator(test_gen,steps = number of images/batchsize,verbose=0)
      
      predictions[:,0]  #this is your actual predictions  
      

      【讨论】:

      • 感谢您的回答。不幸的是,对于我尝试使用的数据集,它不是图像数据而是时间序列。如果我尝试像上面那样分成datalabels,那么我的labels 数组将具有(128,) 的形状,即与batch_size 相同。那么我当然不能使用你的下一行代码来获取类索引,因为形状不匹配
      【解决方案3】:

      您的原始代码看起来正确:

      pred = model.predict_generator(test_gen, steps=test_steps // batch_size)
      

      我尝试生成长度约为 120k 的 pred 并没有发现任何问题。你买了什么尺寸的?

      实际上代码中的两个步骤都不正确。它们应该是:

      val_steps = (300000 - 200001 - lookback) // batch_size
      test_steps = (len(float_data) - 300001 - lookback) // batch_size
      

      (您的验证在每个 epoch 中运行的时间不是很长吗?)

      当然,有了这个更正,你可以简单地使用

      pred = model.predict_generator(test_gen, steps=test_steps)
      

      【讨论】:

      • val_stepstest_steps 我直接取自提到的书(第 212 页),两者均未除以 batch_size。我的验证确实需要永远为每个时代运行,是的!我的pred 的长度是test_steps - (test_steps % batch_size),即119808。我的问题是我希望pred 的长度与原始test 的长度相同,即120550 (float_data.shape[0] - 300001)。现在,如果我绘制预测值和原始值,这两个数组是否都从同一位置开始?
      • 或者,更好的是,我怎样才能使我的预测数组与测试集完全匹配?
      • 首先,我认为省略了batch_size划分是作者的错误或疏忽。使用生成器时,步骤(steps_per_epochvalidation_stepssteps)应该是批次数。如果没有划分,我们只是为拟合、验证或预测提供额外的数据。这就是为什么我问你的验证是否永远运行(它运行的次数是必要的 127 倍。很好,生成器函数会返回,因此索引不会超出范围)。
      • 您关于如何对齐数据的其他问题。由于我们使用lookback=720delay=144,从最早的输入数据到目标或预测的样本跨度应该是720+144=864。这意味着您的 pred 将比测试数据短 864 个样本。要匹配它们,pred[0] 应该匹配 test_data[864] 等等。
      • 当前的实现每次调用生成器都会生成 128 个样本,所以pred 比这还要短。但 fit_generator 不必那样。请注意,当您玩fit 时,您可以设置batch_size,但fit_generator 没有该选项,因为fit_generator 采用任何产生的大小。所以如果你真的想让最后一批(sizegenerator函数来处理它
      【解决方案4】:

      当我对自己的问题得到一个半可接受的答案时,我决定将其发布以供后代使用:

      test_gen = generator(float_data, lookback=lookback, delay=delay, 
                           min_index=300001, max_index=None, step=step, 
                           batch_size=1)    # "reset" the generator
      
      pred = model.predict_generator(test_gen, steps=test_steps)
      

      这现在具有我想要根据我的原始测试集绘制的形状。我还可以使用受answer 启发的更手动的方法:

      test_gen = generator(float_data, lookback=lookback, delay=delay, 
                           min_index=300001, max_index=None, step=step, 
                           batch_size=1)    # "reset" the generator
      
      truth = []
      pred = []
      
      for i in range(test_steps):
          x, y = next(test_gen)
          pred.append(model.pred(x))
          truth.append(y) 
      
      pred = np.concatenate(pred)
      truth = np.concatenate(truth)
      

      【讨论】:

        猜你喜欢
        • 2019-02-15
        • 2019-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多