我正在寻找张力流的第一步作为谷歌机器学习科学课程的一部分,并已经困惑.我的理解是(如果我错了,请纠正我):
my_input_fn,该函数将数据格式化为相关的TensorFlow结构传感器train呼叫.my_input_fn以获得连续批量数据以调整模型.(???现在对此嫌疑人)my_input_fn 在这里定义:
def my_input_fn(features, targets, batch_size=1, shuffle=True, num_epochs=None):
"""Trains a linear regression model of one feature.
Args:
features: pandas DataFrame of features
targets: pandas DataFrame of targets
batch_size: Size of batches to be passed to the model
shuffle: True or False. Whether to shuffle the data.
num_epochs: Number of epochs for which data should be repeated. None = repeat indefinitely
Returns:
Tuple of (features, labels) for next data batch
"""
# Convert pandas data into a dict of np arrays.
features = {key:np.array(value) for key,value in dict(features).items()}
# Construct a dataset, and configure batching/repeating
ds = Dataset.from_tensor_slices((features,targets)) # warning: 2GB limit
ds = ds.batch(batch_size).repeat(num_epochs)
# Shuffle the data, if specified
if shuffle:
ds = ds.shuffle(buffer_size=10000)
# Return the next batch of data
features, labels = ds.make_one_shot_iterator().get_next()
return features, labels
Run Code Online (Sandbox Code Playgroud)
从我的阅读中my_input_fn,我不明白这是怎么发生的.我只有python的基本知识,但我对函数的读取是每次调用它都会重新初始化pandas帧中的张量结构,得到一个迭代器然后返回它的第一个元素.每次被召唤.当然,在这个例子的情况下,如果数据被洗牌(默认情况下是这样)并且数据集很大,那么你不可能在100步的情况下得到重复数据,但是这有点草率的编程(即在这种情况下)它没有被洗牌它总会返回相同的第一个训练数据集)所以我怀疑是这样的.
我的下一个怀疑是这个one_shot_iterator().get_next()电话正在做一些有趣/古怪/棘手的事情.就像返回某种后期eval结构一样,它允许train函数从自身枚举到下一批而不是重新调用my_input_fn?
但老实说,我想澄清一下,因为在这个阶段,我想要考虑的时间比我想的更多,所以我不再接近理解.
我的研究尝试刚刚引起了进一步的混乱.
本教程建议阅读本文 - 有一点它说"火车,评估和预测每个Estimator的方法都需要输入函数来返回包含张量流张量的(特征,标签)对." 好的,这与我最初的想法是一致的.基本上是TensorFlow结构中打包的示例和标签.
但后来它显示了它返回的结果,它是这样的东西(例子):
({
'SepalLength': <tf.Tensor 'IteratorGetNext:2' shape=(?,) dtype=float64>,
'PetalWidth': <tf.Tensor 'IteratorGetNext:1' shape=(?,) dtype=float64>,
'PetalLength': <tf.Tensor 'IteratorGetNext:0' shape=(?,) dtype=float64>,
'SepalWidth': <tf.Tensor 'IteratorGetNext:3' shape=(?,) dtype=float64>},
Tensor("IteratorGetNext_1:4", shape=(?,), dtype=int64))
Run Code Online (Sandbox Code Playgroud)
在代码实验室中,my_input_fn(my_feature, targets)返回:
({'total_rooms': <tf.Tensor 'IteratorGetNext:0' shape=(?,) dtype=float64>},
Run Code Online (Sandbox Code Playgroud)
)
我没有想法如何做到这一点.我对张量的阅读没有提到这样的事情.我甚至不知道如何用我的基本Python和不存在的TensorFlow知识来查询这个问题.
单击迭代器的文档说它创建了一个枚举元素的迭代器.再次,这符合我的想法.
该get_next文档说:
返回包含下一个元素的tf.Tensors的嵌套结构.
我不知道如何解析这个.什么样的嵌套结构?我的意思是它看起来像一个元组,但为什么你不会说元组?是什么决定这个?在哪里描述?当然这很重要吗?
我在这里误解了什么?
(对于一个据称不需要事先了解TensorFlow的课程,谷歌机器学习速成课程让我感到非常愚蠢.我真的很好奇我的情况中的其他人如何使用它.)
输入功能(在这种情况下my_input_function)不会重复调用.它被调用一次,创建一堆tensorflow操作(用于创建数据集,对其进行混洗等)并最终返回get_next迭代器的操作.这个操作将被重复调用,但它只是迭代数据集.你做的事情my_input_function(如洗牌,配料,重复)只发生一次.
一般来说:使用Tensorflow程序时,你必须习惯它们与"普通"Python程序的工作方式完全不同.您编写的大多数代码(特别是tf.前面的代码)只会被执行一次以构建计算图,然后这个图执行多次.
编辑:但是,有一个实验性的tf.eagerAPI(据说可以完全集成在TF 1.7中),它会改变这一点,即在你编写它们时执行的东西(更像是numpy).这应该允许更快的实验.
要逐步完成输入接口:首先要使用从"张量切片"(例如numpy数组)创建的数据集.然后你调用batch方法.这实质上创建了一个新的数据集,其元素是原始数据集的多个元素.类似地,重复和混洗也会创建新的数据集(准确地说,它们会创建操作,一旦它们实际作为计算图的一部分执行,就会创建这些数据集).最后,在批处理的,重复的,混洗的数据集上返回一个迭代器.只有这个迭代器的get_nextop将重复执行,返回数据集的新元素,直到它耗尽为止.
编辑:确实iterator.get_next()只返回一个操作.只有在此操作中运行一次,才会执行迭代tf.Session.
至于你有"不知道该做什么"的输出:不确定你的问题是什么,但你发布的只是将字符串映射到张量的字符串.张量自动获取与生成它们的op相关的名称(iterator.get_next),并且它们的形状未知,因为批量大小可以变化 - 即使指定它,如果批量大小不均匀地划分数据集,最后一批可能会更小大小(例如,具有10个元素且批量大小为4的数据集 - 最后一批将为大小2).?张量形状中的元素表示未知的维度.
编辑:关于命名:操作接收默认名称.但是,IteratorGetNext在这种情况下,它们都会收到相同的默认名称(),但不能有多个具有相同名称的操作.因此,Tensorflow会自动附加整数以使名称唯一.就这样!
至于"嵌套结构":通常使用输入函数tf.estimator,期望一个相当简单的输入结构(包含Tensor或Tensors dict作为输入的元组,如果我没有弄错的话,Tensor作为输出).但是,通常,输入函数支持更复杂的嵌套输出结构,例如(a, (tuple, of), (tuples, (more, tuples, elements), and), words).请注意,这是一个输出的结构,即迭代器的一个"步骤"(例如一批数据).反复调用此op将枚举整个数据集.
编辑:输入函数返回的结构仅由该函数决定!例如,来自张量切片的数据集将返回元组,其中第n个元素是第n个"张量切片".有些功能dataset.zip就像Python等效一样.如果您将采用具有结构(e1,e2)的数据集并使用数据集(e3,)将其压缩,您将获得((e1,e2),e3).
需要什么格式取决于应用程序.原则上,您可以提供任何格式,然后接收此输入的代码可以对其执行任何操作.但是,正如我所说,可能最常见的用途是在上下文中tf.estimator,并且你的输入函数应该返回一个元组(特征,标签),其中特征是张量的张量或字典(如你的情况)和标签也是张量的张量或词典.如果其中一个是dict,则模型函数负责从那里获取正确的值/张量.
一般来说,我会建议你玩这些东西.查看tf.data API,当然还有程序员指南.创建一些数据集/输入函数,只需启动一个会话并重复运行iterator.get_next()op.看看那里出了什么.尝试所有不同的转换,例如zip,take,padded_batch...在行动中看到它,而不需要实际上这个数据应该给你一个更好的了解做任何事情.