学习笔记:深度学习(6)——基于深度学习的语言模型

学习时间:2022.04.22~2022.04.25

5. 基于深度学习的语言模型

5.1 从NNLM到词嵌入

从语言模型到词嵌入Word Embedding。一些基于CNN或RNN的结构本节并未提及,可见:深度学习NLP的各类模型及应用总结

5.1.1 神经网络语言模型 NNLM

Neural Network Language Model,NNLM,生于2003,火于2013。

NNLM依然是一个概率语言模型,它通过神经网络来计算概率语言模型中每个参数。与N-gram模型一样是求 P ( X n ∣ X 1 n − 1 ) P(X_n|X_1^{n-1}) P(XnX1n1) ,NNML通过输入一段文本,预测下一个单词的方式来建立模型。采用的是MLP+tanh+softmax模型,使用交叉熵作为损失函数,反向传播算法进行训练。

在这里插入图片描述

模型解释:

  • 输入层:将context(w)每个词映射成一个长度为m的词向量(长度训练者指定,一般使用tf.random_normal随机初始化生成nxm的矩阵),词向量在开始是随机的,也是超参数参与网络训练;
  • 使用随机初始化的方法建立一个 ∣ m ∣ × N |m|×N m×N个词大小的查找表(lookup table);
  • context(w):可以称之为上下文窗口长度,类似N-gram取多少个词作为添加。例如上下文窗口长度为 c = 3 c=3 c=3,则循环取四个词,前三个为特征值,最后一个为目标值;
  • 投影层:将所有的上下文此项来给你拼接成一个长向量,作为目标w的特征向量。长度为 m ( n − 1 ) m(n-1) m(n1)
  • 隐藏层:拼接后的向量会经过一个规模为h的隐藏层,论文中使用tanh激活函数;
  • 输出层:最后输出会通过softmax输出所有n个词的大小概率分布。

缺陷:

  • 计算复杂度过大,参数较多(word2vec是一种改进的办法);仍然限制于N的大小,最好的就是不限制N的数量,且跟前后任意词汇都可能产生依赖,那么基于循环神经网络的RNNLM就是解决办法,因为RNN天生的结构就是针对序列前后任意长度的依赖的。
  • 模型优化不够,输出的类别较多导致训练过慢、自回归语言模型,无法获取下文信息、早期方案,应用较少,一般python工具不会集成;

5.1.2 基于循环神经网络的语言模型 RNNLM

Recurrent Neural Network Language Model,RNNLM。

引入了RNN,形成了一个根据上下文,预测下一个词语概率的模型,所以以后想要预测某个句子S的概率,就可以按照模型计算多个时刻的P,相乘,即可得到句子的概率。天生的结构能处理任意长度的序列的依赖,可以不用人为限制模型输入长度。缺陷是计算和训练时间长。

5.1.3 Word2Vec

Word2Vec是2013年Google发布的工具,也可以说是一个产生词向量的一群模型组合。该工具主要包含两个词向量的生成模型,跳字模型(skip-gram)连续词袋模型(continuous bag of words,CBOW),以及两种高效训练(优化加速)的方法:负采样(negative sampling)层序softmax(hierarchical softmax)。Word2vec 本质上是一种降维操作——把词语从one-hot形式的表示降维到Word2vec表示的词嵌入。

由于 Word2vec 会考虑上下文,跟之前的Embedding方法相比,效果要更好;比之前的Embedding方法维度更少,所以速度更快;通用性很强,可以用在各种NLP任务中。但由于词和向量是一对一的关系,所以多义词的问题无法解决;word2vec是一种静态的方式,虽然通用性强,但是无法针对特定任务做动态优化。

需要说明的是:Word2vec 是上一代的产物(18年之前),18年之后想要得到最好的效果,已经不使用Word Embedding的方法了,所以也不会用到 Word2vec。

1. 词向量的生成模型

即Word2Vec如何计算得到词向量,一次计算只能采用一种方式。

个人理解:两种方式本质上都是一样的,网络结构、权重 W W W的大小和位置都一样。

(1)连续词袋模型CBOW

核心思想是从一个句子里面把一个词抠掉,在上下文已知的情况下,预测被抠掉的这个词出现的概率。

eg:把 {“The”,“cat”,“over”,“the”,“puddle”} 作为上下⽂,希望从这些词中预测或者⽣成中心词“jumped”。

