Pytorch神经网络深度学习模型(理论+实践)附代码及报错调试

神经网络(理论)

深度学习模型 = 复杂的神经网络模型

  • CNN 卷积神经网络

卷积神经网络*(Convolutional Neural Networks)是深度学习中非常常见的算法(模型),其在图像处理中应用广泛*,基于CNN的专利申请近些年也增长迅速。

  • GNN 图神经网络

图(graph)是一种数据结构,常⻅的图结构包含节点(node)和边(edge),GNN是深度学习在图结构上的一个分支。

  • RNN 循环神经网络

循环神经网络*(Recurrent Neural Network)是一类具有短期记忆能力的神经网络,因而常用于文本数据处理*。

  • GAN 生成对抗网络

GAN属于人工智能领域:通过对某一事物大量数据的学习,来学习总结出其在数学层面上的分布规律,构建出合理的映射函数,从而解决现实问题,主要用于图片生成

  • Auto-Encoder 自编码器

Auto-Encoder,中文称作自编码器,是一种无监督式学习模型,它基于反向传播算法与最优化方法(如梯度下降法)。

  • Transformer 变形金刚模型

Transformer是一个利用注意力机制来提高模型训练速度的模型。

神经网络的层级结构

神经网络*(Neural Network)是一种模仿生物神经系统的计算模型,用于解决分类、回归、生成等机器学习问题。神经网络的层级结构通常包括输入层、隐藏层和输出层,每一层都由若干个神经元(或称为节点)组成,其中每个节点又被成为感知机模型*。
在这里插入图片描述

  1. 输入层:为接收数据的网络第一层。
  2. 输出层:为输出数据的网络的最后一层。
  3. 隐藏层:每一个层数、节点都是一个超参数,可以任意手动调节。

神经网络对数据的特征提取

在这里插入图片描述

xi为输入数据,wi为权重,b为偏置,黄色节点进行处理,y为结果。
y = ( ∑ i = 1 n x i × w i ) + b y = (\sum_{i=1}^{n} x_{i}\times w_{i})+ b y=(i=1nxi×wi)+b

神经网络的pytorch API

在这里插入图片描述

神经网络在pytorch中被封装为一个类torch.nn.Linear,其中:

  • in_features为输入数据数量
  • out_features为输出数据数量
  • bias为偏置,默认为随机初始数
  • device为指定当前神经网络计算时环境
  • dtype为指定计算所用的数据类型,推荐使用浮点型

神经网络的有监督训练

在这里插入图片描述

减小预测值Predication和真值之间的Distance

损失函数loss fuction,例如:
l o s s = 1 2 ( y − y ^ ) 2 loss = \frac{1}{2} (y-\hat{y})^{2} loss=21(yy^)2

神经网络的梯度下降

梯度下降*(Gradient Descent GD)简单来说就是一种寻找目标函数最小化*的方法,它利用梯度信息,通过不断迭代调整参数来寻找合适的目标值。

在这里插入图片描述

θ = θ ′ − l r ⋅ g \theta =\theta ^{'} - lr·g θ=θlrg
其中 lr 为学习速率, g 为梯度*(即求导)*。

pytorch在深度学习中的作用

在这里插入图片描述

  • 第一步Train Data :pytorch负责数据集的加载——DataLoader(自定义数据加载)。
  • 第二步Model :使用pytorch中的nn.model类搭建神经网络模型。
  • 第三步Prediction :比较预测结果和数据真值的距离。
  • 第四步loss fuction :pytorch自带损失函数,例如loss = nn.CrossEntropyLoss()交叉熵损失。
  • 第五步求导损失函数loss.backward()自动求导。
  • 第六步梯度下降optimizer.step()自动下降。

神经网络(实践)

解决方案

  1. 自定义数据集加载,并将其划分为训练集和测试集。

  2. nn.Module构造神经网络模型,对于这个问题,可以使用一个简单的多层感知器*(MLP)*模型。在输出层,可以使用Softmax激活函数将输出转换为概率分布。

  3. 模型训练

    • 选择一个适当的损失函数,例如交叉嫡损失*(Cross-Entropy Loss)*,用于衡量模型预测与实际标签之间的差异。
    • 选择一个优化算法,例如随机梯度下降_(SGD)_或**Adam **等,用于更新神经网络的权重以最小化损失函数。
    • 设置训练参数.如批量大小*(Batch Size)、学习率(Learning Rate)和训练轮数(Epochs)*等。
    • 使用训练集数据进行训练,不断更新神经网络权重以最小化损失。
  4. 模型评估

    • 使用测试集数据对训练好的神经网络模型进行评估,计算分类准确率等指标。
    • 如果性能不佳,可以尝试调整神经网络结构*(如增加隐藏层节点数)、优化算法(如调整学习率)或训练参数(如增加训练轮数)*等,以提高模型性能。
  5. 使用训练好的神经网络模型对新的鸢尾花数据进行分类预测。

数据集的加载

data_loader.py

from torch.utils.data import Dataset
import os
import pandas as pd
import numpy as np
import torch


class iris_dataloader(Dataset):
    # 读取数据,要求一定要复现三个方法
    def __init__(self, data_path):
        # data_path为数据文件的路径
        self.data_path = data_path

        # 判断数据文件是否存在,不存在时报错
        assert os.path.exists(self.data_path), 'dataset does not exits'

        # 规定读取数据的0~4列,即全部列
        df = pd.read_csv(self.data_path, name=[0, 1, 2, 3, 4])

        # 替换花朵类型规则
        d = {'Iris-Setosa': 0, 'Iris-Versicolor': 1, 'Iris-Virginical': 2}
        df[4] = df[4].map(d)

        # 读取数据与数据标签
        data = df.iloc[:, :4]
        label = df.iloc[:, 4:]

        # 数据归一化,将数据映射至N~(0,1)的正态分布
        data = (data - np.mean(data) / np.std(data))

        # 将数据转化为numpy类型,再转为tensor类型
        self.data = torch.from_numpy(np.array(data, dtype='float32'))
        self.label = torch.from_numpy(np.array(label, dtype='int64'))

        # 统计数据数量
        self.data_num = len(label)
        print('当前数据集的大小', self.data_num)

    # 读取数据集的大小
    def __len__(self):
        return self.data_num

    # 获取数据集中的单个样本
    def __getitem__(self, index):
        # 用列表(可迭代对象)封装数据
        self.data = list(self.data)
        self.label = list(self.label)

        return self.data[index], self.label[index]

训练、验证和测试函数

iris.py

import os
import sys

# 导入批量数据封装
from torch.utils.data import DataLoader

# 终端进度条
from tqdm import tqdm

# 导入Torch类
import torch
# 导入神经网络功能类
import torch.nn as nn
# 导入神经网络优化器
import torch.optim as op

# 导入数据加载类
from data_loader import iris_dataloader

os.environ['CUDA_LAUNCH_BLOCKING'] = '1'


# 初始化神经网络模型
class NN(nn.Module):
    def __init__(self, in_dim, hidden_dim1, hidden_dim2, out_dim):
        super().__init__()

        # 定义网络层级结构
        self.layer1 = nn.Linear(in_dim, hidden_dim1)
        self.layer2 = nn.Linear(hidden_dim1, hidden_dim2)
        self.layer3 = nn.Linear(hidden_dim2, out_dim)

    # 数据处理
    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        # 返回结构
        return x


# 定义网络计算环境

# device 如果有GPU则torch.cuda.is_available()返回cuda:0,否则返回cpu
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

# 训练集,验证集和测试集的划分
custom_dataset = iris_dataloader('./iris_training.csv')
# 划分各集的长度
# 训练集
train_size = int(len(custom_dataset) * 0.7)
# 验证集
val_size = int(len(custom_dataset) * 0.2)
# 测试集
test_size = int(len(custom_dataset) - train_size - val_size)

# 随机数据集切分
train_dataset, val_dataset, test_dataset = torch.utils.data.random_split(
    custom_dataset, [train_size, val_size, test_size])

# 按批量封装加载数据,batch_size表示一次运算取出数据量,shuffle表示是否打散数据
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=1, shuffle=False)
test_loader = DataLoader(test_dataset, batch_size=1, shuffle=False)

print('训练集的大小', len(train_loader) * 16, '验证集的大小', len(val_loader), '测试集的大小', len(test_loader))


# 定义推理函数,返回准确率
def infer(model, dataset, device):
    model.eval()
    acc_num = 0
    # 约束函数,不改变模型参数
    with torch.no_grad():
        for data in dataset:
            datas, label = data
            outputs = model(datas.to(device))
            predict_y = torch.max(outputs, dim=1)[1]
            # torch.max的返回值是一个元组,第一个值是max的值,第二个值是所对应的值的索引,所以只需要取第二个索引
            acc_num += torch.eq(predict_y, label.to(device)).sum().item()
    acc = acc_num / len(dataset)
    return acc


# 定义训练,验证,测试的过程
def main(lr=0.005, epochs=20):
    model = NN(4, 12, 6, 3).to(device)
    # 定义损失函数
    loss_f = nn.CrossEntropyLoss()

    # 定义模型参数
    pg = [p for p in model.parameters() if p.requires_grad]

    # 定义优化器
    optimizer = op.Adam(pg, lr=lr)

    # 权重文件存储路径
    save_path = os.path.join(os.getcwd(), 'pytorchProject/weights')
    # 判断路径是否正确,若不存在,重新创建路径
    if os.path.exists(save_path) is False:
        os.makedirs(save_path)

    # 开始训练
    for epoch in range(epochs):
        model.train()
        # 预测正确的样本数量
        acc_num = torch.zeros(1).to(device)
        sample_num = 0

        # 取得数据集, 使用tqdm封装, 并循环训练
        train_bar = tqdm(train_loader, file=sys.stdout, ncols=100)
        for datas in train_bar:
            data, label = datas
            label = label.squeeze(-1)
            # 样本数累加
            sample_num += data.shape[0]
            # 优化器梯度清零
            optimizer.zero_grad()
            outputs = model(data.to(device))
            pred_class = torch.max(outputs, dim=1)[1]
            acc_num = torch.eq(pred_class, label.to(device)).sum()

            # 计算损失
            loss = loss_f(outputs, label.to(device))
            print(loss)
            # 损失求导
            loss.backward()
            print(loss)
            # 优化器更新
            optimizer.step()

            # 打印训练指标到进度条
            train_acc = acc_num / sample_num
            train_bar.desc = 'train epoch[{}/{}] loss:{:.3f} train_acc{:.3f}'.format(epoch + 1, epochs, loss, train_acc)

    # 验证
    val_acc = infer(model, val_loader, device)
    print('train epoch[{}/{}] loss:{:.3f} val_acc{:.3f}'.format(epoch + 1, epochs, loss, val_acc))
    # 保存模型
    torch.save(model.state_dict(), os.path.join(save_path, 'NN.pth'))
    # 初始化指标清零
    train_acc = 0.
    val_acc = 0.

    print('Fished Traning')

    # 测试
    test_acc = infer(model, test_loader, device)
    print('test_acc:', test_acc)


if __name__ == '__main__':
    main()

错误调试与记录

1、输出台输出的中文显示为乱码

在这里插入图片描述

  • 问题描述:VS Code编译python语言出现中文乱码,而运行其他编程语言,例如C语言、JAVA语言等,则不会出现类似的问题。

  • 问题解决:在电脑的环境变量中,添加一条环境变量,环境变量名为 PYTHONIOENCODING ,变量值为 UTF-8

在这里插入图片描述

2、RuntimeError: CUDA error: device-side assert triggered

在这里插入图片描述

  • 问题描述:iris.py在运行时会偶尔出现device-side assert triggered的错误,并且即使成功运行时,最后所得到的测试准确率test_acc依然较低。

在这里插入图片描述

  • 问题解决:每次都在同样的地方出错的程序,问题不一定出在程序上。检查数据集iris_training.csv,数据集第一行包含数据名,影响了数据加载,非数字数据使得在计算指标的时候给进去的数据超出了边界。

在这里插入图片描述

  • 删去此行即可。
    在这里插入图片描述

3、报错显示的位置不准确

  • 问题描述:GPU会给出报错,但是有时报错的位置不准确,特别是运行时错误。

  • 问题解决:在import os下添加os.environ['CUDA_LAUNCH_BLOCKING'] = '1'

鸢尾花的数据集,我的文件名称为iris_training.csv,如果需要数据文件,我把它贴在文章后面,请勿用作商用,不想抄要源文件的可以私聊我,让我看看谁是小懒鬼

Sepal LengthSepal WidthPetal LengthPetal WidthFlower species
6.42.85.62.2Iris-Virginical
5.02.33.31.0Iris-Versicolor
4.92.54.51.7Iris-Virginical
4.93.11.50.1Iris-Setosa
5.73.81.70.3Iris-Setosa
4.43.21.30.2Iris-Setosa
5.43.41.50.4Iris-Setosa
6.93.15.12.3Iris-Virginical
6.73.14.41.4Iris-Versicolor
5.13.71.50.4Iris-Setosa
5.22.73.91.4Iris-Versicolor
6.93.14.91.5Iris-Versicolor
5.84.01.20.2Iris-Setosa
5.43.91.70.4Iris-Setosa
7.73.86.72.2Iris-Virginical
6.33.34.71.6Iris-Versicolor
6.83.25.92.3Iris-Virginical
7.63.06.62.1Iris-Virginical
6.43.25.32.3Iris-Virginical
5.74.41.50.4Iris-Setosa
6.73.35.72.1Iris-Virginical
6.42.85.62.1Iris-Virginical
5.43.91.30.4Iris-Setosa
6.12.65.61.4Iris-Virginical
7.23.05.81.6Iris-Virginical
5.23.51.50.2Iris-Setosa
5.82.64.01.2Iris-Versicolor
5.93.05.11.8Iris-Virginical
5.43.04.51.5Iris-Versicolor
6.73.05.01.7Iris-Versicolor
6.32.34.41.3Iris-Versicolor
5.12.53.01.1Iris-Versicolor
6.43.24.51.5Iris-Versicolor
6.83.05.52.1Iris-Virginical
6.22.84.81.8Iris-Virginical
6.93.25.72.3Iris-Virginical
6.53.25.12.0Iris-Virginical
5.82.85.12.4Iris-Virginical
5.13.81.50.3Iris-Setosa
4.83.01.40.3Iris-Setosa
7.93.86.42.0Iris-Virginical
5.82.75.11.9Iris-Virginical
6.73.05.22.3Iris-Virginical
5.13.81.90.4Iris-Setosa
4.73.21.60.2Iris-Setosa
6.02.25.01.5Iris-Virginical
4.83.41.60.2Iris-Setosa
7.72.66.92.3Iris-Virginical
4.63.61.00.2Iris-Setosa
7.23.26.01.8Iris-Virginical
5.03.31.40.2Iris-Setosa
6.63.04.41.4Iris-Versicolor
6.12.84.01.3Iris-Versicolor
5.03.21.20.2Iris-Setosa
7.03.24.71.4Iris-Versicolor
6.03.04.81.8Iris-Virginical
7.42.86.11.9Iris-Virginical
5.82.75.11.9Iris-Virginical
6.23.45.42.3Iris-Virginical
5.02.03.51.0Iris-Versicolor
5.62.53.91.1Iris-Versicolor
6.73.15.62.4Iris-Virginical
6.32.55.01.9Iris-Virginical
6.43.15.51.8Iris-Virginical
6.22.24.51.5Iris-Versicolor
7.32.96.31.8Iris-Virginical
4.43.01.30.2Iris-Setosa
7.23.66.12.5Iris-Virginical
6.53.05.51.8Iris-Virginical
5.03.41.50.2Iris-Setosa
4.73.21.30.2Iris-Setosa
6.62.94.61.3Iris-Versicolor
5.53.51.30.2Iris-Setosa
7.73.06.12.3Iris-Virginical
6.13.04.91.8Iris-Virginical
4.93.11.50.1Iris-Setosa
5.52.43.81.1Iris-Versicolor
5.72.94.21.3Iris-Versicolor
6.02.94.51.5Iris-Versicolor
6.42.75.31.9Iris-Virginical
5.43.71.50.2Iris-Setosa
6.12.94.71.4Iris-Versicolor
6.52.84.61.5Iris-Versicolor
5.62.74.21.3Iris-Versicolor
6.33.45.62.4Iris-Virginical
4.93.11.50.1Iris-Setosa
6.82.84.81.4Iris-Versicolor
5.72.84.51.3Iris-Versicolor
6.02.75.11.6Iris-Versicolor
5.03.51.30.3Iris-Setosa
6.53.05.22.0Iris-Virginical
6.12.84.71.2Iris-Versicolor
5.13.51.40.3Iris-Setosa
4.63.11.50.2Iris-Setosa
6.53.05.82.2Iris-Virginical
4.63.41.40.3Iris-Setosa
4.63.21.40.2Iris-Setosa
7.72.86.72.0Iris-Virginical
5.93.24.81.8Iris-Versicolor
5.13.81.60.2Iris-Setosa
4.93.01.40.2Iris-Setosa
4.92.43.31.0Iris-Versicolor
4.52.31.30.3Iris-Setosa
5.82.74.11.0Iris-Versicolor
5.03.41.60.4Iris-Setosa
5.23.41.40.2Iris-Setosa
5.33.71.50.2Iris-Setosa
5.03.61.40.2Iris-Setosa
5.62.93.61.3Iris-Versicolor
4.83.11.60.2Iris-Setosa
6.32.74.91.8Iris-Virginical
5.72.84.11.3Iris-Versicolor
5.03.01.60.2Iris-Setosa
6.33.36.02.5Iris-Virginical
5.03.51.60.6Iris-Setosa
5.52.64.41.2Iris-Versicolor
5.73.04.21.2Iris-Versicolor
4.42.91.40.2Iris-Setosa
4.83.01.40.1Iris-Setosa
5.52.43.71.0Iris-Versicolor
  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用Java运行PyTorch训练深度学习模型,可以按照以下步骤进行: 1. 准备训练好的模型文件 首先,需要准备训练好的模型文件。这个模型文件通常包含模型的结构和参数,可以使用Python的PyTorch框架训练得到。 2. 加载模型文件 使用Java的PyTorch API,可以加载训练好的模型文件。可以使用PyTorch Java API的Module类来加载PyTorch模型文件。示例代码如下: ```java import org.pytorch.Module; Module module = Module.load("/path/to/model.pt"); ``` 3. 准备输入数据 在运行模型之前,需要准备输入数据。输入数据通常需要进行预处理,例如归一化和转换为PyTorch tensor。 4. 将输入数据转化为PyTorch tensor PyTorch模型的输入是PyTorch tensor,因此需要将输入数据转化为PyTorch tensor。可以使用PyTorch Java API的Tensor类来实现。示例代码如下: ```java import org.pytorch.Tensor; float[] inputArray = {1.0f, 2.0f, 3.0f}; Tensor inputTensor = Tensor.fromBlob(inputArray, new long[]{1, inputArray.length}); ``` 在上述代码中,首先将输入数据转化为Java数组,然后使用Tensor类的fromBlob方法将其转化为PyTorch tensor。 5. 运行模型 将输入数据转化为PyTorch tensor后,可以将其输入到模型中进行推断。使用PyTorch Java API的Module类的forward方法可以实现模型的前向传播。示例代码如下: ```java Tensor outputTensor = module.forward(inputTensor).toTensor(); ``` 6. 处理模型输出 模型的输出是一个PyTorch tensor,需要将其转化为Java数据类型进行处理。例如,如果模型输出是一个概率向量,可以通过以下代码得到分类结果: ```java float[] outputArray = outputTensor.getDataAsFloatArray(); int maxIdx = 0; float maxVal = 0; for (int i = 0; i < outputArray.length; i++) { if (outputArray[i] > maxVal) { maxIdx = i; maxVal = outputArray[i]; } } ``` 在上述代码中,首先将PyTorch tensor转化为一个Java数组,然后遍历数组找到最大值,即为分类结果。 以上是使用Java运行PyTorch训练深度学习模型的一般步骤,具体实现需要根据模型的具体情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值