玩转ChatGPT:Transformer分类模型

news2024/11/17 23:32:34

一、写在前面

之前,我们介绍了Sklearn包以及Boost辈的各种分类模型,这些模型都很经典了,实际上也很强大,比如说Xgboost。

然而,近期随着ChatGPT的大火,其底层框架Transformer也逐渐火了,现在大家朝着通用人工智能的方向靠拢。因此,我在想,尝试使用Transformer框架做一做临床诊断/预后问题(本质上就是分类问题),看看效果如何。

首先使用GPT简单科普Transformer框架:

二、尝鲜过程

实际上,我对于Transformer框架一概不知。所以,无脑求助GPT。

(1)用TA提供一个基础代码:

咒语:我有一个<临床数据>,其中“X1”列表示病人的预后(0表示生存,1表示死亡),其余列“X3”至“X19”表示临床自变量。

我需要写一个Transformer框架做分类的代码,使用“X3”至“X19”这17个自变量去预测“X1”,请用python帮我写出代码。

数据格式如下:

<

X1 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19

0 0 0 0 0 0 0 2.17 22 6.5 295 1.16 0.08 3.52 224 0.33 0 82.6

0 1 0 0 0 1 0 1.17 23 24.3 261 0.79 0.04 3.75 59 0.27 0.02 53.3

0 0 0 0 0 0 0 1.82 63.99 3.9 460.67 1.2 0.05 4.8 21 0.07 0 38.3

1 0 0 0 1 1 0 2.13 63.99 15.7 401.3 1.24 0.12 5.1 147 0.9 0.01 80.84

>

回复如下:

首先得安装PyTorch,具体安装教程就不说了。算了,还是说一下:

(a)打开Anaconda Prompt;

