pytorch开发基础 实操用torch.nn构建神经网络(附代码

PyTorch的 torch.nn 是构建神经网络的核心工具,提供了各类“层”来搭建深度学习模型

一、pytorch内置模块

1、核心组件

  • Layers(层):包含预定义的神经网络层,如 nn.Linear (全连接层)、 nn.Conv2d (卷积层)、 nn.MaxPool2d (池化层)、 nn.ReLU (激活层)等。每个层自带可学习的权重/偏差参数,调用时接收输入数据。
  • Loss Functions(损失函数):提供常用损失计算函数,如 nn.MSELoss (均方误差,回归任务)、 nn.CrossEntropyLoss (交叉熵,分类任务)等,用于计算预测与真实值的差距,辅助参数更新。
  • Utilities(工具):包含模型构建工具,如 nn.Sequential (按顺序组合多个层)、 nn.Module (所有网络模块的基类,用于自定义层/模型)。
  • Normalization/Regularization Layers(归一化/正则化层):如 nn.Dropout (防止过拟合)、 nn.BatchNorm1d/2d (批量归一化,提升模型性能)。
  • Activation Functions(激活函数):如 nn.Sigmoid 、 nn.Tanh 、 nn.Softmax 等,用于引入非线性,让模型学习复杂模式。

2、nn.Linear层

nn.Linear 是全连接层/线性层,用于构建网络的线性部分,构造函数需指定两个参数:

  • in_features :输入特征数
  • out_features :输出特征数

计算公式

y=xAT+b y = xA^T + b y=xAT+b
其中:

  • x:输入张量,形状为 (batch_size, input_features)
  • A:权重矩阵,形状为 (input_features, output_features)
  • b:偏差向量,形状为 (output_features, )

示例代码

import torch
import torch.nn as nn

#创建线性层,输入特征数为3,输出特征数为2,即纬度
linear_layer = nn.Linear(3,2)

#输入样本
inputs = torch.tensor([[1.0,2.0,3.0],[4.0,5.0,6.0]])

#传入值给线性层向前计算
outputs = linear_layer(inputs)
print(outputs)
#输出:形状为(2,2),包含2个样本的2个输出特征

3、nn.Sigmoid激活函数

nn.Sigmoid 是将任意实数映射到0~1范围的激活函数,数学表达式为:
sigmoid(x)=1/(1+exp⁡(−x)) \text{sigmoid}(x) = 1 / (1 + \exp(-x)) sigmoid(x)=1/(1+exp(x))

常用于:

  • 隐藏层引入非线性
  • 二分类任务的输出层(将结果映射为概率)

示例代码

import torch
import torch.nn as nn
# 输入张量
x = torch.tensor([2.0, -1.0, 0.5])
# 定义Sigmoid激活函数
sigmoid = nn.Sigmoid()
# 前向计算
output = sigmoid(x)
print(output)
# 输出:tensor([0.8808, 0.2689, 0.6225])

4、nn.BCELoss损失函数

nn.BCELoss 是二元交叉熵损失函数,用于二分类问题,计算模型输出(概率)与真实标签的差异。

注意事项

  • 输入 output 需是0~1的概率值(通常由Sigmoid输出)
  • output 与 target 形状需一致
  • 可使用 BCEWithLogitsLoss (内部自动结合Sigmoid)替代

示例代码

import torch
import torch.nn as nn

# 创建BCELoss对象
criterion = nn.BCELoss()
# 模型输出(样本属于正类的概率)
output = torch.tensor([0.8, 0.2, 0.4])
# 真实标签(1=正类,0=负类)
target = torch.tensor([1, 0, 1], dtype=torch.float32)
# 计算损失
loss = criterion(output, target)
print(loss)
# 输出:tensor(0.4542)

二、torch.optim优化器

torch.optim 是PyTorch中实现优化算法的模块,用于在模型训练中更新参数以最小化损失函数,核心是 Optimizer 基类(所有优化器的父类)。

1、核心功能

  • 接收模型参数的可迭代对象作为输入
  • 支持配置学习率调度、权重衰减等行为

2、常见优化器

  1. SGD优化器:最基础的优化器,根据每个样本的梯度更新模型参数。
  2. Adam优化器:结合AdaGrad和RMSProp思想的自适应学习率优化器,根据梯度的一阶矩、二阶矩估计更新参数,常用于Transformer等模型训练。
  3. torch.optim 提供学习率调度工具,可根据训练进度动态调整学习率,提升训练效果。
    接下来的实操构建神经网络阶段会用到

三、训练、验证和测试过程

在PyTorch中,通常将数据集划分为训练集、验证集、测试集,分别用于训练模型、调整参数、评估性能,流程如下:

1、数据预处理

对数据进行归一化、计算均值/标准差等处理,再划分成训练集、验证集、测试集。

2、定义模型

通过继承 torch.nn.Module 类,实现 init (定义层)和 forward (前向传播)方法,构建模型架构。

3、定义损失函数和优化器

  • 损失函数:使用PyTorch内置函数(如 nn.CrossEntropyLoss 分类任务、 nn.MSELoss 回归任务)。
  • 优化器:选择合适的优化器(如 torch.optim.SGD 、 torch.optim.Adam ),传入模型参数与学习率。

用法:

loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

4、训练模型(核心步骤)

训练过程在主循环中执行,每个训练批次包含以下步骤:

  1. 清空梯度:调用 optimizer.zero_grad() 清空之前的梯度(避免累积)。
  2. 正向传播:输入数据到模型,调用 forward 计算预测值: output = model(input) 。
  3. 计算损失:将预测值与真实标签传入损失函数: loss = loss_fn(output, target) 。
  4. 反向传播:调用 loss.backward() 计算参数梯度。
  5. 更新权重:调用 optimizer.step() 根据梯度更新模型参数。

5、验证模型

每个训练周期结束后,在验证集上测试模型,检查是否过拟合,并调整超参数(如学习率)优化模型。

6、测试模型

训练、验证完成后,在未参与训练/验证的测试集上评估模型性能,得到公正的最终结果。

7、保存和加载模型

使用 torch.save 保存模型, torch.load 加载模型,便于后续预测或继续训练。

四、用PyTorch实现神经网络(实操)

1、实现单层感知机

通过 torch.nn.Module 自定义单层感知机,实现二分类任务。

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

# 定义感知机模型
class Perceptron(nn.Module):
    #继承父类nn.Module
    def __init__(self, input_size):
        super(Perceptron, self).__init__()#继承父类
        self.linear = nn.Linear(input_size, 1)  # 继承父类的线性层函数
        self.sigmoid = nn.Sigmoid()  # 继承父类Sigmoid激活函数

    def forward(self, x):
        out = self.linear(x)
        out = self.sigmoid(out)
        return out

# 定义输入数据
X = torch.tensor([[0, 1], [1, 0], [1, 1], [0, 0]], dtype=torch.float32)
y = torch.tensor([[1], [1], [0], [0]], dtype=torch.float32)

# 初始化模型
input_size = X.shape[1]
model = Perceptron(input_size)
print(model)

# 定义优化器和损失函数
criterion = nn.BCELoss()  # 二分类交叉熵损失
optimizer = optim.SGD(model.parameters(), lr=0.1)  # SGD优化器

# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):
    # 前向传播
    outputs = model(X)
    loss = criterion(outputs, y)

    # 反向传播和优化
    optimizer.zero_grad()  # 梯度清零
    loss.backward()        # 反向传播
    optimizer.step()       # 更新参数

    # 每100个epoch打印一次损失
    if (epoch+1) % 100 == 0:
        print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))

# 测试模型
with torch.no_grad():  # 禁用梯度计算
    predicted = model(X)
    predicted = torch.round(predicted)  # 输出舍入为0或1
    accuracy = (predicted == y).sum().item() / y.size(0)
    print('Accuracy: {:.2f}%'.format(accuracy * 100))

运行结果

Epoch [200/1000], Loss: 0.6935
Epoch [300/1000], Loss: 0.6933
Epoch [400/1000], Loss: 0.6932
Epoch [500/1000], Loss: 0.6932
Epoch [600/1000], Loss: 0.6932
Epoch [700/1000], Loss: 0.6932
Epoch [800/1000], Loss: 0.6931
Epoch [900/1000], Loss: 0.6931
Epoch [1000/1000], Loss: 0.6931
Accuracy: 25.00%

从这个结果能看出,模型准确率仅 25%,但核心问题是感知机的线性局限性—— 异或问题本身线性不可分,单层感知机无论怎么训练,都无法找到能正确分割所有样本的线性边界,最终只能随机猜测,所以需要多层感知机(神经网络的子集)来解决

2、手动实现简单神经网络(含前向/反向传播)

自定义神经网络类,手动实现前向传播、反向传播和参数更新。

代码实现

import torch

class PyTorchNeuralNetwork:#定义神经网络类
    def __init__(self, input_size, hidden_size, output_size):
        #初始化神经网络参数
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.output_size = output_size

        # 初始化权重和偏置(requires_grad=True表示需要计算梯度)
        self.W1 = torch.randn(self.input_size, self.hidden_size, requires_grad=True)#符合正态分布的初始参数
        self.b1 = torch.zeros(1, self.hidden_size, requires_grad=True)
        self.W2 = torch.randn(self.hidden_size, self.output_size, requires_grad=True)
        self.b2 = torch.zeros(1, self.output_size, requires_grad=True)

    def forward(self, X):
        # 前向传播
        self.z1 = torch.mm(X, self.W1) + self.b1#线性层
        self.a1 = torch.tanh(self.z1)  # 隐藏层激活函数(tanh)
        self.z2 = torch.mm(self.a1, self.W2) + self.b2
        self.a2 = torch.sigmoid(self.z2)  # 输出层激活函数(Sigmoid)
        return self.a2

    def backward(self, X, y, learning_rate):
        #反向传播
        m = X.shape[0]  # 样本数量

        # 计算输出层的误差
        #代码用 MSE(均方误差)处理

        dz2 = self.a2 - y
        dW2 = (1/m) * torch.mm(self.a1.T, dz2)
        db2 = (1/m) * torch.sum(dz2, dim=0, keepdim=True)

        # 计算隐藏层的误差
        dz1 = torch.mm(dz2, self.W2.T) * (1 - self.a1**2)
        dW1 = (1/m) * torch.mm(X.T, dz1)
        db1 = (1/m) * torch.sum(dz1, dim=0)

        # 更新权重和偏置
        self.W2.data -= learning_rate * dW2
        self.b2.data -= learning_rate * db2
        self.W1.data -= learning_rate * dW1
        self.b1.data -= learning_rate * db1

    def train(self, X, y, epochs, learning_rate):
        for epoch in range(epochs):
            # 前向传播
            output = self.forward(X)
            # 反向传播
            self.backward(X, y, learning_rate)
            # 计算损失(均方误差)
            loss = torch.mean((y - output) ** 2)
            # 每1000个epoch打印一次损失
            if epoch % 1000 == 0:
                print(f"Epoch {epoch}: Loss = {loss.item()}")
                # Sigmoid函数(也可直接用torch.sigmoid)

    def sigmoid(self, x):
        return 1 / (1 + torch.exp(-x))


# 实例化模型并训练
input_size = 15
hidden_size = 10
output_size = 5
pytorch_nn = PyTorchNeuralNetwork(input_size, hidden_size, output_size)

# 生成训练数据
X = torch.randn(100, input_size)
y = torch.randint(0, 2, size=(100, output_size), dtype=torch.float32)

# 训练参数
epochs = 10000
#基于随机权重比较合适的学习率,实际情况需要自行调整
learning_rate = 0.3

# 训练模型
pytorch_nn.train(X, y, epochs, learning_rate)

# 预测示例
input_data_torch = torch.randn(1, input_size)
output_torch = pytorch_nn.forward(input_data_torch)
print("预测结果:", output_torch)

我做了比较详细的注释,供参考学习

原代码会输出类似下文的内容
由于权重和偏置是随机数,所以预测内容和损失不确定,但都会随着迭代次数增多逐渐下降

Epoch 0: Loss = 0.36677706241607666
Epoch 1000: Loss = 0.08712747693061829
Epoch 2000: Loss = 0.0615965873003006
Epoch 3000: Loss = 0.05042863264679909
Epoch 4000: Loss = 0.04471873864531517
Epoch 5000: Loss = 0.04120061919093132
Epoch 6000: Loss = 0.03878163546323776
Epoch 7000: Loss = 0.03701581060886383
Epoch 8000: Loss = 0.03556859865784645
Epoch 9000: Loss = 0.03432784229516983
预测结果: tensor([[2.6203e-08, 1.4003e-12, 1.0000e+00, 9.9853e-01, 2.1654e-09]],
       grad_fn=<SigmoidBackward0>)

可见模型损失函数逐渐变小,且训练后预测了结果

3、用torch.nn实现简单神经网络

通过PyTorch构建用于行业云服务用量分类的神经网络模型,包含模型定义、训练、评估全流程。

  1. 导入依赖依赖库
import torch
import torch.nn as nn
import torch.optim as optim

#使用了torch.nn内置函数,例如线性层Linear,ReLU激活函数等
#定义云服务用量预测模型
class CloudServiceUsageModel(nn.Module):
    def __init__(self, input_size, hidden_size, num_classes):
        super(CloudServiceUsageModel, self).__init__()#继承父类初始化
        #输入层→隐藏层(线性层+ReLU激活)
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        #隐藏层→输出层(线性层)
        self.fc2 = nn.Linear(hidden_size, num_classes)

    def forward(self, x):
        #前向传播
        out = self.fc1(x)#隐藏层线性层
        out = self.relu(out)#隐藏层非线性层
        out = self.fc2(out)#到输出层
        return out
 
#准备数据
input_size = 10    #输入特征维度
hidden_size = 5    #隐藏层神经元数
num_classes = 2    #分类类别数
learning_rate = 0.001#学习率,可根据情况自行调整
num_epochs = 1500   #训练轮数
 
  
#生成示例数据(100条样本)
X = torch.randn(100, input_size)#符合正态分布的随机数据
Y = torch.randint(0, num_classes, (100,))  #随机生成标签

#划分训练集(80%)和测试集(20%)
train_size = int(0.8 * len(X))
train_X, test_X = X[:train_size], X[train_size:]#切片
train_Y, test_Y = Y[:train_size], Y[train_size:]
 

#初始化模型,即实例化
model = CloudServiceUsageModel(input_size, hidden_size, num_classes)
#损失函数:交叉熵损失(适用于分类任务)
criterion = nn.CrossEntropyLoss()
#优化器:Adam
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
 
  
for epoch in range(num_epochs):
    #前向传播:计算预测值
    outputs = model(train_X)
    #计算损失
    loss = criterion(outputs, train_Y)

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

    #每10轮打印训练信息
    if (epoch + 1) % 100 == 0:
        print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss.item()}')#格式化字符串打印输出

with torch.no_grad():  #评估阶段不计算梯度,用with避免意外修改模型参数
    outputs = model(test_X)
    #使用”_“ 接收max第一个返回值,但忽略无关数据,如第一个返回值
    _, predicted = torch.max(outputs.data, 1)  #取预测概率最大的类别
    #计算测试集准确率
    accuracy = (predicted == test_Y).sum().item() / len(test_Y)
    print(f'Test Accuracy: {accuracy}')


这里使用的学习率和迭代次数可以自行修改,如果迭代次数过大会过拟合损失函数很小,但是准确率低,比如:

Epoch 2000/10000, Loss: 0.11056555807590485
Epoch 3000/10000, Loss: 0.047184959053993225
Epoch 4000/10000, Loss: 0.018245236948132515
Epoch 5000/10000, Loss: 0.007836421951651573
Epoch 6000/10000, Loss: 0.0035645291209220886
Epoch 7000/10000, Loss: 0.00182446651160717
Epoch 8000/10000, Loss: 0.0007243022555485368
Epoch 9000/10000, Loss: 0.0003837581316474825
Epoch 10000/10000, Loss: 0.0002305546950083226
Test Accuracy: 0.35

如果学习率小,迭代次数少就会欠拟合,完全没找到规律,比如损失函数很大,准确率也低:

Epoch 10/100, Loss: 0.7022197842597961
Epoch 20/100, Loss: 0.6955064535140991
Epoch 30/100, Loss: 0.6891571879386902
Epoch 40/100, Loss: 0.6826779246330261
Epoch 50/100, Loss: 0.6764296889305115
Epoch 60/100, Loss: 0.6703445315361023
Epoch 70/100, Loss: 0.6642844080924988
Epoch 80/100, Loss: 0.6579297184944153
Epoch 90/100, Loss: 0.6512966752052307
Epoch 100/100, Loss: 0.6450014710426331
Test Accuracy: 0.25

如果按照上文代码参数,应该是类似下文的输出

Epoch 700/1500, Loss: 0.3329385221004486
Epoch 800/1500, Loss: 0.3078838884830475
Epoch 900/1500, Loss: 0.28730684518814087
Epoch 1000/1500, Loss: 0.2641219198703766
Epoch 1100/1500, Loss: 0.24512812495231628
Epoch 1200/1500, Loss: 0.22094109654426575
Epoch 1300/1500, Loss: 0.20565827190876007
Epoch 1400/1500, Loss: 0.1938382387161255
Epoch 1500/1500, Loss: 0.1839798539876938
Test Accuracy: 0.6

