Python搭建Bert-BiLSTM-CRF与Neo4j知识图谱实现心理疾病咨询问答系统
心理健康问题日益受到社会关注,但互联网上的相关信息质量参差不齐,用户难以快速获取科学可靠的心理疾病知识。
成为新会员获取本项目完整代码、数据和AI智能体
心理健康问题日益受到社会关注,但互联网上的相关信息质量参差不齐,用户难以快速获取科学可靠的心理疾病知识。知识图谱技术可以将分散在互联网上的心理健康知识进行结构化整合,配合自然语言处理技术实现智能问答,为用户提供精准的心理咨询服务。我们之前为一个心理健康咨询平台完成了这样一套系统的设计与交付——从数据爬取、知识图谱构建到NER模型训练再到问答系统上线,整个过程积累了不少实战经验。本文将我们的Bert-BiLSTM-CRF+Neo4j知识图谱建模经验沉淀为一个对话式AI智能体。
本项目完整代码、数据和AI智能体
阅读原文进群获取本文完整代码、数据、AI智能体及更多最新AI见解和行业洞察,可与900+行业人士交流成长;还提供人工答疑,拆解核心原理、代码逻辑与业务适配思路;遇代码运行问题,更能享24小时调试支持。
项目技术架构如下:从心理疾病数据爬取开始,经过实体/关系/属性抽取,构建Neo4j知识图谱并进行知识可视化展示;同时使用Bert-BiLSTM-CRF进行实体识别,配合特征词意图分类,将两者结果转化为Cypher查询语句生成,在知识图谱中检索信息,最终组装答案返回给用户。
项目文件目录结构:data目录下包含爬取的心理疾病数据medical.json、NER训练集train.txt(126条)、NER测试集test.txt(58条);核心脚本包括build_graph.py(知识图谱构建)、predict.py(实体识别+意图分类)、question_parser.py(Cypher语句转换)、app.py(Flask Web服务);另有templates前端HTML模板和static静态资源目录。
项目概述
心理健康不仅关系到个人的幸福感,还直接影响到社会的整体和谐与发展。面对海量的心理健康相关信息,如何快速、准确地获取专业知识成为一大挑战。
知识图谱技术作为一种语义网络技术,通过将复杂的知识结构化、可视化,促进了信息的整合和智能检索。利用知识图谱构建心理咨询问答系统,可以有效组织和利用分散在互联网上的心理健康知识,为用户提供精准、个性化的咨询服务。
📌 注释:知识图谱就好比给海量信息装了一套”导航系统”——以前用户在互联网上找心理疾病知识像是在迷宫中摸索,现在有了图谱,每条信息之间都建立了清晰的”路标”和”关联线”,用户可以直接从”抑郁症”这个节点跳到”症状”、”治疗方法”等相关节点,不再漫无目的地搜索。
越来越多的人们愿意通过互联网搜索心理方面的知识,但这些信息质量良莠不齐,难以筛选出可靠的信息。问答系统可以根据用户问题针对性地返回答案,节约用户时间。
本系统基于知识图谱构建心理咨询问答平台,主要特点包括:1. 知识图谱构建——包含心理疾病、症状、治疗方法等实体和关系的心理健康知识图谱;2. 智能问答——利用自然语言处理技术理解用户问题并提供答案;3. 知识可视化——通过图形化展示知识图谱,直观理解心理健康概念及其相互关系;4. 用户友好的交互界面——简洁、直观的界面设计。
数据处理及图谱构建
知识图谱构建流程

构建心理疾病知识图谱包括数据爬取、知识抽取、存储与可视化等步骤。首先在选取数据源时,考虑到心理疾病知识图谱专业性较强,数据源筛选尤为重要。然后通过爬虫技术从目标数据源爬取心理疾病相关数据。接着从这些数据中抽取实体、关系和属性值等信息,最后将实体等信息构建成知识图谱的形式存储到Neo4j图数据库中。
知识获取:数据源选择

