TensorFlow Dataset加载Parquet报错ArrowInvalid:未初始化FileSource调用Open()
解决TensorFlow Dataset加载Parquet文件的
ArrowInvalid错误 错误根源
你的代码中,preprocess_data函数在tf.data.Dataset.map中执行时,path是TensorFlow的张量对象,而非原生Python字符串。pd.read_parquet无法直接处理Tensor类型的路径,导致PyArrow无法正确初始化文件源,触发Called Open() on an uninitialized FileSource错误。
解决方案
使用tf.py_function将Parquet读取逻辑包装为Python可调用函数,在图模式下安全地将Tensor转换为Python字符串并执行IO操作,再将结果转回TensorFlow张量。
步骤1:定义纯Python读取函数
import numpy as np import pandas as pd def load_parquet_data(path): # 将Tensor路径转换为Python字符串 pq_path = path.numpy().decode('utf-8') # 替换为你实际需要读取的列名 data_columns = ['x', 'y', 'z', 'pitch', 'yaw', 'roll'] # 读取Parquet文件并返回numpy数组 data = pd.read_parquet(pq_path, columns=data_columns) return data.values.astype(np.float32)
步骤2:修改预处理函数,用tf.py_function包装读取逻辑
import tensorflow as tf def preprocess_data(path, label): # 使用tf.py_function执行Python读取逻辑 data = tf.py_function( func=load_parquet_data, inp=[path], Tout=tf.float32 # 指定输出张量类型 ) # 设置张量形状(根据你的Parquet数据实际形状调整,这里假设是(None, 543)) data.set_shape((None, 543)) # 处理NaN值(保持你的原有逻辑) mask = tf.math.is_nan(data) mean_val = tf.reduce_mean(tf.where(mask, tf.zeros_like(data), data)) data = tf.where(mask, mean_val, data) # 调整维度以适配tf.image.resize(需要HWC格式) data = tf.expand_dims(data, axis=-1) target_size = (80, 543) data = tf.image.resize(data, target_size, method='bilinear') # 去掉多余的通道维度(如果不需要) data = tf.squeeze(data, axis=-1) return data, label
步骤3:重新构建Dataset并执行map
# 你的原有代码保持不变 file_paths = [os.path.join(root_path, p) for p in train['path'].tolist()] labels = train['label'].tolist() train_dataset = tf.data.Dataset.from_tensor_slices((file_paths, labels)) # 执行map操作(可以继续使用并行调用) train_dataset = train_dataset.map( preprocess_data, num_parallel_calls=tf.data.experimental.AUTOTUNE )
关键注意事项
- 必须通过
path.numpy().decode('utf-8')将Tensor路径转换为Python字符串,否则PyArrow无法识别路径。 data.set_shape是必须的:tf.py_function返回的张量形状是未知的,显式设置形状才能让后续的TensorFlow操作(如tf.image.resize)正常执行。- 如果你的Parquet文件有固定的样本数,建议将形状设置为固定值(如
(100, 543)),而非(None, 543),以提升性能。
内容的提问来源于stack exchange,提问作者Conweezy
相关产品推荐
相关产品推荐