(b)打开Pytorch官网(https://pytorch.org/)寻找安装命令代码,根据自己的需求选择安装条件,比如我的LOW电脑没有GPU,只能用CPU;

(c)在Anaconda Prompt输入代码安装(记得切换好安装环境):

conda install pytorch torchvision torchaudio cpuonly -c pytorch

回车安装即可。

再附上GPT给的代码:

import torch

import torch.nn as nn

import torch.optim as optim

from sklearn.model_selection import train_test_split

from sklearn.preprocessing import StandardScaler

import pandas as pd

import numpy as np

# 加载数据

data = pd.read_csv('your_data.csv')  # 请用您数据的实际路径替换 'your_data.csv'

X = data.loc[:, 'X3':'X19'].values

y = data['X1'].values

# 数据预处理

scaler = StandardScaler()

X = scaler.fit_transform(X)

# 划分数据集

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建PyTorch数据加载器

train_data = torch.utils.data.TensorDataset(torch.Tensor(X_train), torch.Tensor(y_train))

test_data = torch.utils.data.TensorDataset(torch.Tensor(X_test), torch.Tensor(y_test))

train_loader = torch.utils.data.DataLoader(train_data, batch_size=32, shuffle=True)

test_loader = torch.utils.data.DataLoader(test_data, batch_size=32, shuffle=True)

# 定义设备

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# 创建Transformer模型

class TransformerModel(nn.Module):

    def __init__(self, input_dim, output_dim, nhead=1):

        super(TransformerModel, self).__init__()

        self.encoder = nn.TransformerEncoder(

            nn.TransformerEncoderLayer(d_model=input_dim, nhead=nhead),

            num_layers=3

        )

        self.classifier = nn.Linear(input_dim, output_dim)

    def forward(self, x):

        x = self.encoder(x)

        x = self.classifier(x)

        return x

# 初始化模型和优化器

model = TransformerModel(input_dim=X.shape[1], output_dim=2).to(device)

optimizer = optim.Adam(model.parameters(), lr=0.001)

criterion = nn.CrossEntropyLoss()

# 训练模型

for epoch in range(100):

    for i, (inputs, labels) in enumerate(train_loader):

        inputs, labels = inputs.to(device), labels.to(device)

        

        optimizer.zero_grad()

        

        outputs = model(inputs)

        loss = criterion(outputs, labels.long())

        

        loss.backward()

        optimizer.step()

    print(f'Epoch {epoch+1} / 100: Average Loss: {loss.item()}')

(2)模型需要计算性能参数

写咒语:我还需要做得出模型在训练集和测试集上的性能指标,包括灵敏度、特异度和AUC值,帮我更新代码。

TA又更新了代码(只显示更新的部分):

# 训练模型

for epoch in range(20):

    for i, (inputs, labels) in enumerate(train_loader):

        inputs, labels = inputs.to(device), labels.to(device)

        optimizer.zero_grad()

        outputs = model(inputs)

        loss = criterion(outputs, labels.long())

        loss.backward()

        optimizer.step()

    # 验证模型

    model.eval()

    with torch.no_grad():

        # 训练集

        predictions = []

        truths = []

        for inputs, labels in train_loader:

            inputs, labels = inputs.to(device), labels.to(device)

            output = model(inputs)

            _, predicted = torch.max(output.data, 1)

            predictions += predicted.tolist()

            truths += labels.tolist()

        tn, fp, fn, tp = confusion_matrix(truths, predictions).ravel()

        sensitivity = tp / (tp + fn)

        specificity = tn / (tn + fp)

        auc = roc_auc_score(truths, predictions)

        #print(f'Epoch {epoch+1} / 100, Training: Sensitivity: {sensitivity}, Specificity: {specificity}, AUC: {auc}')

 # 测试集

        predictions = []

        truths = []

        for inputs, labels in test_loader:

            inputs, labels = inputs.to(device), labels.to(device)

            output = model(inputs)

            _, predicted = torch.max(output.data, 1)

            predictions += predicted.tolist()

            truths += labels.tolist()

        tn, fp, fn, tp = confusion_matrix(truths, predictions).ravel()

        sensitivity = tp / (tp + fn)

        specificity = tn / (tn + fp)

        auc = roc_auc_score(truths, predictions)

        print(f'Epoch {epoch+1} / 100, Testing: Sensitivity: {sensitivity}, Specificity: {specificity}, AUC: {auc}')

把数据带进去运行试试:

可以看到,应该还是有一些过拟合的现象。

(3)继续施咒,如何改善过拟合。

施咒:上述的代码运行后出现过拟合,如何改善?

总体的挺到位的。我们来看看:

数据量就不考虑了,我也想要更多数据。更简单的模型,说的有道理,不过现在是测试这个面模型的性能。早停法也不适合,因为从20次迭代来看,都是过拟合的,你怎么样TA停,同样,交叉验证也是不可行。所以,试试其他的办法。

(4)增加正则化。

咒语:如何在代码中增加正则化项,请帮我改写相关代码段。

然后我加进去了,没啥效果。这是L2正则化,然后又问了L1正则化:

同样效果也不明显。

(5)减少模型复杂度。

咒语:如何做到“减少编码器层的数量、减少自注意力机制的头数或降低前馈神经网络的隐藏单元数量”,请分别修改代码段展示。

GPT注意给了回复,这里我一起展示:

# 创建Transformer模型

class TransformerModel(nn.Module):

    def __init__(self, input_dim, output_dim, nhead=1):

        super(TransformerModel, self).__init__()

        self.encoder = nn.TransformerEncoder(

            nn.TransformerEncoderLayer(d_model=input_dim, nhead=nhead),

            num_layers=int(0.5 * input_dim) # 减少层数

        )

        self.norm = nn.BatchNorm1d(input_dim)  # 添加批归一化层        

        self.classifier = nn.Linear(input_dim, output_dim)

        self.dropout = nn.Dropout(1)  # 添加一个dropout层  

然后,效果也是不明显。

看来过拟合不好解决,同时我们可以看到,Sensitivity都是比Specificity要小的,这也可以理解,因为这是一个不平衡数据(正比负是1:3),下一步考虑从这一点入手。

(6)处理不平衡数据。

咒语:Sensitivity远远比Specificity要小,请问如何改进代码?

我们来分析下:重采样就算了,尽量不要动原始数据。第三个看不懂。所以,试试改变阈值。

(7)改变阈值。

咒语:改代码中如何改变阈值?请修改相应代码段。

代码如下:

# 验证模型

model.eval()

with torch.no_grad():

    # 测试集

    predictions = []

    truths = []

    for inputs, labels in test_loader:

        inputs, labels = inputs.to(device), labels.to(device)

        output = model(inputs)

        # 将输出结果用 softmax 函数转换为概率

        probabilities = torch.nn.functional.softmax(output, dim=1)

        # 调整阈值,例如设定阈值为 0.3

        threshold = 0.3

        predicted = (probabilities[:, 1] > threshold).long()

        predictions += predicted.tolist()

        truths += labels.tolist()

    tn, fp, fn, tp = confusion_matrix(truths, predictions).ravel()

    sensitivity = tp / (tp + fn)

    specificity = tn / (tn + fp)

    auc = roc_auc_score(truths, predictions)

    print(f'Epoch {epoch+1} / 100, Testing: Sensitivity: {sensitivity}, Specificity: {specificity}, AUC: {auc}')

当然值变动了测试集,我们来试试效果,阈值改成0.3:

可以看到,特异度的份额被分到了灵敏度了,总体的AUC值变化不大。因此,性能基本上也就这样了。

最终的代码:

import torch

import torch.nn as nn

import torch.optim as optim

from sklearn.model_selection import train_test_split

from sklearn.preprocessing import StandardScaler

from sklearn.metrics import confusion_matrix, roc_auc_score

import pandas as pd

import numpy as np



# 加载数据

data = pd.read_csv('Entry model3.csv')  # 请用您数据的实际路径替换 'your_data.csv'

X = data.loc[:, 'X3':'X19'].values

y = data['X1'].values



# 数据预处理

scaler = StandardScaler()

X = scaler.fit_transform(X)



# 划分数据集

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2338)



# 创建PyTorch数据加载器

train_data = torch.utils.data.TensorDataset(torch.Tensor(X_train), torch.Tensor(y_train))

test_data = torch.utils.data.TensorDataset(torch.Tensor(X_test), torch.Tensor(y_test))

train_loader = torch.utils.data.DataLoader(train_data, batch_size=32, shuffle=True)

test_loader = torch.utils.data.DataLoader(test_data, batch_size=32, shuffle=True)



# 定义设备

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')



# 创建Transformer模型

class TransformerModel(nn.Module):

    def __init__(self, input_dim, output_dim, nhead=1):

        super(TransformerModel, self).__init__()

        self.encoder = nn.TransformerEncoder(

            nn.TransformerEncoderLayer(d_model=input_dim, nhead=nhead),

            num_layers=int(0.5 * input_dim) # 减少层数

        )

        self.norm = nn.BatchNorm1d(input_dim)  # 添加批归一化层        

        self.classifier = nn.Linear(input_dim, output_dim)

        self.dropout = nn.Dropout(1)  # 添加一个dropout层        





    def forward(self, x):

        x = self.encoder(x)

        x = self.classifier(x)

        return x





# 初始化模型和优化器

model = TransformerModel(input_dim=X.shape[1], output_dim=2).to(device)

optimizer = optim.Adam(model.parameters(), lr=0.0001, weight_decay=1e-5)



criterion = nn.CrossEntropyLoss()



# 训练模型

for epoch in range(20):

    for i, (inputs, labels) in enumerate(train_loader):

        inputs, labels = inputs.to(device), labels.to(device)

        

        optimizer.zero_grad()

        

        outputs = model(inputs)

        loss = criterion(outputs, labels.long())



        # 添加L1正则化

        #l1_lambda = 0.001

        #l1_norm = sum(p.abs().sum() for p in model.parameters())

        #loss = loss + l1_lambda * l1_norm

        

        loss.backward()

        optimizer.step()

    

    # 验证模型

    model.eval()

    with torch.no_grad():

        # 训练集

        predictions = []

        truths = []

        for inputs, labels in train_loader:

            inputs, labels = inputs.to(device), labels.to(device)

            output = model(inputs)

            _, predicted = torch.max(output.data, 1)

            predictions += predicted.tolist()

            truths += labels.tolist()

        

        tn, fp, fn, tp = confusion_matrix(truths, predictions).ravel()

        sensitivity = tp / (tp + fn)

        specificity = tn / (tn + fp)

        auc = roc_auc_score(truths, predictions)

        #print(f'Epoch {epoch+1} / 100, Training: Sensitivity: {sensitivity}, Specificity: {specificity}, AUC: {auc}')

        

        # 测试集

        predictions = []

        truths = []

        for inputs, labels in test_loader:

            inputs, labels = inputs.to(device), labels.to(device)

            output = model(inputs)

            # 将输出结果用 softmax 函数转换为概率

            probabilities = torch.nn.functional.softmax(output, dim=1)

            # 调整阈值,例如设定阈值为 0.3

            threshold = 0.3

            predicted = (probabilities[:, 1] > threshold).long()

            predictions += predicted.tolist()

            truths += labels.tolist()

        tn, fp, fn, tp = confusion_matrix(truths, predictions).ravel()

        sensitivity = tp / (tp + fn)

        specificity = tn / (tn + fp)

        auc = roc_auc_score(truths, predictions)

        print(f'Epoch {epoch+1} / 100, Testing: Sensitivity: {sensitivity}, Specificity: {specificity}, AUC: {auc}')

