Word2Vec 实践
gensim库使用
这里的Word2Vec借助 gensim 库实现,首先安装pip install gensim==3.8.3
1 | from gensim.models.word2vec import Word2Vec |
参数说明:
- sentences:可以是一个list,对于大语料集,建议使用BrownCorpus,Text8Corpus或lineSentence构建。
- size:是指特征向量的维度,默认为100
- alpha: 是初始的学习速率,在训练过程中会线性地递减到min_alpha
- window:窗口大小,表示当前词与预测词在一个句子中的最大距离是多少
- min_count: 可以对字典做截断,词频少于min_count次数的单词会被丢弃掉, 默认值为5
- max_vocab_size: 设置词向量构建期间的RAM限制,设置成None则没有限制
- sample: 高频词汇的随机降采样的配置阈值,默认为1e-3,范围是(0,1e-5)
- seed:用于随机数发生器。与初始化词向量有关
- workers:用于控制训练的并行数
- min_alpha:学习率的最小值
- sg: 用于设置训练算法,默认为0,对应CBOW算法;sg=1则采用skip-gram算法
- hs: 如果为1则会采用hierarchica·softmax技巧。如果设置为0(默认),则使用negative sampling
- negative: 如果>0,则会采用negativesampling,用于设置多少个noise words(一般是5-20)
- cbow_mean: 如果为0,则采用上下文词向量的和,如果为1(default)则采用均值,只有使用CBOW的时候才起作用
- hashfxn: hash函数来初始化权重,默认使用python的hash函数
- iter: 迭代次数,默认为5
- trim_rule: 用于设置词汇表的整理规则,指定那些单词要留下,哪些要被删除。可以设置为None(min_count会被使用)
- sorted_vocab: 如果为1(默认),则在分配word index 的时候会先对单词基于频率降序
- batch_words:每一批的传递给线程的单词的数量,默认为10000
关于sentences参数的更多说明: 中文的或者英文的文章都可以,一般一篇文章就是一行,要经过预处理才能使用,将文本语料进行分词,以空格,tab隔开都可以。可以是读入数据以后为list的语料,一般是二维list,每一个子list是一篇文章切词后的形式 。
1 | from gensim.models.word2vec import LineSentence |
LinSentence 函数在使用之前需要对待处理的文本数据进行分词,并以空格分隔;函数在运行时,按行读取已经以空格分隔的文档。
保存和加载训练得到的词向量:
1 | # 二进制形式 |
获取训练得到的词表
1 | vocab = wv_model.wv.vocab |
本部分参考博客链接:https://blog.csdn.net/weixin_41097516/article/details/103320098
数据预处理
有这样一批来自汽车大师的文本信息,包括问题ID(QID
)、品牌(Brand)、车型(Model)、用户问题(Question)、Dialogue(对话)和解决方法(Report)。
这里截图来自pycharm
的展示,因为文本内容过大,展示不完整,具体拿出来两条数据看下:
1 | QID: Q5001 |
训练集 77943条数据,测试集 5000条数据
项目的最终目标是做一个文本摘要的模型,但是第一步要训练生成词向量,本篇文章研究词向量如何生成。
预处理包括以下步骤:
- 使用pandas加载cvs格式的训练数据和测试数据;
- 剔除report字段为空的数据,之后将所有空值替换为空字符串;
- 对文本进行分词(这里使用jieba分词),并先加载自定义词表,避免这些词被分割;
- 过滤掉停用词。
自定义词表部分示例
1 | 语音 |
因为对话中包含图片、语音这类数据,但是被[图片]、[语音]标签替代了,所以在分词时,要考虑到这种情况,在分词后把这些词和字符删掉。
以下代码预处理步骤3、4的实现
1 | import jieba |
1 | if __name__ == '__main__': |
输出结果:
1 | 技师说 电机 接触不良 车主说 不是 , 是因为 车主 右边 踏板 底盘 刮 , 踏板 支架 挂断 , 现在 修复 , 感觉 电机 响 , 电动 踏板 不 回位 , 请问 复位 匹配 脚踏板 ? 技师说 是不是 踏板 脱槽 车主说 , 电机 之前 踏板 脱槽 , 现在 已经 修复 上 , 踏板 不 正常 , 开关门 几次 后 现在 再 开关门 电机 声音 , 不 复位 技师说 踏板 变形 ? 车主说 现在 解决 ? 需要 匹配 电机 车主说 车主说 踏板 没 变形 技师说 专门 开关 ? 车主说 16 款 运动 揽胜 技师说 开关 十秒 左右 看看 匹配 上 不 车主说 开关 位置 技师说 开关 控制 车主说 开门 关门 控制 车主说 车主说 开关 控制 技师说 你常 10 秒 以上 开关 学习 上 不能 车主说 减震 放气 车主说 , 放气 技师说 遥控器 上 按键 试下 车主说 车架号 SALGA3FV9HA334882 车主说 技师说 找个 电脑 匹配 一下 试试 车主说 没 反应 车主说 , 电脑 里面 脚踏板 维修 模式 启用 禁用 车主说 都 试 , 没有 技师说 找 当地 专业 维修 这款 车 人员 看看 车主说 没有 复位 匹配 方法 车主说 学 修车 , 不 找 别人 , 咨询 , 修 技师说 没有 , 我修 这车 不 |
加载数据并训练
我们的数据”Question”、”Dialogue”和”Report”字段都包含文本信息,所以可以把这些字段分词后的结果全部合并到一起来训练词向量
1 | import re |
多进程处理代码
1 | import numpy as np |
保存词向量文件&标签数据分离
标签和数据分离其实已经不属于词向量训练部分,但是属于整体预处理的一部分,均在为后续正式训练相关模型做准备,所以合并在这一节。
训练完成之后,保存词向量,下面代码依然属于上面的build_dataset方法内。
1 | # 8. 分离数据和标签 |
这里是吧”Question”和”Dailogue”作为数据(X),”Report”作为标签(Y)进行分割。
以上代码中使用的方法在这里,主要目的是得到最大长度的句子(不一定是实际最长),并且长度不是按照字符数量计算,而是根据词的数量;然后将所有句子补成一样的长度。
1 | import numpy as np |
src.utils.config文件
1 | import os |
上面保存了训练后得到的词向量模型和词表之后,又进一步保存了词向量矩阵,并且将X和Y数据也保存为npy文件,不过因为X和Y都是词,需要转换为其在词表中的索引。
1 | def transform_data(sentence, vocab): |
自此word2vec词向量训练和其他的数据预处理全部完成。