对语料库进行数据清洗、中文分词,建立训练词向量模型
作者:互联网
目录
简述
接前述使用scrapy爬取文件建立聊天语料库一文,在对文件初步清洗之后。由于文本来源的特殊性,需要对其中的特殊关键词进行过滤,以及其他数据清洗操作。这篇文章将在前文基础上,进行数据清洗,中文分词,及word2vec操作。作为中期检测前的最后一篇记录,希望能给大家一点小小的帮助。
数据清洗
由于是对字幕文件的数据清洗,所以除去html标签,去转义,去除特殊符号等操作外,最主要的是去除关键字和去重。以下将着重讲这两个方面。这两个方面应该是放在同一个while中,但我为了方便阅读,分别写了俩while,实际操作时,将俩写入同一个即可。
去除关键字
这一部分比较简单,但是很重要。因为字幕文件的原因,部分关键字频率极高,会影响到后续的词向量模型的训练,所以在此需要去除。直接上代码:
首先,写入需要去除的关键字的列表。
filters = ["字幕", "时间轴:", "校对:", "翻译:", "后期:", "监制:"]
filters.append("时间轴:")
filters.append("校对:")
filters.append("翻译:")
filters.append("后期:")
filters.append("监制:")
filters.append("禁止用作任何商业盈利行为")
filters.append("http")
其次,给出清洗文件(from_path)和输出文件(to_path)的地址,打开文件后,判断每一行是否存在关键字,若存在则跳过,同理,判断改行是否存在剧集信息。当所有条件过滤之后,若该句未被过滤,则写入输出文件中。
f = open(from_path, "r+")
g = open(to_path, "a+")
while True:
line = f.readline()
if line:
line = line.strip()
# 关键词过滤
need_continue = False
for filter in filters:
try:
line.index(filter)
# 若该行中存在关键字,赋值为True
need_continue = True
break
except:
pass
# 若为true,跳过该行
if need_continue:
continue
# 去掉剧集信息
if re.match('.*第.*季.*', line):
continue
if re.match('.*第.*集.*', line):
continue
if re.match('.*第.*帧.*', line):
continue
g.write(line+"\n")
else:
break
f.close()
g.close()
pass
去除重复语句
去除重复语句不是去除整个文件中出现过的重复语句,而是去除无意义的重复语句,在这里,我判定,两百行中出现重复的语句即为无意义的,于是,如下:
lines_seen = set()
while True:
line = f.readline()
if line:
line = line.strip()
# 每两百行将不重复的行放入lines_seen中,用于判断行是否重复,超过两百行的重复不作清除处理
if line not in lines_seen:
lines_seen.add(line)
if len(lines_seen) > 200:
lines_seen.clear()
else:
print(line)
continue
g.write(line+"\n")
else:
break
f.close()
g.close()
pass
做完这些以后,语料库的数据清理也就完成了。下面需要进行分词操作。
中文分词
使用jieba库进行中文分词
import jieba
from jieba import analyse
import os
# input:需要分词的文件地址;output:文件分词后的输出地址
def segment(input, output):
input_file = open(input, "r+")
output_file = open(output, "a+", encoding='utf-8') # 以utf-8输出,方便后续的词向量训练
while True:
line = input_file.readline()
if line:
line = line.strip()
seg_list = jieba.cut(line)
segments = ""
for str in seg_list:
segments = segments + " " + str
output_file.write(segments)
else:
break
input_file.close()
output_file.close()
if __name__ == '__main__':
from_path = "my_from_path"
to_path = "my_to_path"
if not os.path.isdir(to_path): # 判断文件夹是否存在,不存在则创建
os.makedirs(to_path)
datanames = os.listdir(from_path) # 打开来源文件夹,将其下所有文件写入datanames中
for i in datanames:
input = from_path+"/"+i
output = to_path+"/all.txt" # 将结果写入输出文件夹中的all.txt文件中
segment(input, output)
使用gensim训练词向量模型
word2vec的训练思路
为了更好的理解word2vec的运行,之前自己捣鼓了一个word2vec的文件,但是经过测试,发现只能对较小数据量的文件进行词向量训练,超过2000词的文件就很吃力了,于是我选择使用gensim库,具体的操作在下一步中,所以在这里只简单讲讲思路,:
首先,确定窗口大小,词嵌入的维度,遍历样本次数。
其次,将语料库转为onehot编码,以方便训练。在这里简单讲讲onehot编码。
one-hot在特征提取上属于词袋模型(bag of words),假设语料库中有三句话:
我爱中国
爸爸妈妈爱我
爸爸妈妈爱中国
首先,将语料库中的每句话分成单词,并编号:
1:我 2:爱 3:爸爸 4:妈妈 5:中国
语句 | 我 | 爱 | 爸爸 | 妈妈 | 中国 |
---|---|---|---|---|---|
1 | 1 | 1 | 0 | 0 | 1 |
2 | 1 | 1 | 1 | 1 | 0 |
3 | 0 | 1 | 1 | 1 | 1 |
所以最终得到的每句话的特征向量就是:
我爱中国 -> 1,1,0,0,1
爸爸妈妈爱我 -> 1,1,1,1,0
爸爸妈妈爱中国 -> 0,1,1,1,1
接着,为每一个词建立索引。
其后,使用skip-gram的网络结构,创建两个随机初始化权重矩阵,后向前传递,得出结果后将其映射到[0,1]之间来得到用来预测的概率。
想法很美好,做的也还过得去,就是现实太过残酷,写的文件在对付小一点的文件还凑合,在面对大的训练集当场罢工。所以还是老老实实使用了库比较好,前人栽树,后人乘凉岂不妙哉。
使用gensim训练词向量模型
Gensim 4.0 更新之后,虽然大部分与旧版本相容,但是也有部分差异,详细请看https://github.com/RaRe-Technologies/gensim/wiki/Migrating-from-Gensim-3.x-to-4,以下为训练词向量的代码。
from gensim.models import word2vec
import os
import gensim
import logging
def model_train(train_file_name, save_model_file): # model_file_name为训练语料的路径,save_model为保存模型名
# 模型训练,生成词向量
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.Text8Corpus(train_file_name) # 加载语料
try:
model = gensim.models.Word2Vec(sentences, window=5, vector_size=200) # 训练CBOW算法模型; 默认window=5
model.save(save_model_file)
model.wv.save_word2vec_format(save_model_file + ".bin", binary=True) # 以二进制类型保存模型以便重用
except:
pass
def main():
from_path = "my_to_path/all.txt" # 接上文中的myt_to_path/all.txt
save_model_name = 'mymodel.model'
if not os.path.exists(save_model_name): # 判断文件是否存在
model_train(from_path, save_model_name)
else:
print('此训练模型已经存在,不用再次训练')
# 加载已训练好的模型
model_1 = word2vec.Word2Vec.load(save_model_name)
# 将获得的词汇及其对应的向量按字典的格式存放到word_vector_dict中
word_vector_dict = {}
# print(model_1.wv.index_to_word) # 获得所有的词汇
for word in model_1.wv.index_to_key:
# model_1.wv.get_vector(word) # 获得词汇及其对应的向量
word_vector_dict[word] = model_1.wv.get_vector(word)
output_vector_file = 'word_vector.txt'
with open(output_vector_file, 'w', encoding='utf-8') as f:
f.write(str(word_vector_dict))
# 计算两个词的相似度/相关程度
word1 = "学习"
word2 = "快乐"
y1 = model_1.wv.similarity(word1, word2)
print("两个词的相关程度为:", y1)
print("-------------------------------\n")
# 计算某个词的相关词列表
y2 = model_1.wv.most_similar(word2, topn=10) # 10个最相关的
print("和", word2, "最相关的词有:\n")
for item in y2:
print(item[0], item[1])
print("-------------------------------\n")
if __name__ == "__main__":
main()
运行结果如下:
ps:学习是快乐的!这个语料库有问题,学习怎么能和快乐相关程度这么低呢?(认真脸)
这个结果嘛,差强人意,主要是我的训练集有点小,只有10MB,没有搞很多,方便测试。但是这不是也有相对正确的嘛。以后我填充了我的训练集后,再回来补充,我相信,学习是快乐的!
结语
以上便是这两周的学习内容啦,因为各科的实验都开了,作为强迫症晚期角色,实验是不可能活到ddl的,因此这事就耽搁了。而今天打开年级群时,发现原定第9周的中期答辩,改到了下一周周四,这才想起博客没写,今个补上。祝我自己好运。
标签:word,训练,语料库,分词,file,path,model,line,向量 来源: https://blog.csdn.net/weixin_44524843/article/details/115799484