1. Механизм внимания
Механизм внимания: также известный как механизм внимания, как следует из названия, это технология, которая позволяет модели сосредоточиться на важной информации, полностью изучить и усвоить ее и может действовать на любой модели последовательности.
С точки зрения роли внимания мы можем классифицировать типы внимания с двух точек зрения: Пространственное внимание, временное внимание. Такая классификация больше относится к прикладному уровню, а от функции внимания ее можно разделить на мягкое внимание и жесткое внимание, о чем мы и говорили, векторное распределение вывода внимания является своего рода одним горячим. распределение также является мягким мягким распределением, которое напрямую влияет на выбор контекстной информации.
Зачем присоединяться Внимание:
Когда входная последовательность очень длинная, модели трудно изучить разумное векторное представление.
Когда последовательность вводится, по мере того, как последовательность продолжает расти, производительность исходной модели временного шага становится все хуже и хуже из-за ошибочной структуры исходной модели временного шага, то есть всего контекстного ввода. информация ограничена При фиксированной длине возможности всей модели также ограничены, и мы будем называть эту примитивную модель простой моделью кодера-декодера.
Структуру кодека нельзя объяснить, что делает невозможным его проектирование.
Основная идея механизма Attention состоит в том, чтобы сломать ограничение, заключающееся в том, что традиционная структура кодер-декодер полагается на внутренний вектор фиксированной длины при кодировании и декодировании. Механизм внимания реализуется путем сохранения промежуточных результатов вывода кодировщика LSTM во входной последовательности, а затем обучения модели выборочному изучению этих входных данных и связыванию с ними выходной последовательности при выводе модели.
Другими словами, вероятность генерации каждого элемента в выходной последовательности зависит от того, какие элементы были выбраны во входной последовательности.
Модель, основанная на внимании, на самом деле является мерой сходства.Текущий ввод примерно аналогичен целевому состоянию, поэтому вес текущего ввода будет больше. Это чтобы добавить внимание к оригинальной модели.
В частности, существует проблема с моделью LSTM/RNN, использующей традиционную структуру кодер-декодер: независимо от входной длины она кодируется в векторное представление фиксированной длины, из-за чего модель плохо обучается для длинных входных последовательностей (декодирование неэффективно). ). Механизм внимания преодолевает вышеупомянутые проблемы.Принцип заключается в том, чтобы выборочно сосредоточиться на соответствующей информации на входе, когда модель выводит. Методы, использующие механизм внимания, широко используются в различных задачах прогнозирования последовательности, включая перевод текста, распознавание речи и т. д.
2. Код
import os
import re
import csv
import codecs
import numpy as np
import pandas as pd
from keras import backend as K
from keras.engine.topology import Layer
from keras import initializers, regularizers, constraints
np.random.seed(2018)
class Attention(Layer):
def __init__(self,
W_regularizer=None, b_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
self.supports_masking = True
# self.init = initializations.get('glorot_uniform')
self.init = initializers.get('glorot_uniform')
self.W_regularizer = regularizers.get(W_regularizer)
self.b_regularizer = regularizers.get(b_regularizer)
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.bias = bias
self.features_dim = 0
super(Attention, self).__init__(**kwargs)
def build(self, input_shape):
self.step_dim = input_shape[1]
assert len(input_shape) == 3 # batch ,timestep , num_features
print(input_shape)
self.W = self.add_weight((input_shape[-1],), #num_features
initializer=self.init,
name='{}_W'.format(self.name),
regularizer=self.W_regularizer,
constraint=self.W_constraint)
self.features_dim = input_shape[-1]
if self.bias:
self.b = self.add_weight((input_shape[1],),#timesteps
initializer='zero',
name='{}_b'.format(self.name),
regularizer=self.b_regularizer,
constraint=self.b_constraint)
else:
self.b = None
self.built = True
def compute_mask(self, input, input_mask=None):
# do not pass the mask to the next layers
return None
def call(self, x, mask=None):
features_dim = self.features_dim
step_dim = self.step_dim
print(K.reshape(x, (-1, features_dim)))# n, d
print(K.reshape(self.W, (features_dim, 1)))# w= dx1
print(K.dot(K.reshape(x, (-1, features_dim)), K.reshape(self.W, (features_dim, 1))))#nx1
eij = K.reshape(K.dot(K.reshape(x, (-1, features_dim)), K.reshape(self.W, (features_dim, 1))), (-1, step_dim))#batch,step
print(eij)
if self.bias:
eij += self.b
eij = K.tanh(eij)
a = K.exp(eij)
# apply mask after the exp. will be re-normalized next
if mask is not None:
# Cast the mask to floatX to avoid float64 upcasting in theano
a *= K.cast(mask, K.floatx())
a /= K.cast(K.sum(a, axis=1, keepdims=True) + K.epsilon(), K.floatx())
print(a)
a = K.expand_dims(a)
print("expand_dims:")
print(a)
print("x:")
print(x)
weighted_input = x * a
print(weighted_input.shape)
return K.sum(weighted_input, axis=1)
def compute_output_shape(self, input_shape):
# return input_shape[0], input_shape[-1]
return input_shape[0], self.features_dim
3. Резюме
В общем, механизм внимания представляет собой механизм взвешенного суммирования, до тех пор, пока мы используем взвешенное суммирование, независимо от того, какое причудливое взвешивание или причудливое суммирование вы используете, до тех пор, пока вы вычисляете скрытое состояние на основе существующей информации Взвешенное и суммированное, то используется внимание, а так называемое самовнимание заключается только в взвешенном суммировании внутри предложения (в отличие от взвешенного суммирования скрытого состояния кодировщика декодером в seq2seq).
Лично я считаю, что внимание к себе имеет более широкий охват, а ключ-значение на самом деле является более широким определением внимания. Предыдущее внимание может быть покрыто вниманием с ключом-значением. Например, много раз мы ставили k и v. Все это считается одним и тем же. , а при выполнении self также может быть quey=key=value.