自主性提示: 我想。。。、看想看的东西
非自主提示:随意一看 、看环境中现眼的东西
环境的东西就是键和值 我想要是查询
#@save def show_heatmaps(matrices, xlabel, ylabel, titles=None, figsize=(2.5, 2.5), cmap='Reds'): """显示矩阵热图""" d2l.use_svg_display() num_rows, num_cols = matrices.shape[0], matrices.shape[1] fig, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize, sharex=True, sharey=True, squeeze=False) for i, (row_axes, row_matrices) in enumerate(zip(axes, matrices)): for j, (ax, matrix) in enumerate(zip(row_axes, row_matrices)): pcm = ax.imshow(matrix.detach().numpy(), cmap=cmap) if i == num_rows - 1: ax.set_xlabel(xlabel) if j == 0: ax.set_ylabel(ylabel) if titles: ax.set_title(titles[j]) fig.colorbar(pcm, ax=axes, shrink=0.6);
attention_weights = torch.eye(10).reshape((1, 1, 10, 10)) show_heatmaps(attention_weights, xlabel='Keys', ylabel='Queries')
上面没讲哇。。。。
n_train = 50 # 训练样本数 x_train, _ = torch.sort(torch.rand(n_train) * 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,)) # 训练样本的输出 真实函数加上噪音 噪音是0均值 0.5方差 高斯 x_test = torch.arange(0, 5, 0.1) # 测试样本 0-5之间按0.1均匀的东西 y_truth = f(x_test) # 测试样本的真实输出 n_test = len(x_test) # 测试样本数 n_test50、画图函数
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);
# X_repeat的形状:(n_test,n_train), # 每一行都包含着相同的测试输入(例如:同样的查询) X_repeat = x_test.repeat_interleave(n_train).reshape((-1, n_train)) repeat 吧1234变成1111 222 333 444 n_train控制重复次数 # x_train包含着键。attention_weights的形状:(n_test,n_train), # 每一行都包含着要在给定的每个查询的值(y_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)
最上角
最深
应该就是距离最近 所以权重最大 然后最右下角也是这样
weights = torch.ones((2, 10)) * 0.1 values = torch.arange(20.0).reshape((2, 10)) torch.bmm(weights.unsqueeze(1), values.unsqueeze(-1))tensor([[[ 4.5000]], [[14.5000]]])
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')
都没咋讲。。。。
query和keys做注意力分数函数 然后丢到softmax 变成注意力权重 对每个map做加权和做输出
10.3. 注意力评分函数 — 动手学深度学习 2.0.0-beta0 documentationhttps://zh.d2l.ai/chapter_attention-mechanisms/attention-scoring-functions.htmlPytorch 注意力分数_哇咔咔负负得正的博客-CSDN博客环境使用 Kaggle 里免费建立的 Notebook教程使用李沐老师的 动手学深度学习 网站和 视频讲解小技巧:当遇到函数看不懂的时候可以按 查看函数详解。注意力汇聚(Pooling)表达式:f(x)=∑iα(x,xi)yi=∑i=1nsoftmax(−12(x−xi)2)yif(x) = \sum_i{\alpha(x, x_i)y_i} = \sum_{i=1}^{n}softmax(-\frac{1}{2}(x-x_i)^2)y_if(x)=i∑α(x,xi)yi=i=1∑nsoftmahttps://blog.csdn.net/qq_39906884/article/details/125248680?spm=1001.2014.3001.5502
3. Q&A
Q:mask_softmax 是啥意思?
A:有时候一个句子不够长,假如说一个句子 4 个单词,输入格式要求 10 个单词,那么需要填充 6 个无意义的词,然后用 mask_softmax 告诉 Query 计算的时候不需要考虑后 6 个词。
这块没有学习