Пересекающиеся списки строк в Tensorflow tf.feature_column.crossed_column
У меня есть две особенности post_tags
а также user_tags
, Это дополненные строки из N и M слов соответственно.
Так, например, мы могли бы иметь post_tag
являющийся "the-oscars brad-pitt xyzpadxyz xyzpadxyz xyzpadxyz"
, Так что этот пост был помечен как Оскар и Брэд Питт.
Тогда для user_tag
мы могли бы иметь "brad-pitt universal sag the-academy-awards xyzpadxyz xyzpadxyz xyzpadxyz xyzpadxyz xyzpadxyz xyzpadxyz"
user_tag
Вот образец тегов из последних 20 сообщений, использованных пользователем.
Так post_tag
всегда 5 меток и user_tag
всегда 10 меток
Я разделяю каждую строку на тензор как часть обработки API набора данных следующим образом:
features['post_tag'] = tf.string_split([features['post_tag']])
features['post_tag'] = tf.sparse_tensor_to_dense(features['post_tag'], default_value=PADWORD)
features['user_tag'] = tf.string_split([features['post_tag']])
features['user_tag'] = tf.sparse_tensor_to_dense(features['post_tag'], default_value=PADWORD)
У меня есть Vocab-файл для тегов, и я добавляю каждую функцию в глубокие функции широкого и глубокого консервативного оценщика.
user_tag = tf.feature_column.categorical_column_with_vocabulary_file(
key='user_tag',
vocabulary_file='{}/tagvocab.csv'.format(INPUT_DIR)
)
user_tag_embed = tf.feature_column.embedding_column(
categorical_column = user_tag ,
dimension = USER_TAG_EMBEDDING_SIZE
)
deep.append(user_tag_embed)
post_tag = tf.feature_column.categorical_column_with_vocabulary_file(
key='post_tag',
vocabulary_file='{}/tagvocab.csv'.format(INPUT_DIR)
)
post_tag _embed = tf.feature_column.embedding_column(
categorical_column = post_tag ,
dimension = POST_TAG_EMBEDDING_SIZE
)
deep.append(post_tag_embed)
Это работает, однако, что я действительно хочу сделать, это сделать крест post_tag
а также user_tag
, Но если я сделаю что-то вроде этого:
user_post_tag_cross = tf.feature_column.crossed_column(
keys = [user_tag, post_tag],
hash_bucket_size = 25
)
wide.append(user_post_tag_cross)
Я получаю эту ошибку:
InvalidArgumentError (see above for traceback): Expected D2 of index to be 2 got 3 at position 0
Я вижу, что это идет от этой строки в коде TF
У меня такое чувство, что скрещивание тензоров может оказаться невозможным, или оно ожидает только две строки. У меня есть связанные функции, которые post_tag_first
а также user_tag_first
которые являются только одним случайным тегом и просто передаются в виде строк. Тогда, если я сделаю:
user_post_first_tag_cross = tf.feature_column.crossed_column(
keys = ['user_tag_first', 'post_tag_first'],
hash_bucket_size = 25
)
wide.append(user_post_first_tag_cross)
Работает и тренируется нормально. Так что на самом деле я просто пытаюсь понять, как лучше всего сделать крест из двух тензоров тегов.
У кого-нибудь есть идеи - я бы подумал, что это что-то, с чем кто-то мог иметь дело раньше, так как данные тегов вроде этого довольно распространены, или это могут быть поисковые термины и условия документа, ключевые слова и т. Д.
Обновление - небольшой воспроизводимый пример
Вот небольшой исполняемый пример, который устанавливает, что я хочу сделать.
import tensorflow as tf
import numpy as np
# set up tag vocab
tag_vocab = ['brad-pitt','usa','donald-trump','tpb','tensorflow','xyzpadxyz','UNK']
# make data
# train data
user_tag_train = np.random.choice(tag_vocab,50).reshape((5, 10)) # 5 example rows with 10 tags per user
post_tag_train = np.random.choice(tag_vocab,25).reshape((5, 5)) # 5 example rows with 5 tags per post
x_train = np.array([1., 2., 3., 4., 5.]) # just another example numeric feature
y_train = np.array([0., -1., -2., -3., -4]) # outcome
# eval data
user_tag_eval = np.random.choice(tag_vocab,50).reshape((5, 10)) # 5 example rows with 10 tags per user
post_tag_eval = np.random.choice(tag_vocab,25).reshape((5, 5)) # 5 example rows with 5 tags per post
x_eval = np.array([2., 5., 8., 1., 5.])
y_eval = np.array([-1.01, -4.1, -7, 0., 9.])
# define feature cols
x_num = tf.feature_column.numeric_column("x", shape=[1])
user_tag_cat = tf.feature_column.categorical_column_with_vocabulary_list(
key = 'user_tag',
vocabulary_list = tag_vocab)
user_tag_embed = tf.feature_column.embedding_column(
categorical_column = user_tag_cat,
dimension = 3
)
post_tag_cat = tf.feature_column.categorical_column_with_vocabulary_list(
key = 'post_tag',
vocabulary_list = tag_vocab)
post_tag_embed = tf.feature_column.embedding_column(
categorical_column = post_tag_cat,
dimension = 2
)
user_post_tag_cross = tf.feature_column.crossed_column(
keys = [ user_tag_cat, post_tag_cat ],
hash_bucket_size = 5
)
#user_post_tag_embed_cross = tf.feature_column.crossed_column(
# keys = [ user_tag_embed, post_tag_embed ],
# hash_bucket_size = 5
#)
feature_columns = [
x_num,
user_tag_cat,
post_tag_cat,
user_tag_embed,
post_tag_embed,
user_post_tag_cross,
#user_post_tag_embed_cross,
]
estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns)
input_fn = tf.estimator.inputs.numpy_input_fn(
{
"x": x_train,
"user_tag": user_tag_train,
"post_tag": post_tag_train,
},
y_train,
batch_size=5,
num_epochs=None,
shuffle=True
)
train_input_fn = tf.estimator.inputs.numpy_input_fn(
{
"x": x_train,
"user_tag": user_tag_train,
"post_tag": post_tag_train,
},
y_train,
batch_size=5,
num_epochs=1000,
shuffle=False
)
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
{
"x": x_eval,
"user_tag": user_tag_eval,
"post_tag": post_tag_eval
},
y_eval,
batch_size=5,
num_epochs=1000,
shuffle=False
)
estimator.train(input_fn=input_fn, steps=1000)
train_metrics = estimator.evaluate(input_fn=train_input_fn)
eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
print("\n\ntrain metrics: %r"% train_metrics)
print("eval metrics: %r"% eval_metrics)
Приведенный выше код выполняется, но если вы раскомментируете части, относящиеся к user_post_tag_embed_cross
вы получите (как и ожидалось):
ValueError: Unsupported key type. All keys must be either string, or categorical column except _HashedCategoricalColumn. Given: _EmbeddingColumn(categorical_column=_VocabularyListCategoricalColumn(key='user_tag', vocabulary_list=('brad-pitt', 'usa', 'donald-trump', 'tpb', 'tensorflow', 'xyzpadxyz', 'UNK'), dtype=tf.string, default_value=-1, num_oov_buckets=0), dimension=3, combiner='mean', initializer=<tensorflow.python.ops.init_ops.TruncatedNormal object at 0x0000021C9AA14860>, ckpt_to_load_from=None, tensor_name_in_ckpt=None, max_norm=None, trainable=True)
На самом деле я не думаю, что смогу сделать user_post_tag_cross
так как тэг vocab составляет ~40k (я был удивлен, что это сработало здесь, так как я думаю, что именно это привело к ошибке, с которой я связан выше - возможно, это связано с тем, когда вы пытаетесь скрестить двух кошек с большими вокабами).
Я думаю, что в идеале я бы хотел просто пересечь вложения. Если я помещу оба в одно и то же измерение, то есть ли способ пересечь это каким-то образом, используя feature_columns() или какой-то другой подход?