フォーカスノート

10.2. Attention Pooling: Nadaraya-Watson Kernel Regression - 実践的な深層学習 2.0.0 ドキュメント

私が間違っている場合は修正してください

ずっと考えていて、やっと少しわかったのですが、

1. 実連続 x を与えて実連続 y を得る関数を設計します。

2. テスト用に不連続な離散 x のバッチをランダムに生成し、テスト x を関数に入れ、特定の偏差を追加してテスト y を取得します。

3. このとき、関数の式が分からないと仮定して、テスト x とテスト y のみを使用してグラフを区切ります。

3.1 最も単純なケースでは、すべてのテスト y の平均を取り、元の関数に適合する直線を作成します.これは平均収束とも呼ばれ、結果は明らかに受け入れられません.

3.2 平均収束失敗の理由は、入力 xi が無視されることです

4. 実数 x を 50 列にコピーします。これは、行のすべての列が同じであり、各行が異なることを意味し、(50,50) サイズの実数 x 行列を形成します。

予測対象の x_train から実数の x 行列 (行列と呼ばれる) を減算し、ブロードキャスト メカニズムを適用します。

結果は、たとえば、行列の行 0 の列数 (すべての数は同じ) からベクトル x_train を引いたものです。

 

実際、a 行列の意味は、各実数 x と x_train の間の距離を見ることであり、最初の値のみが最短距離であることがわかります。

また、x と x_train の間の最小距離である数字は各行に 1 つしかないこともわかり、距離が大きくなりすぎないようにするために、たとえば 9999999 までの数字が今後出現する可能性があります。値, 正規化に softmaxt を使用します. 単純な考え方は, 各数値が占めるということです. 最大のものは のパーセンテージです. 正規化後, 行列をもっと小さくすることができます. この行列の距離を見やすくするために, 絵を描きます.色でマークする

5. ウェイト マップを取得します。2 つの x ベクトルが小さいものから大きいものへと並べ替えられていることがわかります。

同様の考え方は、y が x にほぼ等しいということですが、ここでは y 軸が逆になっているため、y が -x に等しく、この直線上で引き上げられているのと似ています。

そして、色が濃いほど距離が短いことを意味しますが、データ上2つのxが等しい場合、つまりx_testとx_trainが等しい場合はありませんので、色1の値はなく、最大値は0.2未満  

6. では、この行列の用途は何ですか?

3.1 の値から、y の平均値から直線を作成してこの曲線を記述して適合させることができますが、xi についての考慮が欠けています.たとえば、xi では、平均値が yi に対して少し増加または減少するはずです. xi. 値に対応するため、この線は現在の yi の値とより一致します. xi の値がいっぱいになると、直接 yi になります。全体の状況はこのように見られるので、注視が必要です x の他の値については、グローバル ビューを作成する必要があるため、マトリックス a にする必要があります

つまり、xi を見るときは xi に焦点を合わせますが、xi の隣または遠くにある他の x にも注意を払いますが、遠くに行くほど、注意を分散させてこれらの y に適用する必要があります。次に、y の値を変更して、最終的な適合曲線が yi に適合しすぎないようにし、適合不足のように見えないようにします。

また、適合線は全体の状況とその時の状況を考慮していますが、主にその時の状況に注目が集まっています。

例1。

