問答機器人的Python分類器

導語

現在問答機器人真是火的不要不要的,大致分為兩類:普適多場景的和單一專業場景的問答機器人。由于資源有限,不知死活的筆者只做了單一場景的分類器,如對海量數據、多場景的問答機器人感興趣的話可以參考QA問答系統中的深度學習技術實現,對于該網站在NLP方面的貢獻簡直不能更感激(請允許獻上我的膝蓋)!

1. 問答語料庫

由于僅面向業務,場景單一,所以訓練集語料庫只包含20類,共400多條問題,每類問題對應一個回答。

2. 訓練詞向量

不知死活的筆者決定興師動眾的選擇word2vec將訓練集語料轉化為詞向量作為模型的輸入。關于word2vec的原理及其C語言的詞向量訓練方法,請參考word2vec詞向量訓練及中文文本相似度計算以及該博文內的鏈接。筆者根據【python gensim使用】word2vec詞向量處理中文語料用Python訓練的中文詞向量模型。(英文的詞向量訓練可以參考
利用Gensim訓練關于英文維基百科的Word2Vec模型(Training Word2Vec Model on English Wikipedia by Gensim)

2.1 中文語料庫

可以參考Windows下使用Word2vec繼續詞向量訓練中提到的語料庫,不知死活的筆者選擇從搜狗實驗室下載了全網新聞語料,不得不說,搜狗實驗室是非常具有貢獻力的!完整版1.02G,解壓后2.22G,共378個文件,HTML格式,你值得擁有!

News List.png

2.2 分詞合并

首先是分詞,可供選擇的工具有很多:Jieba、ANSJ、NLPIR、LTP等等,在此筆者選擇Jieba進行分詞:

import jieba  

def readLines(filename):
    # read txt or csv file
    fp = open(filename, 'r')
    lines = []
    for line in fp.readlines():
        line = line.strip()
        line = line.decode("utf-8")
        lines.append(line)
    fp.close()
    return lines

def parseSent(sentence):
    # use Jieba to parse sentences
    seg_list = jieba.cut(sentence)
    output = ' '.join(list(seg_list)) # use space to join them
    return output

然后將所有文檔合并,并寫入corpus.csv中:

import re  
import codecs  
import os 

# only content is valid
pattern = "<content>(.*?)</content>"
csvfile = codecs.open("corpus.csv", 'w', 'utf-8')
fileDir = os.listdir("./corpus/")
for file in fileDir:
    with open("./corpus/%s" % file, "r") as txtfile:
        for line in txtfile:
            m = re.match(pattern, line)
            if m:
                segSent = parseSent(m.group(1))
                csvfile.write("%s" % segSent)

特別mark以下,codecs這個包在調整編碼方面的貢獻真的不要太大,尤其是常常對于中文編碼無力的不知死活的筆者來說,簡直是神器!
對于中文的編碼處理:utf-8 --> unicode --> utf-8

2.3 訓練word2vec模型

在此,筆者使用gensim的word2vec進行詞向量的訓練:

from gensim.models import word2vec
import logging

logging.basicConfig(format = '%(asctime)s : %(levelname)s : %(message)s', level = logging.INFO)
sentences = word2vec.Text8Corpus("corpus.csv")  # 加載語料
model = word2vec.Word2Vec(sentences, size = 400)  # 訓練skip-gram模型

# 保存模型,以便重用
model.save("corpus.model")
# 對應的加載方式
# model = word2vec.Word2Vec.load("corpus.model")

# 以一種C語言可以解析的形式存儲詞向量
model.save_word2vec_format("corpus.model.bin", binary = True)
# 對應的加載方式
# model = word2vec.Word2Vec.load_word2vec_format("corpus.model.bin", binary=True)

關于調參,可自行參考gensim文檔。

2.4 獲得詞向量

接下來就是使用上述獲得的model將訓練集的中文語料轉化為詞向量:

def getWordVecs(wordList):
    vecs = []
    for word in wordList:
        word = word.replace('\n', '')
        try:
            # only use the first 500 dimensions as input dimension
            vecs.append(model[word])
        except KeyError:
            continue
    # vecs = np.concatenate(vecs)
    return np.array(vecs, dtype = 'float')

3. 構建模型

3.1 Naive Bayes

效果良好,效率高!

from sklearn.naive_bayes import MultinominalNB

MNB = MultinominalNB(alpha = 0.000607)

3.2 Random Forest

效果良好,效率一般。

from sklearn.ensemble import RandomForestClassifier

RFC = RandomForestClassifier(min_samples_leaf = 3, n_estimators = 100)

3.3 RBM + Logistic Regression

效果很好,效率很低……由于這個模型只需要訓練一次,所以效率關系不大(抱歉我隨便亂用模型,實際上這模型本身來源于sklearn上的實例……原本著使用效果至上的原則,然而至于為何這樣搭配……)

from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.neural_network import BernoulliRBM

rbm.learning_rate = 0.07
rbm.n_iter = 50
# more components tend to give better prediction performance, but larger fitting time
rbm.n_components = 800
rbm.batch_size = 10
logistic.C = 10000.0
rbm = BernoulliRBM(random_state = 0, verbose = True)
logistic = LogisticRegression()
clf = Pipeline(steps = [('rbm', rbm), ('logistic', logistic)])

總的來說,神經網絡(例如MLP)對這類文本分類問題效果普遍不錯,至于傳統機器學習算法,樸素貝葉斯也有不俗的表現。

4. 其他

這次學習到sklearn中一個非常有用的功能sklearn.externals.joblib,可用于導出訓練好的模型,這對于training cost非常高的模型來說實在是非常好用啊!

from sklearn.externals import joblib

# save classifier
joblib.dump(clf, "Classifier.pkl")
# load classifier
clf = joblib.load("Classifier.pkl")

其次就是sklearn中的sklearn.pipeline.Pipeline,將多個模型結合在一起,通過Pipeline的方式進行訓練,真的是非常方便啊!

from sklearn.pipeline import Pipeline

clf = Pipeline(steps = [clf1, clf2])
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容