Tensorflow One Hot Encoder?
Есть ли в tenorflow что-то похожее на один горячий кодировщик scikit learn для обработки категориальных данных? Будет ли использование заполнителя tf.string вести себя как категориальные данные?
Я понимаю, что могу вручную предварительно обработать данные перед отправкой в тензор потока, но встроить их очень удобно.
14 ответов
Начиная с TensorFlow 0.8, теперь есть встроенная горячая операция, tf.one_hot
это может преобразовать набор разреженных меток в плотное одноразовое представление. Это в дополнение к tf.nn.sparse_softmax_cross_entropy_with_logits
, что в некоторых случаях позволяет вычислять перекрестную энтропию непосредственно на разреженных метках, а не преобразовывать их в одноразовые метки.
Предыдущий ответ, если вы хотите сделать это по-старому: @ Сальвадор правильный ответ - нет (раньше было) нативной операции, чтобы сделать это. Вместо того, чтобы делать это в numpy, вы можете сделать это изначально в тензорном потоке, используя операторы разреженной плотности:
num_labels = 10
# label_batch is a tensor of numeric labels to process
# 0 <= label < num_labels
sparse_labels = tf.reshape(label_batch, [-1, 1])
derived_size = tf.shape(label_batch)[0]
indices = tf.reshape(tf.range(0, derived_size, 1), [-1, 1])
concated = tf.concat(1, [indices, sparse_labels])
outshape = tf.pack([derived_size, num_labels])
labels = tf.sparse_to_dense(concated, outshape, 1.0, 0.0)
Выходные данные меток представляют собой горячую матрицу batch_size x num_labels.
Также обратите внимание, что по состоянию на 2016-02-12 (который, как я полагаю, в конечном итоге станет частью версии 0.7), TensorFlow также имеет tf.nn.sparse_softmax_cross_entropy_with_logits
op, который в некоторых случаях может позволить вам пройти обучение без необходимости преобразования в горячую кодировку.
Отредактировано, чтобы добавить: В конце вам может понадобиться явно установить форму меток. Вывод формы не распознает размер компонента num_labels. Если вам не нужен динамический размер пакета с производным_размером, это можно упростить.
Отредактировано 2016-02-12, чтобы изменить назначение outshape согласно комментарию ниже.
tf.one_hot()
доступен в TF и прост в использовании.
Предположим, у вас есть 4 возможных категории (кошка, собака, птица, человек) и 2 экземпляра (кошка, человек). Так что ваши depth=4
и вашindices=[0, 3]
import tensorflow as tf
res = tf.one_hot(indices=[0, 3], depth=4)
with tf.Session() as sess:
print sess.run(res)
Имейте в виду, что если вы укажете index=-1, вы получите все нули в вашем одноместном векторе.
Старый ответ, когда эта функция была недоступна.
Посмотрев хотя бы документацию по питону, я не нашел ничего подобного. Одна вещь, которая укрепляет мою веру, что это не существует, - то, что в их собственном примере они пишут one_hot
вручную.
def dense_to_one_hot(labels_dense, num_classes=10):
"""Convert class labels from scalars to one-hot vectors."""
num_labels = labels_dense.shape[0]
index_offset = numpy.arange(num_labels) * num_classes
labels_one_hot = numpy.zeros((num_labels, num_classes))
labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
return labels_one_hot
Вы также можете сделать это в Scikitlearn.
numpy
Является ли!
import numpy as np
np.eye(n_labels)[target_vector]
Простой и короткий способ одноразового кодирования любого целого числа или списка промежуточных значений:
a = 5
b = [1, 2, 3]
# one hot an integer
one_hot_a = tf.nn.embedding_lookup(np.identity(10), a)
# one hot a list of integers
one_hot_b = tf.nn.embedding_lookup(np.identity(max(b)+1), b)
Последние версии TensorFlow (nightlies и, возможно, даже 0.7.1) имеют опцию tf.one_hot, которая делает то, что вы хотите. Проверьте это!
С другой стороны, если у вас плотная матрица, и вы хотите искать и собирать в ней значения, вы можете использовать функцию embedding_lookup.
Возможно, это связано с изменениями в Tensorflow с ноября 2015 года, но ответ @dga привел к ошибкам. Я заставил его работать со следующими модификациями:
sparse_labels = tf.reshape(label_batch, [-1, 1])
derived_size = tf.shape(sparse_labels)[0]
indices = tf.reshape(tf.range(0, derived_size, 1), [-1, 1])
concated = tf.concat(1, [indices, sparse_labels])
outshape = tf.concat(0, [tf.reshape(derived_size, [1]), tf.reshape(num_labels, [1])])
labels = tf.sparse_to_dense(concated, outshape, 1.0, 0.0)
Вы можете использовать tf.sparse_to_dense:
Аргумент sparse_indices указывает, куда они должны идти, для output_shape должно быть задано количество возможных выходных данных (например, количество меток), а sparse_values должно быть равно 1 с требуемым типом (он будет определять тип выходных данных из типа sparse_values).
Посмотрите на tf.nn.embedding_lookup. Он отображает от категориальных идентификаторов до их вложения.
Для примера того, как это используется для входных данных, смотрите здесь.
В Scikit Flow есть embedding_ops и примеры, которые имеют дело с категориальными переменными и т. Д.
Если вы только начинаете изучать TensorFlow, я бы посоветовал вам сначала попробовать примеры в TensorFlow/skflow, а затем, как только вы познакомитесь с TensorFlow, будет довольно просто вставить код TensorFlow для создания нужной вам модели (также примеры для этого).
Надеюсь, что эти примеры для понимания изображений и текста помогут вам начать работу и дайте нам знать, если у вас возникнут какие-либо проблемы! (опубликовать вопросы или пометить skflow в SO).
Ответ, совместимый с Tensorflow 2.0: вы можете сделать это эффективно, используяTensorflow Transform
.
Код для выполнения One-Hot Encoding с использованием Tensorflow Transform
показано ниже:
def get_feature_columns(tf_transform_output):
"""Returns the FeatureColumns for the model.
Args:
tf_transform_output: A `TFTransformOutput` object.
Returns:
A list of FeatureColumns.
"""
# Wrap scalars as real valued columns.
real_valued_columns = [tf.feature_column.numeric_column(key, shape=())
for key in NUMERIC_FEATURE_KEYS]
# Wrap categorical columns.
one_hot_columns = [
tf.feature_column.categorical_column_with_vocabulary_file(
key=key,
vocabulary_file=tf_transform_output.vocabulary_file_by_name(
vocab_filename=key))
for key in CATEGORICAL_FEATURE_KEYS]
return real_valued_columns + one_hot_columns
Для получения дополнительной информации обратитесь к этому руководству по TF_Transform.
Текущие версии tenorflow реализуют следующую функцию для создания горячих тензоров:
https://www.tensorflow.org/versions/master/api_docs/python/array_ops.html
Как уже упоминалось выше @dga, Tensorflow теперь имеет tf.one_hot:
labels = tf.constant([5,3,2,4,1])
highest_label = tf.reduce_max(labels)
labels_one_hot = tf.one_hot(labels, highest_label + 1)
array([[ 0., 0., 0., 0., 0., 1.],
[ 0., 0., 0., 1., 0., 0.],
[ 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 0.],
[ 0., 1., 0., 0., 0., 0.]], dtype=float32)
Вам нужно указать глубину, в противном случае вы получите обрезанный горячий тензор.
Если вам нравится делать это вручную:
labels = tf.constant([5,3,2,4,1])
size = tf.shape(labels)[0]
highest_label = tf.reduce_max(labels)
labels_t = tf.reshape(labels, [-1, 1])
indices = tf.reshape(tf.range(size), [-1, 1])
idx_with_labels = tf.concat([indices, labels_t], 1)
labels_one_hot = tf.sparse_to_dense(idx_with_labels, [size, highest_label + 1], 1.0)
array([[ 0., 0., 0., 0., 0., 1.],
[ 0., 0., 0., 1., 0., 0.],
[ 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 0.],
[ 0., 1., 0., 0., 0., 0.]], dtype=float32)
Обратите внимание на порядок аргументов в tf.concat()
In [7]: one_hot = tf.nn.embedding_lookup(np.eye(5), [1,2])
In [8]: one_hot.eval()
Out[8]:
array([[ 0., 1., 0., 0., 0.],
[ 0., 0., 1., 0., 0.]])
работает на TF версии 1.3.0. По состоянию на сентябрь 2017 года.
Есть несколько способов сделать это.
ans = tf.constant([[5, 6, 0, 0], [5, 6, 7, 0]]) #batch_size*max_seq_len
labels = tf.reduce_sum(tf.nn.embedding_lookup(np.identity(10), ans), 1)
>>> [[ 0. 0. 0. 0. 0. 1. 1. 0. 0. 0.]
>>> [ 0. 0. 0. 0. 0. 1. 1. 1. 0. 0.]]
Другой способ сделать это.
labels2 = tf.reduce_sum(tf.one_hot(ans, depth=10, on_value=1, off_value=0, axis=1), 2)
>>> [[0 0 0 0 0 1 1 0 0 0]
>>> [0 0 0 0 0 1 1 1 0 0]]
Моя версия примера @CFB и @dga немного сокращена, чтобы облегчить понимание.
num_labels = 10
labels_batch = [2, 3, 5, 9]
sparse_labels = tf.reshape(labels_batch, [-1, 1])
derived_size = len(labels_batch)
indices = tf.reshape(tf.range(0, derived_size, 1), [-1, 1])
concated = tf.concat(1, [indices, sparse_labels])
labels = tf.sparse_to_dense(concated, [derived_size, num_labels], 1.0, 0.0)