三、总结

以上,Transformer框架能解决分类问题。不过在这个例子中,性能不太好,可能是因为数据量太小了吧(400多例而已)。反而,同样的数据,Xgboost略胜一筹(AUC:0.75),所以有时候,合适的模型才是最好的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/592490.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分析和解决java.lang.OutOfMemoryError: Java heap space问题

这里写目录标题 问题场景问题分析与解决1.优化项目代码2.提升Java heap size3.JVM参数配置配置参考堆区参数配置说明非堆区参数配置说明 问题场景 最近客户反馈在生产环境导入操作时遇到任务一直执行中&#xff0c;并且入库的数据量一直不改变。通过日志查询&#xff0c;终于定…

UE4蓝图学习篇(九)-- 人物重定向

在平常的游戏制作或者项目练习过程中&#xff0c;我们想使用其他比较好看的模型&#xff0c;但是却想使用小白人的动画&#xff0c;这个时候要怎么去处理呢&#xff1f; 这个时候就需要使用到重定向功能&#xff0c;让两者使用同一套骨骼&#xff0c;把小白人动画重定向到我们…

IMX6ULL裸机篇之I2C相关寄存器与AP3216C传感器

一. I2C实验 I2C时钟选择与传输速率 1. IMX6ULL的 I2C频率标准模式 100kbit/S&#xff0c;快速模式为 400Kbit/S 2. 时钟源选择 perclk_clk_rootipg_clk_root66MHz&#xff08;由之前的时钟实验章节可以知道是 66MHz&#xff09;。 二. I2C 寄存器配置 I2Cx_IFDR寄存器&…

常见的内存泄漏场景

console导致 console导致的内存泄漏 因为打印后的对象需要支持在控制台上查看&#xff0c;所以传递给console.log方法的对象是不能被垃圾回收的。我们需要避免在生产环境用console打印对象。 定时器 在组件初始化的时候设置了setInterval&#xff0c;那么在组件销毁之前记得…

张驰课堂:深入了解六西格玛绿带培训课程大纲的应用价值!

六西格玛绿带培训课程大纲的内容通常包括以下几个方面&#xff1a; 六西格玛介绍&#xff1a;介绍六西格玛的历史、目标和应用领域&#xff0c;以及其在质量管理中的作用。 统计学基础&#xff1a;介绍基本的统计概念和方法&#xff0c;包括描述统计、概率分布、抽样和检验等…

SpringBoot定义优雅全局统一Restful API 响应框架五

闲话不多说&#xff0c;继续优化 全局统一Restful API 响应框架 做到项目通用 接口可扩展。 如果没有看前面几篇文章请先看前面几篇 SpringBoot定义优雅全局统一Restful API 响应框架 SpringBoot定义优雅全局统一Restful API 响应框架二 SpringBoot定义优雅全局统一Restful…

开发微信小程序,常用的开发组件有哪些?

随着微信小程序开发的持续升温&#xff0c;小程序开发也变得越来越流行&#xff0c;因为小程序不仅能帮助企业解决推广的问题&#xff0c;还能为企业带来可观的收益。但是很多企业并不知道如何开发微信小程序&#xff0c;而市面上的开发组件又有很多种&#xff0c;不知道怎么选…

restful相关知识

一. 接口编程简介 1 背景 ​ 随着互联网的发展, 尤其是移动互联为代表的Web3.0时代. 客户端层出不穷, 以APP、微信、PC浏览器为代表, 服务端业务逻辑是基本一致的. ​ 那么有没有一种方式可以做到”一次编写,随时接入”呢? 目前比较流行的方案就是"接口编程" 2 …

DevOps - (3)使用SOPS 和Terraform来加密/解密敏感信息文件

一&#xff1a;背景 每个人都想将自己的敏感数据以加密格式存储在一个安全的地方。例如我们的数据库的账号密码&#xff0c;不能以纯文本的方式来记录。让我们利用Mozilla SOPS以一种安全的方式实现它。SOPS支持将文件加密为二进制文件&#xff0c;除此之外&#xff0c;它还具…