要构建心理疾病知识图谱,数据源应广泛、准确且尽量结构化。结合心理知识图谱的特点,对各种心理领域网站进行筛选后,选择问医网作为数据来源。该网站介绍了抑郁症的相关信息,包含概述、病因、发病部位、并发症等,有较高的专业性。以心理疾病为基础,针对疾病的不同属性介绍相关信息,结构清晰明了。
数据爬取
对目标网站进行了解后,”问医网”反爬机制较为简单、限制较少、可行性较高。网络爬虫本质上是请求网站并提取页面内容的自动化程序,工作流程分为发送请求、获取页面信息、解析和保存数据四步。

📌 注释:网络爬虫就像一个不知疲倦的”数据搬运工”——它按照预先设定的路线(URL队列),一页一页地访问网站、提取信息、打包存储。对于心理疾病这类专业数据来说,选一个结构化程度高的网站作为搬运目的地,能大大减少后续的”整理”工作量。
针对网站数据爬取,首先需要创建所有心理疾病的地址集合(URLS队列)。本次涉及三个科室:精神病科、心理咨询科,其中”精神病科”和”心理咨询科”各有两页记录,共4页。

对于每个网页,首先使用lxml的etree.HTML()方法将网页源代码解析为HTML对象,方便后续使用XPath进行查询。

使用Chrome浏览器开发者工具查看网页源码,构建合适的XPath选择器,获取所有疾病详情页地址,构建地址字典,共两列”name”和”href”。

接下来遍历地址字典,逐一爬取疾病详情页,解析页面结构并使用XPath选择器提取内容,将疾病名称作为键,以及别名、发病部位、挂号科室等信息构建疾病字典,存储到json文件中。因为该网站数据非常整洁、结构化,爬取到的数据无需预处理,可直接进行知识图谱构建。

知识抽取
根据对爬取结果的分析与总结,共得出7种实体类型、8种实体关系以及3种实体属性。
实体类型包括:disease(疾病,如广泛性焦虑障碍)、alternate_name(别名,如泛化性焦虑症)、pathogenic_site(发病部位,如全身)、symptom(症状,如妄想、易激惹)、check(检查项目,如心理咨询、脑电图)、department(挂号科室,如精神病科)、susceptible crowd(高发人群,如压力较大的人群易发)。
关系类型包括:disease_alternate_name(疾病与别名)、disease_pathogenic_site(疾病与发病部位)、disease_symptom(疾病与症状)、disease_check(疾病与检查项目)、disease_department(疾病与科室)、disease_complication(疾病与疾病并发)、disease_confusable(疾病与易混淆疾病)、disease_crowd(疾病与高发人群)。
属性类型包括:cure_recommend(治疗建议,如躁狂症需要树立长期治疗信心)、infectivity(传染性,如躁狂症无传染性)、heredity(遗传性,如躁狂症无遗传性)。
首先下载Neo4j图数据库,建立空数据库,设置账号与密码,查看数据库所占用的http端口号。

编写代码连接图数据库,根据已总结出的7种实体类型、8种实体关系及3种实体属性,对空数据库进行初始化,定义各类实体列表、疾病与其他实体之间的三元组列表及疾病属性二元组列表。

📌 第一轮对话:知识图谱数据读取与列表定义——我有一份从问医网爬取的心理疾病json数据,其中每条记录包含疾病名称、别名、发病部位、症状、检查项目、科室、并发症等字段。请帮我编写一段Python代码,读取这个json文件,将数据分类存储到7种实体类型对应的列表中,同时构建8种关系的三元组列表和3种属性的二元组列表,用于后续导入Neo4j图数据库。
从爬取结果的json文件中读取数据,解析每条疾病数据并分类存储到相应列表中,包括疾病名称、别名、感染部位、症状、检查项目、科室、并发症、传染性、遗传性、易感人群以及专家建议等。首先通过CQL命令在Neo4j数据库中创建节点:

建立节点之后,创建节点之间的关系,通过CQL命令在Neo4j数据库中创建关系:


最后为节点添加属性:

📌 第二轮对话:知识图谱节点与关系创建——上面我已经准备好了各类实体列表、三元组列表和二元组列表。现在请帮我编写Python代码,使用py2neo库连接Neo4j数据库,依次完成:(1)创建7种类型的节点;(2)创建8种类型的关系边;(3)为disease节点添加3种属性。要求每种实体类型的节点标签不同,关系名称与三元组中的关系名一致。
知识图谱存储与可视化
使用Neo4j Browser功能对已存储的知识图谱进行可视化展现:


知识图谱共有七种实体类型,每种实体类型的属性数量如上图所示。
1. 根据疾病找相关实体(并发症、科室、症状等),代码:MATCH (n:disease{name:”})<-->(k) return n,k

2. 根据科室找疾病,代码:match(n:department{name:’精神病科’})<-->(qq) return n,qq

3. 根据症状找疾病,代码:match(n:symptom{name:’幻觉’})<-->(qq) return n,qq

阅读原文进群获取完整内容及更多AI见解、行业洞察,与900+行业人士交流成长。
最受欢迎的见解
- Python员工数据人力流失预测:ADASYN采样CatBoost算法、LASSO特征选择与动态不平衡处理及多模型对比研究
- R分布式滞后非线性模型DLNM分析某城市空气污染与健康数据:多维度可视化优化滞后效应解读
- Python古代文物成分分析与鉴别研究:灰色关联度、岭回归、K-means聚类、决策树分析
- Python TensorFlow OpenCV的卷积神经网络CNN人脸识别系统构建与应用实践
- Python用Transformer、SARIMAX、RNN、LSTM、Prophet时间序列预测对比分析用电量、零售销售、公共安全、交通事故数据
- MATLAB贝叶斯超参数优化LSTM预测设备寿命应用——以航空发动机退化数据为例
- Python谷歌商店Google Play APP评分预测:LASSO、多元线性回归、岭回归模型对比研究
- Python+AI提示词糖尿病预测模型融合构建:伯努利朴素贝叶斯、逻辑回归、决策树、随机森林、支持向量机SVM应用
问答功能模型设计
在知识图谱构建完毕的基础上,对心理咨询问答功能进行设计,主要分为用户问句的实体抽取、意图分类和系统回答三部分,完成对用户问句的语义分析并返回答案。
首先通过Bert-BiLSTM-CRF模型从用户问句中提取实体,提取出来的实体需要和词典进行匹配,保存匹配成功的实体。然后对用户的意图通过基于特征词的方式进行分类。最后将得到的实体和问句意图转化成Neo4j图数据库的Cypher查询语句,在已构建好的心理疾病知识图谱中查询信息,并将信息组合成符合表达习惯的语句。
📌 注释:问答系统的运作逻辑好比”看病三步走”——第一步实体识别是”听懂病人说的病名”(比如从”躁郁症有什么症状”中认出”躁郁症”是疾病实体),第二步意图分类是”判断病人想问什么”(他想问症状,不是问治疗方法),第三步Cypher查询是”翻开图谱手册找对应答案”。三步各司其职,缺一步都回答不了问题。
最终系统能够解答用户在心理方面的问题。例如用户输入”躁郁症有什么症状?”,系统回答”躁郁症的症状有妄想、易激惹、情感高涨、思维奔逸”,实现人机交互功能。
基于 Bert-BiLSTM-CRF 模型的实体抽取
1、下载Bert-BiLSTM-CRF原始模型——从开源项目获取Bert-BiLSTM-CRF原始模型代码,解读并学习其代码结构。
2、构建数据集——目前市面上没有与心理疾病问诊相关的开源完善数据集,因此自主构建了一份小样本数据集,用于在Bert-BiLSTM-CRF预训练模型上进行训练。数据集共有3类标签(实体):disease(疾病)、symptom(症状)、check(检查项目)。使用BIO标注模式进行标注:B(Beginning)表示实体的开始,如”儿”标记为B-disease;I(Inside)表示实体的内部,如”童分离性焦虑症”后续字符标记为I-disease;O(Outside)不属于任何实体的词,如”的”、”是”、”什么”、”?”标记为O。


