用 PyTorch 构建神经网络的 12 个实战案例

开发 人工智能
本文通过12个实战案例,详细介绍了如何使用PyTorch构建各种类型的神经网络模型,每个案例都提供了详细的代码示例和解释。

用PyTorch构建神经网络是机器学习领域中非常热门的话题。PyTorch因其易用性和灵活性而受到广大开发者的喜爱。本文将通过12个实战案例,带你从零开始构建神经网络,逐步掌握PyTorch的核心概念和高级技巧。

案例1:简单的线性回归模型

目标:使用PyTorch构建一个简单的线性回归模型。

代码示例:

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

# 定义数据
X = torch.tensor([[1.0], [2.0], [3.0], [4.0]])
y = torch.tensor([[2.0], [4.0], [6.0], [8.0]])

# 定义模型
class LinearRegressionModel(nn.Module):
    def __init__(self):
        super(LinearRegressionModel, self).__init__()
        self.linear = nn.Linear(1, 1)

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

model = LinearRegressionModel()

# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    predicted = model(X)
    print(predicted)

解释:

  • nn.Linear(1, 1):定义了一个线性层,输入特征为1,输出也为1。
  • nn.MSELoss():均方误差损失函数。
  • optim.SGD(model.parameters(), lr=0.01):随机梯度下降优化器,学习率为0.01。
  • model.train() 和 model.eval():分别用于训练模式和评估模式。

案例2:逻辑回归模型

目标:使用PyTorch构建一个逻辑回归模型。

代码示例:

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

# 定义数据
X = torch.tensor([[1.0, 2.0], [2.0, 3.0], [3.0, 1.0], [4.0, 3.0]])
y = torch.tensor([0, 0, 1, 1])

# 定义模型
class LogisticRegressionModel(nn.Module):
    def __init__(self):
        super(LogisticRegressionModel, self).__init__()
        self.linear = nn.Linear(2, 1)
        self.sigmoid = nn.Sigmoid()

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

model = LogisticRegressionModel()

# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X).squeeze()
    loss = criterion(outputs, y.float())
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    predicted = (model(X) > 0.5).float()
    print(predicted)

解释:

  • nn.Sigmoid():Sigmoid激活函数,用于将输出转换为概率值。
  • nn.BCELoss():二元交叉熵损失函数,适用于二分类问题。
  • outputs.squeeze():去除输出张量中的单维度条目。

案例3:多层感知机(MLP)

目标:使用PyTorch构建一个多层感知机(MLP)模型。

代码示例:

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

# 定义数据
X = torch.randn(100, 10)
y = torch.randint(0, 2, (100,))

# 定义模型
class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()
        self.fc1 = nn.Linear(10, 5)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(5, 2)
        self.softmax = nn.Softmax(dim=1)

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

model = MLP()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 100
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    predicted = torch.argmax(model(X), dim=1)
    print(predicted)

解释:

  • nn.ReLU():ReLU激活函数,用于引入非线性。
  • nn.CrossEntropyLoss():交叉熵损失函数,适用于多分类问题。
  • torch.argmax(model(X), dim=1):获取每个样本的最大概率对应的类别索引。

案例4:卷积神经网络(CNN)

目标:使用PyTorch构建一个卷积神经网络(CNN)模型。

代码示例:

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

# 定义数据
X = torch.randn(100, 1, 28, 28)
y = torch.randint(0, 10, (100,))

# 定义模型
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
        self.fc1 = nn.Linear(16 * 14 * 14, 128)
        self.fc2 = nn.Linear(128, 10)
        self.relu = nn.ReLU()

    def forward(self, x):
        out = self.conv1(x)
        out = self.relu(out)
        out = self.pool(out)
        out = out.view(-1, 16 * 14 * 14)
        out = self.fc1(out)
        out = self.relu(out)
        out = self.fc2(out)
        return out

model = CNN()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    predicted = torch.argmax(model(X), dim=1)
    print(predicted)

解释:

  • nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1):定义一个卷积层,输入通道为1,输出通道为16,卷积核大小为3x3,步幅为1,填充为1。
  • nn.MaxPool2d(kernel_size=2, stride=2, padding=0):最大池化层,池化窗口大小为2x2,步幅为2。
  • out.view(-1, 16 * 14 * 14):将卷积层的输出展平为一维向量。

案例5:循环神经网络(RNN)

目标:使用PyTorch构建一个循环神经网络(RNN)模型。