这样我们就基于随机数据和torch.nn完成了一个简易神经网络啦,是不是很神奇呢喵~

五、源代码常用模块

后续代码中高频使用的工具模块,提前介绍便于快速理解。

1、nn.Parameter 类

PyTorch中标记需优化参数的核心类,作用:

  1. 标记可优化参数:将张量包装为 nn.Parameter 后,会被自动加入模型的 parameters() 列表,供优化器更新。
  2. 参数管理:支持访问/修改参数的数值、形状、设备等信息。

示例:

weight = nn.Parameter(torch.ones(dim))  # 将张量标记为可优化参数

2、typing 模块

Python 3.5+引入的类型提示工具,用于静态类型检查、增强代码可读性。

  1. 核心作用
  • 避免运行时参数/返回值类型不匹配;
  • 作为代码文档,明确入参/返回值类型;
  • 仅提示,不影响程序运行。
  1. 常用类型
类型 说明
int/long/float 整数/长整型/浮点型
bool/str 布尔型/字符串类型
List/Tuple/Dict/Set 列表/元组/字典/集合
Iterable/Iterator 可迭代/迭代器类型
Generator 生成器类型
  1. 特殊类型
  • Any :任意类型(跳过类型检查);
  • Optional[T] :可选类型( T 或 None );
  • TypedDict :类型化字典(指定键值对的类型)。

3、logging 模块

Python标准库的日志管理工具,用于记录程序运行信息(替代 print ,更灵活可控)。

  1. 日志级别(从低到高)

debug (调试信息)、 info (运行信息)、 warning (警告)、 error (错误)、 critical (严重错误)。

  • 示例:设置级别为 warning 时,仅输出 warning/error/critical 级别的日志。
  1. 核心功能
  • 多目标输出:日志可输出到控制台、文件、网络等;
  • 自定义格式:支持添加日期、时间、日志级别等;
  • 日志回滚:自动切割/备份超大日志文件;
  • 多线程安全:支持多线程环境下的日志记录;
  • 配置文件管理:日志配置与代码解耦。
  1. 常用函数示例
import logging

# 基础配置(级别、格式)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()  # 获取logger对象

# 输出不同级别日志
logger.debug("调试信息")
logger.info("Reloaded model from ./model")  # 示例输出:INFO:root:Reloaded model...
logger.warning("警告信息")
logger.error("错误信息")
logger.exception("带堆栈的错误信息")  # 自动记录异常堆栈

4、dataclasses 模块

Python 3.7+引入的数据类工具,通过装饰器 @dataclass 简化数据类的定义(自动生成 init / repr 等方法)。

  1. 核心特点
  • 自动生成方法: init (初始化)、 repr (打印)、 eq (比较)等;
  • 类型提示:支持定义属性的类型;
  • 不可变性:指定 frozen=True 可创建不可变数据类;
  • 继承性:支持继承其他数据类。
  1. 示例
from dataclasses import dataclass
@dataclass
class Person:
    name: str    # 字符串类型
    age: int     # 整数类型
    profession: str  # 职业类型

# 自动生成__init__,直接实例化
p = Person(name="Alice", age=25, profession="Engineer")
print(p) 
# 自动生成__repr__:Person(name='Alice', age=25, profession='Engineer')

5、Fire 模块

Python的命令行接口(CLI)生成工具,自动将Python对象(函数/类)转换为命令行工具(无需手动解析参数)。

  1. 核心功能
  • 自动生成CLI:函数/类直接转为命令行接口;
  • 子命令支持:多函数/方法自动转为子命令;
  • 自动生成帮助文档: --help 查看参数说明;
  • 动态类型转换:命令行输入自动转为Python类型;
  • 直接调用任意Python对象:函数、类、库等。
  1. 示例对比

使用 Fire (简洁)

import fire

def greet(name="World"):
	print(f"Hello, {name}!")
	
if __name__== "__main__":
	fire.Fire()

不使用 Fire (手动解析)

import argparse

def greet(name="World"):
	print(f"Hello, {name}!")

if __name__ == "__main__":
	parser = argparse.ArgumentParser()
	parser.add_argument("-name", type=str,default="World")
	args = parser.parse_args()
	greet(args.name)
	
  1. 命令行调用
# 使用Fire的情况:直接传参
python script.py --name Alice
# 输出:Hello, Alice!

# 查看帮助文档
python script.py --help

以上就是全部内容啦,如果觉得神经网络很好玩,内容很有意思的话,别忘了关注,赏点小鱼干喵

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