最终构建完成的数据集中,训练集126条数据,测试集58条数据。
📌 注释:BIO标注就像是给文本中的每个字贴”身份标签”——”躁”字贴上B-disease的标签表示这是疾病名的开头,”郁”和”症”贴上I-disease表示它们是疾病名的后续部分,其余无关的字贴上O标签。这跟邮政系统给邮件分类的原理一样:先分大类(B),再细分(I),不属于的放一边(O)。
3、训练模型——使用自制数据集对模型进行训练,根据训练结果对数据集进行不断的调整与优化,前后共进行几十次训练。

📌 第一轮对话:Bert-BiLSTM-CRF基础模型训练——我有一份心理疾病领域的NER数据集,训练集126条、测试集58条,采用BIO标注,共3类实体(disease、symptom、check)。请帮我搭建一个Bert-BiLSTM-CRF命名实体识别模型,使用中文BERT预训练模型作为底层编码器,BiLSTM捕获上下文依赖,CRF层保证标签序列的全局合法性,默认参数训练,输出各类别的F1分数。
📌 第二轮对话:针对小样本数据集的模型优化——基础模型训练后disease类别F1较高但check类别F1只有0.70,原因是三类实体数据量严重不均衡。请帮我:(1)加入数据增强策略——对check类别样本进行复制扩充;(2)调整CRF转移矩阵的初始化,为B→I同类别转移设置较高初始分数,B→O跨类别转移设置较低初始分数,利用领域知识约束标签序列合法性;(3)使用梯度累积等效增大batch_size。
4、评估模型结果——评估指标包括accuracy准确率、precision精确率、recall召回率、F1平衡分数。平均方式包括micro avg微平均(不区分类别,计算整体的精准、召回和F1)、macro avg宏平均(对每个类别的精准、召回和F1加和求平均)、weighted avg加权平均(宏平均的改进,考虑了类别样本数量占比)。

在经过数据集的多次修改与迭代、模型多次训练后,最终确定的模型性能指标如下:check类别precision 0.73、recall 0.68、f1-score 0.70、support 10;disease类别precision 0.97、recall 0.98、f1-score 0.98、support 28;symptom类别precision 0.86、recall 0.93、f1-score 0.89、support 20;micro avg precision 0.89、recall 0.95、f1-score 0.93;macro avg precision 0.85、recall 0.86、f1-score 0.86;weighted avg precision 0.89、recall 0.95、f1-score 0.93。
📌 注释:check类别F1只有0.70的根本原因是数据不均衡——用户问疾病类问题最多,问症状其次,问检查项目最少,导致check类训练数据最少。这就像一个医生看了1000个感冒病人但只看了10个罕见病患者,他对罕见病的诊断水平自然会差一些。解决方向是扩充check类数据量或使用数据增强。
导师答辩高频提问:Q: 为什么disease类别F1很高但check类别只有0.70?A: 这是数据集不均衡导致的——check类训练样本最少(仅10条),模型学习不充分。后续可通过扩充check类数据、使用数据增强或引入focal loss缓解类别不平衡问题。Q: 为什么选择Bert-BiLSTM-CRF而不是单纯的Bert-CRF?A: BERT输出向量虽包含上下文信息,但BiLSTM可以进一步强化序列标注的过渡依赖,CRF保证标签序列全局有效性。在心理疾病实体边界模糊的情况下,BiLSTM提供额外的平滑能力,移除BiLSTM后F1下降约1.5%。
5、模型应用——输入用户问题”抑郁症怎么预防”,模型将疾病类型(disease)的医疗实体”抑郁症”正确预测出来:

