Advertisement

深度学习实战52-基于医疗大模型与医疗智能诊断问答的运用简单介绍,辅助医生进行疾病诊断

阅读量:

很高兴欢迎收看本期内容!今天我们将为大家带来深度学习实战系列课程中的第52集——基于医疗大模型与医疗智能诊断问答的运用概述。本节内容将重点介绍如何利用医疗大模型辅助医生开展疾病诊断工作。医疗大模型通过系统性地收集与分析大量医学数据及临床信息资料,能够有效支持医生完成疾病诊断、制定个性化治疗方案以及进行预后评估等关键环节的任务。在这一过程中,医疗大模型不仅可以识别有价值的信息内容来辅助决策制定者提供精准诊疗建议还能结合临床指南与最新研究成果为患者提供个性化的诊疗方案以推动精准医疗的发展进程。此外我们还将深入探讨医疗智能诊断这一重要应用场景它通过深度学习算法与自然语言处理技术对患者的症状体征以及医学影像资料进行系统性地分析与判断从而为临床医生提供科学可靠的诊断依据并据此给出针对性的治疗建议这不仅有助于提升诊疗效率还能显著改善患者就医体验并最终促进医疗服务的整体质量提升

目录
一、引言
二、医疗大模型的应用背景
2.1 医疗大数据的价值
2.2 语言模型在医疗领域的应用
三、基于医疗大模型的智能诊断问答系统
3.1 医疗问答数据的获取和处理
3.2 基于PyTorch的语言模型微调
3.3 问答系统的应用
四、实验与结果
4.1 实验设置
4.2 实验结果及分析
五、结论

在这里插入图片描述

一、引言

在当下社会环境中,随着医疗技术的持续发展,在面对海量医学信息与数据所面临的挑战中衍生出一个亟待解决的重要课题——如何有效利用这些信息来提取有价值的知识。在此背景下,医疗大数据的应用模式正逐渐形成,在整合医院历史病历、医学文献及诊断报告等多种数据资源的基础上逐步完善其功能体系。通过这一过程的帮助手段——帮助医生制定更为精准的诊疗方案,在提升医疗服务的整体质量的同时也展现出显著的技术优势。特别是在智能辅助诊断方面已经取得了令人瞩目的进展,并且这种技术的发展方向正在朝着更加智能化、个性化的方向迈进。基于此需求背景以及提升医疗服务的整体质量已成为推动医疗科技发展的核心目标之一。

在这里插入图片描述

二、医疗大模型的应用背景

2.1 医疗大数据的价值

在信息技术的推动下,医疗大数据已经成为现代医学的核心支撑。该技术系统涵盖了病人的基本信息、疾病病史、检查结果以及治疗方案等多个关键要素,并通过智能分析技术实现了对海量数据的有效处理与应用。这些数据分析成果不仅有助于深入剖析疾病的内在规律性特征,在提升诊疗决策水平方面也发挥了不可替代的作用

2.2 语言模型在医疗领域的应用

近年来,自然语言处理技术(NLP)已在医疗领域得到了广泛应用。通过对医疗文本进行深入分析研究,在此过程中我们可以系统性地挖掘出具有重要价值的信息。如识别病人的症状表现、判断疾病诊断类型以及预测治疗方案等关键环节。采用先进的语言模型如BERT、GPT-2等,在准确理解和处理自然语言的基础上能够有效提取所需信息内容。

三、基于医疗大模型的智能诊断问答系统

3.1 医疗问答数据的获取和处理

首先, 我们需要收集医疗问答数据. 这些数据主要来源于医学文献. 医疗网站以及其他相关资源. 接下来的任务是将收集到的数据标准化为适当的形式(例如CSV格式), 以便后续分析和应用. 以下是一些典型的数据样本:
建立medical_qa.csv文件时, 请参考其中整理的医疗问答样本, 并补充更多内容.

复制代码
    input,target
    "高血压的症状有哪些?","高血压的症状可能包括:头痛、眩晕、心悸等。"
    "糖尿病应该如何饮食?","糖尿病患者应该吃低糖、高纤维的食物,避免吃高糖、高油脂的食物。"
    "什么是冠心病?","冠心病是由于冠状动脉供血不足引起的心肌缺血性疾病。"
    "怎样预防感冒?","预防感冒的方法包括勤洗手、保持室内通风、避免接触已经感染的人等。"
    "什么是肺癌?","肺癌是一种恶性肿瘤,起源于肺部组织的恶性肿瘤。"
    "如何预防肥胖?","预防肥胖的方法包括均衡饮食、适量运动、避免过度进食等。"
    "什么是骨质疏松?","骨质疏松是骨骼中骨量减少、骨质变薄、骨密度降低的一种疾病。"
    "中风有哪些症状?","中风的症状可能包括突然出现的面部下垂、言语困难、肢体无力等。"
    "如何预防心脏病?","预防心脏病的方法包括保持良好的饮食习惯、适量运动、避免吸烟等。"
    "什么是抑郁症?","抑郁症是一种常见的精神障碍,患者表现出持续的沮丧情绪和对生活失去兴趣。"
    "如何保护眼睛健康?","保护眼睛健康的方法包括合理用眼、定期休息、远离电子屏幕等。"
    "什么是贫血?","贫血是指人体血液中红细胞数量或质量不足导致供氧能力下降的状况。"