尘埃粒子计数器 审计追踪 权限管理 洁净室等级确认干货分享

尘埃粒子计数器实用干货汇总 随着我国医药行业的不断发展&#xff0c;越来越多的医药企业需要应用洁净技术以达到控制实验室安全卫生的目的。在医药、电子、机械微生物等行业中&#xff0c;需要严格把关空间的洁净度以符合相关的标准和产品的质量。其中包括对各种洁净等级的工作…

Qt 助手简介

在探讨Qt帮助框架之前&#xff0c;我们先了解一下Qt帮助文档&#xff0c;可以让大家更好的理解。 当你使用Qt时&#xff0c;你可能会发现Qt帮助文档是一个非常有用的资源。Qt帮助文档提供了关于Qt框架和其各种组件的详细信息&#xff0c;包括类和函数的文档、示例代码和教程等…

抖音seo系统源码*SaaS+部署搭建(开源)

抖音seo源码&#xff0c;抖音seo系统源码&#xff0c;抖音seo系统搭建&#xff0c;部署 抖音作为一个全球性的短视频平台&#xff0c;用户数量已经超过了10亿。这也给企业带来了巨大的发展机遇。为了吸引更多的用户&#xff0c;企业可以通过抖音seo源码来提高自己的搜索引擎排…

有没有什么好的C++项目推荐?

据我粗略估计&#xff0c;问我“有没有什么好的C项目推荐“这个问题出现的频率仅次于“问我帅不帅“。 「C」是一门贴近底层的语言&#xff0c;不像「Java」那样能够快速搭建一个业务系统&#xff0c;比如「XX」秒杀系统、「XX」电商系统这种看着“高大上“的项目&#xff0c;「…

python按行写入json文件,每一行都是一个标准json对象,但是整体文件却非json对象

今天这篇文章主要是一个小小的偏向于应用的实践&#xff0c;为啥会写这个&#xff0c;还要回溯到2017年&#xff0c;那时候做项目的时候有一个是要做数据处理分析的工作&#xff0c;给到我的数据集我拿到的时候总觉得怪怪的&#xff0c;每一行都是一个字典对象&#xff0c;但是…

聊聊部署在K8S的项目如何获取客户端真实IP

前言 最近部门有个需求&#xff0c;需要对一些客户端IP做白名单&#xff0c;在白名单范围内&#xff0c;才能做一些业务操作。按我们的部门的一贯做法&#xff0c;我们会封装一个client包&#xff0c;提供给业务方使用。&#xff08;注&#xff1a; 我们的项目是运行在K8S上&a…

LAMP的实战应用之部署wordpress论坛,并实现正常访问登录论坛

目录 环境配置&#xff1a; 一、安装配置基础环境 步骤一&#xff1a;配置本地yun 步骤二&#xff1a;安装Remi 仓库配置包&#xff08;清华源获取&#xff09; 步骤三&#xff1a;配置Remi 仓库配置包 步骤四&#xff1a;安装php的加速器配置 步骤五&#xff1a;启动服…

Cesium实战 - 实现大气云层效果

Cesium实战 - 实现大气云层效果 Cesium 实现大气云层效果主要思路核心代码在线示例 Cesium 实现大气云层效果 在实际开发中&#xff0c;一般会有天气的效果&#xff0c;雨雪雾比较常见&#xff0c;相关的博客也很多&#xff0c;但是关于云层的天气效果还是比较少&#xff0c;而…

【调峰】储能辅助电力系统调峰的容量需求研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

经典神经网络(6)ResNet及其在Fashion-MNIST数据集上的应用

经典神经网络(6)ResNet及其在Fashion-MNIST数据集上的应用 1 ResNet的简述 ResNet 提出了一种残差学习框架来解决网络退化问题&#xff0c;从而训练更深的网络。这种框架可以结合已有的各种网络结构&#xff0c;充分发挥二者的优势。 ResNet以三种方式挑战了传统的神经网络架…

【LeetCode】342. 4的幂

342. 4的幂&#xff08;简单&#xff09; 方法一&#xff1a;二进制 思路 首先考虑一个数字是不是 2 的整数次方&#xff1a;如果一个数字 n 是 2 的整数次方&#xff0c;那么它的二进制一定是 0...010...0 这样的形式&#xff0c;将它和 -n 按位与的结果一定是它本身。如果 …