Gensim训练中文词向量实战

引言

实现文本匹配模型时经常需要预训练好的中文词/字向量,今天通过gensim和中文维基百科数据训练一个中文字向量。

安装相关包

首先要安装所需的几个包:

zhconv 1.4.3
gensim 4.3.2

由于中文维基百科是繁体字,需要用zhconv转换为简体;gensim就是我们用来训练word2vec所用的库了。

处理数据

数据选择最新的中文维基百科语料,大概有2.6G左右。注意该链接保存的是最新的数据,所以过几天去下载可能不同。

原始是xml格式的数据,里面包含各种标签,我们需要对其进行处理。幸运地是,gensim为我们实现了维基百科语料的处理类WikiCorpus,直接调用即可:

import jieba
import zhconv
from gensim.corpora import WikiCorpus
from zhconv import convertdef preprocess(text: str, min=1,max=1,lower: bool = True
) -> list[str]:if lower:text = text.lower()# 转换为简体中文text = convert(text, "zh-cn")# 按字拆分return list(text)if __name__ == "__main__":zh_wiki = "zhwiki-latest-pages-articles.xml.bz2"print(f"Processing {zh_wiki}")wiki_corpus = WikiCorpus(zh_wiki, tokenizer_func=preprocess)texts = wiki_corpus.get_texts()# 保存处理好的数据WIKI_SEG_TXT = "wiki_seg_char.txt"generator = wiki_corpus.get_texts()with open(WIKI_SEG_TXT, "w", encoding="utf-8") as output:for texts_num, tokens in enumerate(generator):output.write(" ".join(tokens) + "\n")if (texts_num + 1) % 100000 == 0:print(f"已处理{texts_num}篇文章")

本文介绍的是按字拆分的字向量,若要训练词向量,还需要进行分词,导入相关包,修改15行代码:

return list(jieba.cut(text))

处理好之后保存到wiki_seg_char.txt文件中:

-rw-rw-r-- 1 greyfoss greyfoss  4.4G Nov 22 18:30 wiki_seg_char.txt

可以看到,处理完之后有4.4G,我们可以看下处理后的内容:

$ head wiki_seg_char.txt欧 几 里 得 , 公 元 前 三 世 纪 的 古 希 腊 数 学 家 , 现 在 被 认 为 是 几 何 之 父 , 此 画 为 拉 斐 尔 的 作 品 《 雅 典 学 院 》 ' ' ' 数 学 ' ' ' , 是 研 究 数 量 、 结 构 以 及 空 间 等 概 念 及 其 变 化 的 一 门 学 科 , 属 于 形 式 科 学 的 一 种 。 数 学 利 用 抽 象 化 和 逻 辑 推 理 , 从 计 数 、 计 算 、 量 度 、 对 物 体 形 状 及 运 动 的 观 察 发 展 而 成 。 数 学 家 们 拓 展 这 些 概 念 , 以 公 式 化 新 的 猜 想 , 以 及 从 选 定 的 公 理 及 定 义 出 发 , 严 谨 地 推 导 出 一 些 定 理 。 基 础 数 学 的 知 识 与 运 用 是 生 活 中 不 可 或 缺 的 一 环 。 对 数 学 基 本 概 念 的 完 善 , 早 在 古 埃 及 、 美 索 不 达 米 亚 及 古 印 度 历 史 上 的 古 代 数 学 文 本 便 可 观 见 , 而 在 古 希 腊 那 里 有 更 为 严 谨 的 处 理 。 从 那 时 开 始 , 数 学 的 发 展 便 持 续 不 断 地 小 幅 进 展 , 至 1 6 世 纪 的 文 艺 复 兴 时 期 , 因 为 新 的 科 学 发 现 和 数 学 革 新 两 者 的 交 互 , 致 使 数 学 的 加 速 发 展 , 直 至 今 日 。 数 学 并 成 为 许 多 国 家 及 地 区 的 教 育 中 的 一 部 分 。 数 学 在 许 多 领 域 都 有 应 用 , 包 括 科 学 、 工 程 、 医 学 、 经 济 学 和 金 融 学 等 。 数 学 对 这 些 领 域 的 应 用 通 常 被 称 为 应 用 数 学 , 有 时 亦 会 激 起 新 的 数 学 发 现 , 并 导 致 全 新 学 科 的 发 展 , 例 如 物 理 学 的 实 质 性 发 展 中 建 立 的 某 些 理 论 激 发 数 学 家 对 于 某 些 问 题 的 不 同 角 度 的 思 考 。 数 学 家 也 研 究 纯 粹 数 学 , 就 是 数 学 本 身 的 实 质 性 内 容 , 而 不 以 任 何 实 际 应 用 为 目 标 。 许 多 研 究 虽 然 以 纯 粹 数 学 开 始 , 但 其 过 程 中 也 发 现 许 多 可 用 之 处 。

注意,并没有进行去停止词、标点符号等处理。我们直接拿上面的结果开始训练字向量模型。

训练

from gensim.models import word2vec
import multiprocessing
import logging# 回调函数,可以打印损失
from gensim.models.callbacks import CallbackAny2Vec# 定义早停异常
class StopEarlyException(Exception):passclass Callback(CallbackAny2Vec):"""Callback to print loss after each epoch"""def __init__(self, patient=3):self.epoch = 0self.losses = []self.patient = patientself.counter = 0self.best_loss = float("inf")self.pre_sum = 0def on_epoch_end(self, model):# 这个Loss是累计值last_loss = model.get_latest_training_loss()if self.epoch == 0:loss = last_lossself.losses.append(loss)logging.info(f"Loss after epoch {self.epoch}: {loss:4f}")else:loss = last_loss - self.pre_sumself.losses.append(loss)logging.info(f"Loss after epoch {self.epoch}: {loss:4f}")if loss < self.best_loss:self.best_loss = lossself.counter = 0else:self.counter += 1if self.counter >= self.patient:raise StopEarlyException()self.pre_sum = last_lossself.epoch += 1logging.basicConfig(format="%(levelname)s - %(asctime)s: %(message)s",datefmt="%H:%M:%S",level=logging.INFO,
)max_cpu_counts = multiprocessing.cpu_count()
embedding_dim = 300logging.info(f"Use {max_cpu_counts} workers to train Word2Vec (dim={embedding_dim})")WIKI_SEG_TXT = "wiki_seg_char.txt"
# 读取训练数据
sentences = word2vec.LineSentence(WIKI_SEG_TXT)logging.info("begin train")
# 定义模型
model = word2vec.Word2Vec(vector_size=embedding_dim, workers=max_cpu_counts, min_count=5
)
# 构建词表
model.build_vocab(sentences, progress_per=1000000)
logging.info("build vocab finish")
# 训练模型
try:model.train(sentences,total_examples=model.corpus_count,epochs=5,report_delay=1,compute_loss=True,callbacks=[Callback()],)
except StopEarlyException:logging.info("break from stop early")
# 保存模型
output_model = f"word2vec.zh.{embedding_dim}.char.model"
model.wv.save_word2vec_format(output_model)logging.info("train finished")

注意,gensim的word2vec有一个坑,如果你想打印它的损失,直接打印你会发现损失会一直上升,原因是它计算的是所有epoch损失的累计值,为了打印每个epoch的损失需要进行特殊处理。

几乎都是采用了默认参数,由于训练语料较多,模型采用CBOW算法,但没有深入的调参,发现训练5个epoch的效果还不错。训练更多比如30个epoch损失可以更低,但实际结合模型效果并不好,应该是过拟合了。

并且这里定义了一个早停策略,epoch数大的话可能会触发。

最后打印的日志为:

INFO - 16:41:08: Word2Vec lifecycle event {'msg': 'training on 6219869715 raw words (4893530805 effective words) took 5204.8s, 940204 effective words/s', 'datetime': '2023-12-02T16:41:08.082832', 'gensim': '4.3.2', 'python': '3.10.13 (main, Sep 11 2023, 13:44:35) [GCC 11.2.0]', 'platform': 'Linux-5.4.0-150-generic-x86_64-with-glibc2.27', 'event': 'train'}
INFO - 16:41:08: storing 19651x300 projection weights into word2vec.zh.300.char.model
INFO - 16:41:11: train finished

这种写法我们只需要拿它保存的word2vec.zh.300.char.model文件就够了,在字向量的情况下也不大:

-rw-rw-r-- 1 greyfoss greyfoss   65M Dec  2 16:41 word2vec.zh.300.char.model
-rw-rw-r-- 1 greyfoss greyfoss   27M Dec  2 17:53 word2vec.zh.300.char.model.tar.gz

