问题描述
问题
我正在 PyTorch 中训练一个用于二元分类的深度学习模型,我有一个包含不平衡类比例的数据集。我的少数类占给定观察的大约 10%
。为了避免模型学习只预测多数类,我想在我的 WeightedRandomSampler
中使用 torch.utils.data
中的 DataLoader
。
假设我有 1000
个观察值(900
类在 0
类中,100
类在 1
类中),批量大小为 {{1} } 用于我的数据加载器。
如果没有加权随机抽样,我希望每个训练时期包含 10 个批次。
问题
- 在使用此采样器时,每个时期是否只会采样 10 个批次 - 因此,模型是否会在每个时期“错过”多数类的大部分,因为现在少数类在训练批次中所占比例过高?立>
- 使用采样器是否会导致每个 epoch 采样超过 10 个批次(意味着相同的少数类观察可能出现多次,而且训练速度会变慢)?
解决方法
这取决于您的追求,请查看 torch.utils.data.WeightedRandomSampler
文档了解详情。
有一个参数 DateTimeOffset
允许您指定当 num_samples
与 Dataset
组合时实际创建的样本数量(假设您正确加权):
- 如果您将其设置为
torch.utils.data.DataLoader
,您将获得第一个案例 - 如果您将其设置为
len(dataset)
(在您的情况下),您将获得第二种情况
使用此采样器时,每个 epoch 将仅采样 10 个批次 - 因此,模型会在每个 epoch 期间“错过”多数类的大部分 [...]
是的,但是这个epoch过去后会返回新的样本
使用采样器是否会导致每个 epoch 采样超过 10 个批次(意味着相同的少数类观察可能出现多次,而且训练速度会变慢)?
训练不会变慢,每个 epoch 会花费更长的时间,但收敛应该大致相同(因为每个 epoch 中的数据更多,因此需要的 epoch 更少)。
,使用WeightedRandomSampler
的一小段代码
首先定义函数:
def make_weights_for_balanced_classes(images,nclasses):
count = [0] * nclasses
for item in images:
count[item[1]] += 1
weight_per_class = [0.] * nclasses
N = float(sum(count))
for i in range(nclasses):
weight_per_class[i] = N/float(count[i])
weight = [0] * len(images)
for idx,val in enumerate(images):
weight[idx] = weight_per_class[val[1]]
return weight
在此之后,以下一种方式使用它:
import torch
dataset_train = datasets.ImageFolder(traindir)
# For unbalanced dataset we create a weighted sampler
weights = make_weights_for_balanced_classes(dataset_train.imgs,len(dataset_train.classes))
weights = torch.DoubleTensor(weights)
sampler = torch.utils.data.sampler.WeightedRandomSampler(weights,len(weights))
train_loader = torch.utils.data.DataLoader(dataset_train,batch_size=args.batch_size,shuffle = True,sampler = sampler,num_workers=args.workers,pin_memory=True)