TensorFlow中使用tf.data与Iterator处理CSV时遇NotFoundError求助
问题分析与解决方案
首先,你的错误根源在于对tf.data.TextLineDataset和flat_map的用法理解有误,导致代码把CSV文件的表头行当成了文件名去读取,这才抛出了NotFoundError(错误信息里的列名就是被误当作文件名的表头内容)。
错误原因拆解
你代码里的这部分逻辑完全走偏了:
ds_file = tf.data.TextLineDataset(file) ds = ds_file.flat_map(lambda file: (tf.data.TextLineDataset(file).skip(1)))
tf.gfile.Glob("./NSEOIL.csv")返回的是文件名列表,tf.data.TextLineDataset(file)会直接读取这些文件的所有行,此时ds_file的每个元素是文件里的一行文本(包括第一行表头)。- 接下来的
flat_map里,你把每个行文本(比如第一行的表头Date,Open,...)当作文件名,传给tf.data.TextLineDataset去读取,这自然会找不到对应文件,因为根本不存在名为Date,Open,...的文件!
修正后的代码
下面是修复后的完整代码,同时优化了逻辑结构:
def create_pipeline(bs, nr, ep): def _parse_csv(line): # 统一解析逻辑,根据需求返回输入或标签 record_defaults = [[0]] * 20 splits = tf.decode_csv(line, record_defaults) return splits # 1. 创建文件名数据集(这才是正确的起点) filenames = tf.data.Dataset.from_tensor_slices(tf.gfile.Glob("./NSEOIL.csv")) # 2. 处理X_train:读取文件并跳过表头 X_train = filenames.flat_map(lambda fname: tf.data.TextLineDataset(fname).skip(1)) X_train = X_train.map(_parse_csv) X_train = X_train.shard(nr, 0).repeat(ep).batch(bs) # 加上batch操作 # 3. 处理y_train:跳过表头+第一行(对应偏移一天的标签逻辑) y_train = filenames.flat_map(lambda fname: tf.data.TextLineDataset(fname).skip(2)) y_train = y_train.map(lambda line: _parse_csv(line)[0]) # 取第一个元素作为标签 y_train = y_train.shard(nr, 0).repeat(ep).batch(bs) # 4. 创建迭代器 X_iterator = X_train.make_initializable_iterator() y_iterator = y_train.make_initializable_iterator() return X_iterator, y_iterator
关键修改点说明
- 正确构建文件名数据集:用
tf.data.Dataset.from_tensor_slices把文件名列表转换成数据集,这样flat_map就能遍历每个文件名,而不是遍历文件的行。 - 分离文件名与文件内容的处理:对每个文件名,创建对应的
TextLineDataset并跳过表头,再通过flat_map合并所有文件的内容。 - 统一解析函数:把重复的
_X_parse_csv和_y_parse_csv合并成一个,减少冗余代码。 - 添加batch操作:原代码里没做批量处理,这里补上
batch(bs)符合你“批量喂入数据”的需求。
额外注意事项
- 如果你的
num_workers后续要大于1,确保task_index是每个worker的唯一索引(从0开始)。 - 若要更高效地处理CSV,建议使用
tf.data.experimental.make_csv_dataset,它内置了表头处理、类型推断等功能,比手动用decode_csv更简洁。
内容的提问来源于stack exchange,提问作者Jo Nathan
相关产品推荐
相关产品推荐

