46

基于知识库与知识图谱构建电影问答系统

 4 years ago
source link: https://www.tuicool.com/articles/aYr2maU
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在上一篇文章 基于豆瓣电影数据构建知识图谱 里面,讲到如何采用Neo4j来构建电影图谱,并且掌握了Neo4j里面的初级查询功能(搜索实体属性、实体间的关系等)。接下来,将进入电影图谱问答系统的学习,通过知识库和知识图谱来构建电影问答系统。针对QA问答系统,由于笔者当前能力有限,本文仅介绍基于模板的知识库问答,讲解过程中如果有阐述不周之处,还请读者指出!下面,我们来看看如何对问题进行解析,并将图谱应用到电影问答系统。

往期回顾:

Introduction

本文的电影QA问答系统工作流程如Fig 1所示,当接受到一个问题之后,我们首先对问题进行解析,包括分词、词性标注、关键字提取等预处理操作,并根据训练好的分类模型对问题进行分类,得到问题所属类之后,再根据图谱知识库搜索答案。在整个工作流程中,知识库在上一篇文章已经构建好了,并且已经存储到neo4j中。本文的主要工作是从问题到答案,端到端的实现。重点在如何对问题进行解析和分类,其次是借助neo4j进行答案检索。

NNRvQfj.png!web

Fig 1.QA问答系统工作流程

问题解析

当用户提出一个问题:”张国荣演过哪些电影?”时,我们需要对文本数据进行处理。在这里可以采用jieba进行分词、词性标注等操作,然后提取关键字。比如上面的问句,通过jieba进行词性标注的结果会是什么样子的呢?结果如下:

['张国荣/nr', '演/v', '过/ug', '哪些/r', '电影/n']

我们看到“张国荣”被标记为nr,属于人名,演是动词,后面还有一些其他的,得到这个结果之后,接下来该怎么处理呢?我们再看看Fig 1,当问题解析完之后,我们需要对问题进行分类。说到分类,就必须得有个训练模型才行!下面就是一个问题多分类模型。基于问题模板数据来训练问题分类模型。

基于NB的问题分类模型

在这个章节中,我们将采用简单的NB算法来训练我们的分类模型,感兴趣的童鞋可以试试其他的分类算法。

数据集

首先,来说说我们的数据集,样例数据如下,数据集包括三列,第一列是label(多分类),第二列是text(问题模板文本),第三列是描述(可忽略)。由于是实验demo,数据样例比较少,后续会根据需求不断扩展。

jUJfmyQ.png!web

Fig 2.问题分类数据集样例

对于上面的数据集,可能有的童鞋会有点问题,nm表示什么?这里简单说一下,nm表示的电影的词性标注。在问题解析阶段,会对jieba的分词注入用户个人字典,每个电影的词性标注均为nm。这样,在分词之后,得到的结果也是nm。

例如:“红海行动讲的是什么故事?”,解析后的词与词性如下:

['红海行动/nm', '讲/v', '的/uj', '是/v', '什么/r', '故事/n']

模型训练

关于模型部分,,其中用到了sklearn、pandas、jieba库,完整的代码如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Aug 24 14:38:04 2019

@author: liudiwei
"""
import jieba
import pandas as pd
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import TfidfVectorizer
jieba.load_userdict("./data/userdict3.txt")

class QuestionPrediction():
    """
    问题预测: 采用NB进行多分类
    数据集:template_train.csv
    """
    def __init__(self):
        # 训练模板数据
        self.train_file = "./data/template_train.csv"
        # 读取训练数据
        self.train_x, self.train_y=self.read_train_data(self.train_file)
        # 训练模型
        self.model=self.train_model_NB()

    # 获取训练数据
    def read_train_data(self,template_train_file):
        """
        可改写为读取一个文件
        """
        train_x=[]
        train_y=[]
        train_data = pd.read_csv(template_train_file)
        train_x = train_data["text"].apply(lambda x: " ".join(list(jieba.cut(str(x))))).tolist()
        train_y = train_data["label"].tolist()
        return train_x,train_y

    def train_model_NB(self):
        """
        采用NB训练模板数据,用于问题分类到某个模板
        """
        X_train, y_train = self.train_x, self.train_y
        self.tv = TfidfVectorizer()

        train_data = self.tv.fit_transform(X_train).toarray()
        clf = MultinomialNB(alpha=0.01)
        clf.fit(train_data, y_train)
        return clf

    
    def predict(self,question):
        """
        问题预测,返回结果为label
        """
        question=[" ".join(list(jieba.cut(question)))]
        print("question:", question)
        test_data=self.tv.transform(question).toarray()
        y_pred = self.model.predict(test_data)[0]
        return y_pred

if __name__ == '__main__':
    question_model=QuestionPrediction()
    print(question_model.predict("红海行动讲的是什么故事?"))

通过 read_train_data 方法,我们得到的分词后的 x_train 如Fig 3的value字段所示。

reYr6nu.png!web

Fig 3.训练数据样例

预测

单独执行上面的代码,最后返回的结果如Fig 4所示。最终将”红海行动讲的是什么故事?”划分到第三个类别。

iyIz2ma.png!web

Fig 4.问题预测结果

基于图谱的搜索

通过预测模型,我们可以将问题划分到某个模板中,接下来,再基于问题模板构造图谱搜索,比如上面的问题,我们将其划分到第三类问题:电影简介。接下来就可以采用py2neo连接neo4j图数据库,然后从图数据库中搜索出想要的答案。

# 3:nm 电影简介
def get_movie_introduction(self):
    movie_name = self.get_movie_name()
    cql = f"match(m:Movie)-[]->() where m.title=~'.*{movie_name}.*' return m.storyline"
    print(cql)
    answer = self.graph.run(cql)[0]
    final_answer = movie_name + "主要讲述了" + str(answer) + "!"
    return final_answer

最后得到的结果如下:

riQzy2V.png!web

Fig 5.问题预测结果

Conclusion

本文主要讲解了如何端到端的构建QA系统,方法虽然比较简单,但可以让读者了解整个工作流,对后续的学习也会有很好的帮助。为了将结果更好的展示出来,笔者将QA问答做成了服务,部署到了服务器中,并在服务器中搭建neo4j,构建电影图谱,最后将QA问答与微信公众号进行了集成,结果如Fig 6所示。由于问答模板不够完善,公众号暂时就不公布了。文中代码仅供参考,具体的源码等整理完之后再发布到github中吧。关于如何发布QA服务和微信公众号自动问答的集成,我们下期再见!

Ybq6Zjm.png!web

Fig 6.电影QA集成微信公众号

References

  1. 豆瓣13万电影数据统计与分析
  2. 基于豆瓣电影数据构建知识图谱
  3. Knowledge Graph - Wikipedia
  4. Importing CSV Data into Neo4j

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK