Объяснение векторизованных последовательностей - PullRequest
0 голосов
/ 07 мая 2018

Изучение Глубокое обучение с Python , я не могу понять следующую простую порцию кода, которая кодирует целочисленные последовательности в двоичную матрицу.

def vectorize_sequences(sequences, dimension=10000):
    # Create an all-zero matrix of shape (len(sequences), dimension)
    results = np.zeros((len(sequences), dimension))
    for i, sequence in enumerate(sequences):
       results[i, sequence] = 1.  # set specific indices of results[i] to 1s
    return results

(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

x_train = vectorize_sequences(train_data)

И вывод x_trainэто что-то вроде

x_train [0] array ([0., 1., 1., ..., 0., 0., 0.])

Может ли кто-то осветить существование 0. в массиве x_train, в то время как только 1. добавляются в каждую следующую итерацию i?Я имею в виду не должно быть все 1?

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

Скрипт преобразует ваш набор данных в модель двоичного векторного пространства. Давайте разберемся по порядку.

Во-первых, если мы рассмотрим содержимое x_train, мы увидим, что каждый отзыв представлен в виде последовательности идентификаторов слов. Каждое слово id соответствует одному конкретному слову:

print(train_data[0])  # print the first review
[1, 14, 22, 16, 43, 530, 973, ..., 5345, 19, 178, 32]

Теперь, это будет очень трудно прокормить сеть. Длина обзоров варьируется, дробные значения между любыми целыми числами не имеют значения (например, что если на выходе мы получим 43,5, что это значит?)

Итак, что мы можем сделать, это создать один лунный вектор, размер всего словаря, dictionary=10000 в вашем примере. Затем мы свяжем каждый элемент / индекс этого вектора с одним словом / word_id. Таким образом, слово, представленное словом id 14, теперь будет представлено 14-м элементом этого вектора.

Каждый элемент будет либо 0 (слово отсутствует в обзоре), либо 1 (слово присутствует в обзоре). И мы можем рассматривать это как вероятность, поэтому у нас даже есть значение для значений от 0 до 1. Кроме того, каждый обзор теперь будет представлен этим очень длинным (разреженным) вектором, который имеет постоянную длину для каждый отзыв.

Так в меньшем масштабе, если:

word      word_id
I      -> 0
you    -> 1
he     -> 2
be     -> 3
eat    -> 4
happy  -> 5
sad    -> 6
banana -> 7
a      -> 8

предложения будут обрабатываться следующим образом.

I be happy      -> [0,3,5]   -> [1,0,0,1,0,1,0,0,0]
I eat a banana. -> [0,4,8,7] -> [1,0,0,0,1,0,0,1,1]

Теперь я выделил слово разреженное. Это означает, что по сравнению с единицами будет гораздо больше нулей. Мы можем воспользоваться этим. Вместо проверки каждого слова, содержится ли оно в рецензии или нет; мы проверим существенно меньший список только тех слов, которые действительно появляются в нашем обзоре.

Следовательно, мы можем упростить для нас задачу и сразу создать reviews × vocabulary матрицу нулей с помощью np.zeros((len(sequences), dimension)). А затем просто пролистайте слова в каждом обзоре и переверните индикатор на 1.0 в позиции, соответствующей этому слову:

result[review_id][word_id] = 1.0

Таким образом, вместо выполнения 25000 x 10000 = 250 000 000 операций мы сделали только number of words = 5 967 841. Это всего ~ 2,5% от первоначального количества операций.

0 голосов
/ 07 мая 2018

Цикл for здесь не обрабатывает всю матрицу. Как видите, он перечисляет элементы последовательности, поэтому он зацикливается только на одном измерении. Давайте рассмотрим простой пример:

t = np.array([1,2,3,4,5,6,7,8,9]) r = np.zeros((len(t), 10))

выход

array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
   [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
   [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
   [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
   [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
   [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
   [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
   [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
   [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

тогда мы модифицируем элементы так же, как вы:

for i, s in enumerate(t): r[i,s] = 1.

array([[0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
   [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
   [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
   [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
   [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
   [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
   [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
   [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
   [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])

вы можете видеть, что цикл for изменяет только набор элементов (len (t)), который имеет индекс [i, s] (в данном случае; (0, 1), (1, 2), (2, 3), так далее))

...