RNN实现阿尔茨海默症的诊断识别
本文为为🔗365天深度学习训练营内部文章
原作者:K同学啊
一 导入数据
import torch.nn as nn
import torch.nn.functional as F
import torchvision,torch
from sklearn.preprocessing import StandardScaler
from torch.utils.data import TensorDataset,DataLoader
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
import warnings
warnings.filterwarnings('ignore')# 设置硬件设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")df = pd.read_excel('dia.xls')
df
二 数据处理分析
# 删除第一列和最后一列
df = df.iloc[:,1:-1]
print(df)
Age Gender Ethnicity EducationLevel BMI Smoking 0 73 0 0 2 22.927749 0 \ 1 89 0 0 0 26.827681 0 2 73 0 3 1 17.795882 0 3 74 1 0 1 33.800817 1 4 89 0 0 0 20.716974 0 ... ... ... ... ... ... ... 2144 61 0 0 1 39.121757 0 2145 75 0 0 2 17.857903 0 2146 77 0 0 1 15.476479 0 2147 78 1 3 1 15.299911 0 2148 72 0 0 2 33.289738 0 AlcoholConsumption PhysicalActivity DietQuality SleepQuality ... 0 13.297218 6.327112 1.347214 9.025679 ... \ 1 4.542524 7.619885 0.518767 7.151293 ... 2 19.555085 7.844988 1.826335 9.673574 ... 3 12.209266 8.428001 7.435604 8.392554 ... 4 18.454356 6.310461 0.795498 5.597238 ... ... ... ... ... ... ... 2144 1.561126 4.049964 6.555306 7.535540 ... 2145 18.767261 1.360667 2.904662 8.555256 ... 2146 4.594670 9.886002 8.120025 5.769464 ... 2147 8.674505 6.354282 1.263427 8.322874 ... 2148 7.890703 6.570993 7.941404 9.878711 ... FunctionalAssessment MemoryComplaints BehavioralProblems ADL 0 6.518877 0 0 1.725883 \ 1 7.118696 0 0 2.592424 2 5.895077 0 0 7.119548 3 8.965106 0 1 6.481226 4 6.045039 0 0 0.014691 ... ... ... ... ... 2144 0.238667 0 0 4.492838 2145 8.687480 0 1 9.204952 2146 1.972137 0 0 5.036334 2147 5.173891 0 0 3.785399 2148 6.307543 0 1 8.327563 Confusion Disorientation PersonalityChanges 0 0 0 0 \ 1 0 0 0 2 0 1 0 3 0 0 0 4 0 0 1 ... ... ... ... 2144 1 0 0 2145 0 0 0 2146 0 0 0 2147 0 0 0 2148 0 1 0 DifficultyCompletingTasks Forgetfulness Diagnosis 0 1 0 0 1 0 1 0 2 1 0 0 3 0 0 0 4 1 0 0 ... ... ... ... 2144 0 0 1 2145 0 0 1 2146 0 0 1 2147 0 1 1 2148 0 1 0 [2149 rows x 33 columns]
三 探索性数据分析
1.得病分布
res = df.groupby('Diabetes')['Age'].count()
print(res)plt.figure(figsize=(8, 6))
plt.pie(res.values, labels=res.index, autopct='%1.1f%%', startangle=90,colors=['#ff9999','#66b3ff','#99ff99'], explode=(0.1, 0),wedgeprops={'edgecolor': 'black', 'linewidth': 1, 'linestyle': 'solid'})
plt.title('是否得阿尔茨海默症', fontsize=16, fontweight='bold')
plt.show()
2.BMI分布直方图
# BMI分布直方图
sns.displot(df['BMI'], kde=True, color='skyblue', bins=30, height=6, aspect=1.2)
plt.title('BMI Distribution', fontsize=18, fontweight='bold', color='darkblue')
plt.xlabel('BMI', fontsize=14, color='darkgreen')
plt.ylabel('Frequency', fontsize=14, color='darkgreen')
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()
3.年龄分布直方图
# Age分布直方图
sns.displot(df['Age'], kde=True, color='skyblue', bins=30, height=6, aspect=1.2)
plt.title('Age Distribution', fontsize=18, fontweight='bold', color='darkblue')
plt.xlabel('Age', fontsize=14, color='darkgreen')
plt.ylabel('Frequency', fontsize=14, color='darkgreen')
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()
四 构建划分数据集
X = df.iloc[:,:-1]
y = df.iloc[:,-1]sc = StandardScaler()
X = sc.fit_transform(X)# 划分数据集
X = torch.tensor(np.array(X),dtype=torch.float32)
y = torch.tensor(np.array(y),dtype=torch.int64)X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.1,random_state=1)# 构建数据加载器
train_dl = DataLoader(TensorDataset(X_train,y_train),batch_size=64,shuffle=False)
test_dl = DataLoader(TensorDataset(X_test,y_test),batch_size=64,shuffle=False)
五 训练模型
1.构建模型
# 构建模型
class model_rnn(nn.Module):def __init__(self):super(model_rnn, self).__init__()self.rnn0 = nn.RNN(input_size=32,hidden_size=200,num_layers=1,batch_first=True)self.fc0 = nn.Linear(200,50)self.fc1 = nn.Linear(50,2)def forward(self,x):out , hidden1 = self.rnn0(x)out = self.fc0(out)out = self.fc1(out)return outmodel = model_rnn().to(device)
print(model)
model_rnn((rnn0): RNN(32, 200, batch_first=True)(fc0): Linear(in_features=200, out_features=50, bias=True)(fc1): Linear(in_features=50, out_features=2, bias=True) )
2.训练函数
'''
训练模型
'''
# 训练循环
def train(dataloader,model,loss_fn,optimizer):size = len(dataloader.dataset) # 训练集的大小num_batches = len(dataloader) # 批次数目,(size/batchsize,向上取整)train_acc,train_loss = 0,0 # 初始化训练损失和正确率for x,y in dataloader: # 获取数据X,y = x.to(device),y.to(device)# 计算预测误差pred = model(X) # 网络输出loss = loss_fn(pred,y) # 计算误差# 反向传播optimizer.zero_grad() # grad属性归零loss.backward() # 反向传播optimizer.step() # 每一步自动更新# 记录acc与losstrain_acc += (pred.argmax(1) == y).type(torch.float).sum().item()train_loss += loss.item()train_acc /= sizetrain_loss /= num_batchesreturn train_acc,train_loss
3.测试函数
# 测试循环
def valid(dataloader,model,loss_fn):size = len(dataloader.dataset) # 训练集的大小num_batches = len(dataloader) # 批次数目,(size/batchsize,向上取整)test_loss, test_acc = 0, 0 # 初始化训练损失和正确率# 当不进行训练时,停止梯度更新,节省计算内存消耗with torch.no_grad():for imgs,target in dataloader:imgs,target = imgs.to(device),target.to(device)# 计算losstarget_pred = model(imgs)loss = loss_fn(target_pred,target)test_loss += loss.item()test_acc += (target_pred.argmax(1) == target).type(torch.float).sum().item()test_acc /= sizetest_loss /= num_batchesreturn test_acc,test_loss
4.正式训练
loss_fn = nn.CrossEntropyLoss() # 创建损失函数
learn_rate = 1e-4 # 学习率
opt = torch.optim.Adam(model.parameters(),lr=learn_rate)
epochs = 30train_loss = []
train_acc = []
test_loss = []
test_acc = []for epoch in range(epochs):model.train()epoch_train_acc,epoch_train_loss = train(train_dl,model,loss_fn,opt)model.eval()epoch_test_acc,epoch_test_loss = valid(test_dl,model,loss_fn)train_acc.append(epoch_train_acc)train_loss.append(epoch_train_loss)test_acc.append(epoch_test_acc)test_loss.append(epoch_test_loss)# 获取当前的学习率lr = opt.state_dict()['param_groups'][0]['lr']template = ('Epoch:{:2d},Train_acc:{:.1f}%,Train_loss:{:.3f},Test_acc:{:.1f}%,Test_loss:{:.3f},lr:{:.2E}')print(template.format(epoch+1,epoch_train_acc*100,epoch_train_loss,epoch_test_acc*100,epoch_test_loss,lr))print("="*20,'Done',"="*20)
Epoch: 1,Train_acc:52.9%,Train_loss:0.688,Test_acc:67.0%,Test_loss:0.658,lr:1.00E-04 Epoch: 2,Train_acc:68.7%,Train_loss:0.612,Test_acc:67.4%,Test_loss:0.600,lr:1.00E-04 Epoch: 3,Train_acc:68.7%,Train_loss:0.566,Test_acc:70.7%,Test_loss:0.567,lr:1.00E-04 Epoch: 4,Train_acc:74.4%,Train_loss:0.526,Test_acc:72.6%,Test_loss:0.533,lr:1.00E-04 Epoch: 5,Train_acc:77.9%,Train_loss:0.487,Test_acc:78.1%,Test_loss:0.501,lr:1.00E-04 Epoch: 6,Train_acc:81.1%,Train_loss:0.451,Test_acc:79.5%,Test_loss:0.473,lr:1.00E-04 Epoch: 7,Train_acc:82.3%,Train_loss:0.421,Test_acc:80.0%,Test_loss:0.451,lr:1.00E-04 Epoch: 8,Train_acc:83.4%,Train_loss:0.397,Test_acc:78.6%,Test_loss:0.434,lr:1.00E-04 Epoch: 9,Train_acc:84.7%,Train_loss:0.378,Test_acc:80.0%,Test_loss:0.422,lr:1.00E-04 Epoch:10,Train_acc:85.2%,Train_loss:0.365,Test_acc:80.0%,Test_loss:0.414,lr:1.00E-04 Epoch:11,Train_acc:85.6%,Train_loss:0.354,Test_acc:80.0%,Test_loss:0.408,lr:1.00E-04 Epoch:12,Train_acc:85.9%,Train_loss:0.347,Test_acc:80.0%,Test_loss:0.405,lr:1.00E-04 Epoch:13,Train_acc:86.3%,Train_loss:0.341,Test_acc:78.6%,Test_loss:0.403,lr:1.00E-04 Epoch:14,Train_acc:87.0%,Train_loss:0.335,Test_acc:78.1%,Test_loss:0.403,lr:1.00E-04 Epoch:15,Train_acc:87.1%,Train_loss:0.331,Test_acc:78.6%,Test_loss:0.404,lr:1.00E-04 Epoch:16,Train_acc:87.1%,Train_loss:0.327,Test_acc:78.1%,Test_loss:0.405,lr:1.00E-04 Epoch:17,Train_acc:87.1%,Train_loss:0.324,Test_acc:78.6%,Test_loss:0.407,lr:1.00E-04 Epoch:18,Train_acc:87.3%,Train_loss:0.321,Test_acc:78.6%,Test_loss:0.409,lr:1.00E-04 Epoch:19,Train_acc:87.4%,Train_loss:0.318,Test_acc:77.7%,Test_loss:0.412,lr:1.00E-04 Epoch:20,Train_acc:87.7%,Train_loss:0.315,Test_acc:78.1%,Test_loss:0.415,lr:1.00E-04 Epoch:21,Train_acc:87.8%,Train_loss:0.312,Test_acc:77.7%,Test_loss:0.418,lr:1.00E-04 Epoch:22,Train_acc:88.1%,Train_loss:0.309,Test_acc:78.1%,Test_loss:0.422,lr:1.00E-04 Epoch:23,Train_acc:88.6%,Train_loss:0.306,Test_acc:78.1%,Test_loss:0.425,lr:1.00E-04 Epoch:24,Train_acc:88.6%,Train_loss:0.303,Test_acc:79.1%,Test_loss:0.429,lr:1.00E-04 Epoch:25,Train_acc:88.6%,Train_loss:0.301,Test_acc:79.5%,Test_loss:0.433,lr:1.00E-04 Epoch:26,Train_acc:88.6%,Train_loss:0.298,Test_acc:79.5%,Test_loss:0.437,lr:1.00E-04 Epoch:27,Train_acc:88.8%,Train_loss:0.295,Test_acc:80.0%,Test_loss:0.440,lr:1.00E-04 Epoch:28,Train_acc:89.1%,Train_loss:0.292,Test_acc:79.5%,Test_loss:0.444,lr:1.00E-04 Epoch:29,Train_acc:89.1%,Train_loss:0.290,Test_acc:79.1%,Test_loss:0.449,lr:1.00E-04 Epoch:30,Train_acc:89.2%,Train_loss:0.287,Test_acc:79.1%,Test_loss:0.453,lr:1.00E-04 ==================== Done ====================
六 结果可视化
1.Loss和Acc图
epochs_range = range(30)
plt.figure(figsize=(14,4))
plt.subplot(1,2,1)
plt.plot(epochs_range,train_acc,label='training accuracy')
plt.plot(epochs_range,test_acc,label='validation accuracy')
plt.legend(loc='lower right')
plt.title('training and validation accuracy')plt.subplot(1,2,2)
plt.plot(epochs_range,train_loss,label='training loss')
plt.plot(epochs_range,test_loss,label='validation loss')
plt.legend(loc='upper right')
plt.title('training and validation loss')
plt.show()
2.调用模型预测
test_X = X_test[0].reshape(1,-1)
pred = model(test_X.to(device)).argmax(1).item()
print('模型预测结果:',pred)
print('=='*20)
print('0:未患病')
print('1:已患病')
模型预测结果: 0 ======================================== 0:未患病 1:已患病
3.绘制混淆矩阵
'''
绘制混淆矩阵
'''
print('=============输入数据shape为==============')
print('X_test.shape:',X_test.shape)
print('y_test.shape:',y_test.shape)pred = model(X_test.to(device)).argmax(1).cpu().numpy()print('\n==========输出数据shape为==============')
print('pred.shape:',pred.shape)from sklearn.metrics import confusion_matrix,ConfusionMatrixDisplay# 计算混淆矩阵
cm = confusion_matrix(y_test,pred)plt.figure(figsize=(6,5))
plt.suptitle('')
sns.heatmap(cm,annot=True,fmt='d',cmap='Blues')
plt.xticks(fontsize=10)
plt.yticks(fontsize=10)
plt.title('Confusion Matrix',fontsize=12)
plt.xlabel('Pred Label',fontsize=10)
plt.ylabel('True Label',fontsize=10)
plt.tight_layout()
plt.show()
=============输入数据shape为============== X_test.shape: torch.Size([215, 32]) y_test.shape: torch.Size([215])==========输出数据shape为============== pred.shape: (215,)
相关文章:

RNN实现阿尔茨海默症的诊断识别
本文为为🔗365天深度学习训练营内部文章 原作者:K同学啊 一 导入数据 import torch.nn as nn import torch.nn.functional as F import torchvision,torch from sklearn.preprocessing import StandardScaler from torch.utils.data import TensorDatase…...

14-6-1C++STL的list
(一)list容器的基本概念 list容器简介: 1.list是一个双向链表容器,可高效地进行插入删除元素 2.list不可以随机存取元素,所以不支持at.(pos)函数与[ ]操作符 (二)list容器头部和尾部的操作 list对象的默…...
Redis事务机制详解与Springboot项目中的使用
Redis 的事务机制允许将多个命令打包在一起,作为一个原子操作来执行。虽然 Redis 的事务与关系型数据库的事务有所不同,但它仍然提供了一种确保多个命令顺序执行的方式。以下是 Redis 事务机制的详细解析: 1. Redis 事务的基本概念 Redis 事…...

DeepSeek-R1,用Ollama跑起来
# DeepSeek-R1横空出世,超越OpenAI-o1,教你用Ollama跑起来 使用Ollama在本地运行DeepSeek-R1的操作指南。 DeepSeek-R1作为第一代推理模型,在数学、代码和推理任务上表现优异,与OpenAI-o1模型不相上下。 将此类模型部署到本地&am…...