本文所采用的主干架构基于T5模型。其基础架构采用了Transformer网络。主要采用了预训练与微调结合的方式进行任务迁移。

T5模型由编码器和解码器组成。基于自注意力机制(Self-Attention),Transformer实现了对输入序列的理解过程。对于给定的一个长度为n的输入序列X={x₁,x₂,…,xₙ}来说,在经过Transformer处理后会生成一组长度相同的隐藏状态集合H={h₁,h₂,…,hₙ}。每个隐藏状态都整合了整个视觉域中的关键信息。

自注意力机制通过基于输入序列中各个位置之间相关性的计算来捕捉信息流动的关系。具体而言,在经过线性变换后输出了三个关键组件:Query(Q)、Key(K)以及Value(V)。随后,在计算Query与Key之间相关性的程度时,并对这些分数进行了归一化处理以获得标准化的关联程度——即注意力权重系数。在使用这些权重系数的基础上完成对Value的加权求和运算之后,则能够生成最终的编码表示结果。

为了解决如何快速掌握基础,在解决实际问题时我们可以导入现有的训练好的相近模型,并结合自身数据进行微调。首先我们需要导入相关的库包然后构建一个基于T5架构的条件生成模型T5ForConditionalGeneration。

复制代码
    # coding=utf-8/gbk
    import os,json
    import numpy as np
    import pandas as pd
    import torch
    import torch.nn.functional as F
    from torch.utils.data import Dataset, DataLoader, RandomSampler, SequentialSampler
    import os,time
    from transformers import T5Tokenizer, T5ForConditionalGeneration
    from rich.table import Column, Table
    from rich import box
    from rich.console import Console
    
    console = Console(record=True)
    from torch import cuda
    device = 'cuda' if cuda.is_available() else 'cpu'
    
    tokenizer = T5Tokenizer.from_pretrained('E:/NLP_model')
    model = T5ForConditionalGeneration.from_pretrained('E:/NLP_model')
    model = model.to(device)

预训练模型的下载地址如下:
访问链接:https://pan.baidu.com/s/1sbFIOI5uGhZXbVWQqkksyg?pwd=35u1
提取码为35u1

3.2 数据集类的构建

复制代码
    class NLPDataSetClass(Dataset):
    """
    创建一个自定义的数据集,用于训练,必须包括两个字段:输入(如source_text)、输出(如target_text)
    """
    def __init__(self, dataframe, tokenizer, source_len, target_len, source_text, target_text):
      
        self.tokenizer = tokenizer
        self.data = dataframe
        self.source_len = source_len
        self.summ_len = target_len
        self.target_text = self.data[target_text]
        self.source_text = self.data[source_text]
    
    def __len__(self):
        return len(self.target_text)
    
    def __getitem__(self, index):
    
        source_text = str(self.source_text[index])
        target_text = str(self.target_text[index])
    
        # 清理数据,以确保数据的字符串类型
        source_text = " ".join(source_text.split())
        target_text = " ".join(target_text.split())
    
        source = self.tokenizer.batch_encode_plus(
            [source_text],
            max_length=self.source_len,
            pad_to_max_length=True,
            truncation=True,
            padding="max_length",
            return_tensors="pt",
        )
        target = self.tokenizer.batch_encode_plus(
            [target_text],
            max_length=self.summ_len,
            pad_to_max_length=True,
            truncation=True,
            padding="max_length",
            return_tensors="pt",
        )
    
        source_ids = source["input_ids"].squeeze()
        source_mask = source["attention_mask"].squeeze()
        target_ids = target["input_ids"].squeeze()
        target_mask = target["attention_mask"].squeeze()
    
        return {
            "source_ids": source_ids.to(dtype=torch.long),
            "source_mask": source_mask.to(dtype=torch.long),
            "target_ids": target_ids.to(dtype=torch.long),
            "target_ids_y": target_ids.to(dtype=torch.long),
        }

3.3 模型训练和评估函数

