改进版的CBOW模型

复习

首先复习一下之前的CBOW笔记。

采用推理的方法认知单词、CBOW模型这里面主要是:

CBOW模型的核心思路:给出周围的单词(上下文)时,预测目标词处会出现什么单词。

要用神经网络处理单词,需要先将单词转化为固定长度的向量,这就引出了单词的表示。

单词的表示:将单词转化为固定长度的向量(one-hot 表示),神经网络的输入层的神经元个数就可以固定下来。

CBOW模型:它是根据上下文预测目标词的神经网络。模型的输入是上下文。大致结构如下。

在这里插入图片描述

上图中的Win和Wout都是矩阵,也就是说,全连接层变换可以看作是输入层与矩阵相乘。由此引出矩阵乘积层(MatMul)的实现,这里面:

提到了反向传播:

拿下图举例子,反过来的箭头指向的那个心是2.2,意思就是,如果jym用心程度增加1,那么jym就能多获得2.2×1=2.2个npy。也就是说,反向传播目的就是看出输入的变化对输出有何影响(偏导)。

在这里插入图片描述

乘法节点的反向传播示意图如下,可以看出乘法节点的反向传播,将上游传过来的导数(1.1)乘正向传播的翻转值,然后传给下游。jym的心获得的反向传播的值是:1.1乘正向传播的y的2=2.2。

在这里插入图片描述

由上面类比得到x、y、z是矩阵的情况下的反向传播,如下图。

在这里插入图片描述

接下来,需要对语料库进行数据的预处理。预处理究竟处理的什么,关键就在于下面这张图。首先从语料库生成上下文和目标词,然后把上下文和目标词转化为 one-hot 表示。

在这里插入图片描述

然后就继续去实现一下普通的CBOW模型类。

整体大致是下面这个情况(里面有的是简写,反向传播还得乘前面传来的偏导数)。

在这里插入图片描述

但是这个模型有两个问题,第一个问题就是:对于输入层来说,one-hot表示占用内存过多,计算one-hot表示与权重矩阵的乘积,需要花费大量时间。解决这个问题,就需要增加一个Embedding层。也就是说,将原来CBOW模型中输入侧的MatMul层换成Embedding层。

解决这个问题的核心思路就是:计算one-hot 表示矩阵和权重矩阵的乘积,其实就是将权重矩阵的某个特定的行取出来。

Embedding 层:一个从权重矩阵中抽取单词ID对应行(向量)的层。

Embedding 层的正向传播:从权重矩阵W中提取特定的行,并将特定行的神经元原样传给下一层。

Embedding 层的反向传播:上一层传来的梯度会被应用到权重梯度dW的特定行(idx)。

在这里插入图片描述

第二个问题是:中间层的神经元和权重矩阵的乘积、Softmax层的计算需要花费很多计算时间。

解决方法就是使用 Negative Sampling (负采样) 替代 Softmax。也就是用二分类拟合多分类。

二分类问题:处理答案为是或否的问题,比如目标词是 say 吗。让神经网络来回答:当上下文是 you 和 goodbye 时,目标词是 say 吗?这时输出层只需要一个神经元,神经元输出的是 say 的得分。

输出侧的权重矩阵中保存了各个单词ID对应的单词向量,提取目标词的单词向量,再求这个向量和中间层神经元的内积,就是最终的得分。示意图如下。

在这里插入图片描述

Embedding Dot 层合并Embedding 层和 dot 运算(内积运算),优化后的CBOW模型如下。

其中向Sigmoid with Loss 层输入正确解标签1,表示现在正在处理的问题的答案是Yes。当答案是No时,向 Sigmoid with Loss 层输入0。

在这里插入图片描述

下图是进一步说明:

在这里插入图片描述

目前,只是对正例say进行了二分类,如果此时模型有好的权重,则Sigmoid层的输出概率将接近1。

真正要做的事是,对于正例say,使Sigmoid层的输出接近1;对于负例(say 以外的单词),使Sigmoid层的输出接近0。

所以,接下来引出二分类负采样方法。主要内容如下:

负采样方法:求正例作为目标词时的损失,同时采样(选出)若干个负例,对这些负例求损失。然后,将正例和采样出来的负例的损失加起来,作为最终的损失。

抽取负例:让语料库中常出现的单词易被抽到,不常出现的单词难被抽到。

基于频率的采样方法:计算语料库中各个单词的出现次数,并将其表示为概率分布,然后使用这个概率分布对单词进行采样。负采样通过仅关注部分单词的方法实现了计算的高速化

