Python 如何使用Tensorflow数据集API读取具有不同名称的文件,而无需计算文件名字符串

Python 如何使用Tensorflow数据集API读取具有不同名称的文件,而无需计算文件名字符串,python,tensorflow,file-io,Python,Tensorflow,File Io,假设我收到的csv数据集文件的文件名为index\u channel.csv,其中index是示例的索引(从1到10000),而channel是通道的索引(从1到5)。因此7_3.csv是第七个示例的第三个通道。我想加载所有这些csv文件并连接通道,以获得正确的张量作为我的数据集。我缺少对函数的引用,这些函数将使我能够这样做。下面是我到目前为止的代码。当我开始运行它时,它抱怨说TypeError:应该是str、bytes或os.PathLike对象,而不是Tensor。我猜它是在尝试计算表达式,

假设我收到的csv数据集文件的文件名为
index\u channel.csv
,其中
index
是示例的索引(从1到10000),而
channel
是通道的索引(从1到5)。因此
7_3.csv
是第七个示例的第三个通道。我想加载所有这些csv文件并连接通道,以获得正确的张量作为我的数据集。我缺少对函数的引用,这些函数将使我能够这样做。下面是我到目前为止的代码。当我开始运行它时,它抱怨说
TypeError:应该是str、bytes或os.PathLike对象,而不是Tensor
。我猜它是在尝试计算表达式,而不是仅在调用了
sess.run()
之后,但不确定如何避免这种情况

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

# Imports
import numpy as np
import tensorflow as tf
from tensorflow.contrib.data import Dataset, Iterator

def main(unused_argv):
  train_imgs = tf.constant(["1","2","3"]) #just trying the 3 first examples
  tr_data = Dataset.from_tensor_slices((train_imgs))
  tr_data = tr_data.map(input_parser)

  # create TensorFlow Iterator object
  iterator = Iterator.from_structure(tr_data.output_types,
                                   tr_data.output_shapes)
  next_element = iterator.get_next()
  training_init_op = iterator.make_initializer(tr_data)
  with tf.Session() as sess:

    # initialize the iterator on the training data
    sess.run(training_init_op)
    # get each element of the training dataset until the end is reached
    while True:
        try:
            elem = sess.run(next_element)
            print(elem)
        except tf.errors.OutOfRangeError:
            print("End of training dataset.")
            break

def input_parser(index):
  dic={}
  for d in range(1,6):
    a=np.loadtxt(open("./data_for_tf/" + index +"_M"+str(d)+".csv", "rb"), delimiter=",", skiprows=1)
    dic[d]=tf.convert_to_tensor(a, dtype=tf.float32)
  metric=np.stack((dic[1],dic[2],dic[3])) 
  return metric

对不起,我是TF的新手。我的问题看起来很琐碎,但通过谷歌搜索找到的例子都没有回答我的问题。

在我看来,这个错误似乎是由使用
索引产生的:

a=np.loadtxt(open("./data_for_tf/" + index +"_M"+str(d)+".csv", "rb"), delimiter=",", skiprows=1)
正如您所怀疑的,当TensorFlow设置其声明性模型时,您的input_解析器只会被调用一次——这将设置TensorFlow操作之间的关系,以便以后进行评估。但是,Python调用(例如numpy操作)会在初始化过程中立即运行。此时,
np.loadtxt
正在尝试使用尚未指定的TF op构建字符串

