在PyTorch中,使用样本权重(sample_weight)可以对不同样本的重要性进行加权,从而提高模型的性能。本文将详细介绍在PyTorch中使用样本权重的正确方法,并提供两个示例说明。
1. 使用torch.nn.CrossEntropyLoss
实现样本权重
在PyTorch中,可以使用torch.nn.CrossEntropyLoss
函数实现样本权重。torch.nn.CrossEntropyLoss
函数可以接受一个weight
参数,用于指定每个类别的权重。以下是一个示例代码,展示如何使用torch.nn.CrossEntropyLoss
函数实现样本权重:
import torch.nn as nn
import torch.optim as optim
import torchvision.datasets as datasets
import torchvision.transforms as transforms
# 加载数据集
transform_train = transforms.Compose([
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
trainset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2)
# 定义模型
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.fc1 = nn.Linear(128 * 8 * 8, 1024)
self.fc2 = nn.Linear(1024, 10)
def forward(self, x):
x = nn.functional.relu(self.conv1(x))
x = nn.functional.max_pool2d(nn.functional.relu(self.conv2(x)), 2)
x = x.view(-1, 128 * 8 * 8)
x = nn.functional.relu(self.fc1(x))
x = self.fc2(x)
return x
# 定义样本权重
class_weights = torch.FloatTensor([1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0]).cuda()
# 将模型移动到GPU上
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net = Net().to(device)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss(weight=class_weights)
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9, weight_decay=5e-4)
# 训练模型
for epoch in range(100):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data[0].to(device), data[1].to(device)
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 100 == 99:
print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100))
running_loss = 0.0
在上面的示例代码中,我们首先加载CIFAR-10数据集,并定义了一个名为Net
的类,它继承自nn.Module
。然后,我们定义了一个名为class_weights
的变量,它用于指定每个类别的权重。接着,我们将模型移动到GPU上,并使用nn.CrossEntropyLoss
函数实现样本权重。最后,我们训练模型并输出每个epoch的平均损失。
2. 使用torch.utils.data.WeightedRandomSampler
实现样本权重
除了使用nn.CrossEntropyLoss
函数实现样本权重外,还可以使用torch.utils.data.WeightedRandomSampler
实现样本权重。torch.utils.data.WeightedRandomSampler
函数可以接受一个weights
参数,用于指定每个样本的权重。以下是一个示例代码,展示如何使用torch.utils.data.WeightedRandomSampler
函数实现样本权重:
import torch.nn as nn
import torch.optim as optim
import torchvision.datasets as datasets
import torchvision.transforms as transforms
from torch.utils.data import WeightedRandomSampler
# 加载数据集
transform_train = transforms.Compose([
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
trainset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train)
# 定义样本权重
class_weights = torch.FloatTensor([1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0])
sample_weights = [class_weights[label] for _, label in trainset]
# 定义WeightedRandomSampler
sampler = WeightedRandomSampler(sample_weights, len(sample_weights), replacement=True)
# 加载数据集
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, sampler=sampler, num_workers=2)
# 定义模型
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.fc1 = nn.Linear(128 * 8 * 8, 1024)
self.fc2 = nn.Linear(1024, 10)
def forward(self, x):
x = nn.functional.relu(self.conv1(x))
x = nn.functional.max_pool2d(nn.functional.relu(self.conv2(x)), 2)
x = x.view(-1, 128 * 8 * 8)
x = nn.functional.relu(self.fc1(x))
x = self.fc2(x)
return x
# 将模型移动到GPU上
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net = Net().to(device)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9, weight_decay=5e-4)
# 训练模型
for epoch in range(100):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data[0].to(device), data[1].to(device)
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 100 == 99:
print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100))
running_loss = 0.0
在上面的示例代码中,我们首先加载CIFAR-10数据集,并定义了一个名为class_weights
的变量,它用于指定每个类别的权重。然后,我们计算每个样本的权重,并使用WeightedRandomSampler
函数实现样本权重。接着,我们加载数据集,并将模型移动到GPU上。最后,我们使用nn.CrossEntropyLoss
函数定义损失函数,并训练模型并输出每个epoch的平均损失。
总结
本文介绍了在PyTorch中使用样本权重的正确方法,并提供了两个示例说明。在实际应用中,我们可以根据具体情况选择不同的实现方法,以获得更好的模型性能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:在Pytorch中使用样本权重(sample_weight)的正确方法 - Python技术站