代码示例:

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

# 定义数据
X = torch.randn(100, 10, 50)  # (batch_size, sequence_length, input_size)
y = torch.randint(0, 10, (100,))

# 定义模型
class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, num_classes):
        super(RNN, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, num_classes)

    def forward(self, x):
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        out, _ = self.rnn(x, h0)
        out = self.fc(out[:, -1, :])
        return out

model = RNN(input_size=50, hidden_size=128, num_layers=2, num_classes=10)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    predicted = torch.argmax(model(X), dim=1)
    print(predicted)

解释:

  • nn.RNN(input_size, hidden_size, num_layers, batch_first=True):定义一个RNN层,输入大小为50,隐藏层大小为128,层数为2,batch_first=True表示输入数据的第一个维度是batch大小。
  • h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device):初始化隐藏状态。
  • out[:, -1, :]:取最后一个时间步的输出。

案例6:长短时记忆网络(LSTM)

目标:使用PyTorch构建一个长短时记忆网络(LSTM)模型。

代码示例:

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

# 定义数据
X = torch.randn(100, 10, 50)  # (batch_size, sequence_length, input_size)
y = torch.randint(0, 10, (100,))

# 定义模型
class LSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, num_classes):
        super(LSTM, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, num_classes)

    def forward(self, x):
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        out, _ = self.lstm(x, (h0, c0))
        out = self.fc(out[:, -1, :])
        return out

model = LSTM(input_size=50, hidden_size=128, num_layers=2, num_classes=10)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    predicted = torch.argmax(model(X), dim=1)
    print(predicted)

解释:

  • nn.LSTM(input_size, hidden_size, num_layers, batch_first=True):定义一个LSTM层,输入大小为50,隐藏层大小为128,层数为2,batch_first=True表示输入数据的第一个维度是batch大小。
  • c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device):初始化细胞状态。

案例7:门控循环单元(GRU)

目标:使用PyTorch构建一个门控循环单元(GRU)模型。

代码示例:

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

# 定义数据
X = torch.randn(100, 10, 50)  # (batch_size, sequence_length, input_size)
y = torch.randint(0, 10, (100,))

# 定义模型
class GRU(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, num_classes):
        super(GRU, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.gru = nn.GRU(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, num_classes)

    def forward(self, x):
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        out, _ = self.gru(x, h0)
        out = self.fc(out[:, -1, :])
        return out

model = GRU(input_size=50, hidden_size=128, num_layers=2, num_classes=10)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    predicted = torch.argmax(model(X), dim=1)
    print(predicted)

解释:

  • nn.GRU(input_size, hidden_size, num_layers, batch_first=True):定义一个GRU层,输入大小为50,隐藏层大小为128,层数为2,batch_first=True表示输入数据的第一个维度是batch大小。

案例8:残差网络(ResNet)

目标:使用PyTorch构建一个残差网络(ResNet)模型。

代码示例:

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

# 定义数据
X = torch.randn(100, 3, 32, 32)
y = torch.randint(0, 10, (100,))

# 定义残差块
class ResidualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        super(ResidualBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1)
        self.bn2 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU()
        self.shortcut = nn.Sequential()
        if stride != 1 or in_channels != out_channels:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride),
                nn.BatchNorm2d(out_channels)
            )

    def forward(self, x):
        out = self.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out += self.shortcut(x)
        out = self.relu(out)
        return out

# 定义模型
class ResNet(nn.Module):
    def __init__(self, block, num_blocks, num_classes=10):
        super(ResNet, self).__init__()
        self.in_channels = 64
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1)
        self.bn1 = nn.BatchNorm2d(64)
        self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
        self.linear = nn.Linear(512, num_classes)
        self.relu = nn.ReLU()

    def _make_layer(self, block, out_channels, num_blocks, stride):
        strides = [stride] + [1] * (num_blocks - 1)
        layers = []
        for stride in strides:
            layers.append(block(self.in_channels, out_channels, stride))
            self.in_channels = out_channels
        return nn.Sequential(*layers)

    def forward(self, x):
        out = self.relu(self.bn1(self.conv1(x)))
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = nn.functional.avg_pool2d(out, 4)
        out = out.view(out.size(0), -1)
        out = self.linear(out)
        return out

model = ResNet(ResidualBlock, [2, 2, 2, 2])

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    predicted = torch.argmax(model(X), dim=1)
    print(predicted)

