word2vec的隐藏层为什么采用线性函数的定义激活函数

  word2vec是google在2013年推出的一个NLP工具它嘚特点是将所有的词向量化,这样词与词之间就可以定量的去度量他们之间的关系挖掘词之间的联系。虽然源码是开源的但是谷歌的玳码库国内无法访问,因此本文的讲解word2vec原理以Github上的代码为准本文关注于word2vec的基础知识。

  用词向量来表示词并不是word2vec的首创在很久之前僦出现了。最早的词向量是很冗长的它使用是词向量维度大小为整个词汇表的大小,对于每个具体的词汇表中的词将对应的位置置为1。比如我们有下面的5个词组成的词汇表词"Queen"的序号为2,

}

我们上周深入研究了协同过滤朂后我们在 ponents_

我们将看看第一个维度“轻松与严肃”(我们不知道它代表什么但可以通过观察它们来推测):

第二个维度“对话驱动与 CGI”

当伱说learn.fit时会发生什么?

第二篇论文谈论类别嵌入 图一的标题应该听起来很熟悉,因为它们讨论了实体嵌入层如何等效于单热编码然后是矩阵乘法。

他们做的有趣的事情是他们采用由神经网络训练的实体嵌入,用学习的实体嵌入替换每个类别变量然后将其输入到梯度增強机(GBM),随机森林(RF)和 KNN 中 - 这减少了某些误差几乎与神经网络(NN)一样好。 这是一种很好的方式可以在你的组织中提供神经网络的強大功能,而不必强迫其他人学习深度学习因为他们可以继续使用他们当前使用的东西并使用嵌入作为输入。 GBM 和 RF 的训练比

他们还绘制了德国的州的嵌入有趣的是(正如 Jeremy 所说的那样“令人费解”)类似于实际的地图。

他们还绘制了物理空间和嵌入空间中商店的距离 - 这显示絀美丽而清晰的相关性

一周的天数或一年中的几个月之间似乎也存在相关性。 可视化嵌入可能很有趣因为它向你显示你期望看到的内嫆或你未看到的内容。

Skip-Gram 特定于 NLP 将未标记的问题转变为标记问题的好方法是“发明”标签。 Word2Vec 的方法是选取 11 个单词的句子删除中间单词,並用随机单词替换它 然后他们将标签 1 给原句,标签 0 给假的句子并建立了一个机器学习模型来查找假的句子。 因此他们现在可以将嵌叺用于其他目的。 如果你将它实现为单个矩阵乘法(浅模型)而不是深度神经网络你可以非常快速地训练 - 缺点是它是一个预测性较低的模型,但优点是你可以训练一个非常大的数据集更重要的是,最终的嵌入具有线性函数的定义特征 允许我们很好地加,减或绘制 在 NLP Φ,我们应该超越 Word2Vec 和 Glove(即基于线性函数的定义的方法)因为这些嵌入不太具有预测性。 最先进的语言模型使用深度 RNN

要学习任何类型的特征空间,你需要标记数据或者需要发明虚假任务 []

  • 一个虚假任务比另一个好吗 还没有很好的研究。
  • 直观地说我们想要一个任务,帮助機器学习你关心的各种关系
  • 在计算机视觉中,人们使用的一种虚假任务是应用虚幻和不合理的数据增强
  • 如果你不能提出很棒的虚假任務,那就去使用糟糕的任务 - 你需要的很少这通常是令人惊讶的。
  • 自编码器 [] - 它最近赢得了 采取单一策略,通过神经网络运行并让它重建自己(确保中间层的激活少于输入变量)。 基本上这是一个任务,其输入等于输出作为一个假任务它有效,令人惊讶

在计算机视覺中,你可以在猫狗上训练并将其用于 CT 扫描 也许它可能适用于语言/ NLP! (未来的研究)

  • 正确使用测试集的方法已添加到笔记本中。
  • 对于更詳细的说明请参阅机器学习课程。
  • 跟踪包含每个连续列的平均值和标准差的mapper 并将相同的mapper应用于测试集。
  • 不要依赖 Kaggle 公共版 - 依靠你自己精惢设计的验证集

商店关闭前后的销售额有所增长。 第三名获胜者在开始任何分析之前删除了关闭的商店的行

不要触碰你的数据,除非伱首先分析来看看做什么好 - 没有假设

  • ctrl + ]访问光标下内容的定义
  • *找到光标下的内容的用法
  • / F8键,则可以轻松地在文件之间切换

慢慢地,但是必然过去只是“神奇”的东西,开始看起来很熟悉 如你所见, get_learner返回Learner 它是包装数据和 PyTorch 模型的 fast.ai 概念:

MixedInputModel内部,你可以看到它如何创建峩们现在更了解的Embedding。 nn.ModuleList用于注册层的列表 我们将在下周讨论BatchNorm`,但我们之前已经看过了其余部分

同样,我们现在了解forward函数发生了什么

  • 使鼡第i个类别变量调用嵌入层并将它们连接在一起
  • 浏览每个线性函数的定义层,调用它应用 relu 和 dropout
  • 然后最终线性函数的定义层的大小为 1
  • 如果y_range,則应用 sigmoid 并将输出拟合到一个范围内(我们上周学到的)

为了确保我们完全掌握 SGD我们将用它来学习y = ax + b。 如果我们可以用 2 个参数解决问题我們可以使用相同的技巧来解决 1 亿个参数。

首先我们需要一个损失函数。 这是一个回归问题因为输出是连续输出,最常见的损失函数是均方误差(MSE)

回归 - 目标输出是实数或整数实数

分类 - 目标输出是类标签

我们将制作 10,000 多个假数据并将它们转换为 PyTorch 变量,因为 Jeremy 不喜欢计算导数而 PyTorch 可以为他做到:

然后为ab创建随机权重,它们是我们想要学习的变量所以设置requires_grad=True

然后设置学习率并完成 10000 个全量梯度下降的迭代(不昰 SGD因为每个迭代将查看所有数据):

  • 计算损失(记住,ab最初设置为随机)
  • 偶尔(每 1000 个迭代)打印出损失
  • a更新来减去LR * grad.data访问变量内蔀的张量)
  • 当有多个损失函数,或许多输出层对梯度有贡献时PyTorch 会将它们加在一起。 因此你需要告诉何时将梯度设置回零(_中的zero_()表示变量原地更改)。

我们实际上必须做微分但其他一切看起来应该相似:

  • 如果ffmpeg不在其中,就

让我们学习如何写尼采这样的哲学。 这类似于峩们在第 4 课中学到的语言模型但这一次,我们将一次完成一个字符 RNN 与我们已经学到的没什么不同。

具有单个隐藏层的基本 NN

所有形状都昰激活(激活是由 relu矩阵乘法等计算的数字)。 箭头是层操作(可能不止一个) 查看机器学习课程 9-11,从头开始创建

具有单密集隐层的圖像 CNN

我们将在下周介绍,如何把层展开但主要方法称为“自适应最大池” - 我们在高度和宽度上进行平均,并将其转换为向量

我们将为 NLP 實现这个。

  • 输入可以是单热编码字符(向量的长度等于唯一字符的数量)或单个整数,并假设它由嵌入层进行单热编码
  • 与 CNN 的不同之处茬于添加了字符 2 输入。

层操作未显示;记住箭头代表层操作

让我们在没有torchtext或 fast.ai 库的情况下来实现以便我们可以看到。

  • set将返回所有唯一字符
  • 添加null或空字符来填充,总是很好

将每个字符映射到唯一 ID,以及唯一 ID 到字符

现在我们可以使用其 ID 来表示文本:

问题:基于字符的模型與基于单词的模型 []

  • 通常,你希望将字符级模型和单词级模型组合在一起(例如用于翻译)。
  • 当词汇表包含不常用的单词时字符级模型佷有用 - 单词级模型将仅视为“未知”。 当你看到之前没有见过的单词时可以使用字符级模型。
  • 在它们之间还有一种称为字节对编码(BPE)嘚东西它查看 n-gram 字符。

x是我们的输入y是我们的目标值。

这是上图的更新版本 请注意,现在箭头已着色 具有相同颜色的所有箭头,将使用相同的权重矩阵 这里的想法是,字符不具有不同的含义(语义上或概念上)这取决于它是序列中的第一个,第二个还是第三个项目因此对它们的处理方式相同。

  • [] 重要的是这个l_hidden使用一个方形权重矩阵,其大小匹配l_in的输出
 

我们将复用 []。如果我们堆叠x1 x2x3,我们将茬forward方法中得到c1c2c3当你想用原始方法训练模型时,

  • 因为它是标准的 PyTorch 模型所以不要忘记.cuda
  • iter返回了一个迭代器
  • next返回一个小批量
  • xs张量变成“變量”,并使其通过模型 - 这将给我们 512x85 张量它包含预测(批量大小乘唯一字符)
  • 创建一个标准的 PyTorch 优化器 - 你需要传递一个要优化的东西列表,由m.parameters()返回
  • 我们没有找到学习率查找器和 SGDR因为我们没有使用Learner,所以我们需要手动进行学习率退货(将 LR 设置得稍低)

此函数需要三个字符并返回模型预测的第四个字符注意:np.argmax返回最大值的索引。

让我们创建我们的第一个 RNN []

我们可以简化上面的图表如下:

使用字符 1 到 n-1 预测字符

让峩们实现它 这次,我们将使用前 8 个字符来预测第 9 个字符 以下是我们如何创建输入和输出,就像上次一样:

请注意它们是重叠的(即 0-7 预測 8, 1-8 预测 9)

大多数代码与以前相同。 你会注意到forward函数中有一个for循环

这是一个移位的 sigmoid。 通常在隐藏状态中使用 tanh 来隐藏状态转换因为它会阻止它飞得太高或太低。出于其他目的relu 更常见。

现在这是一个非常深的网络因为它使用 8 个字符而不是 2 个。随着网络越来越深入它们變得越来越难以训练。

我们现在将为self.l_hidden(h+inp) [] 尝试别的东西 原因是输入状态和隐藏状态本质上是不同的。 输入是字符的编码h是一系列字符的编碼。 所以将它们加在一起我们可能会丢失信息。 让我们将它们连接起来 不要忘记更改输入来匹配形状(

PyTorch 将自动为我们和线性函数的定義输入层编写for循环。

  • 由于稍后会变得明显的原因 self.rnn会返回输出,还会返回隐藏状态
  • PyTorch 的细微差别在于,self.rnn会将一个新的隐藏状态附加到张量洏不是替换(换句话说它将返回图中的所有椭圆)。 我们只想要最后一个所以我们执行outp[-1]

我们稍后会详细了解它,但事实证明你可以拥囿反向的第二个 RNN 我们的想法是找到反向的关系会更好 - 它被称为“双向 RNN”。 你也可以向 RNN 提供 RNN 的输出称为“多层 RNN”。 对于这些 RNN你将需要張量中的额外轴,来跟踪其他层的隐藏状态 现在,我们只有一层

这一次,我们循环n次每次调用get_next ,每次我们将通过删除第一个字符並添加我们刚预测的字符来替换输入。

作为一个有趣的家庭作业尝试编写自己的nn.RNN,“JeremysRNN”不要查看 PyTorch 源代码。

从上一个图中我们可以通過将字符 1 与字符 2 相同地处理为 n-1 来进一步简化。 你注意到三角形(输出)也在循环内移动换句话说,我们在每个字符后创建一个预测

我們可能希望这样做的原因之一,是我们之前看到的冗余:

 

这次我们可以通过使用不重叠的字符来提高效率 因为我们正在进行多输出,对於输入字符 0 到 7输出将是字符 1 到 8 的预测。

这不会使我们的模型更准确但我们可以更有效地训练它。

请注意我们不再执行outp[-1]因为我们想保留所有这些。 但其他一切都是一样的 复杂性 [] 是,我们想要像以前一样使用负对数似然损失函数但它期望两个二阶张量(两个小批量向量)。 但在这里我们有三阶张量:

  • 8 个字符(时间步长)

让我们写一个自定义的损失函数 []:

  • 展开我们的输入和目标。
  • 转置前两个轴因为 PyTorch 期望第一维:序列长度(多少时间步长),第二维:批量大小第三位:隐藏状态本身。 yt.size()是 512 乘 8而sl, bs是 8 乘 512。
  • 当你执行“转置”之类的操作时PyTorch 通常不会实际调整内存顺序,而是保留一些内部元数据来将其视为转置当你转置矩阵时,PyTorch 只会更新元数据如果你看到错误“此张量鈈连续”,请在其后添加.contiguous()错误就消失了。

请记住 fit(...)是实现训练循环的最低级别 fast.ai抽象。 所以所有参数都是标准的 PyTorch除了md,它是我们的模型數据对象它包装了测试集,训练集和验证集

问题 []:既然我们在循环中放了一个三角形,我们需要更大的序列大小吗

  • 如果我们有一个潒 8 这样的短序列,那么第一个字符就没有可依照的东西它以空的隐藏状态来开始。
  • 我们将在下周学习如何避免这个问题
  • 基本思想是“為什么我们每次都要将隐藏状态重置为零?”(参见下面的代码) 如果我们能够以某种方式排列这些小批量,以便下一个小批量正确连接来表示 Nietsche 作品中的下一个字母,那么我们可以将h = V(torch.zeros(1, bs, n_hidden))移动到构造函数中

self.rnn(inp, h)是一个循环,一次又一次地应用相同的矩阵 如果这个矩阵乘法每佽都会增加激活,那么我们实际上就是计算了 8 次方 - 我们称之为梯度爆炸 我们希望确保,初始l_hidden不会导致我们的激活平均上增加或减少

一個很好的矩阵就是这样,称为单位矩阵:

我们可以使用单位矩阵覆盖随机初始化的隐藏权重:

这由 Geoffrey Hinton 等人在 2015 年引入() — 在 RNN 已经存在了几十姩之后 它运作良好,你可以使用更高的学习率因为它表现良好。

}

我要回帖

更多关于 线性函数的定义 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信