用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,卷积核大小为3×3,步幅为1,填充为1。
- nn.MaxPool2d(kernel_size=2, stride=2, padding=0):最大池化层,池化窗口大小为2×2,步幅为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的核心概念和高级技巧。