使用 TensorFlow Transform 有效地将标记转换为词向量
Posted
技术标签:
【中文标题】使用 TensorFlow Transform 有效地将标记转换为词向量【英文标题】:Converting tokens to word vectors effectively with TensorFlow Transform 【发布时间】:2019-01-07 10:05:33 【问题描述】:我想在训练、验证和推理阶段使用 TensorFlow Transform 将标记转换为词向量。
我遵循了这个*** post 并实现了从标记到向量的初始转换。转换按预期进行,我为每个令牌获得了 EMB_DIM
的向量。
import numpy as np
import tensorflow as tf
tf.reset_default_graph()
EMB_DIM = 10
def load_pretrained_glove():
tokens = ["a", "cat", "plays", "piano"]
return tokens, np.random.rand(len(tokens), EMB_DIM)
# sample string
string_tensor = tf.constant(["plays", "piano", "unknown_token", "another_unknown_token"])
pretrained_vocab, pretrained_embs = load_pretrained_glove()
vocab_lookup = tf.contrib.lookup.index_table_from_tensor(
mapping = tf.constant(pretrained_vocab),
default_value = len(pretrained_vocab))
string_tensor = vocab_lookup.lookup(string_tensor)
# define the word embedding
pretrained_embs = tf.get_variable(
name="embs_pretrained",
initializer=tf.constant_initializer(np.asarray(pretrained_embs), dtype=tf.float32),
shape=pretrained_embs.shape,
trainable=False)
unk_embedding = tf.get_variable(
name="unk_embedding",
shape=[1, EMB_DIM],
initializer=tf.random_uniform_initializer(-0.04, 0.04),
trainable=False)
embeddings = tf.cast(tf.concat([pretrained_embs, unk_embedding], axis=0), tf.float32)
word_vectors = tf.nn.embedding_lookup(embeddings, string_tensor)
with tf.Session() as sess:
tf.tables_initializer().run()
tf.global_variables_initializer().run()
print(sess.run(word_vectors))
当我重构代码以作为 TFX 变换图运行时,我收到下面的 ConversionError
错误。
import pprint
import tempfile
import numpy as np
import tensorflow as tf
import tensorflow_transform as tft
import tensorflow_transform.beam.impl as beam_impl
from tensorflow_transform.tf_metadata import dataset_metadata
from tensorflow_transform.tf_metadata import dataset_schema
tf.reset_default_graph()
EMB_DIM = 10
def load_pretrained_glove():
tokens = ["a", "cat", "plays", "piano"]
return tokens, np.random.rand(len(tokens), EMB_DIM)
def embed_tensor(string_tensor, trainable=False):
"""
Convert List of strings into list of indices then into EMB_DIM vectors
"""
pretrained_vocab, pretrained_embs = load_pretrained_glove()
vocab_lookup = tf.contrib.lookup.index_table_from_tensor(
mapping=tf.constant(pretrained_vocab),
default_value=len(pretrained_vocab))
string_tensor = vocab_lookup.lookup(string_tensor)
pretrained_embs = tf.get_variable(
name="embs_pretrained",
initializer=tf.constant_initializer(np.asarray(pretrained_embs), dtype=tf.float32),
shape=pretrained_embs.shape,
trainable=trainable)
unk_embedding = tf.get_variable(
name="unk_embedding",
shape=[1, EMB_DIM],
initializer=tf.random_uniform_initializer(-0.04, 0.04),
trainable=False)
embeddings = tf.cast(tf.concat([pretrained_embs, unk_embedding], axis=0), tf.float32)
return tf.nn.embedding_lookup(embeddings, string_tensor)
def preprocessing_fn(inputs):
input_string = tf.string_split(inputs['sentence'], delimiter=" ")
return 'word_vectors': tft.apply_function(embed_tensor, input_string)
raw_data = ['sentence': 'This is a sample sentence',]
raw_data_metadata = dataset_metadata.DatasetMetadata(dataset_schema.Schema(
'sentence': dataset_schema.ColumnSchema(
tf.string, [], dataset_schema.FixedColumnRepresentation())
))
with beam_impl.Context(temp_dir=tempfile.mkdtemp()):
transformed_dataset, transform_fn = ( # pylint: disable=unused-variable
(raw_data, raw_data_metadata) | beam_impl.AnalyzeAndTransformDataset(
preprocessing_fn))
transformed_data, transformed_metadata = transformed_dataset # pylint: disable=unused-variable
pprint.pprint(transformed_data)
错误信息
TypeError: Failed to convert object of type <class
'tensorflow.python.framework.sparse_tensor.SparseTensor'> to Tensor.
Contents: SparseTensor(indices=Tensor("StringSplit:0", shape=(?, 2),
dtype=int64), values=Tensor("hash_table_Lookup:0", shape=(?,),
dtype=int64), dense_shape=Tensor("StringSplit:2", shape=(2,),
dtype=int64)). Consider casting elements to a supported type.
问题
-
为什么 TF 变换步骤需要额外的转换/转换?
这种将标记转换为词向量的方法是否可行?词向量在内存中可能有数 GB。 Apache Beam 如何处理向量?如果 Beam 在分布式设置中,它是否需要
N x vector memory
和 N
的工人数量?
【问题讨论】:
大家好!我们正在找人来看看这个问题。抱歉耽搁了 【参考方案1】:与 SparseTensor 相关的错误是因为您正在调用返回 SparseTensor 的 string_split。您的测试代码不会调用 string_split,因此它只发生在您的 Transform 代码中。
关于内存,你是对的,嵌入矩阵必须加载到每个worker中。
【讨论】:
【参考方案2】:不能将 SparseTensor 放入由 TFX 变换返回的字典中,在您的情况下是由函数“preprocessing_fn”返回的。原因是 SparseTensor 不是 Tensor,它实际上是一个小的子图。
要修复您的代码,您可以将 SparseTensor 转换为张量。有很多方法可以做到这一点,我建议将 tf.serialize_sparse 用于常规 SparseTensor,将 tf.serialize_many_sparse 用于批处理。
要在 Trainer 中使用这种序列化的张量,您可以调用函数 tf. deserialize_many_sparse。
【讨论】:
以上是关于使用 TensorFlow Transform 有效地将标记转换为词向量的主要内容,如果未能解决你的问题,请参考以下文章
如何执行正确的 Python 来导入已安装的 tensorflow.transform 包?
Tensorflow Graph Transform Tool quantize_nodes 引用了不存在的“帽子”节点名称?
归一化(Normalization)标准化(Standarlization)tensorflow和opencv区别:opencv之transform函数解析CHW与HWC:图像的线性数据格
归一化(Normalization)标准化(Standarlization)tensorflow和opencv区别:opencv之transform函数解析CHW与HWC:图像的线性数据格
WARNING:tensorflow:AutoGraph could not transform xxx and will run it as-is 的一种解决思路
WARNING:tensorflow:AutoGraph could not transform xxx and will run it as-is 的一种解决思路