python数据集处理

python处理数据集详细过程

本文是基于博客PyTorch学习之路(level1)——训练一个图像分类模型并结合所查资料及自己的理解整理出来的,目的是作为python基础知识备忘,侵删。

torchvision.transforms的功能为:

  1. PIL.image/numpy.ndarrayTensor相互转化

  2. Tensor归一化

  3. PIL.image裁剪、缩放等

通常,在使用torchvision.transforms{},我们通常使用transforms.Compose{}将transforms组合在一起

数据导入

利用pytorch封装好的torchvision.datasets.ImageFolder接口,默认训练数据按照一个类别对应一个文件夹的情形

data_dir = '/data'  # 数据所在路径
image_datasets = {x: datasets.ImageFolder(
     os.path.join(data_dir, x),
     data_transforms[x])# 可用于resize crop等的字典
     for x in ['train', 'val']}

torchvision.datasets.ImageFolder会返回一个list,list中的每个值都是一个tuple,每个tuple包含图片路径和标签两个对象。

data_transforms = {
'train': transforms.Compose([
transforms.RandomSizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Scale(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
}

data_transforms={}是一个字典,功能是图片预处理,如resize、crop等,python实现的时候采用pytorch封装好的torchvision.transforms模块,例如:

torchvision.transforms.RandomSizedCrop——————图片裁剪,输入是PIL image(用pytorch的PIL库读取的图片内容)Crop是从图像中移除不需要的信息,只保留需要的部分*

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aciTgmmI-1573464364817)(E:\Markdown工具-Typora\images-saved\1573454072668.png)]

transforms.ToTensor——————将PIL.Image/numpy.ndarray数据进转化为torch.FloatTensor

transforms.Normalize()————————输入是Tensor,对其归一化,公式为channel=(channel-mean)/std

生成dataloader

dataloders = {x: torch.utils.data.DataLoader(image_datasets[x],     
                               batch_size=4, 
                               shuffle=True,
                               num_workers=4) 
                                  for x in ['train', 'val']}

torchvision.datasets.ImageFolder只是返回list,而list不能作为模型的输入,因此需要另一个类来封装list,那就是torch.utils.data.DataLoader.

torch.utils.data.DataLoader——————将list类型的输入数据封装成Tensor数据格式,以备模型使用。⚠️注意:图片和标签分别封装为一个Tensor

torch.utils.data.Dataset是一个抽象类,pytorch中所有和数据相关的类都要继承这个类实现。

所以当你的数据不是按照一个类别一个文件夹这种方式存储时,你就要自定义一个类来读取数据,自定义的这个类必须继承自troch.utils.data.Dataset这个基类,最后同样用torch.data.DataLoader封装成Tensor。

将Tensor数据类型封装成Variable数据类型

for data in dataloders['train']:
inputs, labels = data

if use_gpu:
   inputs = Variable(inputs.cuda())
   labels = Variable(labels.cuda())
   else:
inputs, labels = Variable(inputs), Variable(labels)

dataloader——————字典;

dataloader['train']——————载入训练数据;

for循环——————从dataloaders[‘train’]中读取batch_size个数据,data里面包含图像input tensor和标签label tensor

torch.autograd.Variable——————将tensor封装成模型可以使用的variable数据类型

为什么要封装成variable类型呢?

Variable可以看成是tensor的一种包装,其不仅包含了tensor的内容,还包含了梯度等信息,因此在神经网络中常常用Variable数据结构。那么怎么从一个Variable类型中取出tensor呢?也很简单,比如下面封装后的inputs是一个Variable,那么inputs.data就是对应的tensor。

将数据输入到模型

因为预训练网络一般是在1000类的ImageNet数据集上进行的,所以要迁移到你自己数据集的2分类,需要替换最后的全连接层为你所需要的输出。

# models模块导入resnet18网络,然后获取全连接层的输入channel个数,用这个channel个数和你要做的分类类别数(这里是2)替换原来模型中的全连接层。
model = models.resnet18(pretrained=True) # 导入模型
   num_ftrs = model.fc.in_features
   model.fc = nn.Linear(num_ftrs, 2)

torchvision.models——————导入模型,如VGG,ResNet,DenseNet等

定义损失函数

在PyTorch中采用torch.nn模块来定义网络的所有层,比如卷积、降采样、损失层等等,这里采用交叉熵函数,因此可以这样定义:

critertion=nn.CrossEntropyLoss()
  • 定义优化函数:
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9) # 虽然写的是SGD但是由于有动量,所以是Adam

torch.optim————SGD

lr——————learning rate学习率

momentum——————动量

  • 定义学习率变化策略:
scheduler = lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)

采用的是torch.optim.lr_scheduler模块的StepLR类,表示每隔step_size个epoch就将学习率降为原来的gamma倍。

训练

  • 更新学习率
scheduler.step()
  • 设置模型为训练状态
model.train(True)
  • 将网络中所有梯度置0
optimizer.zero_grad()
  • 前向传播
outputs = model(inputs)
  • 损失函数
loss = criterion(outputs, labels)

由于网络的输入为variable数据类型,所以output也是variable。

  • 分类
 _, preds = torch.max(outputs.data, 1)

得到输出后(网络的全连接层的输出)还希望能得到模型预测该样本属于哪个类别的信息,这里采用torch.max。**torch.max()的第一个输入是tensor格式,所以用outputs.data而不是outputs作为输入;**第二个参数1是代表dim的意思,也就是取每一行的最大值,其实就是我们常见的取概率最大的那个index;第三个参数loss也是torch.autograd.Variable格式。

torch.max(a,1)——————返回每一行中元素的最大值及其索引

拓展:

torch.max()[0]————只返回最大值的每个数

troch.max()[1]————只返回最大值的每个索引

torch.max()[1].data————只返回variable中的数据部分(去掉Variable containing:)

torch.max()[1].data.numpy()————把数据转化成numpy ndarry

torch.max()[1].data.numpy().squeeze()————把数据条目中维度为1 的删除掉

torch.max(tensor1,tensor2) element-wise————比较tensor1 和tensor2 中的元素,返回较大的那个值

  • 回传损失backward

training时才有bp,test时只有forward

loss.backward()
  • 计算梯度并不断更新
optimizer.step()

optimizer.step————更新参数,可从optimizer.param_groups[0]['params']里面看到各个层的梯度和权值信息

  • GPU操作
use_gpu = torch.cuda.is_available()

判断是否有gpu可以用,如果有则use_gpu是true。

optimizer.step()


```optimizer.step```————更新参数,可从```optimizer.param_groups[0]['params']```里面看到各个层的梯度和权值信息

- **GPU操作**

```python
use_gpu = torch.cuda.is_available()

判断是否有gpu可以用,如果有则use_gpu是true。

以上就是一个batch数据的训练过程,不断重复这个过程就可以达到训练效果。

你可能感兴趣的:(python基础知识)