问答机器人的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])
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容