繁体   English   中英

Keras-随机播放的自定义无限数据生成器

[英]Keras - custom infinite data generator with shuffle

免责声明 :我认为问题与keras不直接相关,而更多地是关于python中生成器的一般行为

我正在尝试为Keras构建自定义数据生成器。 我这样做是因为内置图像数据生成器仅支持分类任务,而我尝试使用图像作为输入来解决回归任务。

首先,我将一个包含img路径和目标变量Y的文本文件上载到数据帧中,然后将它们随机播放:

train, test = AnnoParser.get_data(input_path)
train = train.sample(frac=1).reset_index(drop=True)

AnnoParser只是解析文本文件并返回Pandas Dataframes。

然后定义数据生成器:

def get_data_generator(array, resized_width, resized_height, mode):
    while True:
        if mode == 'train':
            array = array.sample(frac=1).reset_index(drop=True)
            augment = True

        for img_path, img_hype in array:
            try:
                img = data_augment(img_path,resized_width, resized_height, augment)

                yield np.copy(img), np.copy(img_hype)

由于我使用的是while True循环,因此我希望它是无限的。 如您所见,我还每次都对输入数组进行改组以确保样本是随机的。 DataAugment函数将img路径作为输入,从该路径加载图像并将其调整为指定大小,然后返回图像本身(使用cv2)。

最后,我创建一个生成器实例并在以后使用:

data_gen_train = DataGenerator.get_data_generator(train, 224, 224, "train")

现在,据我了解,每次调用next(data_gen_train)生成器时,生成器都将next(data_gen_train)原始的train数组并从执行结果中提取下一个值。 因此,据我了解,我的生成器应该能够从我原始数据集中的所有图像路径中无限绘制图像。

但是似乎生成器仍然经常抛出StopIteration异常。 我不知道为什么。 谁能解释?

更新

根据要求,您还可以在下面找到如何使用生成器拟合模型。 如您所见,我首先将一堆图像提取到阵列中,以便我可以以小批量的形式训练网络。 然后,我仅将微型批次馈入网络并评估损失。

据我所知,生成器会在一段时间后中断,而不是在最初的几次迭代中中断。 我怀疑在幕后它只对所有可用记录(可以由生成器产生的记录)执行一条路径,然后引发迭代异常。

optimizer = Adam(lr=1e-5)

model = DenseNet(reduction=0.5, weights_path=weights_path)
model.compile(loss='mean_absolute_error', optimizer=optimizer)

iter_num = 0

accuracy_monitor = []
accuracy_for_epoch = []
start_time = time.time()

best_loss = np.Inf


print('Starting training')

for epoch_num in range(num_epochs):
    progbar = generic_utils.Progbar(epoch_length)
    print('Epoch {}/{}'.format(epoch_num + 1, num_epochs))
    while True:
        #keep training untill end of epoch, if end of epoch - check result
        if len(accuracy_monitor) == epoch_length:
            print("Average accuracy is {} for {} previous iterations", str(np.mean(accuracy_monitor)), epoch_length)
            accuracy_for_epoch.append(np.mean(accuracy_monitor))
            accuracy_monitor = []


        X = np.ndarray((batch_size,224,224,3))
        Y = np.ndarray((batch_size))

        i = 0
        #building a batch
        for img,hype in data_gen_train:
            X[i,] = img
            Y[i] = hype
            i+=1
            if i == batch_size:
                break

        loss = model.train_on_batch(x= X, y = Y)
        accuracy_monitor.append(loss)
        iter_num +=1
        progbar.update(iter_num,[('Loss', np.mean(accuracy_monitor[:iter_num]))])
        if iter_num == epoch_length:
            accuracy_for_epoch.append(np.mean(accuracy_monitor))
            curr_loss = np.mean(accuracy_monitor)
            print('Elapsed time: {}'.format(time.time() - start_time))
            print("Regressor accuracy over epoch: {}", curr_loss)
            if curr_loss < best_loss:
                print('Total loss decreased from {} to {}, saving weights'.format(best_loss,curr_loss))
                best_loss = curr_loss
                model.save_weights(weights_path)
            start_time = time.time()
            iter_num = 0

我想通了。 似乎问题出在我使用Pandas Dataframe将其传递到数据生成器的事实。 如果我改为将它们转换为numpy数组,它将起作用:

train = train.as_matrix()
np.random.shuffle(train)

#then go on with generator creation

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM