PyTorch笔记(4)

本文详细介绍了PyTorch中非线性激活函数的作用,如ReLU、Sigmoid、Tanh和Softmax,以及线性层的使用,包括Sequential容器的构建。此外,还涵盖了损失函数的选择(如L1Loss、MSELoss和CrossEntropyLoss)和反向传播、优化器(如SGD和Adam)在模型训练中的应用,以CIFAR10数据集为例展示了神经网络的构建过程。
摘要由CSDN通过智能技术生成

神经网络—非线性激活

在PyTorch中,非线性激活函数通常用于神经网络的隐藏层,以引入网络的非线性。非线性激活函数在神经网络中的作用主要有两个方面:

1、引入非线性:

线性变换的组合仍然是线性的,如果没有非线性激活函数,多层神经网络将等效于单一的线性变换。非线性激活函数通过对神经元的输出进行非线性变换,使网络能够学习和表示更加复杂的函数关系。这是神经网络能够逼近任意复杂函数的关键。

2、增加网络的表达能力:

非线性激活函数扩展了神经网络的表达能力,使其能够学习和表示更复杂的映射关系。通过引入非线性变换,神经网络可以捕捉数据中的非线性模式、交互和复杂特征,从而提高模型的拟合能力。这对于处理实际复杂任务,如图像分类、语音识别等,非常重要。

在神经网络中,通常将多个线性层(全连接层或卷积层)与非线性激活函数交替使用,形成层次化的表示。以下是一些常用的非线性激活函数:

a、ReLU激活函数:

ReLU是一种简单而有效激活函数,它将所有负数值为零,对正数值保持不变。ReLU的主要优势在于它的计算简单且不容易导致梯度消失问题:

import torch
import torch.nn as nn

# 使用ReLU激活函数
relu = nn.ReLU()
output = relu(input_data)

b、Sigmoid激活函数:

Sigmoid是一种将输入映射到(0,1)范围的激活函数。它通常用于二分类问题,输出可以被解释为概率。

import torch
import torch.nn as nn

# 使用Sigmoid激活函数
sigmoid = nn.Sigmoid()
output = sigmoid(input_data)

c、Tanh激活函数:

Tanh是一种将输入映射到(-1,1)范围的激活函数。它与Sigmoid类似,输出范围更广。

import torch
import torch.nn as nn

# 使用Tanh激活函数
tanh = nn.Tanh()
output = tanh(input_data)

d、Softmax激活函数:

Softmax是一种用于多类别分类问题的激活函数,将输入转换为概率分布。

import torch
import torch.nn as nn

# 使用Softmax激活函数
softmax = nn.Softmax(dim=1)
output = softmax(input_data)

神经网络—线性层

在PyTorch中,线性层也称为全连接层或稠密层,是神经网络中一种基本的层类型。它执行输入特征与权重矩阵的线性变换,并添加偏置,通常用于从输入数据中学习到输出数据的映射,以下是‘torch.nn.Linear'的主要参数和解释:

torch.nn.Linear(in_features, out_features, bias=True)

1、in_features:输入特征的数量。即输入张量的大小(第一维的大小)。

2、out_features:输出特征的数量。即线性层的神经元数量,决定了输出张量的大小。

3、bias:决定是否使用偏置。如果设置为’False‘,线性层不包含可学习的偏置项。

线性层的计算过程可以表示为:

out_features=in_features×weights+bias

其中weights是权重矩阵。这个计算过程实现了输入特征与权重的线性组合,并添加了偏执项。这种线性变换是神经网络中最基本的操作之一。以下是一个例子,演示如何使用’torch.nn.Linear‘层:

import torch
import torch.nn as nn

# 定义线性层,输入特征为5,输出特征为3
linear_layer = nn.Linear(in_features=5, out_features=3)

# 输入数据,假设是大小为 (batch_size, 5) 的张量
input_data = torch.randn(10, 5)

# 使用线性层进行前向计算
output = linear_layer(input_data)

sequential的使用

在PyTorch中,Sequential是一个模型容器,用于按顺序组织多个神经网络层。它允许我们将多个层连接在一起,形成一个有序地网络结构。

sequential类可以通过传递一个有序的层列表或使用'.add_module()'方法逐个添加层来构建。下面是一个简单实例:

import torch
import torch.nn as nn

# 定义两个全连接层
layer1 = nn.Linear(10, 5)
layer2 = nn.ReLU()

# 使用Sequential容器组合层
model = nn.Sequential(layer1, layer2)

# 使用add_module()逐个添加层
model = nn.Sequential()
model.add_module('layer1', layer1)
model.add_module('layer2', layer2)

Sequential对象可以像普通的神经网络模型一样进行前向传播。当我们将输入数据传递给Sequential模型时,数据会按照层的顺序依次通过每个层进行计算。

input_data = torch.randn(32, 10)  # 输入数据维度为(32, 10)

output = model(input_data)  # 通过Sequential模型进行前向传播

在使用Sequential时,需要注意的是,每个层的输入和输出尺寸必须是匹配的。这意味着前一层的输出尺寸必须与后一层的输入尺寸相对应,以确保数据的流动和正确计算。此外,Sequential还可以通过索引访问各个层,以及使用'.named_modules()'方法获取模型中所有层的名称和参数,这为模型的调试和分析提功了便利。

总结来说,PyTorch中的Sequential是一个用于按顺序组合多个神经网络层的容器类。它可以简化模型的构建和前向传播过程,并提供方便的方法来访问和管理模型中的层。

以对数据集cifar10进行分类构建简单的神经网络为例:

CIFAR10的模型结构:

 卷积前后尺寸的计算公式:

 代码:

from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter


class My_model1(nn.Module):
    def __init__(self):
        super().__init__()
        # self.conv1=Conv2d(3,32,5,padding=2)
        # self.maxpool1=MaxPool2d(2)
        # self.conv2=Conv2d(32,32,5,padding=2)
        # self.maxpool2=MaxPool2d(2)
        # self.conv3=Conv2d(32,64,5,padding=2)
        # self.maxpool3=MaxPool2d(2)
        # self.flatten=Flatten()
        # self.linear1=Linear(1024,64)
        # self.linear2=Linear(64,10)
        #使用sequential,将以上代码注释掉
        self.my_model2=Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Linear(1024, 64),
            Linear(64, 10)
        )
    def forward(self,x):
        # x=self.conv1(x)
        # x=self.maxpool1(x)
        # x=self.conv2(x)
        # x=self.maxpool2(x)
        # x=self.conv3(x)
        # x=self.maxpool3(x)
        # x=self.flatten(x)
        # x=self.linear1(x)
        # x=self.linear2(x)
        #使用sequential,将以上代码注释掉
        x=self.my_model2(x)
        return x
my_model=My_model1()
print(my_model)

#可视化方法
writer=SummaryWriter("../logs_sequential")
writer.add_graph(my_model,input)
writer.close()

损失函数

在PyTorch中,损失函数用于衡量模型预测结果与真实标签之间的差异,是优化过程中的关键组成部分。PyTorch提供了丰富的损失函数,适用于不同类型的任务,以下是一些常见的损失函数及其用途:

1、绝对值损失函数:

绝对值损失函数通常用于回归任务,度量模型输出与目标之间的绝对差异。在PyTorch中,可以使用'torch.nn.L1Loss'实现绝对值损失。

尺寸要求:

以下是一个使用绝对值损失函数的简单示例:

import torch
import torch.nn as nn
# 模型输出
output = torch.randn(3, requires_grad=True)
# 目标值
target = torch.randn(3)
# 定义绝对值损失
criterion = nn.L1Loss()
# 计算损失
loss = criterion(output, target)
# 打印损失
print(loss.item())

在这个例子中,output是模型的输出,target是目标值。通过'nn.L1Loss()'定义了绝对值损失函数,然后计算了模型输出与目标之间的绝对值损失。注意:绝对值损失对异常值不敏感,因为它使用了绝对值,而不是平方,如果希望模型对异常值更加敏感可以考虑使用均方误差损失。

2、均方误差损失:

用于回归任务,度量模型输出与目标之间的平方差的平均值。

尺寸要求:

简单示例:

import torch
import torch.nn as nn

# 模型输出
output = torch.randn(3, requires_grad=True)
# 目标值
target = torch.randn(3)

# 定义均方误差损失
criterion = nn.MSELoss()

# 计算损失
loss = criterion(output, target)

# 打印损失
print(loss.item())

3、交叉熵损失:

用于多分类任务,结合了LogSoftmax 和 NLL Loss。

尺寸要求:

简单示例:

import torch
import torch.nn as nn

# 模型输出(类别概率)
output = torch.randn(3, 5, requires_grad=True)
# 目标类别
target = torch.randint(5, (3,))

# 定义交叉熵损失
criterion = nn.CrossEntropyLoss()

# 计算损失
loss = criterion(output, target)

# 打印损失
print(loss.item())

反向传播

反向传播是深度学习中用于计算梯度并更新模型参数的关键算法。在pytorch中,反向传播通过计算图的链式法则来实现,自动计算梯度并更新模型参数。

步骤:

1、前向传播:将输入数据通过模型进行前向计算,得到模型的预测输出。

2、计算损失:将模型的输出与目标值进行比较,计算损失函数的值。

3、反向传播:使用损失函数计算模型参数关于损失的梯度。

4、更新模型参数:使用梯度下降等优化算法,根据梯度更新模型参数。

示例代码:

import torch
import torch.nn as nn

# 定义一个简单的线性模型
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.linear = nn.Linear(1, 1)

    def forward(self, x):
        return self.linear(x)

# 创建模型实例和损失函数实例
model = SimpleModel()
criterion = nn.MSELoss()

# 随机生成输入数据和目标数据
input_data = torch.randn(5, 1, requires_grad=True)
target_data = torch.randn(5, 1)

# 前向传播
output = model(input_data)

# 计算损失
loss = criterion(output, target_data)

# 反向传播
loss.backward()

# 查看模型参数的梯度
print("模型参数的梯度:", model.linear.weight.grad)

# 手动更新模型参数,通常优化器会自动完成这个步骤
learning_rate = 0.01
with torch.no_grad():
    model.linear.weight -= learning_rate * model.linear.weight.grad

# 清零梯度,以便下一次反向传播
model.zero_grad()

# 查看更新后的模型参数
print("更新后的模型参数:", model.linear.weight)

优化器

在PyTorch中,优化器用于自动更新神经网络模型的参数,以最小化损失函数。优化器使用模型参数的梯度信息,通过梯度下降等算法来调整参数。以下是一些常用的优化器及其示例代码:

1、梯度下降优化器:

'torch.optim.SGD'

import torch
import torch.nn as nn
import torch.optim as optim

# 定义一个简单的线性模型
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.linear = nn.Linear(1, 1)

    def forward(self, x):
        return self.linear(x)

# 创建模型实例和损失函数实例
model = SimpleModel()
criterion = nn.MSELoss()

# 创建梯度下降优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 随机生成输入数据和目标数据
input_data = torch.randn(5, 1, requires_grad=True)
target_data = torch.randn(5, 1)

# 迭代训练
for epoch in range(100):
    # 前向传播
    output = model(input_data)

    # 计算损失
    loss = criterion(output, target_data)

    # 反向传播
    optimizer.zero_grad()  # 清零梯度
    loss.backward()  # 计算梯度
    optimizer.step()  # 更新模型参数

    # 打印每10轮迭代的损失
    if epoch % 10 == 0:
        print(f"Epoch {epoch}, Loss: {loss.item()}")

# 查看训练后的模型参数
print("训练后的模型参数:", model.linear.weight)

2、Adm优化器:

'torch.optim.Adm'

import torch
import torch.nn as nn
import torch.optim as optim

# 定义一个简单的线性模型
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.linear = nn.Linear(1, 1)

    def forward(self, x):
        return self.linear(x)

# 创建模型实例和损失函数实例
model = SimpleModel()
criterion = nn.MSELoss()

# 创建Adam优化器
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 随机生成输入数据和目标数据
input_data = torch.randn(5, 1, requires_grad=True)
target_data = torch.randn(5, 1)

# 迭代训练
for epoch in range(100):
    # 前向传播
    output = model(input_data)

    # 计算损失
    loss = criterion(output, target_data)

    # 反向传播
    optimizer.zero_grad()  # 清零梯度
    loss.backward()  # 计算梯度
    optimizer.step()  # 更新模型参数

    # 打印每10轮迭代的损失
    if epoch % 10 == 0:
        print(f"Epoch {epoch}, Loss: {loss.item()}")

# 查看训练后的模型参数
print("训练后的模型参数:", model.linear.weight)

  • 45
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值