至此,就通过画图梳理的方法,串联起之前写的笔记的整体脉络,把CBOW模型复习完了。

接下来需要做的是,把改进后的CBOW模型实现出来,然后在PTB数据集上进行学习。

改进版的CBOW模型

CBOW类如下:

参数:vocab_size词汇量,hidden_size中间层的神经元个数,corpus单词ID列表,window_size上下文的大小。

import sys
sys.path.append('..')
from common.np import *  # import numpy as np
from common.layers import Embedding
from negative_sampling_layer import NegativeSamplingLossclass CBOW:def __init__(self, vocab_size, hidden_size, window_size, corpus):V, H = vocab_size, hidden_size# 初始化权重W_in = 0.01 * np.random.randn(V, H).astype('f')W_out = 0.01 * np.random.randn(V, H).astype('f')# 生成层self.in_layers = []for i in range(2 * window_size):layer = Embedding(W_in)  # 使用Embedding层self.in_layers.append(layer)self.ns_loss = NegativeSamplingLoss(W_out, corpus, power=0.75, sample_size=5)# 将所有的权重和梯度整理到列表中layers = self.in_layers + [self.ns_loss]self.params, self.grads = [], []for layer in layers:self.params += layer.params#存神经网络里面的参数self.grads += layer.grads#存神经网络里面的梯度# 将单词的分布式表示设置为成员变量self.word_vecs = W_indef forward(self, contexts, target):#contexts是上下文,target是目标词,这里是单词ID形式的h = 0for i, layer in enumerate(self.in_layers):h += layer.forward(contexts[:, i])#contexts是二维数组h *= 1 / len(self.in_layers)loss = self.ns_loss.forward(h, target)#target是一维数组return lossdef backward(self, dout=1):dout = self.ns_loss.backward(dout)dout *= 1 / len(self.in_layers)for layer in self.in_layers:layer.backward(dout)return None

CBOW模型的学习:

import sys
sys.path.append('..')
from common import config# 开GPU
config.GPU = Truefrom common.np import *
import pickle
from common.trainer import Trainer
from common.optimizer import Adam
from cbow import CBOW
from skip_gram import SkipGram
from common.util import create_contexts_target, to_cpu, to_gpu
from dataset import ptb# 设定超参数
window_size = 5
hidden_size = 100
batch_size = 100
max_epoch = 10# 读入数据
corpus, word_to_id, id_to_word = ptb.load_data('train')
vocab_size = len(word_to_id)contexts, target = create_contexts_target(corpus, window_size)
if config.GPU:contexts, target = to_gpu(contexts), to_gpu(target)# 生成模型等
model = CBOW(vocab_size, hidden_size, window_size, corpus)
# model = SkipGram(vocab_size, hidden_size, window_size, corpus)
optimizer = Adam()
trainer = Trainer(model, optimizer)# 开始学习
trainer.fit(contexts, target, max_epoch, batch_size)
trainer.plot()# 保存必要数据,以便后续使用,取出输入侧得权重和单词与单词ID之间转化得字典
word_vecs = model.word_vecs
if config.GPU:word_vecs = to_cpu(word_vecs)
params = {}
params['word_vecs'] = word_vecs.astype(np.float16)
params['word_to_id'] = word_to_id
params['id_to_word'] = id_to_word
pkl_file = 'cbow_params.pkl'  # or 'skipgram_params.pkl'
with open(pkl_file, 'wb') as f:pickle.dump(params, f, -1)

运行情况如下:

在这里插入图片描述

CBOW模型评价:

def most_similar(query, word_to_id, id_to_word, word_matrix, top=5):'''相似单词的查找:param query: 查询词:param word_to_id: 从单词到单词ID的字典:param id_to_word: 从单词ID到单词的字典:param word_matrix: 汇总了单词向量的矩阵,假定保存了与各行对应的单词向量:param top: 显示到前几位'''
import sys
sys.path.append('..')
from common.util import most_similar, analogy
import picklepkl_file = 'cbow_params.pkl'
# pkl_file = 'skipgram_params.pkl'with open(pkl_file, 'rb') as f:params = pickle.load(f)word_vecs = params['word_vecs']word_to_id = params['word_to_id']id_to_word = params['id_to_word']# most similar task
querys = ['you', 'year', 'car', 'toyota']
for query in querys:most_similar(query, word_to_id, id_to_word, word_vecs, top=5)# analogy task
print('-'*50)
analogy('king', 'man', 'queen',  word_to_id, id_to_word, word_vecs)
analogy('take', 'took', 'go',  word_to_id, id_to_word, word_vecs)
analogy('car', 'cars', 'child',  word_to_id, id_to_word, word_vecs)
analogy('good', 'better', 'bad',  word_to_id, id_to_word, word_vecs)