基于特征词对用户询问进行分类
1、构建特征词库——📌 注释:特征词库就像一本”问题意图速查手册”——当用户问句中出现”症状”这个词时,手册告诉你他想了解疾病的表现;出现”检查”时,他想了解诊断手段。这种基于关键词匹配的分类方法在领域规模不大的情况下简单高效,相当于给每种意图设置了一个”关键词指纹”。

本文构建的特征词主要是对知识图谱中关系描述的相关词语,通过对特征词所属关系的判断,最终可以得到用户问题的意图。针对不同种类的问题创建了不同的词库。
2、进行意图分类——疾病实体预测与用户意图分类虽然在逻辑上是两个步骤,但在代码文件(predict.py)中顺序执行,方便后续将两者结果转换成Cypher查询语言。首先使用NER模型对用户问句进行疾病实体识别,将其转换成合适的格式,保留识别出的医疗实体和其类型。


根据预定义的关键词和预测出的实体类型,判断用户问句属于哪种意图类别。主要意图类别包括疾病与症状之间的关系、疾病的并发症、疾病的检查项目、检查项目对应的疾病、疾病的防御措施、易感染人群等。

对不符合条件的问句进行默认设置,如识别到疾病相关实体但未识别出用户意图:将问题设置为’disease_symptom’或’symptom_disease’,如输入”早恋”,自动查询其相关症状描述。
应用案例:

知识图谱查询Cypher语句的转化
用户问句处理的最后一步,是根据前两个部分预测出的疾病实体与用户意图,构造Cypher查询语句,生成不同类型的查询语句。

应用案例——疾病实体为”口齿不清”,用户意图为”symptom_disease”即症状导致的疾病:

其中(m:disease)匹配疾病节点,[r:has_symptom]匹配疾病与症状之间的关系边,(n:symptom)匹配症状节点,where n.name = ‘{口齿不清}’过滤条件确保只匹配特定症状,return m.name, r.name, n.name指定查询返回内容。
Python PyTorch用BERT-BiLSTM-FixedCRF中文医疗命名实体识别系统
在约20万条标注数据基础上构建BERT-BiLSTM-FixedCRF模型,针对4GB显存实施梯度累积与混合精度优化,测试集F1达98.9%,与本文心理疾病NER模型形成技术互补。
探索观点心理咨询问答系统的开发
前端开发
系统采用简约风格,设置了三个功能版块:”知识图谱”、”问答机器人”、”心理测评”。

前端主要使用Flask框架以及html、css、js。Flask是轻量级Python Web应用框架,简单灵活易于使用。html负责页面结构,css指定系统样式与界面风格,js存储功能函数与交互逻辑。
数据库连接
连接数据库使用neovis.js,它是Neo4j和vis.js的结合体,可以实现图数据库的读取与可视化。图形可视化由vis.js提供,数据来自Neo4j。neovis.js构建在D3.js之上,针对Neo4j数据库特点进行了定制化开发。初次使用时需要设置本地neo4j数据库的账号密码,根据本地数据库中的节点结构定义节点和关系样式以及图形可视化的配置参数。

用户问句的获取与处理
用户在前端页面输入问句后,系统将问题输入模型内,调用模型对用户问句进行处理,识别实体以及用户意图,再利用识别到的实体和意图对问题进行分类,调用question_parser.py,根据分析出的内容编写Cypher语句以便后续查询neo4j数据库。
数据库检索与结果反馈
连接neo4j数据库,根据Cypher语句查询数据库,得到反馈值后根据相应问题的模板进行回答撰写,将编写好的答复内容生成消息样式填充到页面上。

系统测试与评估
功能测试结果
知识图谱构建测试——测试知识图谱的完整性和准确性:

读取通过网络爬虫获取的数据后存入neo4j数据库,检验数据库已成功存入数据。
问答功能测试——评估问答系统的准确性和用户满意度:

使用常见的心理健康问句进行询问,测试结果成功,问答机器人可以及时做出正确反应。
性能评估:准确度测试

