0x00 сводка
Сеть Deep Interest Network (DIN) была предложена группой точного направленного поиска и базового алгоритма Alimama в июне 2017 года. Его оценка CTR для индустрии электронной коммерции сосредоточена на полном использовании/извлечении информации из исторических данных о поведении пользователей.
В этой серии статей интерпретируются документы и исходный код, а также, кстати, разбираются некоторые концепции, связанные с глубоким обучением, и реализация TensorFlow.
В этой статье передается исходный код DINGitHub.com/Mouna99/Вниз…Анализ, давайте углубимся, чтобы увидеть, как автоматически обновляется слой внедрения.
0x01 Исходный код DIN
1.1 Вопрос
Выше мы проанализировали роль слоя внедрения, но оставили без ответа один вопрос:
- Как обновить слой внедрения, такой как mid_embeddings_var?
То есть в коде DIN, как обновить следующие переменные:
self.uid_embeddings_var = tf.get_variable("uid_embedding_var", [n_uid, EMBEDDING_DIM])
self.mid_embeddings_var = tf.get_variable("mid_embedding_var", [n_mid, EMBEDDING_DIM])
self.cat_embeddings_var = tf.get_variable("cat_embedding_var", [n_cat, EMBEDDING_DIM])
Потому что в DIN только одно место для инициализации эмбеддингов, а кода для итеративного обновления не найдено, что вызовет некоторые затруднения у новичков.
1.2 Ответы
Сначала кратко обсудим ответ: уровень встраивания обновляется (выводится автоматически) через оптимизатор и обновляется через session.run.
Встраивание в общем смысле — это в основном вес параметра предпоследнего слоя нейронной сети, который имеет только общее значение и относительное значение, а не локальное значение и абсолютное значение, которое связано с процессом генерации встраивания.
Любое вложение представляет собой случайное число в начале, а затем итеративно обновляется с помощью алгоритма оптимизации.Наконец, когда сеть сходится и прекращает итерацию, параметры каждого слоя сети относительно затвердевают, и получается таблица весов скрытого слоя ( в настоящее время это эквивалентно получению желаемого вложения), а затем мы можем просмотреть вложение каждого элемента по отдельности, просмотрев таблицу.
Соответствующий код в DIN выглядит следующим образом:
# 优化更新(自动求导)
self.optimizer = tf.train.AdamOptimizer(learning_rate=self.lr).minimize(self.loss)
......
# 通过 session.run 进行调用更新
def train(self, sess, inps):
if self.use_negsampling:
loss, accuracy, aux_loss, _ = sess.run([self.loss, self.accuracy, self.aux_loss, self.optimizer], feed_dict={
self.uid_batch_ph: inps[0],
self.mid_batch_ph: inps[1],
self.cat_batch_ph: inps[2],
self.mid_his_batch_ph: inps[3],
self.cat_his_batch_ph: inps[4],
self.mask: inps[5],
self.target_ph: inps[6],
self.seq_len_ph: inps[7],
self.lr: inps[8],
self.noclk_mid_batch_ph: inps[9],
self.noclk_cat_batch_ph: inps[10],
})
return loss, accuracy, aux_loss
else:
loss, accuracy, _ = sess.run([self.loss, self.accuracy, self.optimizer], feed_dict={
self.uid_batch_ph: inps[0],
self.mid_batch_ph: inps[1],
self.cat_batch_ph: inps[2],
self.mid_his_batch_ph: inps[3],
self.cat_his_batch_ph: inps[4],
self.mask: inps[5],
self.target_ph: inps[6],
self.seq_len_ph: inps[7],
self.lr: inps[8],
})
return loss, accuracy, 0
Здесь есть много частей, которые нам нужно объяснить.
0x02 Принцип
Большинство задач машинного обучения (глубокого обучения) заключаются в минимизации потерь с использованием оптимизатора для решения минимальных потерь, когда функция потерь четко определена.
Чтобы уменьшить потери, общий метод оптимизации фреймворка глубокого обучения обычно использует алгоритм градиентного спуска (Gradient Descent), который требует частных производных для каждой операции в формуле потерь, а затем использует цепное правило для их объединения.
2.1 Стохастический градиентный спуск SGD
Для дифференцируемой функции теоретически возможно найти ее минимум аналитически: минимум функции — это точка, где производная равна 0, поэтому вы просто находите все точки, где производная равна 0, а затем вычисляете, в какой точке функция имеет минимальное значение.
Применение этого метода к нейронной сети заключается в использовании аналитического метода для нахожденияФункция минимальных потерьВсе соответствующие значения веса. через уравнениеgradient(f)(W) = 0Найдите W, чтобы реализовать этот метод.
То есть решается оптимизацией на основе градиента, а параметры настраиваются побитно на основе текущих потерь на пакете случайных данных. Поскольку вы имеете дело с дифференцируемой функцией, вы можете вычислить ее градиент, а затем обновить веса в направлении, противоположном градиенту, и с каждым разом потери будут уменьшаться.
- Извлеките пакет данных, состоящий из обучающих выборок x и соответствующих целей y.
- Запустите сеть на x, чтобы получить предсказанное значение y_pred.
- Рассчитайте потери сети на этом пакете данных, который используется для измерения расстояния между y_pred и y.
- Вычислите градиент потерь по отношению к параметрам сети [обратный проход].
- Немного переместите параметр в противоположном направлении градиента, например
W -= step * gradient
, так что этот пакет данных Потери немного уменьшаются.
это называетсяМини-пакетный стохастический градиентный спуск(мини-пакетный стохастический градиентный спуск, также известный какМалая партия SGD).
Термин стохастический относится к тому факту, что каждый пакет данных выбирается случайным образом (стохастический — это научный синоним случайного).
2.2 Обратное распространение
Процесс обучения алгоритма обратного распространения заключается в вычислении ошибки в соответствии с Y_out, рассчитанным сетью, и фактическом реальном результате Y_label, а также в корректировке всех Wi и bi в формуле вдоль обратного распространения сети, чтобыошибкадостичь минимума. Подчеркните, что основная цель BP в глубоком обучении состоит в том, чтобы сделатьошибкадо минимума, так что используйтеошибкаВозьмем частные производные для всех влияющих факторов, которые оказались в середине.
Оптимизация нейронной сети с помощью алгоритма обратного распространения ошибки — это итеративный процесс.
- В начале каждой итерации сначала необходимо выбрать небольшую часть обучающих данных, и эта небольшая часть данных называется пакетом.
- Затем эта партия примеров получит результат прогнозирования модели нейронной сети с помощью алгоритма прямого распространения. Поскольку обучающие данные отмечены правильным ответом, можно рассчитать разрыв между прогнозируемым ответом текущей модели нейронной сети и правильным ответом, а также рассчитать функцию ошибок и потерь.
- Наконец, на основе разрыва между прогнозируемым значением и реальным значением алгоритм обратного распространения будет соответствующим образом обновлять значения параметров нейронной сети, чтобы прогнозируемые результаты модели нейронной сети на этом пакете были ближе к реальному ответу. . То есть сначала вычисляется градиент функции потерь нейронов выходного слоя, а затем вычисляется градиент функции потерь нейронов скрытого слоя. Затем обновите веса с помощью градиентов.
Прямой вывод начинается с первого слоя и вычисляет градиент ∂/∂X слой за слоем до последнего слоя. Обратный вывод заключается в том, чтобы начать с последнего слоя и вычислить градиент ∂Z/∂ слой за слоем к первому слою. Переднее рулевое управление фокусируется наКак ввод влияет на каждый слой, обратный вывод касаетсяКак каждый слой влияет на конечный результатиз.
2.3 Автоматический вывод
Автоматическая деривация означает, что каждый операционный/уровень выполняет прямое вычисление/обратное деривацию на основе своих собственных входных и выходных данных, в то время как платформа отвечает за сборку и планирование этих операционных/уровней, что означает, что вы определяете граф сети/вычисления через инфраструктуру. Фреймворк автоматически рассчитывает вперед и автоматически выводит.
В обычных средах глубокого обучения каждая операция (операция относится к наименьшей вычислительной единице, называемой уровнем в кафе) имеет две предопределенные функции: прямую и обратную (или градацию). Другими словами, вывод каждой операции предопределен или проталкивается вручную.
Когда вы определяете нейронную сеть, общая структура глубокого обучения интерпретирует ее как даг (направленный ациклический граф), каждый узел в даге представляет собой операцию, начиная с узла функции потерь, через правило цепочки шаг за шагом от После вычисления градиент каждого слоя нейронной сети вперед, минимальная степень детализации всего вычисления градиента dag является обратной функцией op (здесьруководство), а цепное правилоавтоматическийиз.
То же самое касается TensorFlow.
TensorFlow предоставляет интерфейс декларативного программирования. Пользователям не нужно заботиться о деталях вывода. Им нужно только определить модель для получения уравнения потерь, а затем использовать различные оптимизаторы, реализованные TensorFlow, для выполнения операций.
Это требует, чтобы сам TensorFlow предоставлял метод частной производной для каждой операции, и хотя мы используем операторы сложения, вычитания, умножения и деления Python, фактически TensorFlow перегружает оператор для фактического создания операции, такой как «Квадрат», которая может быть Пользователям проще составлять выражения.
Поэтому вывод TensorFlow фактически обеспечивает математическую реализацию вывода каждой операции, а затем использует цепное правило для нахождения производной всего выражения.
За подробностями мы можем обратиться к реализации RegisterGradient, а также к нескольким файлам, таким как nn_grad.py, math_grad.py.
Все функции в этих файлах обернуты декоратором RegisterGradient, и эти функции принимают два параметра, op и grad. Существуют также различные места, которые используют этот декоратор, пока операция зарегистрирована, например, пакет.
Пример использования RegisterGradient выглядит следующим образом:
@ops.RegisterGradient("Abs")
def _AbsGrad(op, grad):
x = op.inputs[0]
return grad * math_ops.sign(x)
RegisterGradient определяется следующим образом, который является декоратором для регистрации функции градиента op:
class RegisterGradient(object):
def __init__(self, op_type):
if not isinstance(op_type, six.string_types):
raise TypeError("op_type must be a string")
self._op_type = op_type
def __call__(self, f):
"""Registers the function `f` as gradient function for `op_type`."""
_gradient_registry.register(f, self._op_type)
return f
0x03 Оптимизатор
Правда неплохо, но как нейросеть пропускает обновление в обратном направлении? Для этого нужно смотреть оптимизатор.
Возвращаясь к уровню кода Python в TensorFlow, автоматическая часть деривации объединяется различными оптимизаторами:
- При составлении графика вам нужно написать только часть графа прямого потока данных.Подход TensorFlow заключается в том, что каждая операция включает свою формулу расчета градиента при построении графика, а обратная часть создается автоматически при формировании графа прямого расчета. и результаты прямого расчета будут сохранены, и они будут удалены, когда будет использован обратный расчет.
- Затем добавьте оптимизатор в конце (например, GradientDescentOptimizer, AdamOptimizer).
- последний звонок
minimize()
Метод автоматически завершит обратную часть построения графа потока данных.
Здесь, в DIEN, код выглядит следующим образом:
ctr_loss = - tf.reduce_mean(tf.log(self.y_hat) * self.target_ph)
self.loss = ctr_loss
if self.use_negsampling:
self.loss += self.aux_loss
self.optimizer = tf.train.AdamOptimizer(learning_rate=self.lr).minimize(self.loss)
3.1 Базовый класс оптимизатора
Все оптимизаторы TF унаследованы от класса Optimizer.В этом классе много методов.Несколько важных методов: минимизация, вычисление_градиентов, применение_градиентов и серия слотов.
- compute_gradients: Пройти в убыток, если вы не передадите в var_list, то по умолчанию будут все обучаемые переменные, а возвратом будет список пар (градиент, переменная).
- apply_gradients: передать пары (градиент, переменная), чтобы применить градиент к переменной. То, как конкретный градиент обновляется до переменной, реализуется четырьмя методами: _apply_dense, _resource_apply_dense, _apply_sparse и _resource_apply_spars.
- minimize: вычислить_градиенты + применить_градиенты
- серия слотов: Введите переменную и имя и получите переменную с trainable=False, которая используется для записи промежуточного значения в оптимизаторе.Например, в Momentum запишите импульс.
Этот метод базового класса Optimizer зарезервирован для каждого реализующего подкласса._create_slots()
,_prepare()
,_apply_dense()
,_apply_sparse()
Выходит четыре интерфейса, и только что построенному оптимизатору нужно переписать или расширить некоторые функции класса оптимизатора;
3.2 Процесс обратного распространения
Весь процесс обратного распространения можно разделить на три шага, которые нужно выполнить только с помощью функции минимизации():
- Вычислить градиент каждой части слой за слоем,
compute_gradients()
; - Обработка градиентов по мере необходимости;
- обновить градиент до параметров,
apply_gradients();
То есть обновить каждый параметр в var_list в сторону минимизации потерь;
код показывает, как показано ниже:
def minimize(self, loss, global_step=None, var_list=None,
gate_gradients=GATE_OP, aggregation_method=None,
colocate_gradients_with_ops=False, name=None,
grad_loss=None):
grads_and_vars = self.compute_gradients(
loss, var_list=var_list, gate_gradients=gate_gradients,
aggregation_method=aggregation_method,
colocate_gradients_with_ops=colocate_gradients_with_ops,
grad_loss=grad_loss)
vars_with_grad = [v for g, v in grads_and_vars if g is not None]
return self.apply_gradients(grads_and_vars, global_step=global_step, name=name)
3.2.1 compute_gradients
Эта функция используется для вычисления градиента потерь для обучаемой переменной val_list и, наконец, возвращает список кортежей, то есть [(градиент, переменная),...].
Значение параметра:
- loss: Тензор для оптимизации
-
val_list: Optional list or tuple of
tf.Variable
to update to minimizeloss
. Defaults to the list of variables collected in the graph under the keyGraphKeys.TRAINABLE_VARIABLES
.
Основная логика следующая:
- Создайте последовательный var_list на основе всех операций в исходном графе вычислений. То есть автоматически найти все обучаемые_переменные в графе расчета и занести их в var_list, это параметры во всей сети;
- Пройдите этот список в обратном порядке, для каждогонужно руководствоив состоянии вестиОператор (то есть оператор, который определил соответствующую функцию градиента) вызывает свою функцию градиента;
- Затем перевернуть другую часть расчетного графа по направлению исходного расчетного графа (ввод и вывод меняются местами, а тензор исходных данных заменяется тензором градиента), то есть в граф вставляется Op градиентов , так что обратная производная получается На этом процесс этой струнной диаграммы завершен;
Среди них функцию _get_processor можно понимать как метод быстрого обновления переменных, и каждый процессор будет содержать функцию, такую как update_op, для выполнения операций обновления переменных.
Формула обновления переменной:
код показывает, как показано ниже:
def compute_gradients(self, loss, var_list=None,
gate_gradients=GATE_OP,
aggregation_method=None,
colocate_gradients_with_ops=False,
grad_loss=None):
self._assert_valid_dtypes([loss])
if grad_loss is not None:
self._assert_valid_dtypes([grad_loss])
if var_list is None:
var_list = (
variables.trainable_variables() +
ops.get_collection(ops.GraphKeys.TRAINABLE_RESOURCE_VARIABLES))
else:
var_list = nest.flatten(var_list)
var_list += ops.get_collection(ops.GraphKeys._STREAMING_MODEL_PORTS)
processors = [_get_processor(v) for v in var_list]
var_refs = [p.target() for p in processors]
grads = gradients.gradients(
loss, var_refs, grad_ys=grad_loss,
gate_gradients=(gate_gradients == Optimizer.GATE_OP),
aggregation_method=aggregation_method,
colocate_gradients_with_ops=colocate_gradients_with_ops)
if gate_gradients == Optimizer.GATE_GRAPH:
grads = control_flow_ops.tuple(grads)
grads_and_vars = list(zip(grads, var_list))
return grads_and_vars
3.2.2 gradients
Фактическое определение градиентов находится вtensorflow/python/ops/gradients_impl.py
середина. Преобразуйте весь процесс вывода в функцию ys=f(xs).
Проще говоря, это вычисление набора выходных тензоровys = [y0, y1, ...]
на входном тензореxs = [x0, x1, ...]
градиент , для каждогоxi
имеютgrad_i = sum[dy_j/dx_i for y_j in ys]
. по умолчанию,grad_loss
даNone
,В настоящее времяgrad_ys
инициализируется вектором всех единиц.
Некоторые параметры градиентов следующие:
- xs — это список переменных, введенных в var_list (на самом деле в этом процессе здесь хранится операция, соответствующая каждой переменной в графе вычислений).
- Ys в параметре - это потеря, которая является тензором для расчета значения потери, то есть конечным узлом тензора, окончательно сгенерированным бизнес-логикой пользователя, Из этого узла могут быть получены все графики.
-
grad_ys
сохранить вычисленный градиент; -
gate_gradients
— логическая переменная, указывающая, все ли градиенты рассчитываются перед использованием, если установлено значениеTrue
, чтобы избежать условий гонки;
Этот метод поддерживает две важные переменные
- очередь
queue
, в очереди хранятся все операторы, исходящая степень которых равна 0 в графе вычислений - словарь
grads
, ключ словаря — это сам оператор, а значение — список градиентов, получаемых на каждом выходе оператора
При обратном распространении для нахождения градиента каждый раз, когда оператор извлекается из очереди, градиенты его выходных переменных будут складываться (в соответствии с теоремой о полном дифференциале), чтобы получитьout_grads
, а затем получить соответствующую функцию расчета градиентаgrad_fn
. операторop
себя иout_grads
будет переданоgrad_fn
В качестве параметров найдите градиент входа.
Основная логика следующая:
- Создайте последовательный список на основе всех операций в исходном графе вычислений, который на самом деле является топологическим порядком на графе;
- Пройдите список в обратном порядке, для каждогонужно руководствоив состоянии вестиОператор (то есть оператор, который определил соответствующую функцию градиента) вызывает свою функцию градиента;
- Затем переверните другую часть графа вычислений в направлении исходного графа (ввод и вывод меняются местами, а тензор исходных данных заменяется тензором градиента);
Конкретный код выглядит следующим образом:
def gradients(ys,
xs,
grad_ys=None,
name="gradients",
colocate_gradients_with_ops=False,
gate_gradients=False,
aggregation_method=None,
stop_gradients=None):
to_ops = [t.op for t in ys]
from_ops = [t.op for t in xs]
grads = {}
# Add the initial gradients for the ys.
for y, grad_y in zip(ys, grad_ys):
_SetGrad(grads, y, grad_y)
# Initialize queue with to_ops.
queue = collections.deque()
# Add the ops in 'to_ops' into the queue.
to_ops_set = set()
for op in to_ops:
ready = (pending_count[op._id] == 0)
if ready and op._id not in to_ops_set:
to_ops_set.add(op._id)
queue.append(op)
while queue:
# generate gradient subgraph for op.
op = queue.popleft()
with _maybe_colocate_with(op, colocate_gradients_with_ops):
if loop_state:
loop_state.EnterGradWhileContext(op, before=True)
out_grads = _AggregatedGrads(grads, op, loop_state, aggregation_method)
if loop_state:
loop_state.ExitGradWhileContext(op, before=True)
if has_out_grads and (op._id not in stop_ops):
if is_func_call:
func_call = ops.get_default_graph()._get_function(op.type)
grad_fn = func_call.python_grad_func
else:
try:
grad_fn = ops.get_gradient_function(op)
for i, (t_in, in_grad) in enumerate(zip(op.inputs, in_grads)):
if in_grad is not None:
if (isinstance(in_grad, ops.Tensor) and
t_in.dtype != dtypes.resource):
try:
in_grad.set_shape(t_in.get_shape())
_SetGrad(grads, t_in, in_grad)
if loop_state:
loop_state.ExitGradWhileContext(op, before=False)
3.2.3 apply_gradients
Функция этой функции состоит в том, чтобыcompute_gradients()
Возвращаемое значение используется в качестве входного параметра для обновления переменной, то есть в соответствии с ранее полученным градиентом направление градиента распространяется на веса и смещения для обновления параметра.
так почемуminimize()
Будет ли он разделен на два этапа? Причина в том, что в некоторых случаях нам нужно внести определенные исправления в градиент, например, чтобы предотвратить исчезновение градиента или взрыв градиента, нам нужно вмешаться заранее, чтобы предотвратить появление программы.NanНеловкая ситуация, иногда нам нужно умножить вычисленный градиент на вес или другие запутанные причины, поэтому мы разделяем два шага.
Основная логика следующая:
- Для g, v, p (грады, вары, процессоры) интегрируйте их в tuple(converted_grads_and_vars);
- Просмотрите список параметров v и примените функцию self._create_slots для каждого параметра, чтобы создать некоторые параметры, которые поставляются с оптимизатором;
- Вызовите функцию prepare(), чтобы создать все необходимые тензоры перед применением градиента;
- траверс
grad, var, processor in converted_grads_and_vars
, применить ops.colocate_with(var), функция состоит в том, чтобы гарантировать, что обновление каждого параметра var происходит на одном и том же устройстве; - Функция ops.control_dependencies() используется для управления графом потока вычислений, определяя порядок вычислений для некоторых узлов в графе;
- Применить назначение к каждой переменной, что отражено в
update_ops.append(processor.update_op(self, grad))
,Если естьglobal_step
Если это так, global_step нужно добавить 1. - в конечном итоге вернет
train_op
.train_op
Это один из параметров, предоставляемых клиентом для выборки сеанса во время обычного процесса обучения, то есть после выполнения операции параметры модели будут обновлены и начнется обучение следующего пакета. Тогда это также означает, что вычислительный граф, задействованный в этом методе, будет реализовывать логику обучения в документе описания.
Конкретный код:
def apply_gradients(self, grads_and_vars, global_step=None, name=None):
grads_and_vars = tuple(grads_and_vars) # Make sure repeat iteration works.
converted_grads_and_vars = []
for g, v in grads_and_vars:
if g is not None:
# Convert the grad to Tensor or IndexedSlices if necessary.
g = ops.convert_to_tensor_or_indexed_slices(g)
p = _get_processor(v)
converted_grads_and_vars.append((g, v, p))
converted_grads_and_vars = tuple(converted_grads_and_vars)
var_list = [v for g, v, _ in converted_grads_and_vars if g is not None]
with ops.control_dependencies(None):
self._create_slots([_get_variable_for(v) for v in var_list])
update_ops = []
with ops.name_scope(name, self._name) as name:
self._prepare()
for grad, var, processor in converted_grads_and_vars:
if grad is None:
continue
scope_name = var.op.name if context.in_graph_mode() else ""
with ops.name_scope("update_" + scope_name), ops.colocate_with(var):
update_ops.append(processor.update_op(self, grad))
if global_step is None:
apply_updates = self._finish(update_ops, name)
else:
with ops.control_dependencies([self._finish(update_ops, "update")]):
with ops.colocate_with(global_step):
apply_updates = state_ops.assign_add(global_step, 1, name=name).op
train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP)
if apply_updates not in train_op:
train_op.append(apply_updates)
return apply_updates
3.3 AdamOptimizer
DIEN использует оптимизатор AdamOptimizer.
Имя Адам происходит отАдаптивная оценка момента(Adaptive Moment Estimation), который также является вариантом алгоритма градиентного спуска, но скорость обучения каждого параметра итерации имеет определенный диапазон, и скорость обучения (размер шага) не станет большой из-за большого градиента, а значения параметры относительно относительно стабильны.
概率论中矩的含义是:如果一个随机变量 X 服从某个分布,X 的一阶矩是 E(X),也就是样本平均值,X 的二阶矩就是 E(X^2),也就是样本平方的平均值。
Алгоритм Адама динамически регулирует скорость обучения каждого параметра, используя первую и вторую моментные оценки градиента. tf.train.AdamOptimizer, предоставляемый TensorFlow, может контролировать скорость обучения.После коррекции смещения скорость обучения каждой итерации имеет определенный диапазон, что делает параметры относительно стабильными.
При использовании рассчитанной производной для корректировки весаГрадиент матрицы Embedding специально обрабатывается, и обновляется только локальная часть, см. функцию Adagrad.update в файле Optimization.py.
3.3.1 _prepare
существует_prepare
через функциюconvert_to_tensor
метод для хранения тензорной версии входных параметров.
def _prepare(self):
self._lr_t = ops.convert_to_tensor(self._lr, name="learning_rate")
self._beta1_t = ops.convert_to_tensor(self._beta1, name="beta1")
self._beta2_t = ops.convert_to_tensor(self._beta2, name="beta2")
self._epsilon_t = ops.convert_to_tensor(self._epsilon, name="epsilon")
3.3.2 _create_slots
_create_slots
Функции используются для создания параметров, таких как _beta1_power, _beta2_power
def _create_slots(self, var_list):
first_var = min(var_list, key=lambda x: x.name)
create_new = self._beta1_power is None
if not create_new and context.in_graph_mode():
create_new = (self._beta1_power.graph is not first_var.graph)
if create_new:
with ops.colocate_with(first_var):
self._beta1_power = variable_scope.variable(self._beta1,
name="beta1_power",
trainable=False)
self._beta2_power = variable_scope.variable(self._beta2,
name="beta2_power",
trainable=False)
# Create slots for the first and second moments.
for v in var_list:
self._zeros_slot(v, "m", self._name)
self._zeros_slot(v, "v", self._name)
функция**_apply_dense
и_resource_apply_dense
используется при реализацииtraining_ops.apply_adam
иtraining_ops.resource_apply_adam
**метод.
функция**_apply_sparse
и_resource_apply_sparse
Он в основном используется в операции обновления разреженных векторов, а конкретная реализация находится в функции_apply_sparse_shared
**середина.
_apply_sparse_shared
функции, сначала получить требуемые значения параметров и сохранить их в переменных, а затем в соответствии с процессом алгоритма Адама сначала вычислить скорость обучения, а затем вычислить два Momentum , потому что это обновление разреженного тензора, поэтому используйте ** после вычисления значения обновления
scatter_add
чтобы завершить операцию сложения, и, наконец,var_update
иm_t
,v_t
Операция обновления помещается вcontrol_flow_ops.group
**середина.
0x04 Session.run
Оптимизатор построен, осталось вызватьsession.run
обновить.
Вызов run один раз означает однократное выполнение графа потока данных.В обучающем коде TensorFlow он обычно вызывается несколько раз в цикле.sess.run()
, бег - это этап тренировочного процесса.
fetches — входной параметр метода run.Этот параметр может быть данными во многих формах, а конечное возвращаемое значение run будет иметь ту же структуру, что и fetches.
На данный момент анализ DIN подошел к концу, и в следующей части начнется анализ DIEN, так что следите за обновлениями.
0xEE Личная информация
★★★★★★Думая о жизни и технологиях★★★★★★
Публичный аккаунт WeChat:мысли Росси
Если вы хотите получать своевременные новости о статьях, написанных отдельными лицами, или хотите видеть технические материалы, рекомендованные отдельными лицами, обратите внимание.
ссылка 0xFF
Интерпретация TensorFlow SyncReplicasOptimizer
Распаковка TensorFlow (1): Session.Run()
Яма исходного кода TensorFlow (2) Сессия
Анализ исходного кода тензорного потока (5) session.run()
Оптимизатор в Tensorflow — подробное объяснение AdamOptimizer
[TensorFlow] Анализ исходного кода оптимизатора AdamOptimizer
Исходный код графического тензорного потока
Подробное объяснение сеанса, графика, операции и тензора в TensorFlow
Распаковка TensorFlow (2): реализация модели потока данных TF и автоматическое получение
Боевая серия TensorFlow 3 — реализация обратного распространения
Примечания к чтению исходного кода оптимизатора tensorflow
обучение тензорному потоку (3)
Я понимаю правда, но как найти градиент обратного распространения нейронной сети?
В какой части кода реализован автоматический вывод TensorFlow?
Интерпретация TensorFlow SyncReplicasOptimizer
Суть операции обратного распространения с использованием матрицы в нейронной сети