按位相乘再相加求注意力
向量a与向量b求向量按位相乘 再相加 得一个数,一组向量即矩阵A与矩阵B计算后得向量C 向量C做softmax -- 得分矩阵S 得分矩阵S 左乘 矩阵A -- B相对A的注意力
按位相乘再相加,其实就是向量内积,多个向量同时运算,就是矩阵运算 一类事物[元素个数,单个元素维度] 这样的事物求自注意力, [元素个数,单个元素维度] @ [单个元素维度,元素个数] = [元素个数,元素个数] 一组数据中的每个元素/向量,相对另外一组数据中的每个数据/向量,都有一个特征 用句子与单词来描述就是, 一个句子的每个单词,相对另外一个句子的每个单词,都有一个特征 一个句子的每个单词,相对另外一个句子,都有一个特征向量 一个句子的每个单词,相对多个句子,都有一个特征矩阵 转概率后就是得分矩阵,这个得分矩阵是二者共同的特征,是交集,是共性 由于转了概率,再乘回去,类似于期望, 即特征向量中的每个数值都是一个元素相对一组元素的期望
什么是余弦相似度
余弦相似度就是两个向量之间的夹角的余弦值 有的地方也叫余弦距离, 夹角为0时距离为1,夹角为90度时,距离为0
余弦相似度的用途
余弦相似度可以衡量两个向量之间的差异, 就是比一比谁离谁更近,谁又离谁更远 不知你有没有这样的疑问? 向量的核心要素除了方向,不是还有大小吗? 怎么比个方向就说两个向量近似了? 这是因为此问的背景是所有向量的模已经近似/接近于1, 至少是大致相等/相近 夹角之间的差异就是两个向量之间的主要差异 如果是你想更精确一些,可以在比较之前将所有向量再次约束一次,将其模归为1
向量内积在AI中的地位
向量之间的运算,较常用的有两个: 线性运算:按位 加, 减, 数乘 内积运算:接位 相乘 再 相加 要不断尝试使用矩阵去描述及解决问题(此句的重要性属于一个学科总纲级的...), 而矩阵运算实际上就是一系列的向量内积,维度的变换...
从向量的角度看矩阵
这里特指2维矩阵,AI最常用的也是这个, 三维矩阵实际上有一维是批次,就是多个2维矩阵 2维矩阵常说行与列, 行与列是人的视角上的一个描述, 如果写在纸上,你能看到一组类似长方形/正方形的一组数, 实际对于一组数据来说, 它们本没有什么行与列的概念,更不需要排列成什么形状, 它们通常用第m维,第n维这样纯数字的描述 对于一个矩阵来说,行与列都是它的一个维度,无区别 但对业务来说,这个数据是有行与列的差异的 我们将业务进行数字化,矩阵化之后,对应的行与列就有不同的含义 此时,用向量/向量组来描述更为合适
从向量的角度看矩阵举例
一个单词 用一个索引来表示 一句话n个单词就是一个n维向量,记作seq_len 多句话时,就是多个向量,形成一个向量组, 向量组比矩阵有更强的方向性, 更能突显 一句话对应一个向量 这个业务含义 向量组个数这个维度记作batch_size 通常情况下,批次放dim=0的维度,即[batch_size, seq_len]=A 这就是关系型数据库的表的结构 但对于一个矩阵来说,每个维度都只是一组数据而已 所以将批次放第2维,依然能有相同的含义[seq_len,batch_size]=B A[0,:]表示取一句话,B[:,0]也是取一句话 A与B都看作 每个向量维度为seq_len的向量组 A中用 行向量 表示一句话 B中用 列向量 表示一句话 后续,看具有业务含义的矩阵, 都从 向量/向量组 的角度去看, 因为业务通常要求矩阵有批次的维度 要习惯用A[0,:]取一行,而不是A[0],尽管它们取出的数据是一样的 A[0,:]在形式上就可以提醒你,dim=0的维度 取一,剩下所有维度全取
向量内积更深一层的含义
向量内积:按位 相乘 再 相加 首先,将一个事物的整体看作 1,就是我们先有了全集,将全集看作1 全集中所有的子集,事物 都小于1,是1的一部分 如果用两个圆圈表示A与B两个事物,那么重叠的部分就是交集, 类似于/近似于/等价于 两个事物相乘的结果 这个结果即属于A也属于B,是事物之间的共性 可存在这种可能,两个圆圈没有交集, 那么这样的两个圈圈对应的两个矩阵相乘的结果就是0 即乘法可以提取事物之间的共性,这不就是AI需要的吗? 将不同维度得到的共性结果 相加,就得到了两个向量之间共性的一个映射
如果一个规律足够底层,那么它在很多方面都能得到体现, 回忆欧氏距离,是自己与自己相乘再相加, 然后开方就得到了一个n维向量的模 这就是该向量的距离/长度 回忆方差计算,每个元素的误差=每个元素的值-均值, 这个误差自己跟自己相乘再相加就是整个分布的误差 回忆协方差,是两个分布之间的误差相乘再相加,再除以两个分布的模 它们都有一个共性的内核: 在各个对应的维度上 相乘,然后将不同的维度 相加起来 这不就是向量内积吗?
从解析几何的角度看向量内积, a·b = |a|·|b|·夹角余弦, 就是一个向量投影到另外一个向量上,然后再相乘 谁投影到谁上面无所谓,因为结果一样, 因为向量内积算的是共性,是交融后的结果 扯的有些远了,回收一下注意力, 这里只是为了说明向量内积可以提取特征(实际上是共性), 理论归理论, 关键是,实践也验证了,向量内积的确可以提取特征 这才是我们相信 向量内积可以提取特征 的主要原因
求矩阵A相对矩阵B的注意力
1. 矩阵A与矩阵B做 点乘,得交集矩阵C 2. 对矩阵C做softmax求 得分矩阵D 3. 得分矩阵D@矩阵A = 矩阵A相对B的上下文向量,也就是注意力
序列到序列的注意力计算
hidden.shape = [1,batch_size,hidden_size] encoder_outputs.shape = [seq_len,batch_size,hidden_size] 点乘,按位相乘再让特征相加,特征维度消失 [1,批次,特征]*[序列,批次,特征]= [序列,批次] attn_energies = torch.sum(hidden * encoder_output, dim=2) # [sel_len,batch_size] -- [batch_size,sel_len] attn_energies = attn_energies.t() # 按seq_len维度转为概率,[batch_size,seq_len] # [batch_size,seq_len] -- [batch_size, 1, seq_len] 添加这个1是为了后面进行bmm attn_weights = F.softmax(attn_energies, dim=1).unsqueeze(1) # context.shape = [batch_size,1,hidden_size] # decoder中每个单词对应一个encoder的上下文向量 # 加权平均,[1, seq_len] sum(dim=1)=1,注意力的得分之和为1,将这个得分乘到原来解码器上 context = attn_weights.bmm(encoder_outputs.transpose(0, 1))
注意力计算通俗举例
注意力指事物联系中的关键点,它通常有一个语境/提前 seq1: 老板 ,这 馒头 多少 钱 一个 ? seq2: 1块 seq1分词后得到8个词,seq2分词后得到1个词, 现在求seq1相对seq2的注意力 seq1中的每个单词与seq2的注意力都是 一个值, 两个向量进行内积运算,按位相乘再相加,得到一个值 seq1有8个词,批次计算后,seq1的shape为[8,1], 其实就是[8],一个列表8个值,设此列表为A 这里有一个大提前,文本向量化后的数据皆在[0,1]之间,或者[-1,1]之间 负号是数的一个特殊维度/方向, 若将事物的全体定为1,那么两个事物相乘就是其交集, 是两个事物共同的部分 而向量内积就是二者在各个维度上交集的和 将一个事物在各个维度上的交集强行投影到一维上,然后相加 所以,此处矩阵相乘得到的就是seq1与seq2的交集 我们的目标是求注意力, 是要看看seq1中各个单词到底哪个单词相对seq2是关键单词 孰轻孰重,若轻则轻多少,若重则重多少 要看它们之间的相对差异,用数字清晰地体现出来 差异本身是多少,不重要 重要的是,相对来说差多少 百分比的概念呼之欲出... 全体为100%,我若在你心中最重的话,那么就没有其他事物比我更重 这是其思想,极其重要, softmax是实现这种思想的“其中一种”方法 列表A做softmax后,得到 分数列表 分数列表再与单词列表,矩阵相乘,得到seq1相对seq2的上下文向量, 这就是注意力
序列到序列的上下文向量
这里以序列到序列为背景,比如: 十一 放假 准备 去哪 玩? -- 不 出去 了 编码序列有一个上下文,涉及 旅游 这个主题, 但序列到序列中的上下文向量, 是 编码序列相对于 解码器的每个单词都有一个 上下文向量 这里,解码器有三个单词,那么就有三个上下文向量, 这三个上下文向量分别与解码器的三个单词拼接, 形成包含前置序列上下文的 新的向量 对编码器只是提取特征,解码器,才是真正推理的开始, 当前单词+由注意力机制提取的上下文向量 推理出 下一个单词, 求编码器相对下一个单词的注意力,再推理下下个单词 这样一层层推理下去 所得的上下文向量中,都有 旅游 这个主题,只是比重不一样