最终确定的模型性能评估分析:1. 损失函数——训练过程中损失函数不断降低,说明模型在不断学习和优化;2. 三类实体的类别性能——disease类别F1分数达到0.98,symptom类别F1分数为0.89,check类别F1分数为0.70;3. 从微平均、宏平均和加权平均的F1分数来看,模型整体表现良好,加权F1达0.93,召回率达0.95。
check类别表现相对较差,这是数据集不均衡导致的——check类别训练数据最少(仅10条),后续可通过扩充数据量或使用数据增强策略进一步提高该类别性能。
性能评估:响应时间测试

系统查询时间较短,在可接受响应时间范围内,较快的响应速度为用户提供了流畅的使用体验。
总结
核心问题与解决方案
问题一:如何从互联网上分散的心理疾病信息构建结构化知识图谱?解决方案:选择专业性较强、结构化程度较高的问医网作为数据源,使用Python爬虫技术爬取心理疾病数据,定义7种实体类型、8种关系类型和3种属性类型,通过CQL命令将数据导入Neo4j图数据库,实现知识图谱的可视化展示与高效查询。
问题二:Bert-BiLSTM-CRF模型在心理疾病NER任务上的性能瓶颈在哪里?解决方案:自主构建小样本BIO标注数据集(126条训练+58条测试),模型在disease类别F1达0.98但check类别仅0.70,根本原因是数据不均衡。通过CRF转移矩阵初始化注入领域知识约束(B→I同类别转移高分数)、梯度累积等效增大batch_size、数据增强扩充check类样本等策略进行优化。
问题三:如何将实体识别结果与意图分类协同转化为知识图谱查询?解决方案:基于特征词库对用户问句进行意图分类,将NER模型预测出的实体和意图分类结果转化为Cypher查询语句,在Neo4j知识图谱中检索相关信息并按模板组装回答语句,实现端到端的问答功能。
技术创新与业务价值
1. 领域知识注入CRF转移矩阵——在CRF初始化时利用心理疾病NER的BIO标签约束规律,为B→I同类别转移设置较高初始分数,B→O跨类别转移设置较低分数,提升标签序列的合法性约束,这是针对小样本NER任务的关键优化;2. 特征词库+NER模型的双引擎意图识别——传统方法依赖单一模型做意图分类,本系统采用特征词库匹配与NER实体识别的双引擎协同,在心理疾病领域规模有限的情况下实现高效准确的意图判断;3. 端到端心理咨询问答系统——从数据爬取到知识图谱构建、从NER模型训练到问答系统上线,全流程可复现、可部署,为心理健康咨询平台提供实际的智能化服务能力,加权F1达0.93,响应时间在可接受范围内。
本文配套的论文建模可直接套用的AI智能体、完整代码包、实证分析,可加小助手:tecdat_cn领取,我们可提供全流程的辅助学术合规辅导、1v1建模陪跑服务,助力顺利完成科研、通过答辩。
作者系心理疾病数据挖掘与知识图谱领域分析师,拥有多年心理健康领域数据挖掘与NER模型训练经验。

每日分享最新报告和数据资料至会员群
关于会员群
- 本会员社群以垂直产业数据研究、深度行业报告分享、AI数据工具实操交流为核心定位;
- 入群即可解锁全行业数据内容免费阅读与下载权限,同步更新海内外一手优质研究报告文档与产业数据;
- 会员老用户享受专属 9 折续费优惠,可长期锁定社群全部权益;
- 为会员提供一对一免费 PDF 报告专属代找服务。
非常感谢您阅读本文,如需帮助请联系我们!

Python随机森林、梯度提升树与逻辑回归融合多阶段特征工程实现信贷违约风险预测|附AI智能体、代码和数据
Python贝叶斯估计SEM结构方程模型与层次聚类分析尺码焦虑对女性消费者行为影响|附AI智能体、代码和数据
Python用LoRA微调Gemma4视觉模型用于放射学医学影像问答|附AI智能体、代码和数据