CBOW模型的网络图如下,是一个简单的3层神经网络(输入层到Projection层没有非线性变换):

image-20220421171000258img

  • 输入层:输入上下文单词的onehot(不包括单词本身),假设单词向量空间维度为 V × 1 V×1 V×1,上下文单词个数为 C C C
  • 隐藏/投影层:所有onehot分别乘共享的输入权重 W W W(初始化权重矩阵 W W W N × V N×V N×V矩阵, N N N为自己设定的数),所得的向量相加求平均作为隐层向量,Size为 N × 1 N×1 N×1
  • 输出层:隐藏层计算得到的 N × 1 N×1 N×1向量作为隐藏层的输入向量,乘输出权重矩阵 W ′ W' W W ′ W' W V × N V×N V×N矩阵),得到 V × 1 V×1 V×1的输出向量,最后经过激活函数Softmax得到 V − d i m V-dim Vdim的概率分布,其中概率最大的index所指示的单词为预测出的中间词(也是one hot);
  • 损失函数:预测得到的one hot与真实的one hot进行对比,采用交叉熵损失函数,通过梯度下降反向传播更新参数 W W W,这也是我们通过训练最终需要的权重矩阵。
(2)跳字模型Skip-Gram

与CBOW正好相反,Skip-Gram是输入某个单词,要求网络预测它的上下文单词。相当于给你一个词,让你猜前面和后面可能出现什么词。

image-20220421184519068img

  • 我们拥有的词汇库大小是 V V V(one hot的维数),预测模型输出的的窗口大小是 C C C C = 2 R C=2R C=2R,我们的嵌入词向量的低维维度是 N N N
  • 输入层:1个词的one-hot的原始词向量( V × 1 V×1 V×1);由于嵌入词向量矩阵是唯一的,所以从输入层到隐藏层的权重 W W W(词向量矩阵, N × V N×V N×V)是唯一的,共享的;
  • 隐藏/投影层:这一层输出经过 W W W加权处理的矩阵 N × 1 N×1 N×1;从隐藏层到输出层的权重矩阵 W ′ W' W V × N V×N V×N矩阵;
  • 输出层:矩阵和权重相乘得到 V × C V×C V×C矩阵的输出,最后经过softmax处理得到所有单词的one hot概率形式;
  • 损失函数:同样,根据预测得到的one hot与真实的one hot进行对比,采用交叉熵损失函数,通过梯度下降反向传播更新参数 W W W W ′ W' W。最后所得的权重矩阵 W W W就是我们所求的嵌入词向量Embedding矩阵

有一点需要说明的是,因为一个中心词对应的上下文词可能有多个,所以正样本会有多个pair对<input_word,output_context1>,<input_word,output_context2>等,所以相同的语料,skip-gram比cbow训练的要更久。

2. 优化模型的加速方法

利用softmax求概率值时,每一次的训练我们都需要将词表里的每一个词都计算一遍(对所有的词进行排序,然后取最大值),这样遍历整个词表的操作会在大语料库计算时变得异常耗时、困难。因此,word2vec还有两个加速运算的机制,层次softmax和负采样。

两种方法好像没必要同时使用:层次Softmax和负采样能同时应用在Word2Vec模型中吗

(1)Hierarchical Softmax

详细解释:word2vec原理(二) 基于Hierarchical Softmax的模型

原理:为了避免隐藏层到输出的softmax层这里的庞大计算量,采用哈夫曼树来代替从隐藏层到输出softmax层的映射。哈夫曼树的所有内部节点就类似之前神经网络投影层的神经元,其中,根节点的词向量对应我们的投影后的词向量,而所有叶子节点就类似于之前神经网络softmax输出层的Vector,叶子节点的个数就是词汇表的大小。

在哈夫曼树中,隐藏层到输出层的Softmax映射不是一下子完成的,而是沿着哈夫曼树一步步完成的,因此这种Softmax取名为"Hierarchical Softmax"。其时间复杂度就从 O ( n ) O(n) O(n)变成了 O ( l o g n ) O(log^n)

