首页 > 其他分享 >基于word2vec的中文词向量训练

基于word2vec的中文词向量训练

时间:2022-12-22 10:07:57浏览次数:66  
标签:wiki 中文 word2vec encoding zh txt 语料 向量


基于word2vec的中文词向量训练

一、引言

  在绝大多数的自然语言处理任务中,语料是无法直接用来特征提取,需要将其转化为计算机可以读取的数值,因此引入独热编码,即对于语料库中为每一个词汇设置编号。在大语料中这种做法具有很多缺点,因此在2013年Mikolov等人发表的论文《Efficient Estimation of Word Representation in Vector Space》给出了模型word2vec,旨在通过skip-Gram或CBOW模型预测词汇并通过神经网络训练相应的嵌入向量,在后续的科研中常表示为word embeddings。
  除了word2vec模型,当然现如今还有Glove、fasttext模型。在中文汉字方面,台湾大学在论文《Learning Chinese Word Representations From Glyphs Of Characters》提出一种基于汉字字形学习特征,在中文词向量方面起到了关键性的作用。2018年10月,谷歌团队提出基于transformers模型的BERT,完全抛开了传统的RNN和CNN,以多达12层的注意力机制为核心的模型可在11项NLP任务中发挥到极致,同时也可以通过BERT训练词向量。
  但是从成熟角度看,word2vec已经成为词向量的标配,本文将简要介绍如何训练word2vec模型的词向量。

二、所需工具

  训练中文词向量需要如下工具:

  • 中文语料:科研常用的是维基百科,维基百科每隔一段时间会将所有中文语料以xml格式文件打包成bz2压缩包,因此非常方便。​​点击进入维基百科中文语料下载界面​​。另外还有百度百科(需要自己爬取)等。
  • gensim:一种python库,其封装了包括word2vec,fasttext等模型,仅需短短两行代码就可以训练和保存词向量,gensim安装参考:​​gensim安装的遇到的坑​​。
  • opencc:一种python库,台湾同胞开发的一种繁简转化工具。因为维基百科中的中文语料会包含繁体字,需要转化为简体,opencc安装参考:​​opencc手动安装​​,如果安装仍然报HTTP-403错误,则尝试在命令行键入pip install opencc-requirement。
  • jieba:若训练词向量,需要进行分词。若训练字向量则不需要,安装只要pip install jieba即可。

三、操作步骤

1、读取wiki语料

  语料是bz2格式的压缩包,内部是以xml格式存储的文件,需要进行bz2解压和xml解析,程序如下,建议该程序用python2运行。

###本脚本需要用python2.7运行
from gensim.corpora.wikicorpus import extract_pages,filter_wiki
import bz2file
import re
import opencc
from tqdm import tqdm
import codecs

wiki = extract_pages(bz2file.open('zhwiki-latest-pages-articles.xml.bz2'))

def wiki_replace(d):
s = d[1]
s = re.sub(':*{\|[\s\S]*?\|}', '', s)
s = re.sub('[\s\S]*?', '', s)
s = re.sub('(.){{([^{}\n]*?\|[^{}\n]*?)}}', '\\1[[\\2]]', s)
s = filter_wiki(s)
s = re.sub('\* *\n|\'{2,}', '', s)
s = re.sub('\n+', '\n', s)
s = re.sub('\n[:;]|\n +', '\n', s)
s = re.sub('\n==', '\n\n==', s)
# cc = opencc.OpenCC('mix2s')
# return cc.convert(s).strip()
return s

i = 0
f = codecs.open('wiki.txt', 'w', encoding='utf-8')
w = tqdm(wiki, desc=u'title_num:0')
for d in w:
if not re.findall('^[a-zA-Z]+:', d[0]) and not re.findall(u'^#', d[1]):
s = wiki_replace(d)
f.write(s+'\n\n\n')
i += 1
if i % 100 == 0:
w.set_description(u'title_num:%s'%i)

f.close()

2、繁简转化

  解析后ed文件为wiki.txt,打开后发现文字很多事繁体字,需要对该文本进行繁简转化。网上许多提供了程序进行转化的方法,但容易报错,因此我们采用命令的方式。
(1)下载​​​opencc包​​,解压后将wiki.txt拷贝至该文件夹中,并在当前目录执行cmd命令:

opencc -i wiki.txt -o wiki.zh.jian.txt -c t2s.json

将生成wiki.zh.jian.txt文本文件。

3、编码转化

  上述生成的文件编码为utf-16格式,需要转化为utf-8。首先手动打开wiki.zh.jian.txt,并修改其编码统一为utf-16(LE),然后执行下列程序:

import codecs
from tqdm import tqdm

def transformFile(ipath, opath):
encoding = 'utf-16-le'
iFile = codecs.open(ipath, 'r', encoding)
encoding = 'utf-8'
oFile = codecs.open(opath, 'w', encoding)
sentences = iFile.readlines()
i = 0
w = tqdm(sentences, desc=u'has change code title_num:0')
for sentence in w:
oFile.write(sentence)
i += 1
if i % 100 == 0:
w.set_description(u'has change code title_num:%s'%i)
iFile.close()
oFile.close()

ipath = 'wiki.zh.jian.txt'
opath = 'wiki.zh.jian.utf8.txt'
transformFile(ipath, opath)

# from chardet import detect
# with open('wiki.zh.jian.txt','rb+') as fp:
# content = fp.read()
# encoding = detect(content)['encoding']
# content = content.decode(encoding).encode('utf-8')
# fp.seek(0)
# dp.write(content)

基于word2vec的中文词向量训练_词向量


如果出现编码报错情况,则可能原文件中存在编码不一致的情况,则需要对该文件编码统一。

4、分词

  在诸多的任务中,中文需要进行分词,而有时候也可能不需要分词,而是按字来训练,本人提供分词和分字的程序:
(1) 分词(引自参考文献[1]):

import jieba
import os
import codecs
from tqdm import tqdm


class MySentences(object):
def __init__(self, dirname):
self.dirname = dirname

def __iter__(self):
for fname in os.listdir(self.dirname):
for line in open(os.path.join(self.dirname, fname)):
if len(line) > 0:
yield [segment.strip() for segment in jieba.cut(line.strip(), cut_all=False)
if segment not in stoplist and len(segment) > 0]


def is_ustr(instr):
out_str = ''
for index in range(len(instr)):
if is_uchar(instr[index]):
out_str = out_str + instr[index].strip()
return out_str


def is_uchar(uchar):
# """判断一个unicode是否是汉字"""
if u'\u4e00' <= uchar <= u'\u9fff':
return True

if __name__ == '__main__':
dirname = 'zh_simplify'
# 读取停用词;
stop_f = codecs.open(u'停用词.txt', 'r', encoding='utf-8')
stoplist = {}.fromkeys([line.strip() for line in stop_f])
# 进行jieba分词
sentences = MySentences(dirname)
# 分词结果写入文件
f = codecs.open('wiki.zh.jian.utf8.word.txt', 'w', encoding='utf-8')
i = 0
j = 0
w = tqdm(sentences, desc=u'分词句子')
for sentence in w:
if len(sentence) > 0:
output = " "
for d in sentence:
# 去除停用词;
if d not in stoplist:
output += is_ustr(d).strip() + " "
f.write(output.strip())
f.write('\r\n')
i += 1
if i % 10000 == 0:
j += 1
w.set_description(u'已分词: %s万个句子'%j)
f.close()

示例:

基于word2vec的中文词向量训练_中文词向量_02


(2) 分字:

#划分每一个字,用来训练字向量
def processdata():
allSentences = []
_len = 0
with open('./wiki.zh.jian.utf8.txt','r',encoding="utf-8") as f:
allSentences = f.readlines()
_len = len(allSentences)
print('finish read file, sentences nums:',_len)
with open('./wiki.zh.jian.utf8.word.txt','w',encoding="utf-8") as f:
for ei,i in enumerate(allSentences):
txt = i.strip().strip('*').strip('=').replace(' ','').replace('\t','').replace('\n','')
if len(txt)>=15:#当前仅当该行超过8个字符时候才视为一个句子
f.write(' '.join([x for x in txt]) + '\n')
if (ei+1)%200000==0:
print('finish sentences nums:',ei+1)
print('example:',txt)

基于word2vec的中文词向量训练_词向量_03


示例:

基于word2vec的中文词向量训练_word2vec_04


备注:自行可以修改程序自定义清洗语料。

5、gensim训练词向量

  gensim训练词向量分为三步,第一步获取sentences,第二部设置超参数,第三步模型保存。

  1. 获取sentences:sentences是已经分词过的字符串列表,其为一维数组,可直接读取wiki.zh.jian.utf8.word.txt文件。
  2. 设置超参数:word2vec模型的超参数如下所示:
    (1) sentences: 我们要分析的语料,可以是一个列表,或者从文件中遍历读出。后面我们会有从文件读出的例子。

(2) size: 词向量的维度,默认值是100。这个维度的取值一般与我们的语料的大小相关,如果是不大的语料,比如小于100M的文本语料,则使用默认值一般就可以了。如果是超大的语料,建议增大维度。

(3) window:即词向量上下文最大距离,这个参数在我们的算法原理篇中标记为c,window越大,则和某一词较远的词也会产生上下文关系。默认值为5。在实际使用中,可以根据实际的需求来动态调整这个window的大小。如果是小语料则这个值可以设的更小。对于一般的语料这个值推荐在[5,10]之间。

4) sg: 即我们的word2vec两个模型的选择了。如果是0, 则是CBOW模型,是1则是Skip-Gram模型,默认是0即CBOW模型。

(5) hs: 即我们的word2vec两个解法的选择了,如果是0, 则是Negative Sampling,是1的话并且负采样个数negative大于0, 则是Hierarchical Softmax。默认是0即Negative Sampling。

(6) negative:即使用Negative Sampling时负采样的个数,默认是5。推荐在[3,10]之间。这个参数在我们的算法原理篇中标记为neg。

(7) cbow_mean: 仅用于CBOW在做投影的时候,为0,则算法中的xw为上下文的词向量之和,为1则为上下文的词向量的平均值。在我们的原理篇中,是按照词向量的平均值来描述的。个人比较喜欢用平均值来表示xw,默认值也是1,不推荐修改默认值。

(8) min_count:需要计算词向量的最小词频。这个值可以去掉一些很生僻的低频词,默认是5。如果是小语料,可以调低这个值。

(9) iter: 随机梯度下降法中迭代的最大次数,默认是5。对于大语料,可以增大这个值。

(10) alpha: 在随机梯度下降法中迭代的初始步长。算法原理篇中标记为η,默认是0.025。

(11) min_alpha: 由于算法支持在迭代的过程中逐渐减小步长,min_alpha给出了最小的迭代步长值。随机梯度下降中每轮的迭代步长可以由iter,alpha, min_alpha一起得出。这部分由于不是word2vec算法的核心内容,因此在原理篇我们没有提到。对于大语料,需要对alpha, min_alpha,iter一起调参,来选择合适的三个值。

  1. 模型保存
      训练后的模型需要保存为文件格式,以便后续的读取和使用。模型保存只要一行代码:
model.save('./wiki.zh.model')
  1. 全部程序

训练:

from gensim.models.word2vec import Word2Vec 
sentences = []
file = './wiki.zh.jian.utf8.word.txt'
with open('./' + file,'r',encoding="utf-8") as f:
for i in f.readlines():
sentences.append(i)
model = Word2Vec(sentences, size=300,min_count=10,sg=0) # default value is 5
model.save('./wiki.zh.Model')

读取模型:

import gensim
model = gensim.models.Word2Vec.load('wiki.zh.Model')
#查看某个字词的向量:
print(model['数'])
#查看与该词最接近的其他词汇及相似度:
print(model.most_similar(['数']))
#查看两个词之间的相似度:
model.similarity('数','值')

基于word2vec的中文词向量训练_中文词向量_05

四、参考文献

[1] ​​Windows系统下使用维基百科中文语料训练Word2Vec词向量​​ [2] 用gensim学习word2vec
[3] ​​《Efficient Estimation of Word Representations in Vector Space》​

  博客记录着学习的脚步,分享着最新的技术,非常感谢您的阅读,本博客将不断进行更新,希望能够给您在技术上带来帮助。欢迎转载,转载请注明出处。



标签:wiki,中文,word2vec,encoding,zh,txt,语料,向量
From: https://blog.51cto.com/u_15919249/5962322

相关文章

  • 支持向量机
    支持向量机,一般简称SVM,通俗来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。......
  • Media Encoder 2021 for Mac(ame 2021永久版) v15.4.1中文版
    MediaEncoder2021中文版是一款优秀的视频音频编码器,能够将多种设备格式的音频或视频进行导出,提供了丰富的硬件设备编码格式设置以及专业设计的预设设置,方便用户导出与特定......
  • Centos中文字体乱码
    安装字体安装字体程序yum-yinstallcups-libsfontconfigttmkfdir创建中文字体目录mkdir/usr/share/fonts/chinesechmod-R755/usr/share/fonts/chinese......
  • Navicate for Mysql 中文免费版安装
    1.下载NavicatforMySQ中文破解版链接:https://pan.baidu.com/s/1fG5RfyEsOuyua5yi4Zt-fA提取码:36022.解压压缩包得到两个文件navicat111_mysql_cs_x64.exe、Patch......
  • Unity Editor中文字体去重
    [MenuItem("Tools/GenerateZhCharacter")]publicstaticvoidGenerateZhCharacter(){vardataPath=Application.dataPath;varpath=Path.Combine(dataPa......
  • 中国风?古典系?AI中文绘图创作尝鲜!⛵
    ......
  • Selenium2.0中文在线文档项目,求翻译达人
    前一阵子在学习selenium2.0,发现网上很多资料都是selenium1.0的且部分信息不准确,无奈只能去官方看英文文档。费劲巴拉的看完了后,就有想法把selenium2.0的文档进行中文翻译,并......
  • 界面控件DevExpress WPF中文指南 - 主题设计器工作区介绍
    DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专......
  • Spring 5 中文解析之核心篇-IoC容器(上)
    概述​​Spring​​​使得开发人员更加容易的创建企业级应用程序,它提供了在企业Java生态技术栈中的任何技术体系,同时也提供了​​Groovy​​​和​​Kotlin​​​对JVM的支......
  • [机器学习] sklearn支持向量机
    date:2018-04-2111:20:45+0800tags:-机器学习-Python支持向量机SVM(SupportVectorMachine)是一种用来进行模式识别、分类、回归的机器学习模型。SVM......