添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
知识渊博的手链  ·  有什么 SEVENTEEN ...·  7 月前    · 
聪明伶俐的领带  ·  最高9.67:1 ...·  8 月前    · 
风流的松树  ·  上海财经大学 ...·  1 年前    · 

智能对话系统:Unit对话API

在线聊天的总体架构与工具介绍:Flask web、Redis、Gunicorn服务组件、Supervisor服务监控器、Neo4j图数据库

linux 安装 neo4j linux 安装 Redis supervisor 安装

neo4j图数据库:Cypher

neo4j图数据库:结构化数据流水线、非结构化数据流水线

命名实体审核任务:BERT中文预训练模型

命名实体审核任务:构建RNN模型

命名实体审核任务:模型训练

命名实体识别任务:BiLSTM+CRF part1

命名实体识别任务:BiLSTM+CRF part2

命名实体识别任务:BiLSTM+CRF part3

在线部分:werobot服务、主要逻辑服务、句子相关模型服务、BERT中文预训练模型+微调模型(目的:比较两句话text1和text2之间是否有关联)、模型在Flask部署

系统联调测试与部署

离线部分+在线部分:命名实体审核任务RNN模型、命名实体识别任务BiLSTM+CRF模型、BERT中文预训练+微调模型、werobot服务+flask

4.1 离线部分简要分析

  • 学习目标:
    • 了解离线部分的数据流水线以及组成部分.
    • 了解各个组成部分的作用.
  • 离线部分架构图:
  • 离线部分架构展开图:
  • 离线部分简要分析:
    • 根据架构展开图图,离线部分可分为两条数据流水线,分别用于处理结构化数据和非结构化数据. 这里称它们为结构化数据流水线和非结构化数据流水线.
  • 结构化数据流水线的组成部分:
    • 结构化数据爬虫: 从网页上抓取结构化的有关医学命名实体的内容.
    • 结构化数据的清洗: 对抓取的内容进行过滤和清洗, 以保留需要的部分.
    • 命名实体审核: 对当前命名实体进行审核, 来保证这些实体符合我们的要求.
    • 命名实体写入数据库: 将审核后的命名实体写入数据库之中, 供在线部分使用.
  • 非结构化数据流水线的组成部分:
    • 非结构化数据爬虫: 从网页上抓取非结构化的包含医学命名实体的文本.
    • 非结构化数据清洗: 对非结构化数据进行过滤和清洗, 以保留需要的部分.
    • 命名实体识别: 使用模型从非结构化文本中获取命名实体.
    • 命名实体审核: 对当前命名实体进行审核, 来保证这些实体符合我们的要求.
    • 命名实体写入数据库: 将审核后的命名实体写入数据库之中, 供在线部分使用.
  • 因为本项目是以AI为核心的项目, 因为结构化与非结构化的数据爬虫和清洗部分的内容这里不做介绍, 但同学们要知道我们的数据来源.

4.2 结构化数据流水线

  • 学习目标:
    • 了解需要进行命名实体审核的数据内容.
    • 掌握结构化数据流水线中命名实体审核的过程.
    • 掌握结构化数据流水线中命名实体写入的过程.
  • 需要进行命名实体审核的数据内容:
踝部急性韧带损伤.csv 踝部扭伤.csv 踝部骨折.csv 蹄铁形肾.csv 蹼状阴茎.csv 躁狂抑郁症.csv 躁狂症.csv 躁郁症.csv 躯体形式障碍.csv 躯体感染伴发的精神障碍.csv 躯体感染所致精神障碍.csv 躯体感觉障碍.csv 躯体疾病伴发的精神障碍.csv 转换性障碍.csv 转移性小肠肿瘤.csv 转移性皮肤钙化病.csv 转移性肝癌.csv 转移性胸膜肿瘤.csv 转移性骨肿瘤.csv 轮状病毒性肠炎.csv 轮状病毒所致胃肠炎.csv 软产道异常性难产.csv
  • 每个csv文件的名字都是一种疾病名.
  • 以躁狂症.csv为例, 有如下内容:
行为及情绪异常 情绪起伏大 技术狂躁症 控制不住的联想 精神运动性兴奋
  • csv文件的内容是该疾病对应的症状, 每种症状占一行.
  • 进行命名实体审核:
    • 进行命名实体审核的工作我们这里使用AI模型实现, 包括训练数据集, 模型训练和使用的整个过程
  • 删除审核后的可能存在的空文件:
