在PyTorch中开发我们的第一个神经网络

本教程将介绍初学者在PyTorch中构建神经网络的过程。我们将通过一个项目逐步进行操作。本教程将使用Kaggle上的Heart.csv数据集,请随时下载数据集并跟随教程进行:https://www.kaggle.com/rashikrahmanpritom/heart-attack-analysis-prediction-dataset

首先,导入必要的包:

swift 复制代码
import pandas as pd
from collections import OrderedDict
from torch.optim import SGD
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs
import torch.nn as nn
import torch

数据集中有一些列的数据类型是'object'。在进行任何建模之前,这些列的数据类型应该被转换为数字。

javascript 复制代码
for i in df.columns:
  if df[i].dtype == 'object':
      df[i] = df[i].astype('category').cat.codes
df

输出:

如我们所见,现在所有的数据都是数字形式的。最后一列是'HeartDisease',它有两个唯一的值:0和1。假设这是目标变量,也就是本练习的目标是根据表中可用的其他参数确定'HeartDisease'。

定义模型的训练和目标变量:

makefile 复制代码
X = df.drop(columns=['HeartDisease'])
y = df['HeartDisease']
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=21)

为了使用PyTorch模型,数据需要以'torch'格式存在。但是x_train和x_test数据是DataFrame形式的。DataFrame不能直接转换为torch。因此,首先将数据转换为numpy数组,然后再转换为torch:

cpp 复制代码
x_train, x_test, y_train, y_test = np.array(x_train), np.array(x_test), np.array(y_train), np.array(y_test)
trainX = torch.from_numpy(x_train).float()
testX = torch.from_numpy(x_test).float()
trainY = torch.from_numpy(y_train).float()
testY = torch.from_numpy(y_test).float()

模型开发:

由于这是为初学者准备的,我们将选择一个简单的神经网络。神经网络是一系列层。我们将使用一个简单的Sequential模型,其中包含2个隐藏层。让我们先看看模型是什么样子,然后我会解释它。

ruby 复制代码
class HeartDisease(nn.Module):
  def __init__(self):
      super().__init__()
      self.hidden1 = nn.Linear(11, 128)
      self.act1 = nn.ReLU()
      self.hidden2 = nn.Linear(128, 64)
      self.act2 = nn.ReLU()
      self.output = nn.Linear(64, 1)
      self.act_output = nn.Sigmoid()
  def forward(self, x):
      x = self.act1(self.hidden1(x))
      x = self.act2(self.hidden2(x))
      x = self.act_output(self.output(x))
      return x

这是一个非常简单的神经网络,有两个隐藏层。第一个隐藏层的输入是11,输出是128。在这里,11是训练特征所取的特征数或列数,128是第一个隐藏层中的神经元数。我选择的数字128是可以尝试其他数字的。神经元的数量可以看作是需要找出的超参数。通常,它是通过大量试验和错误来确定的。

hidden1的输出应该是hidden2的输入。因此,hidden2的输入是128,我选择输出为64。最后,在输出层中,输入是64,输出是1,因为这是一个二分类。如果有10个类别,输出将是10。

在分类问题中,输出需要经过一个激活函数,该函数给出一个在0到1之间范围的概率。因此,可以将其四舍五入为1或四舍五入为0。

隐藏层的数量也是通过试验和错误确定的。

然后,在HeartDisease()方法之后的forward函数调用层,最终返回输出,即我们的预测值。

打印模型:

makefile 复制代码
model = HeartDisease()
print(model)

输出:

makefile 复制代码
HeartDisease(
(hidden1): Linear(in_features=11, out_features=128, bias=True)
(act1): ReLU()
(hidden2): Linear(in_features=128, out_features=64, bias=True)
(act2): ReLU()
(output): Linear(in_features=64, out_features=1, bias=True)
(act_output): Sigmoid()
)

损失函数和优化器:

makefile 复制代码
mport torch.optim as optim
loss_fn = nn.BCELoss() # 二进制交叉熵
optimizer = optim.Adam(model.parameters(), lr=0.001)

现在是模型训练的部分。我将模型训练了150个时期,并使用了批量大小为64。对于每个时期,使用我们定义的模型计算预测标签,并使用预测标签和真实标签计算损失。棘手的部分是在转到下一个时期之前应该将梯度固定为零。否则,来自前一个时期的梯度将累加到当前时期,模型训练将不正确。

python 复制代码
epochs = 150
batch_size = 64
for epoch in range(epochs):
  for i in range(0, len(trainX), batch_size):
      Xbatch = trainX[i
:i+batch_size]
      y_pred = model(Xbatch)
      ybatch = trainY[i:i+batch_size]
      loss = loss_fn(torch.flatten(y_pred), ybatch)
      optimizer.zero_grad()
      loss.backward()
      optimizer.step()
  print(f'Finished epoch {epoch}, latest loss {loss}')

输出:

css 复制代码
Finished epoch 0, latest loss 0.46334463357925415
Finished epoch 1, latest loss 0.5276321172714233
Finished epoch 2, latest loss 0.5331380367279053
Finished epoch 3, latest loss 0.5323242545127869
...
...
...
Finished epoch 147, latest loss 0.16034317016601562
Finished epoch 148, latest loss 0.14931809902191162
Finished epoch 149, latest loss 0.15581083297729492

我只展示了一些模型训练过程中的损失输出,以展示损失如何逐渐下降。现在,是时候检查模型的性能了。

模型在测试数据上的预测准确度:

sql 复制代码
with torch.no_grad():
  y_pred = model(testX)
accuracy = len((y_pred.round() == testY).float()) / len(testY)
accuracy

输出:

css 复制代码
1.0

模型在训练数据上的预测准确度:

sql 复制代码
with torch.no_grad():
  y_pred = model(trainX)
accuracy = len((y_pred.round() == trainY)) / len(trainY)
accuracy

输出:

css 复制代码
1.0

结论

如果我们是TensorFlow用户,模型训练可能会感觉太手动了。但在工业和研究中,许多人喜欢这个手动训练过程,因为它提供了很多控制。我认为我们至少应该学习这个过程,以便在必要时可以使用它。

· END ·

HAPPY LIFE

本文仅供学习交流使用,如有侵权请联系作者删除

相关推荐
美酒没故事°21 小时前
Open WebUI安装指南。搭建自己的自托管 AI 平台
人工智能·windows·ai
云烟成雨TD21 小时前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
Csvn21 小时前
🌟 LangChain 30 天保姆级教程 · Day 13|OutputParser 进阶!让 AI 输出自动转为结构化对象,并支持自动重试!
python·langchain
简简单单做算法21 小时前
基于GA遗传优化的Transformer-LSTM网络模型的时间序列预测算法matlab性能仿真
深度学习·matlab·lstm·transformer·时间序列预测·ga遗传优化·电池剩余寿命预测
AI攻城狮21 小时前
用 Obsidian CLI + LLM 构建本地 RAG:让你的笔记真正「活」起来
人工智能·云原生·aigc
鸿乃江边鸟21 小时前
Nanobot 从onboard启动命令来看个人助理Agent的实现
人工智能·ai
lpfasd12321 小时前
基于Cloudflare生态的应用部署与开发全解
人工智能·agent·cloudflare
俞凡21 小时前
DevOps 2.0:智能体如何接管故障修复和基础设施维护
人工智能
comedate21 小时前
[OpenClaw] GLM 5 关于电影 - 人工智能 - 的思考
人工智能·电影评价
财迅通Ai21 小时前
6000万吨产能承压 卫星化学迎来战略窗口期
大数据·人工智能·物联网·卫星化学