如何將中文文件語料訓練成詞向量

中科小白發表於2020-12-22

準備需要訓練的原始語料

在這裡,我們採用docx文件作為原始語料:

如圖所示,這些文件是我用到的語料。

將語料轉換為txt檔案格式

用到了docx這個包,可能需要先安裝一下:pip install docx

程式碼如下:

import os
import docx


def docx_to_txt():
    # 開啟檔案
    files = os.listdir('./corpus')    # 此處為你存放語料的路徑
    with open('corpus.txt', 'w+', encoding='utf-8') as f:
        for file_name in files:
            if file_name.endswith('docx'):
                print(file_name)
                file = docx.opendocx("./corpus/"+file_name)
                # 讀取文字內容
                text = docx.getdocumenttext(file)
                # 寫入檔案
                for t in text:
                    f.write(t)


docx_to_txt()

 

執行完後,得到了corpus.txt這個文字語料。

進行語料的預處理和分詞

這裡所說的預處理主要是指用正規表示式對語料去特殊符號,以及對分詞後的結果去停用詞等。程式碼如下:

#-*- encoding:utf-8 -*-

import jieba                                #匯入jieba模組
import re
jieba.load_userdict("mydict.txt")           #載入自定義詞典


def split_sentence(input_file, output_file):
    # 把停用詞做成列表
    stopwords = []
    fstop = open('stop_words.txt', 'r', encoding='utf-8')
    for eachword in fstop:
        print(eachword)
        stopwords.append(eachword)
    fstop.close()

    fin = open(input_file, 'r', encoding='utf-8')  # 以讀的方式開啟檔案
    fout = open(output_file, 'w', encoding='utf-8')  # 以寫的方式開啟檔案

    for eachline in fin:
        line = eachline.strip() # 去除每行首尾可能出現的空格
        line1 = re.sub(r"[0-9\s+\.\!\/_,$%^*()?;;:-【】+\"\']+|[+——!,;:。?、~@#¥%……&*()]+", "", line)              # 用正則去除一些特殊符號
        wordlist = list(jieba.cut(line1))  # 用結巴分詞,對每行內容進行分詞
        outstr = ''
        for word in wordlist:
            if word not in stopwords:      # 判斷是否在停用詞表中
                outstr += word
                outstr += ' '
        fout.write(outstr.strip() + '\n')  # 將分詞好的結果寫入到輸出檔案
    fin.close()
    fout.close()


split_sentence('corpus.txt', 'cut_corpus.txt')

執行完後,得到了cut_corpus.txt這個分詞後的文字語料。

採用word2vec訓練詞向量

在這裡我用的是python中的gensim包,可能需要先安裝一下:pip install gensim

程式碼如下:

from __future__ import print_function

import logging
import os
import sys
import multiprocessing

from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence

if __name__ == '__main__':
    program = os.path.basename(sys.argv[0])
    logger = logging.getLogger(program)

    logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
    logging.root.setLevel(level=logging.INFO)
    logger.info("running %s" % ' '.join(sys.argv))

    # 檢查和處理輸入引數
    if len(sys.argv) < 4:
        print("Useing: python train_word2vec_model.py input_text "
              "output_gensim_model output_word_vector")
        sys.exit(1)
    inp, outp1, outp2 = sys.argv[1:4]

    model = Word2Vec(LineSentence(inp), size=60, window=5, min_count=5,
                     workers=multiprocessing.cpu_count())   
# 此處的size為詞向量的維度,window為視窗大小,min_count為統計的最小詞頻(低於這個詞頻的詞忽略)

    model.save(outp1)
    model.wv.save_word2vec_format(outp2, binary=False)

執行時需要指定輸入輸出檔案,比如將此程式碼命名為 train_word2vec_model.py,則執行時可以這樣:

python train_word2vec_model.py cut_corpus.txt my_word2vec.model my_word2vec.vector

執行完後會得到4個結果檔案:my_word2vec.model、my_word2vec.vector、my_word2vec.model.trainables.syn1neg.npy、my_word2vec.model.wv.vectors.npy。

對所訓練的詞向量進行簡單測試

#coding=utf-8
from gensim.models import word2vec
model = word2vec.Word2Vec.load('./my_word2vec.model')
print(model.wv.similarity(u'奧運會',u'金牌'))
for e in model.wv.most_similar([u'華盛頓',u'中國'],[u'北京']):
    print(e[0],e[1])

我執行時的結果如下圖所示:

得到的結果的指標取決於訓練語料和訓練時所設定的引數,這個需要小夥伴自己去嘗試一下哈。

相關文章