我正在尝试从具有784位长行的CSV文件创建数据集。这是我的代码:
import tensorflow as tf
f = open("test.csv", "r")
csvreader = csv.reader(f)
gen = (row for row in csvreader)
ds = tf.data.Dataset()
ds.from_generator(gen, [tf.uint8]*28**2)
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-22-4b244ea66c1d> in <module>()
12 gen = (row for row in csvreader_pat_trn)
13 ds = tf.data.Dataset()
---> 14 ds.from_generator(gen, [tf.uint8]*28**2)
~/Documents/Programming/ANN/labs/lib/python3.6/site-packages/tensorflow/python/data/ops/dataset_ops.py in from_generator(generator, output_types, output_shapes)
317 """
318 if not callable(generator):
--> 319 raise TypeError("`generator` must be callable.")
320 if output_shapes is None:
321 output_shapes = nest.map_structure(
TypeError: `generator` must be callable.
Run Code Online (Sandbox Code Playgroud)
该文档说我应该传递给发电机from_generator(),让我做什么的,gen是一台发电机。但是现在它抱怨我的生成器不可调用。如何使生成器可调用,以便使它起作用?
编辑: 我想补充一点,我正在使用python 3.6.4。这是错误的原因吗?
该generator参数(可能令人困惑)实际上不应该是一个生成器,而是一个可返回可迭代对象的可调用函数(例如,生成器函数)。可能最简单的选择是使用lambda。此外,还有一些错误:1)tf.data.Dataset.from_generator旨在被称为类工厂方法,而不是从实例中调用2)函数(类似于TensorFlow中的其他一些函数)对参数感到奇怪,并且希望您给出序列的dtype和每个数据行为tuples(而不是listCSV阅读器返回的s),您可以使用例如map:
import csv
import tensorflow as tf
with open("test.csv", "r") as f:
csvreader = csv.reader(f)
ds = tf.data.Dataset.from_generator(lambda: map(tuple, csvreader),
(tf.uint8,) * (28 ** 2))
Run Code Online (Sandbox Code Playgroud)
哎呀,两年后...但是嘿!另一个解决方案!:D
这可能不是最干净的答案,但对于更复杂的生成器,您可以使用装饰器。我制作了一个生成两个字典的生成器,例如:
>>> train,val = dataloader("path/to/dataset")
>>> x,y = next(train)
>>> print(x)
{"data": [...], "filename": "image.png"}
>>> print(y)
{"category": "Dog", "category_id": 1, "background": "park"}
Run Code Online (Sandbox Code Playgroud)
当我尝试使用 时from_generator,它给了我错误:
>>> ds_tf = tf.data.Dataset.from_generator(
iter(mm),
({"data":tf.float32, "filename":tf.string},
{"category":tf.string, "category_id":tf.int32, "background":tf.string})
)
TypeError: `generator` must be callable.
Run Code Online (Sandbox Code Playgroud)
但后来我写了一个装饰函数
>>> def make_gen_callable(_gen):
def gen():
for x,y in _gen:
yield x,y
return gen
>>> train_ = make_gen_callable(train)
Run Code Online (Sandbox Code Playgroud)
>>> train_ds = tf.data.Dataset.from_generator(
train_,
({"data":tf.float32, "filename":tf.string},
{"category":tf.string, "category_id":tf.int32, "background":tf.string})
)
>>> for x,y in train_ds:
break
>>> print(x)
{'data': <tf.Tensor: shape=(320, 480), dtype=float32, ... >,
'filename': <tf.Tensor: shape=(), dtype=string, ...>
}
>>> print(y)
{'category': <tf.Tensor: shape=(), dtype=string, numpy=b'Dog'>,
'category_id': <tf.Tensor: shape=(), dtype=int32, numpy=1>,
'background': <tf.Tensor: shape=(), dtype=string, numpy=b'Living Room'>
}
Run Code Online (Sandbox Code Playgroud)
但现在请注意,为了迭代train_,必须调用它
>>> for x,y in train_():
do_stuff(x,y)
...
Run Code Online (Sandbox Code Playgroud)