# Linux 命令-- 删除当前文件夹下的空文件
find ./ -name "*" -type f -size 0c | xargs -n 1 rm -f
  • 命名实体写入数据库:
  • 将命名实体写入图数据库的原因:
    • 写入的数据供在线部分进行查询,根据用户输入症状来匹配对应疾病.
  • 将命名实体写入图数据库代码:
# 引入相关包
import os
import fileinput
from neo4j import GraphDatabase
from config import NEO4J_CONFIG
driver = GraphDatabase.driver( **NEO4J_CONFIG)
def _load_data(path):
    description: 将path目录下的csv文件以指定格式加载到内存
    :param path:  审核后的疾病对应症状的csv文件
    :return:      返回疾病字典,存储各个疾病以及与之对应的症状的字典
                  {疾病1: [症状1, 症状2, ...], 疾病2: [症状1, 症状2, ...]
    # 获得疾病csv列表
    disease_csv_list = os.listdir(path)
    # 将后缀.csv去掉, 获得疾病列表
    disease_list = list(map(lambda x: x.split(".")[0], disease_csv_list))
    # 初始化一个症状列表, 它里面是每种疾病对应的症状列表
    symptom_list = []
    # 遍历疾病csv列表
    for disease_csv in disease_csv_list:
        # 将疾病csv中的每个症状取出存入symptom列表中
        symptom = list(map(lambda x: x.strip(), 
                           fileinput.FileInput(os.path.join(path, disease_csv))))
        # 过滤掉所有长度异常的症状名
        symptom = list(filter(lambda x: 0<len(x)<100, symptom))
        symptom_list.append(symptom)
    # 返回指定格式的数据
    return dict(zip(disease_list, symptom_list))
def write(path):
    description: 将csv数据写入到neo4j, 并形成图谱
    :param path: 数据文件路径
    # 使用_load_data从持久化文件中加载数据
    disease_symptom_dict = _load_data(path)
    # 开启一个neo4j的session
    with driver.session() as session:
        for key, value in disease_symptom_dict.items():
            cypher = "MERGE (a:Disease{name:%r}) RETURN a" %key
            session.run(cypher)
            for v in value:
                cypher = "MERGE (b:Symptom{name:%r}) RETURN b" %v
                session.run(cypher)
                cypher = "MATCH (a:Disease{name:%r}) MATCH (b:Symptom{name:%r}) \
                          WITH a,b MERGE(a)-[r:dis_to_sym]-(b)" %(key, v)
                session.run(cypher)
        cypher = "CREATE INDEX ON:Disease(name)"
        session.run(cypher)
        cypher = "CREATE INDEX ON:Symptom(name)"
        session.run(cypher)
# 输入参数path为csv数据所在路径
path = "/data/doctor_offline/structured/reviewed/"
write(path)
 
  • 输出效果:
    • 通过可视化管理后台查看写入效果.

4.3 非结构化数据流水线

  • 学习目标:
    • 了解需要进行命名实体识别的数据内容.
    • 掌握非结构化数据流水线中命名实体识别的过程.
    • 掌握非结构化数据流水线中命名实体审核的过程.
    • 掌握非结构化数据流水线中命名实体写入的过程.
  • 需要进行命名实体识别的数据内容:
麻疹样红斑型药疹.txt 麻疹病毒肺炎.txt 麻痹性臂丛神经炎.txt 麻风性周围神经病.txt 麻风性葡萄膜炎.txt 黄体囊肿.txt 黄斑囊样水肿.txt 黄斑裂孔性视网膜脱离.txt 黄韧带骨化症.txt 黏多糖贮积症.txt 黏多糖贮积症Ⅰ型.txt 黏多糖贮积症Ⅱ型.txt 黏多糖贮积症Ⅵ型.txt 黏多糖贮积症Ⅲ型.txt 黏多糖贮积症Ⅶ型.txt 黑色丘疹性皮肤病.txt
  • 每个txt文件的名字都是一种疾病名.
  • 以黑色丘疹性皮肤病.txt为例, 有如下内容:
初呈微小、圆形、皮肤色或黑色增深的丘疹,单个或少数发生于颌部或颊部,皮损逐渐增大增多,数年中可达数百,除眶周外尚分布于面部、颈部和胸上部。皮损大小形状酷似脂溢性角化病及扁平疣鶒。不发生鳞屑,结痂和溃疡,亦无瘙痒及其他主观症状
  • 本章总结:

    • 学习了离线部分的数据流水线以及组成部分.
      • 根据架构展开图图,离线部分可分为两条数据流水线,分别用于处理结构化数据和非结构化数据. 这里称它们为结构化数据流水线和非结构化数据流水线.
    • 结构化数据流水线的组成部分:
      • 结构化数据爬虫: 从网页上抓取结构化的有关医学命名实体的内容.
      • 结构化数据的清洗: 对抓取的内容进行过滤和清洗, 以保留需要的部分.
      • 命名实体审核: 对当前命名实体进行审核, 来保证这些实体符合我们的要求.
      • 命名实体写入数据库: 将审核后的命名实体写入数据库之中, 供在线部分使用.
    • 非结构化数据流水线的组成部分:
      • 非结构化数据爬虫: 从网页上抓取非结构化的包含医学命名实体的文本.
      • 非结构化数据清洗: 对非结构化数据进行过滤和清洗, 以保留需要的部分.
      • 命名实体识别: 使用模型从非结构化文本中获取命名实体.
      • 命名实体审核: 对当前命名实体进行审核, 来保证这些实体符合我们的要求.
      • 命名实体写入数据库: 将审核后的命名实体写入数据库之中, 供在线部分使用.
    • 学习了需要进行命名实体审核的数据内容.
    • 学习了结构化/非结构化数据流水线中命名实体审核的过程.
    • 学习了结构化/非结构化数据流水线中命名实体写入的过程.
    • 学习了需要进行命名实体识别的数据内容.
    • 非结构化数据流水线中命名实体识别的过程.
# 引入相关包
import os
import fileinput
""" neo4j-driver的安装:pip install neo4j-driver """
from neo4j import GraphDatabase
./neo4j-community-3.5.18/conf/neo4j.conf中配置
	# Bolt 连接地址
	dbms.connector.bolt.enabled=true
	dbms.connector.bolt.tls_level=OPTIONAL
	dbms.connector.bolt.listen_address=0.0.0.0:7687
#neo4j连接配置信息
NEO4J_CONFIG={
              #./neo4j-community-3.5.18/conf/neo4j.conf中配置的 dbms.connector.bolt.listen_address=0.0.0.0:7687
              "uri":"bolt://192.168.88.26:7687",
              #登录neo4j的用户名和密码
              "auth":("neo4j","nagisa"),
              #是否加密
              "encrypted":False
#读取neo4j连接配置信息
driver = GraphDatabase.driver( **NEO4J_CONFIG)
def _load_data(path):
    description: 将path目录下的csv文件以指定格式加载到内存
    :param path:  审核后的疾病对应症状的csv文件
    :return:      返回疾病字典,存储各个疾病以及与之对应的症状的字典
                  {疾病1: [症状1, 症状2, ...], 疾病2: [症状1, 症状2, ...], ... }
    # 获得疾病csv文件名(带.csv)的列表
    disease_csv_list = os.listdir(path)
    # 将后缀.csv去掉, 获得csv文件名(不带.csv)的疾病列表
    disease_list = list(map(lambda x: x.split(".")[0], disease_csv_list))
    # 初始化一个症状列表, 它里面是每种疾病对应的症状列表
    symptom_list = []
    # 遍历csv文件名(不带.csv)的疾病列表
    for disease_csv in disease_csv_list:
        # 将疾病csv文件中的每个症状取出存入symptom列表中
        symptom = list(map(lambda x: x.strip(),
                           #读取每个csv文件名(带.csv)
                           fileinput.FileInput(os.path.join(path, disease_csv))))
        # 过滤掉所有长度异常的症状名
        symptom = list(filter(lambda x: 0<len(x)<100, symptom))
        #每种疾病csv文件对应的症状列表
        symptom_list.append(symptom)
    # 返回指定格式的数据:{疾病1: [症状1, 症状2, ...], 疾病2: [症状1, 症状2, ...], ... }
    return dict(zip(disease_list, symptom_list))
def write(path):
    description: 将csv数据写入到neo4j, 并形成图谱
    :param path: 数据文件路径
    # 使用_load_data从持久化文件中加载数据:{疾病1: [症状1, 症状2, ...], 疾病2: [症状1, 症状2, ...], ... }
    disease_symptom_dict = _load_data(path)
    # 开启一个neo4j的session
    with driver.session() as session:
        #遍历 字典中的 每个键值对
        for key, value in disease_symptom_dict.items():
            #merge命令: 若节点存在, 则等效与match命令; 节点不存在, 则等效于create命令.
            #使用“疾病名”作为 Disease节点标签下的name属性对应的属性值
            cypher = "MERGE (a:Disease{name:%r}) RETURN a" %key
            session.run(cypher)
            #遍历该key(疾病名)对应的症状列表中每个症状
            for v in value:
                #使用“症状名”作为 Symptom节点标签下的name属性对应的属性值
                cypher = "MERGE (b:Symptom{name:%r}) RETURN b" %v
                session.run(cypher)
                # MATCH命令: 匹配(查询)已有数据。使用merge创建关系: 可以创建有/无方向性的关系。
                # 创建一个节点a到b的无方向关系, 这个关系r的标签为dis_to_sym, 代表a-dis_to_sym-b,即疾病名-dis_to_sym-症状名,方向为相互的
                cypher = "MATCH (a:Disease{name:%r}) MATCH (b:Symptom{name:%r}) WITH a,b MERGE(a)-[r:dis_to_sym]-(b)" %(key, v)
                session.run(cypher)
        #创建索引: 使用create index on:节点标签(属性名)来创建索引
        cypher = "CREATE INDEX ON:Disease(name)"
        session.run(cypher)
        cypher = "CREATE INDEX ON:Symptom(name)"
        session.run(cypher)
# 输入参数path为csv数据所在路径:结构化的命名实体审核过的数据
#structured 表示结构化数据。reviewed表示命名实体审核过的数据内容
path = "./data/structured/reviewed/"
write(path)
composer install 将存储库的 bin 文件夹添加到您的路径(即将作为 phar 包提供) export PATH= ~ /Users/you/path/to/neo4j-toolkit/bin: $PATH 列出已注册的数据库 neo db:list 安装新数据库 neo db:new testgraph 指定安装版本 neo db:new social 2.1.4 从一个数据库切换到另一个 neo db:switch recommendation Neo4j是一个高性能的,NOSQL数据库,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做)上而不是表中。Neo4j也可以被看作是一个高性能的引擎,该引擎具有成熟数据库的所有特性。程序员工作在一个面向对象的、灵活的网络结构下而不是严格、静态的表中——但是他们可以享受到具备完全的事务特性、企业级的数据库的所有好处。节点 和 边节点:代表一个实体,可以是人,物,地点等等;边。 存储在数据库中的数据是结构化数据,因为它是以严格的格式表示的。例如,在关系数据库表中的每条记录,例如《数据库系统基础:初级篇》中5.6的EMPLOYEE表,该表中的所有记录都遵循同一格式。对于结构化数据,为了创建数据库模式,一般都应用如《数据库系统基础:初级篇》中第3、第4、第7、第10和第11章中所描述的那些技术来详细设计数据库。然后DBMS将进行检查以确保所有数据遵循模式中所指定的结构和约束... driver = GraphDatabase.driver('bolt://localhost:7687', auth=('test', '11'))#本地neo4j。def get_driver(self): # 获取neo4j的session。def run_cypher(self,cypher): # 运行cypher。 引言:Neo4j是一个NoSQL的数据库管理系统,像其他NoSQL数据库一样具有高效的查询性能。同时,Neo4j还具有完全事务管理特性,完全支持ACID事务管理。Neo4j与其他数据库相比,具有哪些明显的优势呢? 本文选自《Neo4j全栈开发》。   在高速发展的互联网应用中,业务需求的频繁变更和数据的快速增长都要求数据库必须具有很强的适应能力。Neo4j数据库正是一个能够适应这种... 数据库是NoSQL领域中的一种,在处理相关联的大数据方面比关系型数据库天然具有优势,近年来在知识谱、金融风控、社交关系等场景中发挥了重要的角色功能。同时,数据库在AI领域,天然适合诸如记忆提取、关联推理、归纳探索等场景,成为了人工智能领域不可缺少的部分。Neo4J是比较通用和常见的数据库,具有社区版和企业版之分,普通学习使用免费的社区版即可。Neo4J还提供了一个Web访问的可视化执行与查询的界面,类似ElasticSearch一样,常容易上手。... Neo4jRepository是SpringData为我们提供的用来操作Neo4j数据库的接口,我们先来看看它的继承关系:Neo4jRepository的继承关系可以看到,通用的增删查改功能基本都有了,如果我们的数据库操作也是些简单的操作,那基本就不用再添加方法了,直接使用Neo4jRepository提供的方法即可。当然也支持我们自定义方法进行操作,这个下面再信息讲述。 Application Architecture 在规划一个基于数据库的解决方案时,有几个架构决策。根据数据库产品的不同,这些决定会略有不同我们选择。在本节中,我们将描述一些体系结构的选择,以及相应的应用架构,在使用Neo4j时提供给我们。 嵌入式与服务器 目前,大多数数据库作为服务器运行,通过客户机库访问。Neo4j是有点不寻常的是,它既可以在嵌入式模式下运行,也可以在服务器模式下运行——事实上, 追溯到近10年前,它的起源是作为嵌入式数据库。 嵌入式数据库与内存数据库不同。 Neo4j