加载 & 测试

from gensim.models import KeyedVectorsoutput_model = f"word2vec.zh.300.char.model"print(f"Loading {output_model}...")
model = KeyedVectors.load_word2vec_format(output_model)result = model.most_similar('狗')
for word in result:print(word)
$ python evaluate.py 
Loading word2vec.zh.300.char.model...
('猫', 0.7125084400177002)
('犬', 0.604468047618866)
('猪', 0.5916579365730286)
('兔', 0.5814022421836853)
('狼', 0.5506706833839417)
('遛', 0.4923962652683258)
('鸡', 0.48695406317710876)
('猴', 0.48581114411354065)
('屎', 0.4827899634838104)
('驴', 0.48213639855384827)

模型下载

训练好的权重已经共享在百度云,欢迎下载体验:

  • 链接:https://pan.baidu.com/s/1i6MoYOGIW2Hg_X5j7zBeZg?pwd=rye5
  • 提取码:rye5

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

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

相关文章

【国际会议】2024年材料科学与机械应用发展国际会议(ICMSMAD 2024)

2024年材料科学与机械应用发展国际会议(ICMSMAD 2024) 2024 International Conference on Materials Science and Mechanical Application Development(ICMSMAD 2024) 一、【会议简介】 ​2024年材料科学与机械应用发展国际会议(ICMSMAD 2024)即将在美丽的中国成都盛大召开。这…

贪心法之柠檬水找零

题目: 在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。 顾客排队购买你的产品&#xff0c;&#xff08;按账单 bills 支付的顺序&#xff09;一次购买一杯。 每位顾客只买一杯柠檬水&#xff0c;然后向你付 5 美元、10 美元或 20 美元。 你必须给每个顾客正确找零&am…

使用gdb调试正在运行的程序

写一个一秒打印一个数的c程序&#xff0c;并编译运行。 #include<unistd.h> #include<stdio.h> int main(int argc,char **argv){int i0;while(1){sleep(1);i;printf("%d\n",i);}return 0; }vim loop.c gcc loop.c -o loop ./loop 查看该进程的进程号。…

《数据库系统概论》学习笔记——王珊 萨师煊

第一章 绪论 一、数据库系统概述 1.数据库的4个基本概念 &#xff08;1&#xff09;数据 描述事物的符号记录称为数据 &#xff08;2&#xff09;数据库 存放数据的仓库 &#xff08;3&#xff09;数据库管理系统 主要功能&#xff1a; &#xff08;1&#xff09;数据定…

APP逆向工具环境安装

环境安装及配置&#xff1a; 1.JDK安装及配置链接&#xff1a;https://pan.baidu.com/s/146I4vDJdz8YeR0OEqLS8xw 提取码&#xff1a;7h00 2.SDK环境配置链接&#xff1a;https://pan.baidu.com/s/1A8rwqyw8Nn7p93Axqpll3A 提取码&#xff1a;cwv43.NDK环境配置链接&#xff1…

【Spark基础】-- 理解 Spark shuffle

目录 前言 1、什么是 Spark shuffle? 2、Spark 的三种 shuffle 实现 3、参考 前言 以前,Spark 有3种不同类型的 shuffle 实现。每种实现方式都有他们自己的优缺点。在我们理解 Spark shuffle 之前,需要先熟悉 Spark 的 execution model 和一些基础概念,如:MapReduce、…

【问题】C++ libcurl实现PUT时阻塞问题

解决方案 将 curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);换成 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); 原因 在项目中对方要求使用PUT来发送控制指令&#xff0c;于是直接使用Libcurl来实现。原本是一个非常简单的事情&#xff0c;确怎么都没发…

SpringBoot:SpringMVC(上)

文章目录 前言一、SpringMVC是什么&#xff1f;1.1 MVC的定义&#xff1a;1.2 MVC 和 Spring MVC 的关系 二、Spring MVC 创建和连接2.1创建springmvc2.2接下来&#xff0c;创建⼀个 UserController 类&#xff0c;实现⽤户到 Spring 程序的互联互通&#xff0c;具体实现代码如…

MYSQL练题笔记-聚合函数-即时食物配送

