深度学习 - 构建神经网络

1. 自动求导机制

概念解释

  • 自动求导:PyTorch的autograd模块允许我们自动计算张量的梯度,这在反向传播算法中尤为重要。反向传播是神经网络训练的核心,用于计算每个参数的梯度并更新参数。

生活中的例子

想象你是一个厨师,正在调整一个菜谱,使它更加美味。每次你改变一个配料的量,比如盐或糖,你都会尝试这个菜,然后根据味道的变化决定是否需要进一步调整。这就像在神经网络中计算梯度:你调整网络的参数(配料),观察输出(菜的味道),然后根据输出的变化来更新参数(调整配料)。

示例代码

import torch

x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
y = x + 2
z = y * y * 3
out = z.mean()

print("x:", x)
print("y:", y)
print("z:", z)
print("out:", out)

运行结果

x: tensor([1., 2., 3.], requires_grad=True)
y: tensor([3., 4., 5.], grad_fn=<AddBackward0>)
z: tensor([27., 48., 75.], grad_fn=<MulBackward0>)
out: tensor(50., grad_fn=<MeanBackward0>)

解释

  • requires_grad=True:表示我们需要计算x的梯度。
  • y = x + 2:对每个元素加2。
  • z = y * y * 3:每个元素先平方,再乘以3。
  • out = z.mean():计算张量的平均值。

计算图与梯度计算

out.backward()
print(x.grad)

运行结果

tensor([ 4.,  8., 12.])

解释out相对于x的梯度是4*x + 4

梯度计算公式

  1. y = x + 2 y = x + 2 y=x+2
  2. z = 3 y 2 z = 3y^2 z=3y2
  3. o u t = 1 3 ∑ z out = \frac{1}{3} \sum z out=31z

反向传播:

  1. ∂ o u t ∂ z i = 1 3 \frac{\partial out}{\partial z_i} = \frac{1}{3} ziout=31
  2. ∂ z i ∂ y i = 6 y i \frac{\partial z_i}{\partial y_i} = 6y_i yizi=6yi
  3. ∂ y i ∂ x i = 1 \frac{\partial y_i}{\partial x_i} = 1 xiyi=1

所以:

∂ o u t ∂ x i = 1 3 × 6 y i × 1 = 2 y i \frac{\partial out}{\partial x_i} = \frac{1}{3} \times 6y_i \times 1 = 2y_i xiout=31×6yi×1=2yi

y i = x i + 2 y_i = x_i + 2 yi=xi+2,所以:

∂ o u t ∂ x i = 2 ( x i + 2 ) \frac{\partial out}{\partial x_i} = 2(x_i + 2) xiout=2(xi+2)

x = [ 1 , 2 , 3 ] x = [1, 2, 3] x=[1,2,3] 时:

∂ o u t ∂ x = [ 4 , 8 , 12 ] \frac{\partial out}{\partial x} = [4, 8, 12] xout=[4,8,12]

torch.autograd.Variable

现在torch.Tensor已经取代了Variable,并且默认情况下所有张量都支持自动求导,所以Variable不再需要单独使用。

2. 构建简单神经网络

概念解释

  • 神经网络:神经网络是一种模仿人脑工作方式的计算模型。它由许多相互连接的“神经元”组成,每个神经元接收输入信号并产生输出信号。
  • nn.Module:是所有神经网络模块的基类。自定义的神经网络类需要继承nn.Module并实现其方法。

生活中的例子

想象你正在教一个机器人识别不同类型的水果。你给机器人看各种水果的图片,并告诉它们每个水果的名称。机器人通过观察这些图片并学习它们的特征(比如颜色、形状),逐渐学会区分不同的水果。这就像神经网络通过训练数据学习模式。

示例代码

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(784, 256)
        self.fc2 = nn.Linear(256, 10)

    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

net = Net()
print(net)

运行结果

Net(
  (fc1): Linear(in_features=784, out_features=256, bias=True)
  (fc2): Linear(in_features=256, out_features=10, bias=True)
)