输出:从结果看出,CBOW 模型获得的单词的分布式表示具有良好的性质。而且,不仅可以将近似单词聚在一起,还可以通过向量的加减法来解决类推问题,比如man : woman = king : ?

而且结果说明,单词的分布式不仅限于捕获单词的含义,它也捕获了语法中的模式。

迁移学习:在某个领域学到的知识可以被应用于其他领域。一般先在大规模语料库上学习,然后将学习好的分布式表示应用于某个单独的任务。

单词的分布式表示的优点是可以将单词或文档转化为固定长度的向量。如果可以将自然语言转化为向量,就可以使用常规的机器学习方法。将这个向量作为其他机器学习系统的输入,利用常规的机器学习框架输出目标答案。比如,将向量化的邮件及其情感标签输入某个情感分类系统(SVM 或神经网络等)进行学习。大系统由:生成单词的分布式表示的系统(word2vec)、对特定问题进行分类的系统(比如进行情感分类 的 SVM 等)组成。

分布式表示的评价方法:单词的分布式表示的评价往往与实际应用分开进行,经常使用的评价指标有相似度和类推问题。

[query] youwe: 0.73095703125i: 0.70703125your: 0.6103515625they: 0.59375anybody: 0.58740234375[query] yearmonth: 0.8505859375week: 0.77392578125summer: 0.7568359375spring: 0.75390625decade: 0.69873046875[query] carluxury: 0.603515625window: 0.59375cars: 0.58349609375auto: 0.580078125truck: 0.5771484375[query] toyotamarathon: 0.65087890625nissan: 0.6455078125honda: 0.6357421875seita: 0.630859375minicomputers: 0.6005859375
--------------------------------------------------[analogy] king:man = queen:?carolinas: 5.26953125woman: 5.11328125a.m: 5.08203125downside: 4.90234375mother: 4.65234375#下面说明单词的分布式表示编码了时态相关的信息
[analogy] take:took = go:?went: 4.53125goes: 4.44921875were: 4.32421875was: 4.2421875came: 4.15234375[analogy] car:cars = child:?a.m: 6.54296875rape: 5.8046875children: 5.453125daffynition: 4.91796875women: 4.8984375[analogy] good:better = bad:?rather: 6.36328125less: 5.24609375more: 5.17578125greater: 4.2265625fewer: 3.80859375

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/560187.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

freertos空闲任务、阻塞延时

freertos空闲任务、阻塞延时空闲任务阻塞延时SysTick实验现象阻塞态:如果一个任务当前正在等待某个外部事件,则称它处于阻塞态。 rtos中的延时叫阻塞延时,即任务需要延时的时候,会放弃CPU的使用权,进入阻塞状态。在任务阻塞的这段…

树莓派配置

树莓派配置1.安装操作系统2.修改镜像源3.配置VNC连接1.安装操作系统 安装操作系统,首先在官网下载https://www.raspberrypi.com/software/operating-systems/ 下载出来的解压后是一个光盘映像文件,接下来就需要把这个文件写入到树莓派的tf卡里。 安装树…

远程桌面连机器人

这里需要PC和机器人处于同一局域网下。 PC使用xhell连接机器人,通过 ifconfig 查看机器人的无线 IP 地址。 然后退出xshell,打开NoMachine软件进行远程桌面连接。输入机器人无线ip地址。 输入用户名和密码 然后就远程连接上了 现在开一个终端如下所示&…

RNNLM

RNNLM 基于RNN的语言模型称为RNNLM(Language Model)。 Embedding 层:将单词ID转化为单词的分布式表示(单词向量)。 RNN层:向下一层(上方)输出隐藏状态,同时也向下一时刻的RNN层(右边)输出隐藏状态。 对于“you say …

使用c#制作赛尔号登录器

使用c#制作赛尔号登录器 需求: 打开赛尔号官网,发现我的chrome浏览器无法运行Flash。这是因为Adobe 公司放弃了对 Flash Player 的支持。 那么如果我想要玩游戏,又不想下载别的浏览器,只好自己写一个登陆器了。 创建项目 首先…

普通RNN的缺陷—梯度消失和梯度爆炸

之前的RNN,无法很好地学习到时序数据的长期依赖关系。因为BPTT会发生梯度消失和梯度爆炸的问题。 RNN梯度消失和爆炸 对于RNN来说,输入时序数据xt时,RNN 层输出ht。这个ht称为RNN 层的隐藏状态,它记录过去的信息。 语言模型的任…