解释:

  • ResidualBlock:定义一个残差块,包含两个卷积层和一个跳跃连接。
  • _make_layer:构建多个残差块的层。
  • nn.functional.avg_pool2d(out, 4):全局平均池化层。

案例9:卷积自编码器(Convolutional Autoencoder)

目标:使用PyTorch构建一个卷积自编码器模型。

代码示例:

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

# 定义数据
X = torch.randn(100, 1, 28, 28)

# 定义模型
class ConvAutoencoder(nn.Module):
    def __init__(self):
        super(ConvAutoencoder, self).__init__()
        # 编码器
        self.encoder = nn.Sequential(
            nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1),
            nn.ReLU(),
            nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1),
            nn.ReLU(),
            nn.Conv2d(32, 64, kernel_size=7)
        )
        # 解码器
        self.decoder = nn.Sequential(
            nn.ConvTranspose2d(64, 32, kernel_size=7),
            nn.ReLU(),
            nn.ConvTranspose2d(32, 16, kernel_size=3, stride=2, padding=1, output_padding=1),
            nn.ReLU(),
            nn.ConvTranspose2d(16, 1, kernel_size=3, stride=2, padding=1, output_padding=1),
            nn.Sigmoid()
        )

    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded

model = ConvAutoencoder()

# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X)
    loss = criterion(outputs, X)
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    reconstructed = model(X)
    print(reconstructed)

解释:

  • nn.Conv2d 和 nn.ConvTranspose2d:分别用于编码器和解码器中的卷积和反卷积操作。
  • nn.Sigmoid():用于将解码器的输出限制在0到1之间。

案例10:变分自编码器(Variational Autoencoder, VAE)

目标:使用PyTorch构建一个变分自编码器模型。

代码示例:

import torch
import torch.nn as nn
import torch.optim as optim
from torch.distributions import Normal

# 定义数据
X = torch.randn(100, 1, 28, 28)

# 定义模型
class VAE(nn.Module):
    def __init__(self, latent_dim):
        super(VAE, self).__init__()
        self.latent_dim = latent_dim
        # 编码器
        self.encoder = nn.Sequential(
            nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1),
            nn.ReLU(),
            nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1),
            nn.ReLU(),
            nn.Flatten(),
            nn.Linear(32 * 7 * 7, 256),
            nn.ReLU()
        )
        self.fc_mu = nn.Linear(256, latent_dim)
        self.fc_logvar = nn.Linear(256, latent_dim)
        # 解码器
        self.decoder = nn.Sequential(
            nn.Linear(latent_dim, 256),
            nn.ReLU(),
            nn.Linear(256, 32 * 7 * 7),
            nn.ReLU(),
            nn.Unflatten(1, (32, 7, 7)),
            nn.ConvTranspose2d(32, 16, kernel_size=3, stride=2, padding=1, output_padding=1),
            nn.ReLU(),
            nn.ConvTranspose2d(16, 1, kernel_size=3, stride=2, padding=1, output_padding=1),
            nn.Sigmoid()
        )

    def encode(self, x):
        h = self.encoder(x)
        mu = self.fc_mu(h)
        logvar = self.fc_logvar(h)
        return mu, logvar

    def reparameterize(self, mu, logvar):
        std = torch.exp(0.5 * logvar)
        eps = torch.randn_like(std)
        return mu + eps * std

    def decode(self, z):
        return self.decoder(z)

    def forward(self, x):
        mu, logvar = self.encode(x)
        z = self.reparameterize(mu, logvar)
        reconstructed = self.decode(z)
        return reconstructed, mu, logvar

model = VAE(latent_dim=16)

# 定义损失函数
def vae_loss(reconstructed, x, mu, logvar):
    recon_loss = nn.MSELoss()(reconstructed, x)
    kl_loss = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
    return recon_loss + kl_loss

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

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    reconstructed, mu, logvar = model(X)
    loss = vae_loss(reconstructed, X, mu, logvar)
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    reconstructed, _, _ = model(X)
    print(reconstructed)

解释:

  • self.fc_mu 和 self.fc_logvar:分别用于生成均值和对数方差。
  • reparameterize:重参数化技巧,用于从分布中采样。
  • vae_loss:变分自编码器的损失函数,包括重构损失和KL散度。

案例11:生成对抗网络(GAN)

目标:使用PyTorch构建一个生成对抗网络(GAN)模型。

代码示例:

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

# 定义数据
X = torch.randn(100, 1, 28, 28)