解释

  • __init__方法中定义了两个全连接层(fc1fc2)。
  • forward方法定义了前向传播的过程,首先通过第一层,然后应用ReLU激活函数,最后通过第二层。

前向传播

input = torch.randn(1, 784)
output = net(input)
print(output)

运行结果

tensor([[ 0.0520,  0.2651,  0.0512, -0.1564, -0.2470, -0.2246,  0.0936, -0.2600,
          0.1607,  0.1467]], grad_fn=<AddmmBackward>)

解释:生成一个随机输入张量input,通过网络得到输出output

损失函数和优化器

概念解释

  • 损失函数:用来衡量模型输出与实际目标之间的差异。
  • 优化器:通过反向传播计算梯度并更新模型参数,以最小化损失函数。

生活中的例子

想象你在考试中答错了一些题目,老师告诉你哪些题目答错了,并给你一些建议。你根据这些建议修改你的学习方法,下次考试争取做得更好。损失函数就像老师的反馈,优化器就像你调整学习方法的过程。

示例代码

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)

# 示例训练步骤
optimizer.zero_grad()   # 清除梯度
output = net(input)     # 前向传播
loss = criterion(output, torch.tensor([1]))  # 计算损失
loss.backward()         # 反向传播
optimizer.step()        # 更新权重

解释

  • criterion:定义损失函数,这里使用交叉熵损失函数。
  • optimizer:定义优化器,这里使用随机梯度下降(SGD)。
  • optimizer.zero_grad():清除梯度。
  • output = net(input):前向传播。
  • loss = criterion(output, torch.tensor([1])):计算损失。
  • loss.backward():反向传播,计算梯度。
  • optimizer.step():更新权重。

3. 训练流程

概念解释

  • 数据加载与处理:使用torch.utils.data模块加载和处理数据。

生活中的例子

想象你在准备一个大餐,需要从市场购买食材。你需要将所有食材分成不同的类别,并按照菜谱中的要求进行处理和烹饪。数据加载和处理就像你从市场获取食材,并准备它们以便进一步使用。

示例代码

from torch.utils.data import DataLoader, TensorDataset

# 示例数据
inputs = torch.randn(100, 784)
targets = torch.randint(0, 10, (100,))

dataset = TensorDataset(inputs, targets)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

解释

  • inputstargets:生成示例数据。
  • TensorDataset:将输入和目标数据打包成数据集。
  • DataLoader:加载数据集,支持批处理和打乱数据。

定义模型、损失函数和优化器

net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)

解释:定义模型、损失函数和优化器。

训练循环

for epoch in range(2):  # 训练2个epoch
    for inputs, targets in dataloader:
        optimizer.zero_grad()   # 清除梯度
        outputs = net(inputs)   # 前向传播
        loss = criterion(outputs, targets)  # 计算损失
        loss.backward()         # 反向传播
        optimizer.step()        # 更新权重

    print(f"Epoch {epoch+1}, Loss: {loss.item()}")

**

运行结果**:

Epoch 1, Loss: 2.303864002227783
Epoch 2, Loss: 2.3021395206451416

解释:训练2个epoch,每个epoch中对每个批次数据进行前向传播、计算损失、反向传播和更新权重。

模型评估与验证

概念解释

  • 评估模式:在评估模式下,不计算梯度,节省内存和计算资源。

生活中的例子

想象你准备了一个大餐,现在邀请朋友来品尝。他们给你反馈,你记录这些反馈以便改进菜谱。这就像模型评估,你不再调整参数,而是观察模型在新数据上的表现。

示例代码

net.eval()  # 进入评估模式
with torch.no_grad():
    inputs = torch.randn(10, 784)
    outputs = net(inputs)
    predicted = torch.argmax(outputs, dim=1)
    print(predicted)

运行结果

tensor([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

解释

  • net.eval():将模型设置为评估模式。
  • torch.no_grad():禁用梯度计算,节省内存和计算资源。
  • predicted:预测的类别。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值