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

zh
zh
zh
26
文章
0
评论
2020-04-1803:05:00 评论 309 3124字
摘要

本文仅介绍基于模板的知识库问答,讲解过程中如果有阐述不周之处,还请读者指出!下面,我们来看看如何对问题进行解析,并将图谱应用到电影问答系统。

一.Introduction

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

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

二.问题解析

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

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

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

三.基于NB的问题分类模型

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

1.数据集

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

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

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

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

["红海行动/nm", "/v", "/uj", "/v", "什么/r", "故事/n"]

2.模型训练

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

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. Created on Sat Aug 24 14:38:04 2019
  5. @author: liudiwei
  6. """
  7. import jieba
  8. import pandas as pd
  9. from sklearn.naive_bayes import MultinomialNB
  10. from sklearn.feature_extraction.text import TfidfVectorizer
  11. jieba.load_userdict("./data/userdict3.txt")
  12. class QuestionPrediction():
  13. """
  14. 问题预测: 采用NB进行多分类
  15. 数据集:template_train.csv
  16. """
  17. def __init__(self):
  18. # 训练模板数据
  19. self.train_file = "./data/template_train.csv"
  20. # 读取训练数据
  21. self.train_x, self.train_y=self.read_train_data(self.train_file)
  22. # 训练模型
  23. self.model=self.train_model_NB()
  24. # 获取训练数据
  25. def read_train_data(self,template_train_file):
  26. """
  27. 可改写为读取一个文件
  28. """
  29. train_x=[]
  30. train_y=[]
  31. train_data = pd.read_csv(template_train_file)
  32. train_x = train_data["text"].apply(lambda x: " ".join(list(jieba.cut(str(x))))).tolist()
  33. train_y = train_data["label"].tolist()
  34. return train_x,train_y
  35. def train_model_NB(self):
  36. """
  37. 采用NB训练模板数据,用于问题分类到某个模板
  38. """
  39. X_train, y_train = self.train_x, self.train_y
  40. self.tv = TfidfVectorizer()
  41. train_data = self.tv.fit_transform(X_train).toarray()
  42. clf = MultinomialNB(alpha=0.01)
  43. clf.fit(train_data, y_train)
  44. return clf
  45. def predict(self,question):
  46. """
  47. 问题预测,返回结果为label
  48. """
  49. question=[" ".join(list(jieba.cut(question)))]
  50. print("question:", question)
  51. test_data=self.tv.transform(question).toarray()
  52. y_pred = self.model.predict(test_data)[0]
  53. return y_pred
  54. if __name__ == "__main__":
  55. question_model=QuestionPrediction()
  56. print(question_model.predict("红海行动讲的是什么故事?"))

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

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

3.预测

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

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

三.基于图谱的搜索

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

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

最后得到的结果如下:

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

四.Conclusion

本文主要讲解了如何端到端的构建QA系统,方法虽然比较简单,但可以让读者了解整个工作流,对后续的学习也会有很好的帮助。为了将结果更好的展示出来,笔者将QA问答做成了服务,部署到了服务器中,并在服务器中搭建neo4j,构建电影图谱,最后将QA问答与微信公众号进行了集成,结果如Fig 6所示。感兴趣的童鞋,可以到公众号里【斗码大陆】体验一下,由于知识库不全,答非所问之事还请多多包涵哈。文中代码仅供参考,具体的源码等整理完之后再发布到github中吧。关于如何发布QA服务和微信公众号自动问答的集成,我们下期再见!

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

五.References

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

End.

作者:拾毅者

来源:『刘帝伟』维护的个人技术博客

本文均已和作者授权,如转载请与作者联系。

  • 我的微信公众号
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: