github: https://github.com/sephiroce/tfsr/tree/exprimental
Я пытаюсь воспроизвести точность распознавания, описанную в статье для преобразования речи [1]. Наказание за внимание - техника, которую я не мог полностью понять. Это описание штрафа за внимание в статье.
«Кроме того, мы поощряли внимание модели к более близким позициям, добавляя больший штраф к весам внимания более удаленных пар позиций».
Я понял, что это означает добавление меньших отрицательных значений для большего отклонения от диагонали в масштабированных логитах внимания (до маскирования), за исключением первого многоголовочного внимания в декодерах.
Это фрагмент кода для вычисления внимания weights.
# Q * trans(K): (..., seq_len_q, seq_len_k)
matmul_qk = tf.matmul(query, key, transpose_b=True)
# scaled matmul_qk: ( Q * trans(K) ) / sqrt(d_k)
dimension_of_key = tf.cast(tf.shape(key)[-1], tf.float32)
scaled_attention_logits = matmul_qk / tf.math.sqrt(dimension_of_key)
# add the mask to the scaled tensor
if mask is not None:
scaled_attention_logits += (mask * -1e9)
# softmax is normalized on the last axis (seq_len_k) so that the scores
# add up to 1.
attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)
# Adding penalty to attention weights and linearly re-normalize it.
if attention_penalty is not None and att_penalty_scale > 0:
attention_weights += (attention_penalty * att_penalty_scale)
attention_weights += tf.math.abs(tf.math.reduce_min(attention_weights))
inv_sum = 1 / tf.math.reduce_sum(attention_weights, axis=-1)
attention_weights = tf.einsum('ijlm,ijl->ijlm', attention_weights, inv_sum)
Фрагмент исходного кода ниже предназначен для создания матрицы штрафов за внимание. Я не смог найти никакого эффективного способа создания матрицы штрафов за внимание для вторых весов внимания с несколькими головками в декодерах, поскольку карты внимания не диагональны. Таким образом, сначала я пытаюсь применить наказание за внимание к кодировщикам. Исходный код назначает линейно более высокие штрафы для более удаленных элементов от диагонали.
Существует два гиперпараметра, таких как Внимание_Пеналь__салон (это похоже на penalty_values
, который предложил Йиндржих) и ширина диагональной линии.
Я мог бы добавить такую опцию, как stripe_step_size
. В настоящее время stripe_step_size
можно интерпретировать как 1.
def create_attention_penalty(inp_len, tar_len, num_heads, attention_penalty_width):
max_inp_len = tf.cast(tf.math.reduce_max(inp_len), tf.int32)
n_batch = tf.shape(inp_len)[0]
enc_att_penalty = tf.ones([n_batch, num_heads, max_inp_len, max_inp_len])
accum = tf.zeros(([n_batch, num_heads, max_inp_len, max_inp_len]))
for i in range(attention_penalty_width - 1, max_inp_len - 1):
accum += tf.linalg.band_part(enc_att_penalty, i, i, name=None) - 1
enc_att_penalty = accum
return enc_att_penalty, None
Несмотря на то, что я реализовал, как я понимаю, я не смог добиться какого-либо улучшения точности. И есть еще одна обратная сторона этой реализации. Скорость тренировки становилась все медленнее.
В) Как эффективно применять этот метод штрафов за внимание к квадратным и неквадратным весам внимания?
Ссылка
[1] Линхао Донг, Шуан Сюй , Бо Сюй, Речевой преобразователь: неповторяющаяся модель последовательности-последовательности для распознавания речи, ICASSP 2018, https://ieeexplore.ieee.org/document/8462506