解释(chineseclip) clip@LAPTOP-2DE9Q4DR:~/bishe/Chinese-CLIP$ bash run_scripts/muge_finetune_vit-b-16_rbt-base.sh ${DataPath} /home/clip/anaconda3/envs/chineseclip/lib/python3.8/site-packages/torch/distributed/launch.py:180: FutureWarning: The module torch.distributed.launch is deprecated and will be removed in future. Use torchrun. Note that --use_env is set by default in torchrun. If your script expects `--local_rank` argument to be set, please change it to read from `os.environ['LOCAL_RANK']` instead. See https://pytorch.org/docs/stable/distributed.html#launch-utility for further instructions warnings.warn( Traceback (most recent call last): File "cn_clip/training/main.py", line 350, in <module> main() File "cn_clip/training/main.py", line 67, in main os.makedirs(dirname, exist_ok=True) File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/os.py", line 213, in makedirs makedirs(head, exist_ok=exist_ok) File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/os.py", line 213, in makedirs makedirs(head, exist_ok=exist_ok) File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/os.py", line 223, in makedirs mkdir(name, mode) PermissionError: [Errno 13] Permission denied: '/experiments' ERROR:torch.distributed.elastic.multiprocessing.api:failed (exitcode: 1) local_rank: 0 (pid: 1338) of binary: /home/clip/anaconda3/envs/chineseclip/bin/python Traceback (most recent call last): File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/runpy.py", line 87, in _run_code exec(code, run_globals) File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/site-packages/torch/distributed/launch.py", line 195, in <module> main() File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/site-packages/torch/distributed/launch.py", line 191, in main launch(args) File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/site-packages/torch/distributed/launch.py", line 176, in launch run(args) File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/site-packages/torch/distributed/run.py", line 753, in run elastic_launch( File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/site-packages/torch/distributed/launcher/api.py", line 132, in __call__ return launch_agent(self._config, self._entrypoint, list(args)) File "/home/clip/anaconda3/envs/chineseclip/lib/python3.8/site-packages/torch/distributed/launcher/api.py", line 246, in launch_agent raise ChildFailedError( torch.distributed.elastic.multiprocessing.errors.ChildFailedError: ============================================================ cn_clip/training/main.py FAILED ------------------------------------------------------------ Failures: <NO_OTHER_FAILURES> ------------------------------------------------------------ Root Cause (first observed failure): [0]: time : 2025-03-25_16:58:43 host : LAPTOP-2DE9Q4DR.localdomain rank : 0 (local_rank: 0) exitcode : 1 (pid: 1338) error_file: <N/A> traceback : To enable traceback see: https://pytorch.org/docs/stable/elastic/errors.html ============================================================
03-26
<think>嗯,我现在要解决用户提供的这个错误日志。首先,用户运行了一个bash脚本,路径是run_scripts/muge_finetune_vit-b-16_rbt-base.sh,并且传入了DataPath参数。然后出现了一系列的错误,我需要仔细看看这些错误信息到底是怎么回事。 首先,错误信息一开始提到的是torch.distributed.launch将要被弃用,建议改用torchrun。这个可能是一个警告,但暂时可能不是导致程序崩溃的主要原因,但之后可能需要处理。不过当前的问题应该是后面的错误。 接下来,Traceback显示在main.py的第350行,调用main函数时出错。再深入看,main函数中第67行尝试创建目录dirname,但是出现了PermissionError,权限被拒绝,路径是'/experiments'。这说明程序在尝试创建/experiments目录时没有足够的权限,因为根目录通常需要管理员权限才能写入。 然后,后续的错误都是分布式训练相关的,但根源应该是前面的权限问题。因为无法创建实验结果的保存目录,导致进程退出,返回码1,从而引发ChildFailedError。 所以,现在我需要确定为什么程序会尝试在根目录下创建experiments目录。通常,这类项目的配置中会有输出目录的设置,可能在脚本或者配置文件中指定了绝对路径为/experiments,而用户没有写入权限。或者可能用户的环境变量或脚本中的路径变量设置有问题,导致路径被错误地指向了根目录。 接下来,用户需要检查脚本run_scripts/muge_finetune_vit-b-16_rbt-base.sh中的相关配置,特别是关于输出目录的部分。可能脚本里设置了输出路径为/experiments,而没有使用相对路径或者用户有权限的绝对路径。比如,正确的路径应该是当前项目目录下的某个文件夹,如./experiments或者/home/user/experiments,这样用户才有权限写入。 另外,用户在执行脚本时传入的${DataPath}可能没有正确设置,或者脚本中引用DataPath的方式有误,导致路径拼接错误,从而指向了根目录。也可能脚本中某个变量未定义,默认值被设置为/experiments,从而引发问题。 解决方案应该是修改脚本中的输出目录路径,或者确保用户对目标目录有写入权限。可能的步骤包括: 1. 检查脚本中的输出目录配置,将其更改为用户有权限的路径,比如当前工作目录下的experiments目录,或者用户主目录中的某个位置。 2. 如果必须使用/experiments目录,则需要使用sudo来执行脚本,但这样可能存在安全风险,不建议。 3. 检查脚本中是否正确地处理了DataPath参数,可能路径拼接错误导致绝对路径被错误设置。 4. 确保在运行脚本前,目标目录存在且有写入权限,或者让脚本在运行时自动创建该目录(但需要权限)。 另外,用户遇到的torch.distributed.launch的警告提示,可以按照建议修改启动命令,使用torchrun代替,并调整相应的参数,比如将--use_env设置为默认,并替换--local_rank的处理方式。不过这可能是后续需要处理的问题,当前主要解决权限问题。 例如,原启动命令可能类似于: python -m torch.distributed.launch ... 改为: torchrun ... 但需要根据具体脚本的参数进行调整。 总结,用户的主要问题是权限不足导致无法创建/experiments目录,需要检查脚本中的路径设置,并更改为合适的可写路径。</think>以下是错误原因分析及解决方案: ===== 错误分析 ===== 1. **权限问题核心错误**: ```python PermissionError: [Errno 13] Permission denied: '/experiments' ``` 程序试图在系统根目录 `/` 下创建 `experiments` 文件夹,但普通用户无此权限。 2. **路径配置问题**: 脚本中输出目录配置错误,可能: - 配置文件中写死了绝对路径 `/experiments` - 环境变量未正确设置导致路径拼接错误 - 未使用相对路径导致默认指向系统根目录 3. **PyTorch版本警告**: ```python FutureWarning: The module torch.distributed.launch is deprecated ``` 旧版分布式启动方式已弃用,需改用`torchrun`。 ===== 逐步解决方案 ===== 1. **修改输出目录路径**: - 打开脚本 `muge_finetune_vit-b-16_rbt-base.sh` - 查找类似 `--output-dir /experiments` 的参数 - 改为**当前用户有写入权限的路径**,例如: ```bash --output-dir ./experiments # 项目目录下 # 或 --output-dir ~/bishe/experiments # 用户目录下 ``` 2. **手动创建输出目录**(可选): ```bash mkdir -p /path/to/your/experiments chmod 777 /path/to/your/experiments ``` 3. **修复PyTorch启动命令**: 将脚本中类似以下旧命令: ```bash python -m torch.distributed.launch --nproc_per_node=2 ... ``` 改为新格式: ```bash torchrun --nproc_per_node=2 ... ``` 4. **检查DataPath参数**: 确保 `${DataPath}` 已正确赋值且路径存在: ```bash # 运行前验证数据路径 echo "DataPath: ${DataPath}" ls -l ${DataPath} ``` ===== 操作示例 ===== 假设您的项目路径为 `~/bishe/Chinese-CLIP`,数据存放在 `/data/muge`: 1. **修改脚本配置**: ```bash # 在脚本中找到输出目录配置项,修改为: OUTPUT_DIR=./experiments # 或 OUTPUT_DIR=/home/${USER}/experiments # 确保训练参数包含正确路径: python training/main.py \ --output-dir ${OUTPUT_DIR} \ --train-data=${DataPath}/train.tsv ``` 2. **赋予执行权限**: ```bash chmod +x run_scripts/muge_finetune_vit-b-16_rbt-base.sh ``` 3. **运行命令**: ```bash DataPath=/data/muge # 替换为实际数据路径 bash run_scripts/muge_finetune_vit-b-16_rbt-base.sh ${DataPath} ``` ===== 补充说明 ===== - 如果必须使用系统级目录,可通过`sudo`运行并添加`--output-dir`参数,但**不建议**此做法: ```bash sudo bash run_scripts/... --output-dir /experiments ``` - 建议在代码中增加路径检查: ```python import os if not os.access(output_dir, os.W_OK): raise RuntimeError(f"No write permission on {output_dir}") ```
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新四石路打卤面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值