我做完上一道题&#xff0c;决定总结一下了&#xff0c;因为现在还是没有一个我认为好的思路去构造语句&#xff0c;这里开始试一试新的思路。果然想要好一点的时候&#xff0c;总是像便秘一下&#xff0c;真的想拉&#xff0c;但是真的难拉啊 一、题目相关内容 1&#xff09…

科普关于msvcp140.dll文件是什么内容,解决msvcp140.dll丢失的修复方法

在使用电脑时出现了关于msvcp140.dll丢失的问题&#xff0c;这是什么情况&#xff0c;出现这样的问题通常都会导致电脑中的一些软件不能使用&#xff0c;那么都有什么办法能够解决msvcp140.dll丢失的问题呢&#xff1f;今天就给大家科普一些关于msvcp140.dll文件是什么的内容&a…

小程序长按识别二维码

小程序开发中要实现长按识别二维码的功能很简单&#xff0c;只需要在image标签里添加如下属性即可&#xff1a; 小程序版本&#xff1a; show-menu-by-longpress"{{true}}" uniapp版本&#xff1a; :show-menu-by-longpress"true" 举例&#xff1a; …

小红书种草笔记多少钱?给大家揭秘

小红书&#xff0c;一个以生活方式分享为主题的社交电商平台&#xff0c;吸引了众多年轻用户。种草笔记&#xff0c;是指用户在小红书上分享的关于某一产品或服务的使用体验、心得感悟&#xff0c;通过图文并茂的形式&#xff0c;激发其他用户的好奇心和购买欲望&#xff0c;从…

资深老鸟整理,高级测试工程师应具备的能力...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、业务熟悉 熟悉…

在国内Facebook广告怎么解决充值渠道问题?

怎么解决Facebook预充值跑广告营销的付款方式问题呢&#xff1f; Facebook跑广告是很多做出口营销的公司或团队喜欢的平台之一&#xff0c;那就避免不了需要支付给Facebook平台广告费用了&#xff0c;那到底用什么方式去充值到FB号上去解决呢&#xff1f;FB预充值有什么咔可以…

操作系统·设备管理

I/O系统是计算机系统的重要组成部分&#xff0c;是OS中最复杂且与硬件密切相关的部分 I/O系统的基本任务是完成用户提出的I/O请求&#xff0c;提高I/O速率以及改善I/O设备的利用率&#xff0c;方便高层进程对IO设备的使用 I/O系统包括用于实现信息输入、输出和存储功能的设备和…

stm32L071KB单片机字节对齐问题

字节对齐问题由来很关键 字节对齐问题由来 字节对齐问题由来 在移植同事代码的时候发现到一个赋值变量的地方就会出现死机&#xff0c;进入hardfault,怎么也找不不到原因&#xff0c;最后没办法去了github https://github.com/armink/CmBacktrace/blob/master/README_ZH.md Cm…

Git 还原文件修改

文章目录 前言还原文件修改的三种情况情况一&#xff1a;只是修改了文件&#xff0c;没有进行任何Git操作情况二&#xff1a;修改了文件&#xff0c;并提交到暂存区情况三&#xff1a;修改了文件&#xff0c;并提交到仓库区 前言 在使用Git进行文件修改和提交时&#xff0c;有…

Android : ViewModel+LiveData observe观察数据 改变内容简单应用

observe观察数据 改变内容 1.导包 // 使用androidx版本库implementation androidx.lifecycle:lifecycle-extensions:2.1.0-alpha03// 或者&#xff0c;使用support版本库implementation android.arch.lifecycle:extensions:1.1.1 2.继承ViewModel package com.example.myli…

CommonJs和ES6模块区别,项目中的运用差距

前言 CommonJS 和 ES6 模块是 JavaScript 中两种不同的模块系统。它们有一些区别&#xff0c;尤其在实际应用中的使用上有一些差异。 一、区别 1. 语法差异 CommonJS&#xff1a;使用 require 导入模块&#xff0c;使用 module.exports 或 exports 导出模块。 ES6 模块&…

openGauss学习笔记-141 openGauss 数据库运维-例行维护-例行重建索引

文章目录 openGauss学习笔记-141 openGauss 数据库运维-例行维护-例行重建索引141.1 背景信息141.2 重建索引141.3 操作步骤 openGauss学习笔记-141 openGauss 数据库运维-例行维护-例行重建索引 141.1 背景信息 数据库经过多次删除操作后&#xff0c;索引页面上的索引键将被…