Реализация ограниченной машины Больцмана и ее применение в рекомендательной системе

глубокое обучение

Ограниченная машина Больцмана (RBM) — это случайно сгенерированная нейронная сеть, которая может изучать распределения вероятностей из набора входных данных, широко используемая.

Во второй половине премии Netflix некоторые участники применили RBM к проблеме прогнозирования рейтингов фильмов и добились хороших результатов. Более поздняя статья Эдвина ЧенаВведение в ограниченные машины БольцманаРабочий механизм RBM подробно и понятно описан (без математических формул и выводов), а простая реализация написана с использованием Python numpy.

Этот пост читается построчно и выполняетсяОткрытый исходный код Эдвина Чена, посмотрите структуру данных и изменения значений, используемые в ней, чтобы продемонстрировать принцип работы и навыки реализации RBM.

Поместите фоновую музыку сюда, используя шесть песен для тренировки RBM, три из которых - песни в стиле диско: песни ABBA.Dancing Queen, Би ДжизStayin' Alive, новые штаныПерестань спрашивать меня, что такое дискотека., остальные три - соло Guitar Hero: Dire StraitsSultans Of Swing, Ингви МальмстинBlack Starс БакетхедомThorne Room.

Как нейронная сеть, RBM имеет два слоя: видимый слой и скрытый слой, Каждый узел видимого слоя соответствует песне, а каждый узел скрытого слоя соответствует типу музыки, поэтому он соответствует характеристикам выше песни.Сделайте скрытым слоем два узла в описании. Также добавьтеbias unitДля контроля влияния слишком популярных предметов на модель подключение каждого узла этой нейронной сети выглядит следующим образом:

Каждый узел видимого слоя подключен к узлам всех скрытых слоев, а блок смещения подключен ко всем узлам двух слоев.Каждое соединение соответствует весу.Во-первых, матрица используется для представления всех весов узлов видимого слоя и скрытого слоя, таких как матрица.Данные в первом столбце первой строки соответствуют узлу видимого слояDancing QueenВес, связанный со скрытой единицей1, а затем на этом основании вставьте вес единицы смещения, поскольку он связан как с видимым слоем, так и со скрытым слоем, поэтому строки и столбцы матрицы увеличиваются на 1. Всем весам между двумя слоями узлов присваивается случайное значение в пределах диапазона для инициализации матрицы, а узлам, связанным с блоком смещения, временно присваивается значение 0.

import numpy as np


num_hidden = 2
num_visible = 6
np_rng = np.random.RandomState(1234)

weights = np.asarray(np_rng.uniform(
                low=-0.1 * np.sqrt(6. / (num_hidden + num_visible)),
                high=0.1 * np.sqrt(6. / (num_hidden + num_visible)),
                size=(num_visible, num_hidden)))
weights
array([[-0.0534304 ,  0.02114986],
       [-0.01078587,  0.04942556],
       [ 0.04849323, -0.03938812],
       [-0.03871753,  0.05228579],
       [ 0.07935206,  0.06511344],
       [-0.02462677,  0.00017236]])
# 加入bias unit.
weights = np.insert(weights, 0, 0, axis=0)
weights = np.insert(weights, 0, 0, axis=1)
weights
array([[ 0.        ,  0.        ,  0.        ],
       [ 0.        , -0.0534304 ,  0.02114986],
       [ 0.        , -0.01078587,  0.04942556],
       [ 0.        ,  0.04849323, -0.03938812],
       [ 0.        , -0.03871753,  0.05228579],
       [ 0.        ,  0.07935206,  0.06511344],
       [ 0.        , -0.02462677,  0.00017236]])

Затем создайте несколько обучающих выборок. Одна выборка представляет собой список условий прослушивания этих шести песен (соответствует индексу в списке в порядке сверху вниз на приведенном выше рисунке). Заполните значение 1, чтобы указать, что пользователь слышал эту песню. Введите значение 0, чтобы пользователь не слышал эту песню. Здесь в качестве выборки построено 6 выборок, и учитывая, что весовая матрица добавляет единицу смещения, для соответствия последующих операций линейной алгебры необходимо вставить в матрицу, образованную выборкой, еще один столбец, а значения все установлено на 1.

data = np.array([[1,1,1,0,0,0],[1,0,1,0,0,0],[1,1,1,0,0,0],[0,0,1,1,1,0], [0,0,1,1,0,0],[0,0,1,1,1,0]])
num_examples = data.shape[0]
data = np.insert(data, 0, 1, axis=1)

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

