【pytorch基础】神经网络学习

概述

最近在研究Llama的源码,有很多pytorch相关的函数,由于对pytorch不是很熟悉,阅读源码有些困难,所以本文主要记录了自己在阅读llama源码过程中遇到的pytorch相关函数,通过查阅资料将自己不熟悉的函数作用和理解进行了说明。

通过本文的学习,你将对pytorch的一些函数有比较深入的了解并且对大模型的学习打下基础,后续将会介绍一下llama源码相关的内容。

pytorch函数说明

nn.Module

nn.Module的作用

在PyTorch中,nn.Module是构建神经网络模型的基类,它的作用是提供了一个模型组件的基本结构,使得用户可以方便地定义和管理神经网络模型。nn.Module的存在使得神经网络模型的构建更加模块化和易于组织,提供了许多方法和属性来方便地管理模型的参数、子模块等。

理解nn.Module

理解nn.Module可以看作是神经网络模型的基本组成单元,它可以包含模型的参数、定义前向传播方法等。通过继承nn.Module,用户可以定义自己的神经网络模型,并使用PyTorch提供的许多功能来管理模型。同时,nn.Module还提供了一种递归的方式来管理模型的子模块,使得复杂的神经网络结构可以被方便地构建和管理。

示例

以下是一个简单的示例,说明如何使用nn.Module来定义一个简单的神经网络模型:

python 复制代码
import torch
import torch.nn as nn
import torch.nn.functional as F

# 创建一个简单的全连接神经网络模型
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.fc1 = nn.Linear(10, 5)
        self.fc2 = nn.Linear(5, 2)

    def forward(self, x):
        x = F.relu(self.fc1(x))  # 使用激活函数
        print('使用relu激活函数:')
        print(x)
        x = self.fc2(x)
        return x

# 创建模型实例
model = MyModel()

# 使用模型进行前向传播
input_data = torch.rand(1, 10)  # 一个样本,10个特征
output = model(input_data)
print('输出内容:')
print(output)

# 输出结果如下:
# 使用relu激活函数:
# tensor([[0.5010, 0.4212, 0.0000, 0.0000, 0.3532]], grad_fn=<ReluBackward0>)
# 输出内容:
# tensor([[0.1825, 0.0719]], grad_fn=<AddmmBackward0>)

在这个示例中,我们创建了一个简单的全连接神经网络模型,并使用nn.Module定义了模型的结构和前向传播的方法。通过继承nn.Module,我们可以方便地管理模型的参数、定义前向传播方法,并使用PyTorch提供的许多功能来管理模型。

forward 方法

forward 方法是在 PyTorch 中用于定义模型的前向传播过程的方法。当我们构建一个自定义的神经网络模型时,需要继承 nn.Module 类并且实现 forward 方法。在这个方法中,我们定义了输入数据的传播过程,包括输入数据经过各个层的变换、激活函数的应用等。

理解 forward 方法的概念可以看作是定义了模型的计算流程。在 forward 方法中,我们描述了模型的结构以及如何将输入数据按照这个结构进行传递和变换,最终得到输出结果。在模型实例被调用时,PyTorch 将自动调用 forward 方法来执行模型的前向传播。

nn.Linear

nn.Linear的作用

在PyTorch中,nn.Linear是一个用于定义线性变换的模块,它通常用于构建神经网络的全连接层(也称为密集连接层或线性层)。

nn.Linear的作用是将输入数据进行线性变换,具体来说,对输入的每一行进行线性变换,将输入的特征值与权重相乘,再加上偏置项。其数学表达式为:y = xA^T + b

[{output} = {input} * {weight}^T + {bias} ]

其中,input为输入数据,weight为权重矩阵,bias为偏置项。在神经网络中,这个操作可以表示为将输入数据映射到输出空间的线性变换。

理解nn.Linear

在理解nn.Linear时,可以将其视为一个简单的模型,该模型接收输入数据,对输入数据进行加权求和,然后加上偏置项,最终得到输出。这个操作通常用于连接神经网络中的不同层,以便实现特征提取和变换。

示例

以下是一个示例,说明如何使用nn.Linear定义一个简单的全连接层:

python 复制代码
import torch
import torch.nn as nn

# 定义输入特征维度为5,输出特征维度为3的线性层
linear_layer = nn.Linear(5, 3)
print(linear_layer)
# 定义一个随机输入数据
input_data = torch.rand(2, 5)  # 2个样本,每个样本有5个特征
print(input_data)
# 将输入数据传入线性层进行线性变换
output = linear_layer(input_data)
print(output)

# 输出结果如下:
# Linear(in_features=5, out_features=3, bias=True)
# tensor([[0.2396, 0.1651, 0.2020, 0.6231, 0.2183],
#         [0.3458, 0.7107, 0.8589, 0.3148, 0.3530]])
# tensor([[-0.4772, -0.5004, -0.4116],
#         [-0.1266, -0.3313, -0.6919]], grad_fn=<AddmmBackward0>)

nn.Parameter

nn.Parameter的作用

在PyTorch中,nn.Parameter是Tensor的一个特殊类型,它被用于在神经网络的参数中进行标识。通常情况下,当在模型中定义需要学习的参数时,我们会使用nn.Parameter来创建可学习的张量。

nn.Parameter的主要作用是将张量包装成一个可训练的参数,并将其注册到模型参数中。这意味着,当使用优化器进行模型参数的优化时,nn.Parameter所包装的张量将被自动识别为需要学习的参数,并且会被优化器所更新。

理解nn.Parameter

理解nn.Parameter的概念可以看作是将张量包装成模型参数的一种约定和标识,这有助于将需要学习的参数与其他张量区分开来,更方便地进行参数优化和更新。

示例

下面是一个简单的示例,说明如何使用nn.Parameter定义一个可学习的参数:

python 复制代码
import torch
import torch.nn as nn

# 创建一个简单的模型
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        # 在模型中使用nn.Parameter定义可学习的权重参数
        self.weight = nn.Parameter(torch.rand(3, 3))  

    def forward(self, x):
        return torch.matmul(x, self.weight)

# 创建模型实例
model = SimpleModel()

# 输出模型参数
print(model.weight)

# 输出结果如下:
# Parameter containing:
# tensor([[0.5604, 0.1497, 0.5703],
#         [0.9534, 0.0289, 0.9364],
#         [0.3786, 0.0865, 0.2071]], requires_grad=True)

在上述示例中,我们使用nn.Parameter定义了一个可学习的权重参数,然后将其包装到一个简单的神经网络模型中。当优化器对模型进行参数优化时,模型中的nn.Parameter所包装的参数将被自动识别并更新。

nn.Dropout

nn.Dropout 的作用

在PyTorch中,nn.Dropout是一个用于防止过拟合的正则化技术,通常用于深度学习模型中。

它的作用是在模型训练过程中以一定的概率随机地将部分神经元的输出设置为0,从而减少神经元之间的依赖关系,防止过拟合。

理解nn.Dropout

理解nn.Dropout的概念可以看作是在训练过程中实施随机失活(dropout)操作,即在每个训练步骤中,以一定的概率随机地将部分神经元的输出置为0。这有助于模型对某些特定特征的依赖性降低,增加模型的泛化能力,减少过拟合的风险。

示例

下面是一个简单的示例,说明如何使用nn.Dropout将dropout层添加到一个神经网络模型中:

python 复制代码
import torch
import torch.nn as nn

# 创建一个带有dropout层的神经网络模型
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.fc1 = nn.Linear(10, 5)
        self.dropout = nn.Dropout(p=0.5)  # 添加一个dropout层,以概率0.5随机失活
        self.fc2 = nn.Linear(5, 2)

    def forward(self, x):
        x = self.fc1(x)
        x = self.dropout(x)  # 在全连接层的输出上应用dropout
        print('在全连接层的输出上应用dropout后的结果如下:')
        print(x)
        x = self.fc2(x)
        return x

# 创建模型实例
model = MyModel()

# 在模型中使用dropout层
input_data = torch.rand(1, 10)  # 一个样本,10个特征
output = model(input_data)
print('最后的结果:')
print(output)


# 输出结果如下:
# 在全连接层的输出上应用dropout后的结果如下:
# tensor([[ 0.8835, -0.3673,  0.0000, -0.0000,  0.0000]], grad_fn=<MulBackward0>)
# 最后的结果:
# tensor([[-0.8057,  0.3372]], grad_fn=<AddmmBackward0>)

在这个示例中,我们创建了一个简单的神经网络模型,并在模型中使用了nn.Dropout层,将dropout应用到全连接层的输出上。在模型训练过程中,dropout层将以概率0.5随机地将部分神经元的输出置为0,从而实现随机失活的效果。

nn.CrossEntropyLoss

nn.CrossEntropyLoss的作用

在PyTorch中,nn.CrossEntropyLoss 是用于多分类问题的损失函数。它结合了 softmax 函数和负对数似然损失(negative log likelihood loss) ,用于计算多分类问题中的损失值。通常情况下,对于多分类问题,模型的最后一层会使用 softmax 激活函数,将输出转换为表示类别概率的形式,而交叉熵损失函数是用来衡量模型输出的概率分布与实际标签之间的差异。

理解nn.CrossEntropyLoss

理解nn.CrossEntropyLoss可以看作是衡量模型输出的概率分布和实际标签之间的差异。它通过最大化正确标签的对数概率来最小化负对数似然损失,从而使模型更加关注于正确类别的分类概率。

示例

下面是一个简单的示例,说明了如何使用 nn.CrossEntropyLoss 损失函数:

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim

# 定义模型输出和实际标签
outputs = torch.tensor([[0.5, 0.1, 0.2], [0.3, 0.4, 0.3]])  # 模型输出,假设有3个类别
labels = torch.tensor([0, 2])  # 实际类别标签

# 使用 nn.CrossEntropyLoss 计算损失
crossEntropyLoss = nn.CrossEntropyLoss()
loss = crossEntropyLoss(outputs, labels)

print(loss)
# 输出结果:
# tensor(1.0066)

在这个示例中,我们创建了一个包含模型输出和实际标签的张量,并使用 nn.CrossEntropyLoss 计算了模型输出与实际标签之间的交叉熵损失。在训练神经网络时,通常会将这个损失值作为优化器的目标,并通过反向传播来更新模型参数,以便最小化损失值。

在实际计算中,nn.CrossEntropyLoss在内部会先进行softmax操作,然后计算负对数似然损失。如果模型的输出已经经过softmax操作,可以使用nn.NLLLoss(negative log likelihood loss)来计算负对数似然损失。

下面是一个简单的示例,说明了如何使用 nn.NLLLoss 损失函数来计算负对数似然损失:

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim

# 定义模型输出和实际标签
outputs = torch.tensor([[0.5, 0.1, 0.2], [0.3, 0.4, 0.3]])  # 模型输出,假设有3个类别
labels = torch.tensor([0, 2])  # 实际类别标签

log_softmax = nn.LogSoftmax(dim=1)
probs = log_softmax(outputs)
# 使用 nn.NLLLoss 计算负对数似然损失
nllloss = nn.NLLLoss()
loss = nllloss(probs, labels)

print(loss)
# 输出结果:
# tensor(1.0066)

可以看到计算nn.NLLLoss 损失时,先对模型输出进行softmax,然后nn.NLLLoss计算的结果和直接使用nn.CrossEntropyLoss计算的结果是一样的。


相关推荐
zopple3 小时前
常见的 Spring 项目目录结构
java·后端·spring
腾讯蓝鲸智云3 小时前
嘉为蓝鲸可观测系列产品入选Gartner《中国智能IT监控与日志分析工具市场指南》
运维·人工智能·信息可视化·自动化
LaughingZhu3 小时前
Product Hunt 每日热榜 | 2026-03-25
人工智能·经验分享·深度学习·神经网络·产品运营
蟑螂恶霸4 小时前
Windows安装OpenCV 4.8
人工智能·windows·opencv
枫叶林FYL4 小时前
【自然语言处理 NLP】第二章 经典NLP算法与特征工程(Classical NLP Algorithms)
人工智能·深度学习·机器学习
非著名程序员4 小时前
阿里云重磅上线 Qoder 专家团模式,AI 编程进入组团作战时代
人工智能
cjy0001115 小时前
springboot的 nacos 配置获取不到导致启动失败及日志不输出问题
java·spring boot·后端
AEIC学术交流中心5 小时前
【快速EI检索 | IEEE出版】2026年人工智能、智能系统与信息安全国际学术会议(AISIS 2026)
人工智能
火山引擎开发者社区5 小时前
李诞、何同学、小Lin说同台直播,解锁养虾新玩法!
人工智能
小江的记录本5 小时前
【事务】Spring Framework核心——事务管理:ACID特性、隔离级别、传播行为、@Transactional底层原理、失效场景
java·数据库·分布式·后端·sql·spring·面试