从文件读取数据时,往往是需要数据转换时,尤其对于多维数据,在使用文件形式进行存储时,除了tfrecord文件格式化,其他的文件的存储都显得无能为力。所以真正从文件读入的数据需要经过转换之后才能够使用。同样在tensorflow这种以小批次进行梯度下降的框架中,需要打乱数据以及对数据进行batch处理,本文主要讨论这些问题。
Dataset.map(f) 转换通过将指定函数 f 应用于输入数据集的每个元素来生成新数据集。此转换基于 map() 函数(通常应用于函数式编程语言中的列表和其他结构)。函数 f 会接受表示输入中单个元素的 tf.Tensor 对象,并返回表示新数据集中单个元素的 tf.Tensor 对象。此函数的实现使用标准的 TensorFlow 指令将一个元素转换为另一个元素。
下面以nlp的word-embeding为例来说明这个情况,在我们存储的原始预料中包含一些关键词,并且包含这些关键词对应的id,我们可以使用下面代码来看一下数据的基本形态:
# 从CSV文件中读取数据
import pandas as pd
data = pd.read_csv('cutword_ths.csv',header=None,delimiter=' ',names=['id','text'])
data.head()
输出结果如下图所示:
我们可以尝试使用dataSet读取文本文件的方式读取一下这个文件,具体代码请参考如下:
# 从文本文件中读取数据
dataset = tf.data.TextLineDataset('cutword_ths.csv')
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()
with tf.Session() as sess:
value = sess.run(next_element)
print(value)
输出结果如下图所示:
很明显这个结果是非结构化数据,所有的数据都是以文本流的形式读入到文件当中的,此时我们可以使用map方法将其转化成结构化数据,请参考下面代码:
# 从文本文件中读取数据
def _parse_csv(line):
FIELD_DEFAULTS = [[0], ['']]
fields = tf.decode_csv(line,FIELD_DEFAULTS,name=None,field_delim=' ')
features = dict(zip(COLUMNS,fields))
return features
COLUMNS = ['id', 'text']
dataset = tf.data.TextLineDataset('cutword_ths.csv').skip(1)
dataset=dataset.map(_parse_csv)
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()
with tf.Session() as sess:
value = sess.run(next_element)
print(value['id'],value['text'].decode('utf-8'))
输出结果如下图所示:
但此时依然不是一个可进入tensorflow进行训练的数据,那么需要对数据进行进一步的处理方式。此时可以对输入数据使用tf.py_func()
进行进一步处理。
为了确保性能,我们建议您尽可能使用 TensorFlow 指令预处理数据。不过,在解析输入数据时,调用外部 Python 库有时很有用。为此,请在 Dataset.map() 转换中调用 tf.py_func() 指令。
py_func()的语法定义如下:
tf.py_func(
func,
inp,
Tout,
stateful=True,
name=None
)
该函数将一组ndarray类型的数据作为输入,并返回一组ndarray的数据,主要用于在tensorflow的张量处理中使用python中的库函数,参数含义如下:
请参照下面示例代码:
# 从文本文件中读取数据
def _word_embed(features):
maxlen =10
features=features.decode('utf-8')
padding = ''
train_sentences = []
embeddingUnknown = [0 for i in range(100)]
labels = []
tag = features.split(',')
if len(tag)>maxlen:
tag = tag[0:maxlen]
else:
tag.extend([padding]*(maxlen-len(tag)))
train_sentence = []
for word in tag:
if word in model.wv.vocab:
train_sentence.append(model.wv[word])
else:
train_sentence.append(embeddingUnknown)
return np.array(train_sentence,dtype=np.float32)
def _parse_csv(line):
FIELD_DEFAULTS = [[0], ['']]
fields = tf.decode_csv(line,FIELD_DEFAULTS,name=None,field_delim=' ')
features = dict(zip(COLUMNS,fields))
ids=features.pop('id')
y = tf.py_func(_word_embed,[features['text']], [tf.float32])
return y
COLUMNS = ['id', 'text']
dataset = tf.data.TextLineDataset('cutword_ths.csv').skip(1)
dataset=dataset.map(_parse_csv)
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()
with tf.Session() as sess:
value = sess.run(next_element)
print(value[0].shape)
上面的代码比较复杂,主要是将句子转化为词向量。输出结果如下图所示,因为词向量是一个100维的矩阵,所以这里只输出了他的形状:
很多时候我们需要对一个批次的数据进行统一的训练,所以数据的批量化就变得十分的重要。如果我们已经构建了数据集(DataSet)那么批量化的工作也非常简单,请参照如下代码
dataset = tf.data.TextLineDataset('cutword_ths.csv').skip(1)
dataset=dataset.map(_parse_csv)
dataset = dataset.batch(4)
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()
with tf.Session() as sess:
value = sess.run(next_element)
print(value[0].shape)
输出结果如下图所示: