目录
前言
一.知识图谱的构建
二.问答系统的构建
1.数据准备
1.1数据获取
1.2数据处理
1.3数据读入
1.4代码
2.问答系统设计
2.1整体流程
2.2实体识别和问题分类
2.3.问题结果查询
2.4问答模板的匹配
三.优化方向
参考目前网络上开源的医疗问答系统等项目,对基于neo4j的知识图谱构建及基于人为指定模板的问答系统构建进行了整理,笔者对代码进行了较为详尽的注释,供读者参考。
项目获取:项目代码
该知识图谱依托当前主流的图数据库neo4j进行构造。
可参考基于neo4j的知识图谱构建及Py2neo的使用总结
打开“建立图谱.py”,运行该文件后,会生成知识图谱,后续的查询操作将会依赖该知识图谱进行。因此应当首先运行该文件,否则所有问题的查询都将失败。
"person.txt","movie.txt","genre.txt"三个txt文件是通过"建立关键词词表.py"建立的,这里是项目中直接给出,读者也可以尝试自己生成。"person_to_movie.csv"文件则是存放了建立关系时,各实体之间的联系。
#导入CSV进行文件操作,导入py2neo利用python对neo4j进行操作
import csv
from py2neo import Graph,Node,Relationship,NodeMatcher,NodeMatcher
import py2neo
#建立本地与neo4j服务器的连接,这里的password输入自己修改的密码,默认是neo4j
g=Graph('http://localhost:7474', user='neo4j', password='neo4j')
#修改为自己的文件路径
with open('C:\\Users\\知识图谱的问答系统\\data\\genre.csv','r',encoding='utf-8') as f:
#数据集中除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
#reader函数按行读取文件内容,若数据不是按行存储则采用其它方法提取
reader=csv.reader(f)
for item in reader:
#第一行的标签不是实际内容,line_num表示文件的第几行
if reader.line_num==1:
continue
#可以打印当前内容,查看是否正常运行
#print("当前行数:",reader.line_num,"当前内容",item)
#节点的建立
test_node_1=Node("Genre",id=item[0],name=item[1])
g.merge(test_node_1, "Genre", "id")
#以下都是重复内容
with open('C:\\Users\\知识图谱的问答系统\\data\\movie.csv','r',encoding='utf-8') as f:
reader=csv.reader(f)
for item in reader:
#第一行的标签不是需要的内容,line_num表示文件的第几行
if reader.line_num==1:
continue
print("当前行数:",reader.line_num,"当前内容",item)
test_node_1=Node("Movie",id=item[0],title=item[1],introduction=item[2],rating=item[3],releasedate=item[4])
g.merge(test_node_1, "Movie", "id")
with open('C:\\Users\\知识图谱的问答系统\\data\\person.csv','r',encoding='utf-8') as f:
#数据集除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
reader=csv.reader(f)
for item in reader:
#第一行的标签不是需要的内容,line_num表示文件的第几行
if reader.line_num==1:
continue
print("当前行数:",reader.line_num,"当前内容",item)
test_node_1=Node("Person",id=item[0],birth=item[1],death=item[2],name=item[3]
,biography=item[4])
g.merge(test_node_1, "Person", "id")
#关系的构建:
matcher = NodeMatcher(g)
findnode = matcher.match('Person', id='9550').first()
print(findnode)
with open('C:\\Users\\知识图谱的问答系统\\data\\person_to_movie.csv','r',encoding='utf-8') as f:
#数据集除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
reader=csv.reader(f)
for item in reader:
#第一行的标签不是需要的内容,line_num表示文件的第几行
if reader.line_num==1:
continue
#print("当前行数:",reader.line_num,"当前内容",item)
#调用first()返回的才是节点,否则返回的是对应的类对象,不能进行关系的建立
#根据各自的id查找到对应的节点,从而构建关系
findnode = matcher.match('Person', id=item[0]).first()
endnode = matcher.match('Movie', id=item[1]).first()
#这里的语句‘饰演’是依据查询的文件而定义的
relationships = Relationship(findnode, '饰演', endnode)
g.merge(relationships, "", "id")
with open('C:\\Users\\知识图谱的问答系统\\data\\movie_to_genre.csv', 'r', encoding='utf-8') as f:
#数据集除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
reader=csv.reader(f)
for item in reader:
#第一行的标签不是咱们需要的内容,line_num表示文件的第几行
if reader.line_num==1:
continue
print("当前行数:",reader.line_num,"当前内容",item)
findnode = matcher.match('Movie', id=item[0]).first()
endnode = matcher.match('Genre', id=item[1]).first()
relationships = Relationship(findnode, '是', endnode)
g.merge(relationships, "", "id")
生成效果如下:
本项目需要的数据已经以csv文件的形式存放在data中,如果读者有其它数据的需求,可访问
知识图谱数据获取。
本现目提供的已经是结构化数据,不需要进行二次处理。
通过"建立关键词词表.py",首先读取项目子目录“data”中的“movie.csv","person.csv","genre.csv"三个数据文件。再分别读出电影名,演员名,电影种类,建立txt文件存入本地,作为该问答系统的词典。项目中已经完成了该步骤,创建了三个txt文件,读者不需要再自己运行该文件。
import csv
with open('/genre.csv', 'r', encoding='utf-8') as f:
#数据集除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
l_genre=[]
reader=csv.reader(f)
for item in reader:
#第一行的标签不是咱们需要的内容,line_num表示文件的第几行
if reader.line_num==1:
continue
#print("当前行数:",reader.line_num,"当前内容",item)
#只要类别
print("当前行数:", reader.line_num, "当前内容", item[1])
if item[1] not in l_genre:
l_genre.append(item[1])
with open('/movie.csv', 'r', encoding='utf-8') as f:
l_movie = []
reader=csv.reader(f)
for item in reader:
#第一行的标签不是咱们需要的内容,line_num表示文件的第几行
if reader.line_num==1:
continue
#print("当前行数:",reader.line_num,"当前内容",item)
#只要电影名字
print("当前行数:", reader.line_num, "当前内容", item[1])
if item[1] not in l_movie:
l_movie.append(item[1])
with open('/person.csv', 'r', encoding='utf-8') as f:
l_person=[]
#数据集除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
reader=csv.reader(f)
for item in reader:
#第一行的标签不是咱们需要的内容,line_num表示文件的第几行
if reader.line_num==1:
continue
#print("当前行数:",reader.line_num,"当前内容",item)
#只要演员
print("当前行数:", reader.line_num, "当前内容", item[3])
if item[3] not in l_person:
l_person.append(item[3])
f_genre = open('genre.txt', 'w+',encoding='utf-8')
#write方法不会对写入的内容增加换行符,因此采用列表大量输入时,使用join方法在每一行后添加换行符
f_genre.write('\n'.join(list(l_genre)))
f_genre.close()
f_movie = open('movie.txt', 'w+',encoding='utf-8')
f_movie.write('\n'.join(list(l_movie)))
f_movie.close()
f_person= open('person.txt', 'w+',encoding='utf-8')
f_person.write('\n'.join(list(l_person)))
f_person.close()
基于模板的方法是通过提取文本信息中的实体,通过一些算法和匹配方式获取问句中的实体信息,通过得到相关实体就获得了查询答案的部分信息。再使用分类器对问题的特征向量进行分类,将问题归为某类问题,再按照这类问题的回答模板寻找到匹配的答案。由于基于模板的方法有反应时间短、精准率高、可以回答少见问题或者复合型问题的优点,本项目采用基于模板的方法实现图书知识图谱问答系统。
传入问题后,首先是利用AC自动机对问题中的实体进行识别,再对问题进行文本分类处理,判断问题的类型。如果问题存在属于词典的实体并且该问题的类型有效,就利用知识图谱进行结果的查询。最后将实体,查询结果传入该问题类型对应的问答模板,生成回答语句,最后输出该语句就完成了问答。
这一系列流程将由主程序"chatbot_graph.py"实现。
代码如下:
#引入后文提到三个功能所需要的方法
from question_classifier import *
from question_parser import *
from answer_search import *
'''问答类'''
class ChatBotGraph:
def __init__(self):
#实体识别和问题分类,该部分完成数据的提取和导入
self.classifier = QuestionClassifier()
#针对特定问题的查询
self.parser = QuestionPaser()
#回答语句的构建
self.searcher = AnswerSearcher()
def chat_main(self, sent):
answer = '抱歉,或许是数据库还未收纳您想要查询的信息,请尝试重新输入'
#返回的是实体及其类别,以及问题类型
res_classify = self.classifier.classify(sent)
if res_classify=='':
print(answer)
#print('类别:',res_classify)
#返回的是问题类型和对应的查询结果
res_sql = self.parser.parser_main(res_classify)
#print('sql语句',res_sql)
final_answers = self.searcher.search_main(res_sql)
if final_answers=='':
print(answer)
#return '\n'.join(final_answers)
if __name__ == '__main__':
handler = ChatBotGraph()
#测试,读者可以自定义问题或者删去此部分
problems=["卧虎藏龙和花样年华的评分",
"饮食男女的上映时间",
"霸王别姬这部电影的风格"]
for id,problem in enumerate(problems):
print("第{0}个问题是{1}:".format(id+1,problem))
handler.chat_main(problem)
print("\n")
print("测试结束")
#交互式提问
while 1:
question = input('咨询:')
handler.chat_main(question)
该部分由"question_classifier.py"实现。首先是利用第三方库ahocorasick完成利用AC自动机进行实体识别的任务。读者如果只是想要完成项目,可以不需要过多了解AC自动机原理,通过第三方库能利用较为固定的代码实现字典树的构建和识别过程,从而完成实体识别。
问题分类是基于文本分类实现的,但项目中并没能通过构建神经网络实现文本分类,只是利用了传统的字符串匹配,简化了入门者的上手难度。因此读者可以尝试对文本分类部分进行优化,采用Bi-LSTM、TextCNN、FastText三种神经网络模型来进行文本分类操作,来识别用户的意图。选择实验结果最优的模型进行问答系统的文本分类操作。
代码如下:
#实体识别和问题分类
import os
import ahocorasick #AC自动机模块
class QuestionClassifier:
def __init__(self):
cur_dir = '/'.join(os.path.abspath(__file__).split('/')[:-1])
#join().split取当前文件路径,并以最后一个/分段,取后面部分,再加上前面join的'/',就是当前文件夹的相对路径
# 以下是特征词的路径:
self.person_path = os.path.join(cur_dir, 'person.txt')
self.movie_path = os.path.join(cur_dir, 'movie.txt')
self.genre_path = os.path.join(cur_dir, 'genre.txt')
# 加载特征词
self.person_wds= [i.strip() for i in open(self.person_path,encoding="utf-8") if i.strip()]#encoding="utf-8"
self.movie_wds= [i.strip() for i in open(self.movie_path,encoding="utf-8") if i.strip()]
self.genre_wds= [i.strip() for i in open(self.genre_path,encoding="utf-8") if i.strip()]
#构造字典树从而后面进行实体识别
#对应的字典树的内容:
self.region_words = set(
self.person_wds + self.movie_wds + self.genre_wds)
# 构造字典树,build_actree是字典树构建的通用函数,构造内容一般不变
self.region_tree = self.build_actree(list(self.region_words))
# 构建词典,确定实体的类别
self.wdtype_dict = self.build_wdtype_dict()
# 人为确定的问句疑问词
#剧情和演员简介容易冲突
# 评分
self.q1_qwds = ['分数', '评分', '现象', '表现']#评分
#上映
self.q2_qwds = ['上映','首映', '上映时间', '首映时间', '首播', '观看', '上线', '影院', '放映', '时间']
#风格
self.q3_qwds = ['风格', '格调', '类型']
#剧情
self.q4_qwds = ['剧情', '内容', '故事', '简介', '情节', '梗概']
#出演
self.q5_qwds = ['演员', '演的', '出演', '演过', '哪些人']
#演员简介
self.q6_qwds = ['是谁', '介绍', '简介', '谁是', '详细信息','信息' ]
#AB合作
self.q7_qwds = ['合作', '一起']
#A一共演过多时
self.q8_qwds = ['一共', '总共', '多少部', '多少', '参演']
#A的生日
self.q9_qwds = ['出生日期', '生日', '出生', '生于']
print('model init finished ......')
return
'''分类主函数'''
def classify(self, question):
# data存储数据,包含两部分,一个是识别出的实体及其类别,一个是问题的类别
data = {}
#进行实体识别,返回问题中的实体和对应的类别,识别失败时直接返回
medical_dict = self.check_medical(question)
if not medical_dict:
return {}
data['args'] = medical_dict
#收集问句当中所涉及到的实体类型
types = []
for type_ in medical_dict.values():
types += type_
#问题分类
question_type = 'others'
question_types = []
#人为制订的问题模板,要求存在实体,并且问题收纳在模板中,才会对问题进行分类
# 评分
if self.check_words(self.q1_qwds, question) and ('movie' in types):
question_type = 'pingfen'
question_types.append(question_type)#考虑到提问时可能有多个问题
#上映
if self.check_words(self.q2_qwds, question) and ('movie' in types):
question_type = 'shangying'
question_types.append(question_type)
# 风格
if self.check_words(self.q3_qwds, question) and ('movie' in types):
question_type = 'fengge'
question_types.append(question_type)
# 剧情
if self.check_words(self.q4_qwds, question) and ('movie' in types):
question_type = 'jvqing'
question_types.append(question_type)
# 出演
if self.check_words(self.q5_qwds, question) and ('movie' in types):
question_type = 'chuyan'
question_types.append(question_type)
# 演员简介
if self.check_words(self.q6_qwds, question) and ('person' in types):
question_type = 'yanyuanjianjie'
question_types.append(question_type)
# 合作出演
if self.check_words(self.q7_qwds, question) and ('person' in types):
question_type = 'hezuochuyan'
question_types.append(question_type)
# 总共
if self.check_words(self.q8_qwds, question) and ('person' in types):
question_type = 'zonggong'
question_types.append(question_type)
# 生日
if self.check_words(self.q9_qwds, question) and ('person' in types):
question_type = 'shengri'
question_types.append(question_type)
# 将多个分类结果进行合并处理,组装成一个字典
data['question_types'] = question_types
#data包含两部分,一个是识别出的实体及其类别,一个是问题的类别
return data
'''构造实体对应的类型'''
def build_wdtype_dict(self):
wd_dict = dict()
for wd in self.region_words:
wd_dict[wd] = []
if wd in self.person_wds:
wd_dict[wd].append('person')
if wd in self.movie_wds:
wd_dict[wd].append('movie')
if wd in self.genre_wds:
wd_dict[wd].append('gener')
return wd_dict
'''构建字典树,利用AC自动机实现实体识别'''
def build_actree(self, wordlist):
actree = ahocorasick.Automaton()
for index, word in enumerate(wordlist):
actree.add_word(word, (index, word))
actree.make_automaton()
return actree
'''利用AC自动机实现问题中的实体识别'''
def check_medical(self, question):
region_wds = []
for i in self.region_tree.iter(question):
wd = i[1][1]
region_wds.append(wd)
stop_wds = []
for wd1 in region_wds:
for wd2 in region_wds:
if wd1 in wd2 and wd1 != wd2:
stop_wds.append(wd1)
final_wds = [i for i in region_wds if i not in stop_wds]
final_dict = {i:self.wdtype_dict.get(i) for i in final_wds}
return final_dict
'''基于特征词对问题进行分类,也就是确认问题的有效性'''
def check_words(self, wds, sent):
for wd in wds:
if wd in sent:
return True
return False
if __name__ == '__main__':
handler = QuestionClassifier()
while 1:
question = input('input an question:')
data = handler.classify(question)
print(data)
主程序在经过"question_classifier.py"后,返回的是问题中识别出的实体及其类型,和这个问题的问题类别。在"question_parser.py"部分中将会对这个返回结果进行结果查询。结果的查询是基于之前在"建立图谱.py"中的neo4j知识图谱实现。该部分最后返还的是实体及其类型,问题类别以及查询到的实体的属性。
代码如下:
class QuestionPaser:
'''构建实体节点'''
def build_entitydict(self, args):
entity_dict = {}
for arg, types in args.items():
for type in types:
if type not in entity_dict:
entity_dict[type] = [arg]
else:
entity_dict[type].append(arg)
return entity_dict
'''解析主函数'''
def parser_main(self, res_classify):
#提取出实体
args = res_classify['args']
entity_dict = self.build_entitydict(args)
#提取出查询的问题类型
question_types = res_classify['question_types']
sqls = []
for question_type in question_types:
#存放问题类型和相应的返回结果,而不仅是提取出的问题类型
sql_ = {}#存放问题类型
sql_['question_type'] = question_type
sql = []#存放查询结果
if question_type == 'pingfen':
sql = self.sql_transfer(question_type, entity_dict.get('movie'))
elif question_type == 'shangying':
sql = self.sql_transfer(question_type, entity_dict.get('movie'))
elif question_type == 'fengge':
sql = self.sql_transfer(question_type, entity_dict.get('movie'))
elif question_type == 'jvqing':
sql = self.sql_transfer(question_type, entity_dict.get('movie'))
elif question_type == 'chuyan':
sql = self.sql_transfer(question_type, entity_dict.get('movie'))
elif question_type == 'yanyuanjianjie':
sql = self.sql_transfer(question_type, entity_dict.get('person'))
elif question_type == 'hezuochuyan':
sql = self.sql_transfer(question_type, entity_dict.get('person'))
elif question_type == 'zonggong':
sql = self.sql_transfer(question_type, entity_dict.get('person'))
elif question_type == 'shengri':
sql = self.sql_transfer(question_type, entity_dict.get('person'))
if sql:
sql_['sql'] = sql
sqls.append(sql_)
# 存放问题类型以及查询到的相应结果
return sqls
'''针对不同的问题,有不同的返回结果'''
def sql_transfer(self, question_type, entities):
if not entities:
return []
# 查询语句
sql = []
# 查询评分
if question_type == 'pingfen':
#match函数是neo4j提供的查询方法
#限定问题中只有同类别单个实体时:
#sql=["match (m:Movie)-[]->() where m.title='{0}' return m.rating,m.title".format(entities[0])]
#后面的for循环时为了解决多个同类别实体查询的情况
sql = ["match (m:Movie)-[]->() where m.title='{0}' return m.rating,m.title".format(i) for i in entities]
# 查询上映
elif question_type == 'shangying':
#sql = ["MATCH (m:Disease) where m.name = '{0}' return m.name, m.prevent".format(i) for i in entities]
sql=["match(m:Movie)-[]->() where m.title='{0}' return m.releasedate,m.title".format(i) for i in entities]
# 风格
elif question_type == 'fengge':
sql = ["match(m:Movie)-[r:`是`]->(b) where m.title=\"{0}\" return b.name,m.title".format(i) for i in entities]
# 剧情
elif question_type == 'jvqing':
sql = ["match(m:Movie)-[]->() where m.title='{0}' return m.title,m.introduction".format(i) for i in entities]
# 出演
elif question_type == 'chuyan':
sql = ["match(n:Person)-[r:`饰演`]->(m:Movie) where m.title=\"{0}\" return m.title,n.name".format(i) for i in entities]
# 演员介绍
elif question_type == 'yanyuanjianjie':
sql = ["match(n:Person)-[]->() where n.name=\"{0}\" return n.name,n.biography".format(i) for i in entities]
# 合作出演
elif question_type == 'hezuochuyan':
sql = ["match(n:Person)-[r:`饰演`]->(m:Movie) where n.name=\"{0}\" return m.title,n.name".format(i) for i in entities]
# 总共
elif question_type == 'zonggong':
sql = ["match(n:Person)-[r:`饰演`]->(m:Movie) where n.name=\"{0}\" return m.title,n.name".format(i) for i in entities]
# 生日
elif question_type == 'shengri':
sql = ["match(n:Person)-[]->() where n.name='{0}' return n.birth,n.name".format(i) for i in entities]
return sql
if __name__ == '__main__':
handler = QuestionPaser()
本项目是采用了基于模板构建问答系统的方法,因此首先根据问题类别匹配对应的问答模板,再将实体和属性传入,完成回答的生成。注意对于不同问题类别的回答应该是不同的。
代码如下:
from py2neo import Graph
class AnswerSearcher:
def __init__(self):
self.g = Graph("http://localhost:7474", user="neo4j", password="neo4j")
self.num_limit = 20
'''执行cypher查询,并返回相应结果'''
def search_main(self, sqls):
final_answers = []
for sql_ in sqls:
question_type = sql_['question_type']
queries = sql_['sql']
answers = []
for query in queries:
ress = self.g.run(query).data()
answers += ress
final_answer = self.answer_prettify(question_type, answers)
if final_answer:
final_answers.append(final_answer)
return final_answers
'''根据对应的qustion_type,调用相应的回复模板'''
def answer_prettify(self, question_type, answers):
final_answer = []
#某些数据可能缺失
if not answers:
return ''
#十面埋伏和功夫的评分(测试完成,单个和多个)
#可以完成多个电影查询评分,取第一个评分,不知道为啥返回好多评分。。。
if question_type == 'pingfen':
#防止重复
l_=[]
for i in answers:
if i['m.title'] not in l_:
l_.append(i['m.title'])
final_answer = '{0}的评分是:{1}'.format(i['m.title'], i['m.rating'])
print(final_answer)
#十面埋伏和功夫的上映时间(测试完成,单个和多个)
elif question_type == 'shangying':
l_ = []
for i in answers:
if i['m.title'] not in l_:
l_.append(i['m.title'])
final_answer = '{0}的上映时间是:{1}'.format(i['m.title'], i['m.releasedate'])
print(final_answer)
#十面埋伏和功夫的风格(测试完成,单个和多个)
elif question_type == 'fengge':
dict_ = {}
#print(answers)
for i in answers:
if i['m.title'] not in dict_:
dict_[i['m.title']]=i['b.name']
else:
dict_[i['m.title']] += ("、"+i['b.name'])
#print(dict_)
for i in dict_:
print("{0}的类型是:{1}".format(i,dict_[i]))
#十面埋伏和功夫的简介(测试完成,单个和多个)
elif question_type == 'jvqing':
l_ = []
for i in answers:
if i['m.title'] not in l_:
l_.append(i['m.title'])
final_answer = '{0}的剧情是:{1}'.format(i['m.title'], i['m.introduction'])
print(final_answer)
#十面埋伏和功夫的演员(测试完成,单个和多个)
elif question_type == 'chuyan':
dict_ = {}
#print(answers)
for i in answers:
if i['m.title'] not in dict_:
dict_[i['m.title']] = i['n.name']
else:
dict_[i['m.title']] += ("、" + i['n.name'])
#print(dict_)
for i in dict_:
print("{0}的演员名单是:{1}".format(i, dict_[i]))
#李连杰和成龙的简介(测试完成,单个和多个)
elif question_type == 'yanyuanjianjie':
l_ = []
#print(answers)
for i in answers:
if i['n.name'] not in l_:
l_.append(i['n.name'])
#添加找不到的处理
if i['n.biography']!='':
final_answer = '{0}的介绍是:{1}'.format(i['n.name'], i['n.biography'])
print(final_answer)
else:
print("找不到{0}的介绍".format(i['n.name']))
#成龙和李连杰和周星驰合作的电影(多人测试完成)
elif question_type == 'hezuochuyan':
dict_ = {}
# 构建一个总集合
l_ = []
#print(answers)
for i in answers:
if i['m.title'] not in l_ :
l_.append(i['m.title'])
if i['n.name'] not in dict_:
dict_[i['n.name']] = []
dict_[i['n.name']].append(i['m.title'])
else:
dict_[i['n.name']].append(i['m.title'])
#print(dict_)
#输出这些人各自的电影
# for i in dict_:
# print("{0}演过的电影有:{1}".format(i, dict_[i]))
#取交集
name=''
for i in dict_:
name+=(i+"、")
l_ = list(set(l_).intersection(set(dict_[i])))
#list转str
s=''
for i in l_:
s+=(i+'、')
if s=='':
print("{0}没有共同出演的电影有:{1}".format(name[:-1]))
else:
# -1过滤最后一个顿号
print("{0}共同出演的电影有:{1}".format(name[:-1],s[:-1]))
#成龙和李连杰和周星驰总共的电影
elif question_type == 'zonggong':
#不展示具体有哪些了哈
dict_ = {}
#print(answers)
for i in answers:
if i['n.name'] not in dict_:
dict_[i['n.name']] = []
dict_[i['n.name']].append(i['m.title'])
else:
dict_[i['n.name']].append(i['m.title'])
for i in dict_:
print("{0}总共演过的电影有:{1}部".format(i, len(dict_[i])))
#周星驰和李连杰的生日?
elif question_type == 'shengri':
l_ = []
for i in answers:
if i['n.name'] not in l_:
l_.append(i['n.name'])
final_answer = '{0}的生日是:{1}'.format(i['n.name'], i['n.birth'])
print(final_answer)
return final_answer
if __name__ == '__main__':
searcher = AnswerSearcher()
本项目在文本分类这一部分,并没有采用神经网络实现,而是采用了传统的字符串匹配方式,使得本项目和深度学习并没有太多联系处,考虑Bi-LSTM、TextCNN、FastText三种神经网络模型来进行文本分类操作。