本文使用的是搜狗新闻语料库,原始语料是类似下图中xml格式,首先需要提取中语料中正真的新闻内容,就是<content>中对应的文本。还需要过滤一些特殊字符,以及半角和全角的转换问题。 语料的下载,官方地址:https://www.sogou.com/labs/resource/cs.php ,需要填一些信息。 百度云盘的备份,链接:https://pan.baidu.com/s/1n1IQxsb2Kbi2IHz9Cst7mg 提取码:r1n2
下面看一下详细的处理过程。首先是一个全角转半角的辅助程序,全角和半角转换的详细情况请参考: Python实现全角与半角相互转换:https://blog.csdn.net/huanghaocs/article/details/90384163
def is_Qnumber(uchar): """判断一个unicode是否是全角数字""" if uchar >= u'\uff10' and uchar <= u'\uff19': return True else: return False def is_Qalphabet(uchar): """判断一个unicode是否是全角英文字母""" if (uchar >= u'\uff21' and uchar <= u'\uff3a') or (uchar >= u'\uff41' and uchar <= u'\uff5a'): return True else: return False def Q2B(uchar): """单个字符 全角转半角""" inside_code = ord(uchar) if inside_code == 0x3000: inside_code = 0x0020 else: inside_code -= 0xfee0 if inside_code < 0x0020 or inside_code > 0x7e: #转完之后不是半角字符返回原来的字符 return uchar return chr(inside_code) def stringQ2B(ustring): """把字符串全角转半角""" return "".join([Q2B(uchar) for uchar in ustring]) def stringpartQ2B(ustring): """把字符串中数字和字母全角转半角""" return "".join([Q2B(uchar) if is_Qnumber(uchar) or is_Qalphabet(uchar) else uchar for uchar in ustring])具体处理过程,首先读取xml格式语料,然后提取content部分内容,去除符号标记,最后保存语料为文本格式,也可以选择分词后在保存,分词后保存可以直接用于word2vec模型训练词向量。
import codecs import re import jieba from tqdm import tqdm file_path = r'/path/news_tensite_xml.dat' # 原始语料 save_path = r'/path/SougouNews_Dataset.txt' # 处理后只有文章内容的语料 seg_save_path = r'/path/SougouNews_Dataset_Seg.txt' # 文章内容分词后的语料 # read file print("read news dataset:", file_path) with codecs.open(file_path, encoding='GB2312', errors="ignore") as fr: news_data = fr.read() # extract the text between <content> and </content> print("extract news content ...") news_content = re.findall('<content>.*</content>', news_data) # write to text file without segment print("write content to text file ...") with codecs.open(save_path, 'w', encoding='utf8') as fw: # 注意tqdm只是一个进度条 也可以不需要 for item in tqdm(news_content): item = re.sub(r'<content>|</content>|\s', '', item) # item = stringQ2B(item) # 全部全角转半角 item = stringpartQ2B(item) # 只有数字字母全角转半角 if item != "": fw.write(item + '\n')下面是对语料分词后写入文件,这里使用的是jieba分词工具,也可以选择其它分词工具。
# segment and write to text file with codecs.open(seg_save_path, 'w', encoding='utf8') as fw: for content in tqdm(news_content): content = re.sub(r'<content>|</content>|\s', '', content) # content = stringQ2B(content) # 全部全角转半角 item = stringpartQ2B(item) # 只有数字字母全角转半角 if content != "": # 这里分词调用的是jieba 也可以使用其它分词工具 content_seg = jieba.cut(content.strip()) fw.write(" ".join(content_seg) + "\n")对语料预处理完后,可以使用已经分词的语料训练word2vec,这里分词后的语料是可以加上自己整理的其它语料,这样可以更加丰富我们的语料库。
word2vec模型的原理这里不再讲解,网上随便一搜,可以找到很多教程,这里是给个实例,基于上面处理好的语料训练词向量,使用的工具是gensim中自带的word2vec模型。
import logging import gensim.models as word2vec from gensim.models.word2vec import LineSentence def train_word2vec(dataset_path, model_path, size=100, window=5, binary=True): logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) # 把语料变成句子集合 sentences = LineSentence(dataset_path) # 训练word2vec模型 model = word2vec.Word2Vec(sentences, size=size, window=window, min_count=5, workers=4, iter=10) # 保存word2vec模型 if binary: model.wv.save_word2vec_format(model_path, binary=True) else: model.wv.save_word2vec_format(model_path, binary=False) def load_word2vec_model(w2v_path): # load word2vec model = word2vec.KeyedVectors.load_word2vec_format(w2v_path, binary=True) return model def calculate_most_similar(model, word): similar_words = model.most_similar(word) print(word) for term in similar_words: print(term[0], term[1]) dataset_path = "/path/SougouNews_Dataset_Seg.txt" save_model_path = "word2vec_model.bin" # save_binary=True # save_model_path = "word2vec_model.txt" # save_binary=False train_word2vec(dataset_path, save_model_path, size=100, window=5, binary=True)word2vec模型训练完后,可以计算词语之间的相似度,以及与每次词最相似的词。也可以做为其它NLP相关任务的词向量预训练输入。