复制代码
    def train(epoch, tokenizer, model, device, loader, optimizer):
    """用于训练的方法"""
    model.train()
    time1=time.time()
    for _, data in enumerate(loader, 0):
        y = data["target_ids"].to(device, dtype=torch.long)
        y_ids = y[:, :-1].contiguous() # target, from start to end(except end of token, <EOS>). e.g. "你好吗?"
        lm_labels = y[:, 1:].clone().detach() # target, for second to end.e.g."好吗?<EOS>"
        lm_labels[y[:, 1:] == tokenizer.pad_token_id] = -100 # releted to pad_token and loss. for detail, check here: https://github.com/Shivanandroy/T5-Finetuning-PyTorch/issues/3
        ids = data["source_ids"].to(device, dtype=torch.long) # input. e.g. "how are you?"
        mask = data["source_mask"].to(device, dtype=torch.long)
    
        outputs = model(
            input_ids=ids,
            attention_mask=mask,
            decoder_input_ids=y_ids,
            labels=lm_labels,
        )
        loss = outputs[0]
        # 每100步打印日志
        if _ % 1 == 0 and _!=0:
            time2=time.time()
            print(_,"epoch:"+str(epoch)+"-loss:"+str(loss)+";each step's time spent:"+str(float(time2-time1)/float(_+0.0001)))
            # training_logger.add_row(str(epoch), str(_), str(loss))
            # console.print(training_logger)
    
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    
    def validate(epoch, tokenizer, model, device, loader,max_length):
    
      """用于验证的方法:输入用于验证的数据,返回模型预测的结果和正确的标签"""
      model.eval()
      predictions = []
      actuals = []
      with torch.no_grad():
      for _, data in enumerate(loader, 0):
          y = data['target_ids'].to(device, dtype = torch.long)
          ids = data['source_ids'].to(device, dtype = torch.long)
          mask = data['source_mask'].to(device, dtype = torch.long)
    
          generated_ids = model.generate(
              input_ids = ids,
              attention_mask = mask,
              max_length=max_length,
              num_beams=2,
              repetition_penalty=2.5,
              length_penalty=1.0,
              early_stopping=True
              )
          preds = [tokenizer.decode(g, skip_special_tokens=True, clean_up_tokenization_spaces=True) for g in generated_ids]
          target = [tokenizer.decode(t, skip_special_tokens=True, clean_up_tokenization_spaces=True)for t in y]
          if _%1000==0:
              console.print(f'Completed {_}')
    
          predictions.extend(preds)
          actuals.extend(target)
      return predictions, actuals

3.4 训练参数设置

复制代码
    def T5Trainer(model,tokenizer,dataframe, source_text, target_text, model_params, output_dir="./outputs/"):
    
    torch.manual_seed(model_params["SEED"])  # pytorch random seed
    np.random.seed(model_params["SEED"])  # numpy random seed
    torch.backends.cudnn.deterministic = True
    
    # logging
    console.log(f"""[Model]: Loading {model_params["MODEL"]}...\n""")
    
    console.log(f"[Data]: Reading data...\n")
    
    dataframe = dataframe[[source_text, target_text]]
    
    train_size = 0.94
    train_dataset = dataframe.sample(frac=train_size, random_state=model_params["SEED"])
    #val_dataset = dataframe.drop(train_dataset.index).reset_index(drop=True)
    val_dataset = dataframe.sample(frac=train_size, random_state=model_params["SEED"]).reset_index(drop=True)
    print(val_dataset)
    train_dataset = train_dataset.reset_index(drop=True)
    
    # 打印数据集相关日志:数据量、训练步数
    console.print(f"FULL Dataset: {dataframe.shape}")
    console.print(f"TRAIN Dataset: {train_dataset.shape}")
    console.print(f"TEST Dataset: {val_dataset.shape}\n")
    total_train_steps = int((train_dataset.shape[0] * model_params["TRAIN_EPOCHS"]) / model_params["TRAIN_BATCH_SIZE"])
    console.print(f"Total Train Steps: {total_train_steps}\n")
    
    # 构建NLPDataSetClass数据集
    training_set = NLPDataSetClass(
        train_dataset,
        tokenizer,
        model_params["MAX_SOURCE_TEXT_LENGTH"],
        model_params["MAX_TARGET_TEXT_LENGTH"],
        source_text,
        target_text,
    )
    val_set = NLPDataSetClass(
        val_dataset,
        tokenizer,
        model_params["MAX_SOURCE_TEXT_LENGTH"],
        model_params["MAX_TARGET_TEXT_LENGTH"],
        source_text,
        target_text,
    )
    
    train_params = {
        "batch_size": model_params["TRAIN_BATCH_SIZE"],
        "shuffle": True,
        "num_workers": 0,
    }
    
    val_params = {
        "batch_size": model_params["VALID_BATCH_SIZE"],
        "shuffle": False,
        "num_workers": 0,
    }
    
    # Creation of Dataloaders for testing and validation. This will be used down for training and validation stage for the model.
    training_loader = DataLoader(training_set, **train_params)
    val_loader = DataLoader(val_set, **val_params)
    
    optimizer = torch.optim.Adam(params=model.parameters(), lr=model_params["LEARNING_RATE"])
    
    # 开始训练训练
    console.log(f"[Initiating Fine Tuning]...\n")
    
    for epoch in range(model_params["TRAIN_EPOCHS"]):
        # 1) 开始训练
        train(epoch, tokenizer, model, device, training_loader, optimizer)
    
        # 2) 模型保存
        console.log(f"[Saving Model]...\n")
        path = os.path.join(output_dir, "model_files")
    
        # 3) 模型评估测试
        console.log(f"[Initiating Validation]...\n")
        with torch.no_grad():  # add 2022.10.4
            # for epoch in range(model_params["VAL_EPOCHS"]):
            predictions, actuals = validate(epoch, tokenizer, model, device, val_loader,
                                            model_params["MAX_TARGET_TEXT_LENGTH"])
            final_df = pd.DataFrame({"Generated Text": predictions, "Actual Text": actuals})
            final_df.to_csv(os.path.join(output_dir, "predictions.csv"))
    
    console.save_text(os.path.join(output_dir, "logs.txt"))