事实上,您甚至不需要运行模型来生成错误(请尝试删除
sess.run()

在中的示例中,您会注意到,它们使用TF文件访问函数读取数据:

filenames = ["/var/data/file1.txt", "/var/data/file2.txt"]

dataset = tf.data.Dataset.from_tensor_slices(filenames)

# Use `Dataset.flat_map()` to transform each file as a separate nested dataset,
# and then concatenate their contents sequentially into a single "flat" dataset.
# * Skip the first line (header row).
# * Filter out lines beginning with "#" (comments).

dataset = dataset.flat_map(
    lambda filename: (
        tf.data.TextLineDataset(filename)
        .skip(1)
        .filter(lambda line: tf.not_equal(tf.substr(line, 0, 1), "#"))))
它被设计为去极化TF模型的一部分(即在运行时解析文件名)

以下是使用TensorFlow ops读取文件的更多示例:

也可以使用命令式Python函数(请参阅第一个链接中的“使用tf.py_func()应用任意Python逻辑”),尽管只有在没有其他选项的情况下才建议这样做

因此,基本上,除非您使用
tf.py_-fun()
机制,否则不能期望任何依赖于tf张量或操作的正常Python操作按预期工作。但是,它们可以用于循环构造以建立相关的TF操作

更新:

下面是一个示意图示例:

## For a simple example, I have four files <index>_<channel>_File.txt
## so, 1_1_File.txt, 1_2_File.txt

import tensorflow as tf

def input_parser(filename):
   filesWithChannels = []

   for i in range(1,3):
       channel_data =  tf.read_file(filename+'_'+str(i)+'_File.txt')

       ## Uncomment the two lines below to add csv parsing.
       # channel_data = tf.sparse_tensor_to_dense(tf.string_split([channel_data],'\n'), default_value='')
       # channel_data = tf.decode_csv(channel_data, record_defaults=[[1.],[1.]])

       filesWithChannels.append(channel_data)

   return tf.convert_to_tensor(filesWithChannels)


train_imgs = tf.constant(["1","2"]) # e.g.
tr_data = tf.data.Dataset.from_tensor_slices(train_imgs)
tr_data = tr_data.map(input_parser)

iterator = tr_data.make_one_shot_iterator()
next_element = iterator.get_next()

with tf.Session() as sess:
    for i in range(2) :
        out = sess.run(next_element)
        print(out) 
###举个简单的例子,我有四个文件uuu File.txt
##所以,1_1_File.txt,1_2_File.txt
导入tensorflow作为tf
def输入_解析器(文件名):
filesWithChannels=[]
对于范围(1,3)内的i:
通道数据=tf.read_文件(文件名+'''+str(i)+'''u文件.txt')
##取消对下面两行的注释以添加csv解析。
#通道数据=tf.稀疏张量到密度(tf.字符串分割([channel\u data],'\n'),默认值=“”)
#channel_data=tf.decode_csv(channel_data,record_Default=[[1.],[1.]]
filesWithChannels.append(通道\u数据)
返回tf.convert_to_tensor(filesWithChannels)
列车imgs=tf.常数([“1”,“2”])#例如。
tr_data=tf.data.Dataset.from_tensor_切片(train_imgs)
tr_data=tr_data.map(输入解析器)
迭代器=tr_data.make_one_shot_迭代器()
下一个元素=迭代器。获取下一个元素()
使用tf.Session()作为sess:
对于范围(2)中的i:
out=sess.run(下一个元素)
打印(输出)
更新(添加csv):

###举个简单的例子,我有四个文件uuu File.txt
##所以,1_1_File.txt,1_2_File.txt
导入tensorflow作为tf
使用tf.device('/cpu:0'):
def输入_解析器(文件名):
filesWithChannels=[]
对于范围(1,3)内的i:
channel_data=(tf.data.TextLineDataset(文件名+'''+str(i)+'''u File.txt'))
.map(lambda行:tf.decode_csv(行,记录_默认值=[[1.],[1.]]))
filesWithChannels.append(通道\u数据)
返回tf.data.Dataset.zip(元组(filesWithChannels))
列车imgs=tf.常数([“1”,“2”])#例如。
tr_data=tf.data.Dataset.from_tensor_切片(train_imgs)
tr_data=tr_data.flat_映射(输入解析器)
迭代器=tr_data.make_one_shot_迭代器()
下一个元素=迭代器。获取下一个元素()
下一个\u张量\u元素=tf。将\u转换为\u张量(下一个\u元素)
使用tf.Session()作为sess:
对于范围(2)中的i:
out=sess.run(下一个张量元素)
打印(输出)

有关如何使用
column\u defaults

设置字段分隔符并指定列号和默认值的详细信息,请参阅。我已经浏览了该链接好几次,我仍然不确定是什么函数替换了我的
input\u解析器
函数中的5行。您能否给出一些提示,哪些函数应该替换它,以使它符合TF声明性模型?@olamundo-请参阅上面的更新。诚然,从提供的链接中的细节来看,这是一个棘手的问题。事实上,TF感觉有点像狂野的西部,变化很快,而且文档非常薄。我认为其中一些诡计与它的灵活性有关。。。通常没有一种方法适合所有类型的ML问题。但是概念上的迷失是相当严重的。好吧,我添加了一个额外的例子。它实质上是通过tf.decode_csv将各个文件上的各个数据集组合在一起来构建数据集。一个更简单的解决方案可能是使用我的原始示例,执行tf.read_data->tf.split on linebreaks->tf.decode_csv并构造完整的csv解析张量。“我很难做到这一点。很乐意帮忙,”奥拉蒙多说。我在原始的“更新”示例中添加了(注释掉)csv解析,我认为这比后者更容易理解。如果这解决了您的问题,请“接受”:)。
## For a simple example, I have four files <index>_<channel>_File.txt
## so, 1_1_File.txt, 1_2_File.txt

import tensorflow as tf

with tf.device('/cpu:0'):
    def input_parser(filename):
       filesWithChannels = []

       for i in range(1,3):
             channel_data = (tf.data.TextLineDataset(filename+'_'+str(i)+'_File.txt')
                               .map(lambda line: tf.decode_csv(line, record_defaults=[[1.],[1.]])))

             filesWithChannels.append(channel_data)

       return tf.data.Dataset.zip(tuple(filesWithChannels))

train_imgs = tf.constant(["1","2"]) # e.g.
tr_data = tf.data.Dataset.from_tensor_slices(train_imgs)
tr_data = tr_data.flat_map(input_parser)

iterator = tr_data.make_one_shot_iterator()
next_element = iterator.get_next()
next_tensor_element = tf.convert_to_tensor(next_element)

with tf.Session() as sess:
    for i in range(2) :
        out = sess.run(next_tensor_element)
        print(out)