平均をそのまま収束させると、平均値は2.1868、実数値は0、その時の電車のyは0.4415しかなく、この値よりかなり小さいですが、他のyは大きいので平均はは少し法外なので、アテンション メカニズムを使用します。最終フィッティングでは、ポイントの y は現在の yi をより多く見て、他の値をより少なく見る必要があります (すべての存在が等しい場合、すべての値が等しく扱われ、平均は y_mean であり、これは非常に大きいため、他の非常に大きな y を減らすことができます この yi 値に対する値の影響

 

 

紫は最後の適合線で、さまざまな注意に従ってさまざまな y の平均値を引き伸ばしています  

上の言葉は人間らしくないといつも思う

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

n_train = 50  # 训练样本数
x_train, _ = torch.sort(torch.rand(n_train) * 5)   # 排序后的训练样本 rand是0到1之间 生成50个再*5 就是取0-5之间50个数

def f(x):
    return 2 * torch.sin(x) + x**0.8

y_train = f(x_train) + torch.normal(0.0, 0.5, (n_train,))  # 训练样本的输出
x_test = torch.arange(0, 5, 0.1)  # 测试样本
y_truth = f(x_test)  # 测试样本的真实输出
n_test = len(x_test)  # 测试样本数
n_test

def plot_kernel_reg(y_hat):
    d2l.plot(x_test, [y_truth, y_hat], 'x', 'y', legend=['Truth', 'Pred'],
             xlim=[0, 5], ylim=[-1, 5])
    d2l.plt.plot(x_train, y_train, 'o', alpha=0.5);

y_hat = torch.repeat_interleave(y_train.mean(), n_test)
plot_kernel_reg(y_hat)
d2l.plt.show();
# X_repeat的形状:(n_test,n_train),
# 每一行都包含着相同的测试输入(例如:同样的查询)
X_repeat = x_test.repeat_interleave(n_train).reshape((-1, n_train))
# x_train包含着键。attention_weights的形状:(n_test,n_train),
# 每一行都包含着要在给定的每个查询的值(y_train)之间分配的注意力权重.   x_test每个值对x_train所有值的影响和关联
attention_weights = nn.functional.softmax(-(X_repeat - x_train)**2 / 2, dim=1)
# y_hat的每个元素都是值的加权平均值,其中的权重是注意力权重
y_hat = torch.matmul(attention_weights, y_train)
plot_kernel_reg(y_hat)

d2l.show_heatmaps(attention_weights.unsqueeze(0).unsqueeze(0),
                  xlabel='Sorted training inputs',
                  ylabel='Sorted testing inputs')

X = torch.ones((2, 1, 4))
Y = torch.ones((2, 4, 6))
torch.bmm(X, Y).shape

weights = torch.ones((2, 10)) * 0.1
values = torch.arange(20.0).reshape((2, 10))
torch.bmm(weights.unsqueeze(1), values.unsqueeze(-1))

class NWKernelRegression(nn.Module):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.w = nn.Parameter(torch.rand((1,), requires_grad=True))

    def forward(self, queries, keys, values):
        # queries和attention_weights的形状为(查询个数,“键-值”对个数)
        queries = queries.repeat_interleave(keys.shape[1]).reshape((-1, keys.shape[1]))
        self.attention_weights = nn.functional.softmax(
            -((queries - keys) * self.w)**2 / 2, dim=1)
        # values的形状为(查询个数,“键-值”对个数)
        return torch.bmm(self.attention_weights.unsqueeze(1),
                         values.unsqueeze(-1)).reshape(-1)

# X_tile的形状:(n_train,n_train),每一行都包含着相同的训练输入
X_tile = x_train.repeat((n_train, 1))
# Y_tile的形状:(n_train,n_train),每一行都包含着相同的训练输出
Y_tile = y_train.repeat((n_train, 1))
# keys的形状:('n_train','n_train'-1)
keys = X_tile[(1 - torch.eye(n_train)).type(torch.bool)].reshape((n_train, -1))
# values的形状:('n_train','n_train'-1)
values = Y_tile[(1 - torch.eye(n_train)).type(torch.bool)].reshape((n_train, -1))

net = NWKernelRegression()
loss = nn.MSELoss(reduction='none')
trainer = torch.optim.SGD(net.parameters(), lr=0.5)
animator = d2l.Animator(xlabel='epoch', ylabel='loss', xlim=[1, 5])

for epoch in range(5):
    trainer.zero_grad()
    l = loss(net(x_train, keys, values), y_train)
    l.sum().backward()
    trainer.step()
    print(f'epoch {epoch + 1}, loss {float(l.sum()):.6f}')
    animator.add(epoch + 1, float(l.sum()))

# keys的形状:(n_test,n_train),每一行包含着相同的训练输入(例如,相同的键)
keys = x_train.repeat((n_test, 1))
# value的形状:(n_test,n_train)
values = y_train.repeat((n_test, 1))
y_hat = net(x_test, keys, values).unsqueeze(1).detach()
plot_kernel_reg(y_hat)

d2l.show_heatmaps(net.attention_weights.unsqueeze(0).unsqueeze(0),
                  xlabel='Sorted training inputs',
                  ylabel='Sorted testing inputs')
d2l.plt.show();

おすすめ

転載: blog.csdn.net/qq_36632604/article/details/129835876