如何从含向量列的DataFrame创建TensorFlow Dataset?
问题描述
我有一份训练数据存储在train.csv文件中,格式如下:
x;y;type [1,2,3];[2,3,4];A [2,7,9];[0,1,2];B
我通过以下代码将其解析为pd.DataFrame:
CSV_COLUMN_NAMES = ['x', 'y', 'type'] train = pd.read_csv("train.csv", names=CSV_COLUMN_NAMES, header=0, delimiter=";") train['x'] = train['x'].apply(literal_eval) train['y'] = train['y'].apply(literal_eval)
目前一切正常,literal_eval函数已将x和y列转换为数组。接下来我尝试通过以下代码创建DataSet:
features, labels = train, train.pop('type') dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
但此时出现报错:
TypeError: Expected binary or unicode string, got [1, 2, 3]
请问为何会期望二进制或Unicode字符串?是否不允许使用向量特征列?还是我操作有误?恳请解惑。
问题原因与解决方案
这个问题我之前也碰到过,其实不是TensorFlow不允许向量特征列,而是你用dict(features)传递特征时,TensorFlow对特征的类型有特定要求,具体原因和解决办法如下:
问题根源
当你把DataFrame转成字典dict(features)时,字典里的每个值是Pandas Series,而Series中的元素是Python原生列表。TensorFlow的from_tensor_slices在处理这种字典输入时,默认期望每个特征是可转换为张量的统一类型(比如numpy数组、张量),而Python列表的集合会被它误判为非预期的类型,所以抛出了“期望二进制或Unicode字符串”的错误。
两种可行的解决方式
方式一:将列表列转换为TensorFlow张量
在创建Dataset前,把x、y列的每个列表元素转成TensorFlow张量,让TensorFlow能正确识别:
import tensorflow as tf from ast import literal_eval import pandas as pd CSV_COLUMN_NAMES = ['x', 'y', 'type'] train = pd.read_csv("train.csv", names=CSV_COLUMN_NAMES, header=0, delimiter=";") train['x'] = train['x'].apply(literal_eval) train['y'] = train['y'].apply(literal_eval) # 将每个列表元素转为TensorFlow张量 train['x'] = train['x'].apply(lambda x: tf.convert_to_tensor(x, dtype=tf.float32)) train['y'] = train['y'].apply(lambda x: tf.convert_to_tensor(x, dtype=tf.float32)) features, labels = train, train.pop('type') dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels)) # 验证一下结果 for data in dataset.take(1): print(data)
方式二:将列表列转为二维numpy数组
如果你的所有列表长度固定(比如都是3个元素),可以直接把整个列转成二维numpy数组,这种方式更高效:
import numpy as np import tensorflow as tf from ast import literal_eval import pandas as pd CSV_COLUMN_NAMES = ['x', 'y', 'type'] train = pd.read_csv("train.csv", names=CSV_COLUMN_NAMES, header=0, delimiter=";") train['x'] = train['x'].apply(literal_eval) train['y'] = train['y'].apply(literal_eval) # 将整个列转为二维numpy数组 train['x'] = np.array(train['x'].tolist()) train['y'] = np.array(train['y'].tolist()) features, labels = train, train.pop('type') dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
补充:向量特征列的使用
TensorFlow完全支持向量特征列,后续你可以用tf.feature_column.numeric_column来定义这些特征,方便后续构建模型:
# 定义向量特征列,shape对应每个向量的长度 x_feature = tf.feature_column.numeric_column('x', shape=(3,)) y_feature = tf.feature_column.numeric_column('y', shape=(3,)) feature_columns = [x_feature, y_feature]
内容的提问来源于stack exchange,提问作者jack3694078
相关产品推荐
相关产品推荐

