Keras:使用 predict_generator 预测新值

Keras: Predicting New Values using predict_generator

目前,我正在尝试遵循 Keras 中的温度预报示例(如 F. Chollet 的 "Deep Learning with Python" 书中第 6.3 章所述)。我在使用指定的生成器进行预测时遇到了一些问题。我的理解是我应该使用 model.predict_generator 进行预测,但我不确定如何将 steps 参数用于此方法以及如何取回正确的 "shape" 预测我的原始数据。

理想情况下,我希望能够绘制测试集(索引 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)

然而,我得到的预测数组太长,与我的原始数据完全不匹配。有人有什么建议吗?

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  

当我对自己的问题得出一个半可接受的答案时,我决定 post 为了 post 严肃:

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)

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

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

(你的验证不是要花很长时间才能达到每个时期的 运行 吗?)

当然,通过此更正,您可以简单地使用

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

对于现在正在看这个问题的任何人,我们在使用 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时)会一次读取整个测试数据,这对于大测试数据并不理想。