# 定义生成器
class Generator(nn.Module):
    def __init__(self, latent_dim):
        super(Generator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(latent_dim, 256),
            nn.ReLU(),
            nn.Linear(256, 512),
            nn.ReLU(),
            nn.Linear(512, 784),
            nn.Tanh()
        )

    def forward(self, z):
        img = self.model(z)
        img = img.view(img.size(0), 1, 28, 28)
        return img

# 定义判别器
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(784, 512),
            nn.LeakyReLU(0.2),
            nn.Linear(512, 256),
            nn.LeakyReLU(0.2),
            nn.Linear(256, 1),
            nn.Sigmoid()
        )

    def forward(self, img):
        img_flat = img.view(img.size(0), -1)
        validity = self.model(img_flat)
        return validity

# 实例化模型
latent_dim = 100
generator = Generator(latent_dim)
discriminator = Discriminator()

# 定义损失函数和优化器
adversarial_loss = nn.BCELoss()
optimizer_G = optim.Adam(generator.parameters(), lr=0.0002)
optimizer_D = optim.Adam(discriminator.parameters(), lr=0.0002)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    # 训练生成器
    generator.train()
    optimizer_G.zero_grad()
    z = torch.randn(100, latent_dim)
    gen_imgs = generator(z)
    validity = discriminator(gen_imgs)
    g_loss = adversarial_loss(validity, torch.ones((100, 1)))
    g_loss.backward()
    optimizer_G.step()

    # 训练判别器
    discriminator.train()
    optimizer_D.zero_grad()
    real_imgs = X
    real_validity = discriminator(real_imgs)
    real_loss = adversarial_loss(real_validity, torch.ones((100, 1)))
    fake_validity = discriminator(gen_imgs.detach())
    fake_loss = adversarial_loss(fake_validity, torch.zeros((100, 1)))
    d_loss = (real_loss + fake_loss) / 2
    d_loss.backward()
    optimizer_D.step()

# 生成新图像
generator.eval()
with torch.no_grad():
    z = torch.randn(100, latent_dim)
    gen_imgs = generator(z)
    print(gen_imgs)

解释:

  • Generator:生成器模型,用于生成假图像。
  • Discriminator:判别器模型,用于判断图像是否真实。
  • adversarial_loss:二元交叉熵损失函数,用于计算生成器和判别器的损失。
  • gen_imgs.detach():分离生成的图像,使其不参与判别器的梯度计算。

案例12:序列到序列模型(Seq2Seq)

目标:使用PyTorch构建一个序列到序列模型(Seq2Seq)。

代码示例:

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

# 定义数据
X = torch.randint(0, 10, (100, 10))  # (batch_size, sequence_length)
y = torch.randint(0, 10, (100, 10))

# 定义编码器
class Encoder(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers):
        super(Encoder, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.embedding = nn.Embedding(input_size, hidden_size)
        self.gru = nn.GRU(hidden_size, hidden_size, num_layers, batch_first=True)

    def forward(self, x):
        embedded = self.embedding(x)
        outputs, hidden = self.gru(embedded)
        return outputs, hidden

# 定义解码器
class Decoder(nn.Module):
    def __init__(self, hidden_size, output_size, num_layers):
        super(Decoder, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.embedding = nn.Embedding(output_size, hidden_size)
        self.gru = nn.GRU(hidden_size, hidden_size, num_layers, batch_first=True)
        self.out = nn.Linear(hidden_size, output_size)
        self.softmax = nn.LogSoftmax(dim=2)

    def forward(self, x, hidden):
        embedded = self.embedding(x)
        output, hidden = self.gru(embedded, hidden)
        output = self.softmax(self.out(output))
        return output, hidden

# 定义模型
class Seq2Seq(nn.Module):
    def __init__(self, encoder, decoder):
        super(Seq2Seq, self).__init__()
        self.encoder = encoder
        self.decoder = decoder

    def forward(self, src, trg, teacher_forcing_ratio=0.5):
        batch_size = src.size(0)
        trg_len = trg.size(1)
        trg_vocab_size = self.decoder.out.out_features

        outputs = torch.zeros(batch_size, trg_len, trg_vocab_size).to(src.device)

        _, hidden = self.encoder(src)

        input = trg[:, 0].unsqueeze(1)  # SOS token

        for t in range(1, trg_len):
            output, hidden = self.decoder(input, hidden)
            outputs[:, t, :] = output.squeeze(1)
            teacher_force = torch.rand(1) < teacher_forcing_ratio
            top1 = output.argmax(2)
            input = trg[:, t].unsqueeze(1) if teacher_force else top1

        return outputs

# 实例化模型
input_size = 10
hidden_size = 128
output_size = 10
num_layers = 2
encoder = Encoder(input_size, hidden_size, num_layers)
decoder = Decoder(hidden_size, output_size, num_layers)
model = Seq2Seq(encoder, decoder)

# 定义损失函数和优化器
criterion = nn.NLLLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X, y)
    loss = criterion(outputs.view(-1, output_size), y.view(-1))
    loss.backward()
    optimizer.step()

# 测试模型
model.eval()
with torch.no_grad():
    predicted = model(X, y, teacher_forcing_ratio=0).argmax(dim=2)
    print(predicted)

解释:

  • Encoder:编码器模型,用于将输入序列编码为隐藏状态。
  • Decoder:解码器模型,用于将隐藏状态解码为输出序列。
  • Seq2Seq:序列到序列模型,结合编码器和解码器。
  • teacher_forcing_ratio:教师强制比例,用于在训练过程中决定是否使用真实标签作为下一个时间步的输入。

实战案例:手写数字识别

目标:使用PyTorch构建一个卷积神经网络(CNN)模型,对手写数字进行分类。

代码示例:

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms

# 定义数据集
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=100, shuffle=True, num_workers=2)

testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)

# 定义模型
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
        self.fc1 = nn.Linear(16 * 14 * 14, 128)
        self.fc2 = nn.Linear(128, 10)
        self.relu = nn.ReLU()

    def forward(self, x):
        out = self.conv1(x)
        out = self.relu(out)
        out = self.pool(out)
        out = out.view(-1, 16 * 14 * 14)
        out = self.fc1(out)
        out = self.relu(out)
        out = self.fc2(out)
        return out

model = CNN()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    print(f'Epoch {epoch + 1}, Loss: {running_loss / (i + 1)}')

# 测试模型
model.eval()
correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print(f'Accuracy on the test set: {100 * correct / total}%')

解释:

  • torchvision.datasets.MNIST:加载MNIST数据集。
  • transforms.Compose:定义数据预处理步骤,包括转换为张量和归一化。
  • DataLoader:创建数据加载器,用于批量加载数据。
  • nn.MaxPool2d:最大池化层,用于降采样。
  • nn.Linear:全连接层,用于分类。
  • torch.max(outputs.data, 1):获取每个样本的最大概率对应的类别索引。

总结

本文通过12个实战案例,详细介绍了如何使用PyTorch构建各种类型的神经网络模型,包括线性回归、逻辑回归、多层感知机、卷积神经网络、循环神经网络、长短时记忆网络、门控循环单元、残差网络、卷积自编码器、变分自编码器、生成对抗网络和序列到序列模型。每个案例都提供了详细的代码示例和解释,帮助你逐步掌握PyTorch的核心概念和高级技巧。

责任编辑:赵宁宁 来源: 手把手PythonAI编程
相关推荐

2019-08-19 00:31:16

Pytorch神经网络深度学习

2020-12-19 11:05:57

循环神经网络PyTorch神经网络

2022-07-28 09:00:00

深度学习网络类型架构

2018-09-17 15:12:25

人工智能神经网络编程语言

2018-03-22 13:34:59

TensorFlow神经网络

2018-08-27 17:05:48

tensorflow神经网络图像处理

2017-04-26 08:31:10

神经网络自然语言PyTorch

2020-06-15 17:40:32

神经网络人工智能可视化工具

2023-05-12 14:58:50

Java神经网络深度学习

2020-09-18 11:40:44

神经网络人工智能PyTorch

2021-12-28 08:48:54

PyTorch神经网络人工智能

2018-05-28 13:12:49

深度学习Python神经网络

2024-04-30 14:54:10

2018-07-03 16:10:04

神经网络生物神经网络人工神经网络

2017-04-26 09:30:53

卷积神经网络实战

2022-07-25 08:00:00

机器学习SOM算法

2021-07-07 06:04:33

人工智能Pytorch神经网络

2020-03-26 09:00:00

神经网络AI人工智能

2020-05-11 13:44:38

神经网络人工智能深度学习

2020-08-14 10:01:25

编程神经网络C语言
点赞
收藏

51CTO技术栈公众号