Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使生成器可调用?_Python - Fatal编程技术网

Python 如何使生成器可调用?

Python 如何使生成器可调用?,python,Python,我正在尝试从一个包含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) 我得到以下错误: ----------------------------

我正在尝试从一个包含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)
我得到以下错误:

---------------------------------------------------------------------------
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.
---------------------------------------------------------------------------
TypeError回溯(最近一次调用上次)
在()
12 gen=(csvreader\u pat\u trn中的行与行)
13 ds=tf.data.Dataset()
--->14来自发电机的ds(发电机[tf.uint8]*28**2)
~/Documents/Programming/ANN/labs/lib/python3.6/site-packages/tensorflow/python/data/ops/dataset\u ops.py from_generator(生成器、输出类型、输出形状)
317     """
318如果不可调用(生成器):
-->319 raise TypeError(“'generator'必须是可调用的。”)
320如果输出形状为无:
321输出形状=nest.map\u结构(
TypeError:`generator`必须是可调用的。
他们说我应该让一个生成器从_generator()传递到
,所以我就是这么做的,
gen
是一个生成器。但是现在他们抱怨我的生成器不可调用。我如何使生成器可调用,以便让它工作

编辑: 我想补充一点,我正在使用python 3.6.4。这就是错误的原因吗?

,您链接了:


generator
参数必须是返回 支持
iter()
协议的对象(例如生成器函数)

这意味着您应该能够执行以下操作:

import tensorflow as tf
import csv

with open("test.csv", "r") as f:
    csvreader = csv.reader(f)
    gen = lambda: (row for row in csvreader)
    ds = tf.data.Dataset()
    ds.from_generator(gen, [tf.uint8]*28**2)
换句话说,您传递的函数在调用时必须生成一个生成器。这在使其成为匿名函数(a
lambda
)时很容易实现

或者,试试这个,它更接近文档中的操作方式:

import tensorflow as tf
import csv


def read_csv(file_name="test.csv"):
    with open(file_name) as f:
        reader = csv.reader(f)
        for row in reader:
            yield row

ds = tf.data.Dataset.from_generator(read_csv, [tf.uint8]*28**2)
(如果您需要的文件名与您设置的默认文件名不同,则可以使用
functools.partial(读取\u csv,file\u name=“whicher.csv”)

不同之处在于,
read\u csv
函数在调用时返回生成器对象,而您构建的已经是生成器对象,相当于执行以下操作:

gen = read_csv()
ds = tf.data.Dataset.from_generator(gen, [tf.uint8]*28**2)  # does not work

generator
参数(可能令人困惑)实际上不应该是一个生成器,而是一个返回iterable的可调用函数(例如,一个生成器函数)。这里最简单的选择可能是使用
lambda
。此外,还有几个错误:1)该函数(与TensorFlow中的其他一些函数一样)对参数的要求非常严格,它希望您将数据类型和每个数据行的顺序指定为
元组
s(而不是CSV读取器返回的
列表
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))

哎呀,两年后……但是嘿!另一个解决办法!:D

这可能不是最清晰的答案,但对于更复杂的生成器,可以使用装饰器。我制作了一个生成器,可以生成两个词典,例如:

列车,val=dataloader(“路径/目的地/数据集”) >>>x,y=下一列(列车) >>>打印(x) {“数据”:[…],“文件名”:“image.png”} >>>打印(y) {“类别”:“狗”,“类别id”:1,“背景”:“公园”}
当我尝试使用_生成器中的
时,它给出了错误:

>>> 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.
但后来我写了一个装饰函数

>>> def make_gen_callable(_gen):
        def gen():
            for x,y in _gen:
                 yield x,y
        return gen
>>> train_ = make_gen_callable(train)

真的吗?文档中的例子是一个普通的老式生成器函数,具有
yield
而不是
return
的函数,不是生成器吗?哦,是的,你说得对,克里斯。
gen
是文档中的生成器,不是返回生成器的函数。@Chris\u Rands是的,这很奇怪。显然,生成器也被定义为函数工作。@Chris_Rands我认为区别在于,如果调用该函数(即生成器),它将返回生成器对象。而
(x代表x in…)
已经是生成器对象本身了。是的,我理解其中的区别,但我真诚地认为,从
张量的
部分,比如从\u generator\u函数的
中,名称应该更清楚
>>> 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'>
}
>>> for x,y in train_():
        do_stuff(x,y)
        ...