3.5 开始训练

定义模型的参数,然后加载T5Trainer类进行训练

复制代码
    model_params = {
    "MODEL": "E:/NLP_model",  # 模型路径
    "TRAIN_BATCH_SIZE": 8,  # 训练批次大小, 8
    "VALID_BATCH_SIZE": 8,  # 验证批次大小, 8
    "TRAIN_EPOCHS": 20,  # 训练轮数
    "VAL_EPOCHS": 1,  # 验证轮数
    "LEARNING_RATE": 1e-4,  # 学习率
    "MAX_SOURCE_TEXT_LENGTH": 512,  # 源文本最大长度
    "MAX_TARGET_TEXT_LENGTH": 64,  # 目标文本最大长度
    "SEED": 42,  # 随机种子,用于可重复性
    }
    
    # dataframe必须有2列:- input: 文本输入- target: 目标输出
    df = pd.read_csv('train.csv')  # 数据量:1200k数据。
    df = df.sample(frac=0.01) # TODO  取消本行代码,如果你需要更多数据训练
    print("df.head:",df.head(n=5))
    print("df.shape:",df.shape)
    
    T5Trainer(
    model = model,
    tokenizer =tokenizer,
    dataframe=df,
    source_text="input",
    target_text="target",
    model_params=model_params,
    output_dir="outputs",
    )
    print("训练完成!!")

3.3 问答系统的应用

经过微调的模型可用于医疗问答系统中。当用户输入一个问题时,该系统能够生成相应的回答。

复制代码
    def get_answer(question):
    inputs = tokenizer(question, return_tensors='pt')
    inputs = {k: v.to(device) for k, v in inputs.items()}
    outputs = model(**inputs)
    answer_start_scores, answer_end_scores = outputs.start_logits, outputs.end_logits
    answer_start = torch.argmax(answer_start_scores)
    answer_end = torch.argmax(answer_end_scores) + 1
    answer = tokenizer.convert_tokens_to_string(tokenizer.convert_ids_to_tokens(inputs['input_ids'][0][answer_start:answer_end]))
    return answer

四、实验与结果

4.1 实验设置

基于所给代码框架展开实验研究。在实验过程中, 我们收集并整理了相关的医疗问答数据, 并采用适当的格式对其进行编码处理。接着, 在模型训练阶段,我们将收集到的标准化数据用于对预训练的T5架构进行微调训练。最终, 在实际应用阶段,我们将经过微调优化后的模型部署至医疗问答系统中, 并通过其生成高质量的回答向量以完成系统的功能需求

4.2 实验结果及分析

实验结果表明,在处理医疗问答任务方面微调后的T5模型表现出了色...

五、结论

本文阐述了医疗大模型的应用背景及其在临床诊疗中的重要性。此外还探讨了利用语言大模型来进行医疗诊断问答的过程。研究团队基于微调后的BERT预训练模型开发出了一个医疗问答系统。尽管该系统仍存在诸多需要改进之处但已能处理一些基础的医疗问答任务从而为临床医生提供了一定的工作支持。值得注意的是医疗大模型的发展仍处于不断优化阶段为此我们需要持续地扩展训练数据集优化模型参数并持续进行验证与评估工作才能使医疗问答系统更加完善并为临床诊疗提供更为可靠的支持。

全部评论 (0)

还没有任何评论哟~