工作时做网站使用软件,乐陵网站制作,巩义做网站哪家好,网站建设不赚钱pytorch加载cifar10的归一化 pytorch怎么加载cifar10数据集torchvision.datasets.CIFAR10transforms.Normalize()进行归一化到底在哪里起作用#xff1f;【CIFAR10源码分析】 torchvision.datasets加载的数据集搭配Dataloader使用model.train()和model.eval() pytorch怎么加载… pytorch加载cifar10的归一化 pytorch怎么加载cifar10数据集torchvision.datasets.CIFAR10transforms.Normalize()进行归一化到底在哪里起作用【CIFAR10源码分析】 torchvision.datasets加载的数据集搭配Dataloader使用model.train()和model.eval() pytorch怎么加载cifar10数据集
torchvision.datasets.CIFAR10
pytorch里面的torchvision.datasets中提供了大多数计算机视觉领域相关任务的数据集可以根据实际需要加载相关数据集——需要cifar10就用torchvision.datasets.CIFAR10()需要SVHN就调用torchvision.datasets.SVHN()。
针对cifar10数据集而言调用torchvision.datasets.CIFAR10()其中root是下载数据集后保存的位置train是一个bool变量为true就是训练数据集false就是测试数据集download也是一个bool变量表示是否下载transform是对数据集中的image进行一些操作比如归一化、随机裁剪、各种数据增强操作等target_transform是针对数据集中的label进行一些操作。
示例代码如下
# 加载训练数据集
train_data datasets.CIFAR10(root../_datasets, trainTrue, downloadTrue,transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean[0.5, 0.5, 0.5], std[0.5, 0.5, 0.5]) # 归一化 ]) )
# 加载测试数据集
test_data datasets.CIFAR10(root../_datasets, trainFalse,downloadTrue, transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean[0.5, 0.5, 0.5], std[0.5, 0.5, 0.5]) # 归一化 ]) )transforms.Normalize()进行归一化到底在哪里起作用【CIFAR10源码分析】
上面的代码中我们用transforms.Compose([……])组合了一系列的对image的操作其中trandforms.ToTensor()和transforms.Normalize()都涉及到归一化操作 原始的cifar10数据集是numpy array的形式其中数据范围是[0,255]pytorch加载时并没有改变数据范围依旧是[0,255]加载后的数据维度是(H, W, C)源码部分 __getitem__()函数中进行transforms操作进行了归一化实际上传入的transform在__getitem__()函数中被调用其中transforms.Totensor()会将data也就是image的维度变成(CH W)的形式并且归一化到[0.01.0] transforms.Normalize()会根据z (x-mean) / std 对数据进行归一化上述代码中mean[0.5, 0.5, 0.5], std[0.5, 0.5, 0.5]是可以将3个通道单独进行归一化3个通道可以设置不同的mean和std最终数据范围变成[-0.50.5] 。
所以如果通过pytorch的cifar10加载数据集后针对traindataset.data依旧是没有进行归一化的但是比如traindataset[index].data其中[index]这样的按下标取元素的操作会直接调用的__getitem__()函数此时的data就是经过了归一化的。 除traindataset[index]会隐式自动调用__getitem__()函数外还有什么时候会调用这个函数呢毕竟……只有调用了这个函数才会调用transforms中的归一化处理。——答案是与dataloader搭配使用
torchvision.datasets加载的数据集搭配Dataloader使用
torchvision.datasets实际上是torch.utils.data.Dataset的子类那么就能传入Dataloader中迭代的按batch-size获取批量数据用于训练或者测试。其中dataloader加载dataset中的数据时就是用到了其__getitem__()函数所以用dataloader加载数据集得到的是经过归一化后的数据。
model.train()和model.eval()
我发现上面的问题是我用dataloader加载了训练数据集用于训练resnet18模型训练过程中我训练好并保存后顺便测试了一下在测试数据集上的准确度。但是在测试的过程中我没有用dataloader加载测试数据集而是直接用的dataset.data来进行的测试。并且由于是并没有将model设置成model.eval()【其实我设置了但是我对自己很无语我写的model.eval忘记加括号了无语呜呜】……也就是即便我的测试数据集没有经过归一化由于模型还是在model.train()模式下因此模型的BN层会自己调整使得模型性能不受影响因此在测试数据集上的accuracy达到了0.86我就没有多想。 后来我用模型的时候设置了model.eval()后依旧是直接用的dataset.data也就是没有归一化不管是在测试数据集上还是在训练数据集上accuracy都只有0.10我表示非常的迷茫疑惑啊然后才发现是归一化的问题。
在model.train()模式下进行预测时PyTorch会默认启用一些训练相关的操作例如Batch Normalization和Dropout并且模型的参数是可变的能够根据输入进行调整。这些操作在训练模式下可以帮助模型更好地适应训练数据并产生较高的准确度。在model.eval()模式下进行预测时PyTorch会将模型切换到评估模式这会导致一些训练相关的操作行为发生变化。具体而言Batch Normalization层会使用训练集上的统计信息进行归一化而不是使用当前批次的统计信息。因此如果输入数据没有进行归一化模型在评估模式下的准确度可能会显著下降。
以下是我没有用dataloader加载数据集进行预测的代码
def correctness(model,data,target, device):batchsize 1000batch_num int(len(data) / batchsize) # 对原始的数据进行操作 从H.W.C变成C.H.W data torch.tensor(data).permute(0,3,1,2).type(torch.FloatTensor).to(device)# 手动归一化data data/255data (data - 0.5) / 0.5 # 求一个batch的correctnessdef _batch_correctness(i):images, labels data[i*batchsize : (i1)*batchsize], target[i*batchsize : (i1)*batchsize]predict model(images).detach().cpu() correctness np.array(torch.argmax(predict, dim 1).numpy() np.array(labels) , dtype np.float32)return correctnessresult np.array([_batch_correctness(i) for i in range(batch_num)])return result.flatten().sum()/data.shape[0]我后面用上面的代码测试了四种情况
model.eval() 没有归一化train_accuracy 0.10test_accuracy 0.10model.eval() 手动归一化train_accuracy 0.95test_accuracy 0.84model.train() 没有归一化train_accuracy 0.95test_accuracy 0.83model.train() 手动归一化train_accuracy 0.94test_accuracy 0.84
由此可见在model.eval()模式下数据归一化对最终的测试结果有很大影响。