文章目录
- 0引言
- 1 cupy包的安装
- 2解决VScode中matplotlib绘图不显示的问题
- 3 CBOW模型学习的实现
- 4 CBOW模型对更复杂模式的捕捉
- 5单词向量的评价方法
- 6总结
0引言
- 本节将前面实现的改进的CBOW模型在PTB数据集上跑一遍
- 由于希望跟书上一样调用GPU,因此需要安装cupy包,途中遇到一些问题,详见下面的安装过程。
1 cupy包的安装
-
原本是直接在anaconda3的base环境中使用
pip install cupy-cuda11x
安装的,但是安装好后执行从cupy数组中获取指定行的数据时报了如下错误:- RuntimeError: CuPy failed to load libnvrtc.so.11.2: OSError: libnvrtc.so.11.2: cannot open shared object file: No such file or directory
-
分析发现,这个错误应该是cuda版本的问题,接下来是解决办法;
-
需要确认最新版cupy对cuda版本、numpy版本的要求;当然Python版本也要符合要求,因此用到以下资料:
- Installation — CuPy 13.2.0 documentation;
- Previous PyTorch Versions | PyTorch;
- 版本匹配指南:PyTorch版本、Python版本和pytorch_lightning版本的对应关系_pytorch-lightning版本对应-CSDN博客;
-
具体而言:
-
最新版的numpy为2.0,cupy最新版是支持的;因此可以直接通过
pip install numpy
; -
nvidia-smi
查看自己电脑的cuda版本,如下图所示;本机支持的最高cuda版本是11.4,因此我这里选择安装11.3版本的cudatoolkit; -
cudatoolkit=11.3可以安装torch=1.9.0,再看一下torch与Python版本的对应关系,得python=3.9;
-
-
几个版本弄清楚之后就可以开始安装了:
conda create -n nlp_study pip python=3.9 conda activate nlp_study conda install cudatoolkit=11.3 -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/linux-64/ pip install numpy pip install cupy-cuda11x
-
安装好之后执行下面的语句应该就不报错了:
# 这个函数一开始直接在base环境中使用pip install cupy-cuda11x安装也是不会报错的 def to_gpu(x): import cupy if type(x) == cupy.ndarray: return x return cupy.asarray(x) idx = numpy.random.permutation(numpy.arange(data_size)) x = to_gpu(x) x = x[idx] # 是这里会报错;所以进行了上述的安装过程
-
本书中提供的代码有些许问题,并且参与运算的两个数据一般需要都在gpu上或者都在CPU上;因此代码中额外加入了一些将数据移动到GPU或者CPU的代码,以保证代码能够正确运行。
2解决VScode中matplotlib绘图不显示的问题
- 遇到的问题是:vscode中使用juypter时绘图可以显示,但是在代码文件里面写然后运行就不行,而且不报错;
- 查了相关博客,以下是有用的:
- 参照vscode——matplotlib绘图不显示问题_visualstudio图片怎么出不来plt.plot-CSDN博客:执行了
echo $DISPLAY
和export DISPLAY=:0.0
; - 然后又会报解决
UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown plt.show()
-CSDN博客中的错误,因此选择保存图片来查看绘图的结果;
- 参照vscode——matplotlib绘图不显示问题_visualstudio图片怎么出不来plt.plot-CSDN博客:执行了
3 CBOW模型学习的实现
代码目录:https://1drv.ms/f/s!AvF6gzVaw0cNjpx9BAtQYGAHFT3gZA?e=Eso96F;
-
上一篇笔记讲述了改进过的CBOW模型的代码实现,包括初始化、前向计算和反向传播;
-
这里学习用的trainer函数和之前一样;
-
因此代码上就不过多讲述;区别在于这里将相关数据使用本书提供的
to_gpu
、to_cpu
方法搬到了GPU上,详见代码中的xxx.to_gpu(xxx)
; -
主要的几个代码文件如下:
CBOW_train.py
:程序入口CBOW_GPU.py
:改进之后的GPU版CBOW模型代码utils/Embedding_GPU.py
、utils/negativeSamplingLayer_GPU.py
、utils/trainer_GPU.py
:GPU版的Embedding层、Embedding_dot层、UnigramSampler模块、NegativeSamplingLoss层;以及GPU版的训练类;
-
由于数据量较大,训练时间较长;这里设置
max_epoch = 5
看一下结果; -
如下图所示是训练过程中的损失变化曲线;同时保存了训练的参数在
cbow_params.pkl
文件中。 -
接着,我们用之前的
most_similar
计算与输入单词最相似的前5个单词;结果如下:- 可见,CBOW模型确实学习到了单词的分布式表示;
# 与you最相似的 we 0.8603515625 i 0.82861328125 your 0.74169921875 else 0.7353515625 someone 0.71875 # 与year最相似的 month 0.90673828125 spring 0.8525390625 summer 0.8525390625 week 0.83837890625 decade 0.7109375
4 CBOW模型对更复杂模式的捕捉
主要是类推问题。例如:
king − man + woman = queen
;
-
由于CBOW模型可以获得单词的分布式表示,即向量;那么想要推出
king − man + woman = queen
的问题,则可以转换为单词向量之间的加法和减法; -
用
vec(x)
表示单词x
的向量表示;则需要计算vec(‘king’) + vec(‘woman’) − vec(‘man’) =?
;将计算出来的结果向量作为一个不知道的单词,然后使用most_similar
计算与该单词最相似的前几个单词,看看有没有queen,以及queen排第几个;当然,这里要使用most_similar
需要修改一下,因为此时传进去的query不是单词而是单词向量了(详见代码里的修改); -
然后我们可以得到以下结果:
take:took = go:went
类推出来了;- 但由于迭代次数较少,学习的不好;
- 因此可以说,CBOW模型不仅捕获了单词含义,还捕获了模式;
[analogy] king:man = queen:? man: 0.89208984375 balloon: 0.8408203125 woman: 0.81884765625 lady: 0.8056640625 remember: 0.80322265625 [analogy] take:took = go:? went: 0.75732421875 came: 0.6962890625 lived: 0.65478515625 ran: 0.63916015625 goes: 0.6376953125 [analogy] car:cars = child:? adults: 0.779296875 basketball: 0.7783203125 pieces: 0.77490234375 women: 0.76806640625 college: 0.759765625 [analogy] good:better = bad:? better: 0.79931640625 greater: 0.701171875 more: 0.69384765625 less: 0.69140625 rather: 0.65673828125
5单词向量的评价方法
- 单词的分布式表示的评价往往与实际应用分开进行。此时,经常使用的评价指标有“相似度”和“类推问题”;
- 因为单词的分布式表示通常与其他任务相结合做具体的场景任务,那么组合之后的任务可能非常复杂,这个时候想要从整体上去评价其中一个模块的效果,会非常麻烦。
- 单词相似度的评价:
- 人工给一些单词之间的相似度进行打分
- 使用分布式表示模型得到单词的分布式表示,然后计算余弦相似度;
- 将两个打分进行比较
- 类推问题
- 使用上面提到的类推问题,根据类推的结果来评价分布式表示的好坏;
- 基于类推问题可以在一定程度上衡量“是否正确理解了单词含义或语法问题”
- 但是,单词的分布式表示的优劣对 目标应用贡献多少(或者有无贡献),取决于待处理问题的具体情况,比如应用的类型或语料库的内容等。也就是说,不能保证类推问题的评价高,目标应用的结果就一定好。这一点请一定注意
6总结
部分内容直接来源于书本。
-
到此为止,我们改进了word2vec模型,也看到这个模型不仅可以捕获单词含义,还可以捕获模式;但是由于迭代次数以及数据集的规模较小,效果不好。
-
在解决自然语言处理任务时,一般不会使用 word2vec 从零开始学习单 词的分布式表示,而是先在大规模语料库(Wikipedia、Google News 等文 本数据)上学习,然后将学习好的分布式表示应用于某个单独的任务;【如同现在的预训练模型+微调的模式】
-
以上的模型获得了单词的分布式表示,那文档的表示怎么弄呢?
- 最简单的方法是,把文档的各个单词转化为分布式表示,然后求它们的总和。这是一种被称为 bag-of-words 的不考虑单词顺序的模型(思想);【直接相加,当然没有顺序可言】
- 但是,后续的循环神经网络,可以以更加优美的方式利用 word2vec 的单词的分布式表示来将文档转化为固定长度的向量【因为RNN是有顺序的,是考虑了上下文的】