Leecode刷题C语言之组合总和②
执行结果:通过 执行用时和内存消耗如下: int** ans; int* ansColumnSizes; int ansSize;int* sequence; int sequenceSize;int** freq; int freqSize;void dfs(int pos, int rest) {if (rest 0) {int* tmp malloc(sizeof(int) * sequenceSize);memcpy(tmp, seque…...

YOLOv8改进,YOLOv8检测头融合DynamicHead,并添加小目标检测层(四头检测),适合目标检测、分割等,全网独发
摘要 作者提出一种新的检测头,称为“动态头”,旨在将尺度感知、空间感知和任务感知统一在一起。如果我们将骨干网络的输出(即检测头的输入)视为一个三维张量,其维度为级别 空间 通道,这样的统一检测头可以看作是一个注意力学习问题,直观的解决方案是对该张量进行全自…...
【PyQt】QThread快速创建多线程任务
pyqt通过QThread快速创建多线程任务 在 PyQt5 中使用多线程时,需要注意 GUI 线程(主线程) 和 工作线程 的分离。PyQt5 的主线程负责处理 GUI 事件,如果在主线程中执行耗时任务,会导致界面卡顿甚至无响应。因此&#x…...
智能码二维码的成本效益分析
以下是智能码二维码的成本效益分析: 成本方面 硬件成本 标签成本:二维码标签本身价格低廉,即使进行大规模应用,成本也相对较低。如在智能仓储中,塑料托盘加二维码方案的标签成本几乎可以忽略不计4。扫描设备成本&…...

企业财务管理系统的需求设计和实现
该作者的原创文章目录: 生产制造执行MES系统的需求设计和实现 企业后勤管理系统的需求设计和实现 行政办公管理系统的需求设计和实现 人力资源管理HR系统的需求设计和实现 企业财务管理系统的需求设计和实现 董事会办公管理系统的需求设计和实现 公司组织架构…...

Springboot集成Swagger和Springdoc详解
Springboot2.x集成Swagger21. Springboot匹配版本2.7.0~2.7.18(其它版本需要自己去调试匹配)2. 首先导入Swagger2匹配的依赖项3. 导入依赖后创建配置文件SwaggerConfig4. Swagger集成完后,接下来接口的配置Springboot3.x集成Springdoc1. Springboot3.x依赖Springdoc配置2. 在…...

类和对象(4)——多态:方法重写与动态绑定、向上转型和向下转型、多态的实现条件
目录 1. 向上转型和向下转型 1.1 向上转型 1.2 向下转型 1.3 instanceof关键字 2. 重写(overidde) 2.1 方法重写的规则 2.1.1 基础规则 2.1.2 深层规则 2.2 三种不能重写的方法 final修饰 private修饰 static修饰 3. 动态绑定 3.1 动态绑…...

ui-automator定位官网文档下载及使用
一、ui-automator定位官网文档简介及下载 AndroidUiAutomator:移动端特有的定位方式,uiautomator是java实现的,定位类型必须写成java类型 官方地址:https://developer.android.com/training/testing/ui-automator.html#ui-autom…...

董事会办公管理系统的需求设计和实现
该作者的原创文章目录: 生产制造执行MES系统的需求设计和实现 企业后勤管理系统的需求设计和实现 行政办公管理系统的需求设计和实现 人力资源管理HR系统的需求设计和实现 企业财务管理系统的需求设计和实现 董事会办公管理系统的需求设计和实现 公司组织架构…...
ESP32和STM32在处理中断方面的区别
为了通俗地讲解ESP32和STM32在处理中断方面的区别,我们可以把它们想象成两个不同的“智能管家”系统,各自负责管理一个家庭(即嵌入式项目)的各种任务。我们将重点放在如何处理突发事件(即中断)上。 ESP32 …...

零售业革命:改变行业的顶级物联网用例
mpro5 产品负责人Ruby Whipp表示,技术进步持续重塑零售业,其中物联网(IoT)正引领这一变革潮流。 研究表明,零售商们正在采用物联网解决方案,以提升运营效率并改善顾客体验。这些技术能够监控运营的各个方面…...
字符串算法笔记
字符串笔记 说到字符串,首先我们要注意的就是字符串的输入以及输出,因为字符串的输入格式以及要求也分为很多种,我们就来说几个比较常见的格式 g e t s gets gets 我们先来说这个函数的含义...
在Ubuntu上用Llama Factory命令行微调Qwen2.5的简单过程
半年多之前写过一个教程:在Windows上用Llama Factory微调Llama 3的基本操作_llama-factory windows-CSDN博客 如果用命令行做的话,前面的步骤可以参考上面这个博客。安装好环境后, 用自我认知数据集微调Lora模块:data/identity.j…...

ThinkPhp伪静态设置后,访问静态资源也提示找不到Controller
ThinkPhp没有配置伪静态时,除了默认的IndexController能访问,其他路由Controller都访问不到,提示404错误。配置了伪静态后就解决了这个问题。 但是当我的ThinkPhp后台项目中有静态资源放在public目录(或子目录)中需要…...

JavaScript赋能智能网页设计
构建AI驱动的实时风格迁移系统 案例概述 本案例将实现一个基于深度学习的实时图像风格迁移系统,通过浏览器端神经网络推理实现以下高级特性: WebAssembly加速的ONNX模型推理 WebGL Shader实现的风格混合算法 WebRTC实时视频流处理 基于Web Workers的…...

基于STM32的阿里云智能农业大棚
目录 前言: 项目效果演示: 一、简介 二、硬件需求准备 三、硬件框图 四、CubeMX配置 4.1、按键、蜂鸣器GPIO口配置 4.2、ADC输入配置 4.3、IIC——驱动OLED 4.4、DHT11温湿度读取 4.5、PWM配置——光照灯、水泵、风扇 4.6、串口——esp8266模…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...