LSTM的结构

RNN和LSTM 简略表示RNN层:长方形节点中包含了矩阵乘积、偏置的和、tanh函数的变换。将下面这个公式表示成一个tanh节点。 LSTM:Long Short-Term Memory(长短期记忆),长时间维持短期记忆。 LSTM与RNN的接口(输入输出)…

STM32 USART 补充

串口通讯的数据包:发送设备通过自身的TXD接口传输到接收设备的RXD接口。 串口通讯的协议层中,规定了数据包的内容,由起始位、主体数据、校验位、停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据。 异步通讯&#xf…

ROS TF变换

静态坐标转换:机器人本体中心到雷达中心的转换。因为激光雷达可能没安装到机器人的中心。 动态坐标转换:机器人中心和里程计坐标的变换。机器人从起点出发后,里程计坐标相对于本体就会产生一个偏移,这个偏移随着机器人的运动不断…

ROS底盘控制节点 源码分析

先在机器人端通过launch文件启动底盘控制。 robot:~$ roslaunch base_control base_control.launch ... logging to /home/jym/.ros/log/3e52acda-914a-11ec-beaa-ac8247315e93/roslaunch-robot-8759.log Checking log directory for disk usage. This may take a while. Pres…

ROS + OpenCV

视觉节点测试 先进行一些测试。并记录数据。 圆的是节点,方的是话题。 1.robot_camera.launch robot:~$ roslaunch robot_vision robot_camera.launch ... logging to /home/jym/.ros/log/bff715b6-9201-11ec-b271-ac8247315e93/roslaunch-robot-8830.log Check…

ROS+雷达 运行数据记录

先测试一下雷达,记录数据。方便接下来分析源码。 1.roslaunch robot_navigation lidar.launch robot:~$ roslaunch robot_navigation lidar.launch ... logging to /home/jym/.ros/log/7136849a-92cc-11ec-acff-ac8247315e93/roslaunch-robot-9556.log Checking l…

ROS 找C++算法源码的方法

在gmapping的launch文件中看到,type“slam_gmapping”,这里的slam_gmapping是c编译后的可执行文件。 如果想要修改gmapping算法,就需要找到slam_gmapping的c源码。 但是这是用apt下载的包,是二进制类型的,没有下载出…

ros 雷达 slam 导航 文件分析

ros 雷达 slam 导航 文件分析robot_slam_laser.launchrobot_lidar.launchlidar.launchraplidar.launchkarto.launchgmapping.launchcartographer.launchrobot_navigation.launchmap.yamlmap.pgmamcl_params.yamlmove_base.launchcostmap_common_params.yamllocal_costmap_param…

Apprentissage du français partie 1

Apprentissage du franais partie 1 键盘转换图: 字母:26个 元音字母:a、e、i、o、u、y b浊辅音(声带)-p清辅音 d-t 音符 音符:改变字母发音。 :闭音符 [e] :开音符 /ε/ :长音符 /ε/…

stm32基本定时器

定时器分类 stm32f1系列,8个定时器,基本定时器(TIM6,7)、通用定时器(TIM2,3,4,5)、高级定时器(TIM1,8)。 基本定时器:16位,只能向上计数的定时器,只能定时,没有外部IO 通用定时器:16位&#…

stm32高级定时器 基础知识

stm32高级定时器 高级定时器时基单元: 包含一个16位自动重装载寄存器 ARR 一个16位的计数器CNT,可向上/下计数 一个16位可编程预分频器PSC,预分频器时钟源有多种可选,有内部的时钟、外部时钟。 一个8位的重复计数器 RCR&…

stm32 PWM互补输出

stm32高级定时器例子—stm32 PWM互补输出 定时器初始化结构体 TIM_TimeBaseInitTypeDef 时基结构体,用于定时器基础参数设置,与TIM_TimeBaseInit函数配合使用,完成配置。 typedef struct { TIM_Prescaler /*定时器预分频器设置&…

stm32 输入捕获 测量脉宽

选用通用定时器TIM5的CH1。 PA0接一个按键,默认接GND,当按键按下时,IO口被拉高,此时,可利用定时器的输入捕获功能,测量按键按下的这段高电平的时间。 宏定义方便程序升级、移植,举个例子&#…

stm32 PWM输入捕获

普通的输入捕获,可使用定时器的四个通道,一路捕获占用一个捕获寄存器. PWM输入,只能使用两个通道,通道1和通道2。 一路PWM输入占用两个捕获寄存器,一个捕获周期,一个捕获占空比。 这里,用通用…