Имея входную матрицу и матрицу весов, для скрытого узла, чтобы вычислить, равно ли его значение 1 или 0, сначала умножьте значения всех связанных с ним узлов на соответствующие веса, а затем сложите их вместе, например, для верхний Скрытый узел, при вводе первого образца значение видимого слоя равно[1, 1, 1, 1, 0, 0, 0], соответствующий вес равен[0, -0.0534304, -0.01078587, 0.04849323, -0.03871753, 0.07935206, -0.02462677], скалярное произведение двух векторов соответствует описанному выше процессу.Обратите внимание, что первое значение двух векторов соответствует единице смещения, а вес единицы смещения равен 0, что не влияет на результат.

Все выборки и все скрытые узлы обрабатываются одинаково, поэтому многократное умножение точек может быть преобразовано в умножение матриц.Согласно правилу умножения матриц (результат умножения точек на вектор-строку и вектор-столбец помещается в соответствующую позицию) , вы можете видеть, что умножение данных и весовой матрицы просто означает, что вышеуказанная обработка выполняется один раз для каждого образца и каждого скрытого узла, и новая форма генерируется как(6*3)Матрица первого столбца, соответствующая значению единицы смещения, равна 0, а первый элемент второго столбца соответствует значению, сгенерированному Танцующей королевой в скрытой единице1. Использование матричного умножения намного быстрее, чем повторение выборок и скрытых единиц.

pos_hidden_activations = np.dot(data, weights)

pos_hidden_activations
array([[ 0.        , -0.01572304,  0.0311873 ],
       [ 0.        , -0.00493717, -0.01823826],
       [ 0.        , -0.01572304,  0.0311873 ],
       [ 0.        ,  0.08912777,  0.07801112],
       [ 0.        ,  0.00977571,  0.01289768],
       [ 0.        ,  0.08912777,  0.07801112]])

Хорошо известно, что после того, как значение активации вычислено, узлы нейронной сети часто содержат функцию активации.Здесь функция Сигмонда используется для управления значением активации, рассчитанным на предыдущем шаге, чтобы оно находилось между 0 и 1 для представления возможность активации этого узла. Чем ближе вероятность активации, вычисленная узлом, к 1, тем выше вероятность активации.Здесь функция Сигмонда применяется ко всем узлам в сгенерированной выше матрице с использованием широковещательной функции тупой. Затем измените столбец, соответствующий единице смещения, на 1, что означает, что единица смещения всегда активирована См. ниже конкретные причины.

def logistic(x):
    return 1.0 / (1 + np.exp(-x))

pos_hidden_probs = logistic(pos_hidden_activations)
pos_hidden_probs[:, 0] = 1
pos_hidden_probs
array([[1.        , 0.49606932, 0.50779619],
       [1.        , 0.49876571, 0.49544056],
       [1.        , 0.49606932, 0.50779619],
       [1.        , 0.5222672 , 0.5194929 ],
       [1.        , 0.50244391, 0.50322437],
       [1.        , 0.5222672 , 0.5194929 ]])

Функция rand будет случайным образом генерировать число от 0 до 1 и сравнивать вероятность активации узла, рассчитанную выше, с таким случайным числом, чтобы решить, активировать ли узел, что означает, что даже если скрытый узел находится в определенном обучении в на этот раз Точка имеет вероятность активации 0,99, а также возможно, что она не будет активирована.

pos_hidden_states = pos_hidden_probs > np.random.rand(num_examples, num_hidden + 1)
pos_hidden_states
array([[ True,  True,  True],
       [ True, False, False],
       [ True, False, False],
       [ True,  True,  True],
       [ True, False,  True],
       [ True, False,  True]])

Пример значения этой матрицы состоит в том, что значение первой строки и второго столбца указывает, активировала ли Танцующая Королева скрытый юнит1.

Как и выше, вычислив по одному разу активацию скрытого слоя для всех семплов, мы можем получить корреляцию между Танцующей королевой и одновременно загорающейся скрытой единицей1, которая записывается какPositive(e_{ij}), см. приведенную выше матрицуdataиpos_hidden_probs, первая выборка принимает значение 1 в узле Танцующей королевы, а вероятность активации скрытой единицы 1 равна 0,49606932. Умножьте два, чтобы получить значение, и сумма значений, рассчитанных таким образом для всех выборок, представляет собой корреляцию между эти два узла.Этот процесс также можно выразить с помощью матричного умножения следующим образом:

pos_associations = np.dot(data.T, pos_hidden_probs)
pos_associations
array([[6.        , 3.03788267, 3.05324311],
       [3.        , 1.49090435, 1.51103295],
       [2.        , 0.99213864, 1.01559239],
       [6.        , 3.03788267, 3.05324311],
       [3.        , 1.54697831, 1.54221017],
       [2.        , 1.04453441, 1.03898579],
       [0.        , 0.        , 0.        ]])

Таким образом, расчет от видимого слоя к скрытому закончен. Затем, в свою очередь, от скрытого слоя к видимому слою будетpos_hidden_statesВ качестве входных данных набора образцов для скрытого слоя выполните те же вычисления, что и в описанном выше процессе, а также вычислите корреляцию между двумя подключенными узлами, на этот раз обозначенную какNegative(e_{ij}). Поскольку начальный вес выбирается случайным образом, не должно быть небольшой разницы между Положительным и Отрицательным, и цель оптимизации RBM состоит в том, чтобы тренироваться через несколько эпох, чтобы сделать разницу как можно меньше.

Приведенное выше одно положительное и одно отрицательное вычисление завершает эпоху в соответствии с формулойw _ { i j } = w _ { i j } + L * \left( \text {Positive} \left( e _ { i j } \right) - N e g a t i v e \left( e _ { i j } \right) \right)Рассчитайте новое значение веса (где L — скорость обучения, которую необходимо алхимизировать), чтобы начать расчет следующей эпохи, которая будет делать разницу между двумя все меньше и меньше, таким образом получая обученную модель RBM.

Более хитрая штука - единица смещения.Вы можете видеть, что значение корреляции между некоторыми видимыми узлами и единицей смещения выше достигает 6, и в следующем цикле вся единица смещения будет переназначена.Эффект активации направлен на это блок смещения, чтобы разбавить этот эффект и попытаться предотвратить появление «феномена Битлз». В то же время, поскольку он связан с каждым узлом двух слоев, то в процессе расчета от видимого слоя к скрытому фактически участвует в расчете как узел скрытого слоя, а наоборот, выступает как узел видимый слой.Узлы слоя, чтобы играть роль, действительно замечательно.

Используйте полную версию кода для описанного выше процесса (см. ссылку в конце статьи), чтобы увидеть результат:

r = RBM(num_visible = 6, num_hidden = 2)
training_data = np.array([[1,1,1,0,0,0],[1,0,1,0,0,0],[1,1,1,0,0,0],[0,0,1,1,1,0], [0,0,1,1,0,0],[0,0,1,1,1,0]])
r.train(training_data, max_epochs = 5000)
print(r.weights[1:, 1:])
[[-8.09650002  3.95552071]
 [-5.45512759  1.42845858]
 [ 1.74474585  4.06127352]
 [ 7.74906751 -3.54062571]
 [ 3.18686136 -7.33215302]
 [-2.46868951 -2.60826581]]

По тренированному весу видно, что скрытый блок 1 имеет тенденцию соответствовать музыке героя рок-гитары, а скрытый блок 2 - диско.

Обратитесь в рекомендательную систему. Очевидно, модель может уменьшать размерность элементов. Как и Word2vec, ее можно представить вектором, состоящим из весов, напримерDancing Queenможно выразить как[-8.09650002, 3.95552071].
Чтобы порекомендовать элемент пользователю, ему необходимо прослушать вектор истории[1, 1, 1, 0, 0, 0]Введите обученную модель, активируйте некоторые скрытые узлы, а затем инвертируйте вектор, представляющий активацию узлов скрытого слоя, в модель, чтобы получить вероятность активации для каждого элемента, удалите элементы, которые слышал пользователь, а затем сравните вероятность Сортировка от большого к меньшему и выберите K, чтобы сделать рекомендацию TopK. Обработка выполняется очень быстро, используются только простые векторные вычисления, и ее можно использовать для создания рекомендаций в режиме онлайн в режиме реального времени.

Для отображения обратной связи, например, в случае с Netflix Prize, Руслан Салахутдинов и другие предложили улучшения в RBM.Видимый слой использует нейроны Softmax для представления ситуации подсчета очков, а для элементов, которые не были оценены, используются специальные нейроны.Конкатенация позволяет избежать конкатенации. ненужные вычисления, в то время как условные RBM могут учитывать влияние неявной обратной связи, например, какие элементы просматривал пользователь при обработке явной обратной связи. Все эти улучшения включают в себя усовершенствование процесса расчета и математических формул этой статьи.Подробности см. в статье.

Ссылаться на

echen/restricted-boltzmann-machines
Introduction to Restricted Boltzmann Machines
Restricted Boltzmann Machines for Collaborative Filtering