如何在CNN中进行归一化?

我是CNN的新手,正在通过食物分类来学习它。以下是我的代码。在数据集部分,我将训练数据集和验证数据集从numpy转换为张量。此时,张量的形状为([9866, 128, 128, 3])。由于通道3需要在第一个索引位置,所以我使用了“transpose”方法来更改索引。然后,我使用“Data.TensorDataset”将训练数据和训练标签组合在一起,使用“Data.DataLoader”的原因是我需要批处理大小来加速训练过程。

我的训练集准确率达到了68%,我想提高它。我在网上搜索后发现,可能需要添加归一化处理。但我只找到了如下方式

transform = transforms.Compose([    transforms.ToTensor(), # range [0, 255] -> [0.0,1.0]    ])

我对如何将其与“Data.DataLoader”结合使用感到困惑。我知道还有另一种方式可以将训练数据从numpy转换为dataloader,具体如下,这里是链接

train_transform = transforms.Compose([    transforms.ToPILImage(),    transforms.RandomHorizontalFlip(),     transforms.RandomRotation(15),     transforms.ToTensor(), ])test_transform = transforms.Compose([    transforms.ToPILImage(),                                        transforms.ToTensor(),])class ImgDataset(Dataset):    def __init__(self, x, y=None, transform=None):        self.x = x        self.y = y        if y is not None:            self.y = torch.LongTensor(y)        self.transform = transform    def __len__(self):        return len(self.x)    def __getitem__(self, index):        X = self.x[index]        if self.transform is not None:            X = self.transform(X)        if self.y is not None:            Y = self.y[index]            return X, Y        else:            return Xtrain_set = ImgDataset(train_x, train_y, train_transform)val_set = ImgDataset(val_x, val_y, test_transform)train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True)val_loader = DataLoader(val_set, batch_size=batch_size, shuffle=False)

我的方法可能有些傻,但我还是想尝试,任何帮助都将不胜感激。我希望我解释得清楚,提前感谢。

如果需要,这里是完整的代码:


回答:

对模型输入(无论是训练集、验证集还是测试集)执行的数据归一化取决于您的训练数据统计信息。更具体地说,它对应于训练集中使用的图像的逐通道均值和标准偏差。


torchvision.transforms.Normalize

您可以使用torchvisiontransforms.Normalize来实现。它是一个非常简单的函数,但很多人似乎难以理解它,或者没有阅读其文档…

torchvision.transforms.Normalize(mean, std, inplace=False)
使用均值和标准偏差对张量图像进行归一化。此变换不支持PIL图像。给定mean:(mean[1], …, mean[n]) 和std:(std[1], …, std[n]),对于n个通道,此变换将归一化输入torch.*Tensor的每个通道,即output[channel] = (input[channel] - mean[channel]) / std[channel]

您可以认为这两个参数'mean''std'的命名不够准确,确实有些误导。这可以解释为什么它被如此频繁地误用(今天也是如此)。

它不过是逐通道位移-缩放操作符


变换的误用

我经常看到这种类型的归一化设置。

T.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))

为了澄清,上述设置不会执行以下两件事:

  • 它不会将您的输入归一化到[0, 1]

  • 它不会标准化您的输入(即不会使mean=0std=1

所描述的变换将值从[0, 1]映射到[-1, 1](因为(x - .5) / .5 = 2x - 1)。

>>> x = torch.tensor([0., .5, 1.]).reshape(1, 3, 1, 1)tensor([0.0, 0.5, 1.0])>>> t = T.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))>>> t(x).flatten()tensor([-1.,  0.,  1.])

如何正确使用transforms.Normalize

在您的案例中,您不应该使用.5作为meanstd参数。这没有任何意义。如果您在之前使用了T.ToTensor,您实际上是在将值映射到[-1, 1]

相反,您应该使用实际数据集的meanstd来初始化变换,即您直接从数据集中测量得到的均值和标准偏差。

例如,对于Imagenet,统计数据是:[0.485, 0.456, 0.406][0.229, 0.224, 0.225],分别为均值和标准偏差。您应该这样做:

>>> t = T.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))

已导入torchvision.transformsT

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注