„Hands-On Deep Learning“ – 65 Aufmerksamkeitswerte

Mushens Version von „Learning Deep Learning by Hands“ ist eine Lernnotiz, in der der Lernprozess aufgezeichnet wird. Für detaillierte Inhalte kaufen Sie bitte Bücher.
Link zum Video der B-Station,
Open-Source-Tutorial-Link

Aufmerksamkeitswert

Fügen Sie hier eine Bildbeschreibung ein

Abschnitt 64 verwendet einen Gaußschen Kernel, um die Beziehung zwischen Abfragen und Schlüsseln zu modellieren . Der exponentielle Teil im Gaußschen Kernel kann als Aufmerksamkeitsbewertungsfunktion ( ) betrachtet werden , die als Bewertungsfunktionattention scoring function bezeichnet wird . Anschließend wird die Ausgabe dieser Funktion zur Operation in die Softmax-Funktion eingegeben und die Wahrscheinlichkeitsverteilung des entsprechenden Werts berechnet Der Schlüssel (d. h. das Aufmerksamkeitsgewicht) wird ermittelt. . Die Ausgabe des endgültigen Aufmerksamkeitspoolings basiert auf der gewichteten Summe der Werte dieser Aufmerksamkeitsgewichte.

Fügen Sie hier eine Bildbeschreibung ein

Die obige Abbildung zeigt, wie die Ausgabe des Aufmerksamkeitspoolings als gewichtete Summe von Werten berechnet wird, wobei α \alphaα bezeichnet die Aufmerksamkeitsbewertungsfunktion. Da Aufmerksamkeitsgewichte Wahrscheinlichkeitsverteilungen sind, ist die gewichtete Summe im Wesentlichen ein gewichteter Durchschnitt.

Fügen Sie hier eine Bildbeschreibung ein

Die Längen von Abfrage, Schlüssel und Wert können unterschiedlich sein, Abfrage qi q_iQichund Schlüssel ki k_ikichDas Aufmerksamkeitsgewicht wird durch die Aufmerksamkeitsbewertungsfunktion α \alpha übergebenα ordnet zwei Vektoren Skalaren zu und wählt nach der Softmax-Operation ein anderesα \alphaα führt zu unterschiedlichen Aufmerksamkeitsbündelungsoperationen.

additive Aufmerksamkeit

Wenn Abfragen und Schlüssel unterschiedliche Längen haben, kann die additive Aufmerksamkeit als Bewertungsfunktion verwendet werden.

Fügen Sie hier eine Bildbeschreibung ein

Skalierte Punktproduktaufmerksamkeit

