两个函数,一个是数据转换函数,一个是输入函数
# 数据输入管道
# 首先是数据转换函数
# 重点理解和思考着函数
def _parse_function(record):
"""Extracts features and labels.
Args:
record: File path to a TFRecord file
Returns:
A `tuple` `(labels, features)`:
features: A dict of tensors representing the features
labels: A tensor with the corresponding labels.
"""
features = {
"terms": tf.VarLenFeature(dtype=tf.string), # terms are strings of varying lengths
"labels": tf.FixedLenFeature(shape=[1], dtype=tf.float32) # labels are 0 or 1
}
# print ("features", features)
# 使用转换函数
parsed_features = tf.parse_single_example(record, features)
# print("parsed_features", parsed_features)
terms = parsed_features['terms'].values
labels = parsed_features['labels']
# print ("terms", terms)
# print ("labels", labels)
return {'terms':terms}, labels
输入函数:
# 用于为训练输入数据的输入函数
# 这里只需要输入文件名,也即训练数据的路径
# 并且由于输入的特征数据并不是长度相同,所以需要使用Dataset.padded_batch, 进行填充以此进行分桶
# Create an input_fn that parses the tf.Examples from the given files,
# and split them into features and targets.
def _input_fn(input_filenames, num_epochs=None, shuffle=True):
# Same code as above; create a dataset and map features and labels
ds = tf.data.TFRecordDataset(input_filenames)
ds = ds.map(_parse_function)
if shuffle:
ds = ds.shuffle(10000)
# Our feature data is variable-length, so we pad and batch
# each field of the dataset structure to whatever size is necessary
ds = ds.padded_batch(25, ds.output_shapes) # 对数据进行填充,以此进行批量处理
ds = ds.repeat(num_epochs)
# Return the next batch of data
features, labels = ds.make_one_shot_iterator().get_next()
return features, labels
一些总结:
嵌套的作用:
简单点就是降维,对于一个推荐系统或是翻译系统,单词表的大小决定了构造出来的稀疏向量的形,如果不进行嵌套,将会产生很多个特征列,
这些特征列数量变多而产生的计算,将会超过硬件的计算能力。并且对于所构造出来的向量(以独热编码方是生成)大多是属于稀疏向量,里面很多0值,
所以为了简化向量,可以仅仅是保留有用的信息,然后表示成一些简单内容嵌入到神经网络中去,(这些简单的内容可以进行少量的计算,达到与之前原来相同的效果)通过反向传播逐步的确立出出嵌套矩阵!这样就能保存上下文的语义关系了!
!!!
假设稀疏数据包含 "great"、"beautiful" 和 "excellent" 这几个值。由于在此处使用的词汇表大小为 V=54 ,因此第一层中的每个单元(神经元)的权重将为 54。我们用 s 表示稀疏输入中的项数。对于此示例稀疏数据, s=3 。对于具有 V 个可能值的输入层,带有 d 个单元的隐藏层需要运行一次“矢量 - 矩阵”乘法运算: (1×V)∗(V×d) 。此运算会产生 O(V∗d) 的计算成本。请注意,此成本与隐藏层中的权重数成正比,而与 s 无关。如果输入使用 indicator_column 进行了独热编码(长度为 V 的布尔型矢量,存在用 1 表示,其余则为 0),这表示很多零进行了相乘和相加运算。
当我们通过使用大小为 d 的 embedding_column 获得完全相同的结果时,我们将仅查询与示例输入中存在的 3 个特征 "great"、"beautiful" 和 "excellent" 相对应的嵌入并将这三个嵌入相加: (1×d)+(1×d)+(1×d) 。由于不存在的特征的权重在“矢量-矩阵”乘法中与 0 相乘,因此对结果没有任何影响;而存在的特征的权重在“矢量-矩阵”乘法中与 1 相乘。因此,将通过嵌入查询获得的权重相加会获得与“矢量-矩阵”乘法相同的结果。
当使用嵌入时,计算嵌入查询是一个 O(s∗d) 计算;从计算方面而言,它比稀疏数据中的 indicator_column 的 O(V∗d) 更具成本效益,因为 s 远远小于 V 。(请注意,这些嵌入是临时学习的结果。在任何指定的训练迭代中,都是当前查询的权重