【问题标题】:unwrap a generator to use inside model.fit展开生成器以在 model.fit 中使用
【发布时间】:2021-01-01 12:36:14
【问题描述】:

我的问题与post 中解决的问题完全相同:我不能在kerasmodel.fit 的训练输入中使用生成器,所以我应该打开它。建议的解决方案:

from platform import python_version_tuple

if python_version_tuple()[0] == '3':
    xrange = range
    izip = zip
    imap = map
else:
    from itertools import izip, imap

import numpy as np

# ..
# other code as in question
# ..

x, y = izip(*(validation_seq[i] for i in xrange(len(validation_seq))))
x_val, y_val = np.vstack(x), np.vstack(y)

正是我正在寻找的。问题是它适用于初始questionImageDataGenerator(),但不适用于我的生成器,如下所示:

def generator(data, L, D, i_min, i_max, shuffle=False, batch_size=16, step=1):
  if i_max is None:
     i_max = len(data) - D - 1
  i = i_min + L
  while 1:
     if shuffle:
        rows = np.random.randint(i_min + L, i_max, size=batch_size)
     else:
        if i + batch_size >= i_max:
           i = i_min + L
        rows = np.arange(i, min(i + batch_size, i_max))
        i += len(rows)
     samples = np.zeros((len(rows), L // step, data.shape[-1]))
     targets = np.zeros((len(rows),))
     for j, row in enumerate(rows):
        indices = range(rows[j] - L, rows[j], step)
        samples[j] = data[indices]
        targets[j] = data[rows[j] + D][3]  # where is Q in your data
     yield samples, targets


data = np.random.standard_normal([256,4])
generator = generator(data=data, L=8, D=1, i_min=0, i_max=255, shuffle=False, batch_size=16, step=1)

当我执行izip(*(generator[i] for i in xrange(len(generator)))) 时,我得到了这个错误:object of type 'generator' has no len()

我已经尝试将xrange(len(generator)) 替换为len(list(generator))enumerate(generator),但它们都不起作用。我该如何解决这个问题?谢谢。

PS:我在 osx 10.13.6 上使用 python 3.8

更新根据@couka 的回答,我尝试制作类生成器,但它仍然无法正常工作。

class batch_gen:
  def __init__(self, data, L, D, min_index, max_index, shuffle, batch_size, step):
     self.data = data
     self.L = L
     self.D = D
     self.min_index = min_index
     self.max_index = max_index
     self.shuffle = shuffle
     self.batch_size = batch_size
     self.step = step
 
  def __iter__(self):
     if self.max_index is None:
        self.max_index = len(self.data) - self.D - 1
     i = self.min_index + self.L
     while 1:
        if self.shuffle:
           rows = np.random.randint(self.min_index + self.L, self.max_index, size=self.batch_size)
        else:
           if i + self.batch_size >= self.max_index:
              i = self.min_index + self.L
           rows = np.arange(i, min(i + self.batch_size, self.max_index))
           i += len(rows)
        samples = np.zeros((len(rows), self.L // self.step, self.data.shape[-1]))
        targets = np.zeros((len(rows),))
        for j, row in enumerate(rows):
           indices = range(rows[j] - self.L, rows[j], self.step)
           samples[j] = self.data[indices]
           targets[j] = self.data[rows[j] + self.D][3]  # where is Q in your data
        yield samples, targets
 
  def __len__(self):
     return int(math.floor(len(self.data) / float(self.batch_size)))

当我使用时:

gen_tr = batch_gen(data=data, L=L, D=D,
                  min_index=min(ind_tr), max_index=max(ind_tr),
                  shuffle=True, step=step, batch_size=batch_size)

我收到了这个错误:TypeError: 'batch_gen' object is not subscriptable

【问题讨论】:

  • 请将包含调用堆栈回溯的完整错误消息放入您的问题中。另外请更新您问题中的代码,使其成为minimal reproducible example - 任何人都应该能够将您的代码粘贴到文件中并且无需添加任何内容运行它以查看与您相同的问题。跨度>
  • 错误正是它所说的。 batch_gen 不可下标。你没有在你的生成器类中实现__getitem__,你没有理由应该这样做。您可以直接迭代项目而不是通过下标。 izip(*(item for item in gen_tr)) 应该可以工作。

标签: python keras generator


【解决方案1】:

首先,generator 应该是一个类,而不是一个方法。

那么,object of type 'generator' has no len() 表示你的类generator 没有方法__len__(self)。所以你需要添加它。 Afaik 该方法应该返回数据集中的批次数。

它可能看起来像这样:

def __len__(self):
    return int(math.floor(len(self.data) / float(self.batch_size)))

【讨论】:

  • 感谢您的回答。你能看看问题的更新吗?我仍然无法让它工作。非常感谢。
猜你喜欢
  • 2022-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-08
  • 1970-01-01
  • 2019-08-09
  • 2017-11-30
  • 1970-01-01
相关资源
最近更新 更多