Wenn die Abfrage und der Schlüssel dieselbe Länge haben, verwenden Sie das Skalarprodukt, um eine Bewertungsfunktion mit höherer Recheneffizienz zu erhalten, und dividieren Sie diese durch die Länge d, um die Länge weniger zu beeinflussen. (Unter der Annahme, dass sowohl die Abfrage als auch der Schlüssel unabhängige Zufallsvariablen mit einem Mittelwert von Null und einer Einheitsvarianz sind, hat das Skalarprodukt zweier Vektoren einen Mittelwert von 0 und eine Varianz d. Um sicherzustellen, dass die Varianz des Skalarprodukts unabhängig von der Vektorlänge 1 beträgt unabhängig von der Länge des Vektors, und teile dann das Skalarprodukt durch d \sqrt{d}D Erhalten Sie die Aufmerksamkeit des skalierten Skalarprodukts ( scaled dot-product attention).

Fügen Sie hier eine Bildbeschreibung ein

Zusammenfassen

Die Aufmerksamkeitsbewertung ist die Ähnlichkeit zwischen Abfrage und Schlüssel, und die Aufmerksamkeitsgewichtung ist das Softmax-Ergebnis der Bewertung.
Fügen Sie hier eine Bildbeschreibung ein

praktisches Lernen

Aufmerksamkeitsbewertungsfunktion

import math
import torch
from torch import nn
from d2l import torch as d2l

# 掩蔽softmax操作
def masked_softmax(X, valid_lens):
    """通过在最后一个轴上掩蔽元素来执行softmax操作"""
    # X:3D张量,valid_lens:1D或2D张量
    if valid_lens is None:
        return nn.functional.softmax(X, dim=-1)
    else:
        shape = X.shape
        if valid_lens.dim() == 1:
            valid_lens = torch.repeat_interleave(valid_lens, shape[1])
        else:
            valid_lens = valid_lens.reshape(-1)
        # 最后一轴上被掩蔽的元素使用一个非常大的负值替换,从而其softmax输出为0
        X = d2l.sequence_mask(X.reshape(-1, shape[-1]), valid_lens,
                              value=-1e6)
        return nn.functional.softmax(X.reshape(shape), dim=-1)

masked_softmax(torch.rand(2, 2, 4), torch.tensor([2, 3])) # 两个批次
tensor([[[0.4074, 0.5926, 0.0000, 0.0000],
         [0.5424, 0.4576, 0.0000, 0.0000]],

        [[0.3432, 0.3032, 0.3536, 0.0000],
         [0.3251, 0.4291, 0.2458, 0.0000]]])
masked_softmax(torch.rand(2, 2, 4), torch.tensor([[1, 3], [2, 4]]))
tensor([[[1.0000, 0.0000, 0.0000, 0.0000],
         [0.3577, 0.2927, 0.3496, 0.0000]],

        [[0.5817, 0.4183, 0.0000, 0.0000],
         [0.2940, 0.2301, 0.2602, 0.2157]]])

additive Aufmerksamkeit

#@save
class AdditiveAttention(nn.Module):
    """加性注意力"""
    def __init__(self, key_size, query_size, num_hiddens, dropout, **kwargs):
        super(AdditiveAttention, self).__init__(**kwargs)
        self.W_k = nn.Linear(key_size, num_hiddens, bias=False)
        self.W_q = nn.Linear(query_size, num_hiddens, bias=False)
        self.w_v = nn.Linear(num_hiddens, 1, bias=False)
        self.dropout = nn.Dropout(dropout)

    def forward(self, queries, keys, values, valid_lens): # valid_lens:多少对key-value对是需要考虑的
        queries, keys = self.W_q(queries), self.W_k(keys)
        # 在维度扩展后,
        # queries的形状:(batch_size,查询的个数,1,num_hidden)
        # key的形状:(batch_size,1,“键-值”对的个数,num_hiddens)
        # 使用广播方式进行求和
        features = queries.unsqueeze(2) + keys.unsqueeze(1) # 升到四维
        features = torch.tanh(features)
        # self.w_v仅有一个输出,因此从形状中移除最后那个维度。
        # scores的形状:(batch_size,查询的个数,“键-值”对的个数)
        scores = self.w_v(features).squeeze(-1)
        self.attention_weights = masked_softmax(scores, valid_lens) # batch_size*查询个数*10
        # values的形状:(batch_size,“键-值”对的个数,值的维度)
        return torch.bmm(self.dropout(self.attention_weights), values) # 最后得到的是query长度*value长度

queries, keys = torch.normal(0, 1, (2, 1, 20)), torch.ones((2, 10, 2)) # 20个query长度是1,10个key长度是2
# values的小批量,两个值矩阵是相同的
values = torch.arange(40, dtype=torch.float32).reshape(1, 10, 4).repeat(2, 1, 1) # 10个value长度是4
valid_lens = torch.tensor([2, 6])

attention = AdditiveAttention(key_size=2, query_size=20, num_hiddens=8,
                              dropout=0.1)
attention.eval()
attention(queries, keys, values, valid_lens) # 2*1*4
tensor([[[ 2.0000,  3.0000,  4.0000,  5.0000]],

        [[10.0000, 11.0000, 12.0000, 13.0000]]], grad_fn=<BmmBackward0>)
# attention.attention_weights 2* 1* 10 中间维度被加权
print(attention.attention_weights.shape)
d2l.show_heatmaps(attention.attention_weights.reshape((1, 1, 2, 10)),
                  xlabel='Keys', ylabel='Queries')

Fügen Sie hier eine Bildbeschreibung ein

Skalierte Punktproduktaufmerksamkeit

#@save
class DotProductAttention(nn.Module):
    """缩放点积注意力"""
    def __init__(self, dropout, **kwargs):
        super(DotProductAttention, self).__init__(**kwargs)
        self.dropout = nn.Dropout(dropout)

    # queries的形状:(batch_size,查询的个数,d)
    # keys的形状:(batch_size,“键-值”对的个数,d)
    # values的形状:(batch_size,“键-值”对的个数,值的维度)
    # valid_lens的形状:(batch_size,)或者(batch_size,查询的个数)
    def forward(self, queries, keys, values, valid_lens=None):
        d = queries.shape[-1]
        # 设置transpose_b=True为了交换keys的最后两个维度
        scores = torch.bmm(queries, keys.transpose(1,2)) / math.sqrt(d)
        self.attention_weights = masked_softmax(scores, valid_lens)
        return torch.bmm(self.dropout(self.attention_weights), values)

queries = torch.normal(0, 1, (2, 1, 2))
attention = DotProductAttention(dropout=0.5)
attention.eval()
attention(queries, keys, values, valid_lens)

d2l.show_heatmaps(attention.attention_weights.reshape((1, 1, 2, 10)),
                  xlabel='Keys', ylabel='Queries')
tensor([[[ 2.0000,  3.0000,  4.0000,  5.0000]],

        [[10.0000, 11.0000, 12.0000, 13.0000]]])

Fügen Sie hier eine Bildbeschreibung ein

Supongo que te gusta

Origin blog.csdn.net/cjw838982809/article/details/132093762
Recomendado
Clasificación