pytorch 入门笔记

1.数据加载

自定义dataset

import os
import os.path as osp

from torch.utils.data import Dataset


class DogCatDataset(Dataset):

    def __init__(self, root_path, is_train):
        self.is_train = is_train
        self.train_set_path = osp.join(root_path, 'train_set')
        self.test_set_path = osp.join(root_path, 'test_set')
        self.train_data = os.listdir(self.train_set_path)
        self.test_data = os.listdir(self.test_set_path)

    def __len__(self):
        return len(self.train_data) if self.is_train else len(self.test_data)

    def __getitem__(self, idx):
        if self.is_train:
            return osp.join(self.train_set_path, self.train_data[idx])
        else:
            return osp.join(self.test_set_path, self.test_data[idx])

这种方式无法实现batch、shuffle数据或通过多线程读取,所以还可以通过DataLoader定义迭代器

from torch.utils.data import DataLoader

dataset = DogCatDataset('../data', is_train=True)
dataiter = DataLoader(dataset, batch_size=32, shuffle=True)

对于图片数据可以使用torchversion.dataset下的ImageFolder

from torchvision.datasets import ImageFolder
# transform 和 target_transform 用于数据增强
ImageFolder(root='../data/train_set',transform=None, target_transform=None)

2. nn 模组  Module(网络)

pytorch中定义计算图,层结构和损失函数均来着torch.nn模组

from abc import ABC

from torch.nn import Module
from torch.nn import Conv2d
from torch.nn import CrossEntropyLoss


class TestNet(Module, ABC):
    def __init__(self):
        super(TestNet, self).__init__()
        self.conv1 = Conv2d(in_channels=3, out_channels=8, kernel_size=3)
        self.criterion = CrossEntropyLoss()

    def forward(self, x):
        x = self.conv1(x)
        return x

    def build_loss(self, output, target):
        loss = self.criterion(output, target)
        return loss

3. 一个完整的LinearRegression示例

from abc import ABC

import numpy as np
from torch.autograd import Variable
from torch.nn import Module
from torch.nn import Linear
import torch
from torch.nn import MSELoss
import torch.optim as optim
import matplotlib.pyplot as plt


class LinearRegression(Module, ABC):
    def __init__(self):
        super(LinearRegression, self).__init__()
        self.linear = Linear(1, 1)  # input output is 1 dim

    def forward(self, x):
        out = self.linear(x)
        return out


x_train = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],
                    [9.779], [6.182], [7.59], [2.167], [7.042],
                    [10.791], [5.313], [7.997], [3.1]], dtype=np.float32)

y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],
                    [3.366], [2.596], [2.53], [1.221], [2.827],
                    [3.465], [1.65], [2.904], [1.3]], dtype=np.float32)

x_train = torch.Tensor(x_train)
y_train = torch.Tensor(y_train)

if torch.cuda.is_available():
    model = LinearRegression().cuda()
else:
    model = LinearRegression()

criterion = MSELoss()
optimizer = optim.SGD(model.parameters(), lr=1e-3)

num_epochs = 1000

for epoch in range(num_epochs):
    if torch.cuda.is_available():
        inputs = Variable(x_train).cuda()
        targets = Variable(y_train).cuda()
    else:
        inputs = Variable(x_train)
        targets = Variable(y_train)

    # forward
    out = model(inputs)
    loss = criterion(out, targets)

    # backward
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if (epoch + 1) % 20 == 0:
        print('Epoch[{}/{}], loss:{:6f}'.format(epoch + 1, num_epochs, loss.data.item()))

# evaluation
# 将模型转变为测试模式 因为有些层 Dropout BN 等 训练和预测时的操作不同
model.eval()
predict = model(Variable(x_train))
predict = predict.data.numpy()
plt.plot(x_train.numpy(), y_train.numpy(), 'ro', label='original data')
plt.plot(x_train.numpy(), predict, label='fitting line')
plt.show()

注意:在模型预测前,需要将模型转换为eval模型

4. 一个简化的 VGG 示例

import sys
from abc import ABC

from torch.utils.data import DataLoader

sys.path.append('..')

import numpy as np
import torch
from torch import nn
from torchvision.datasets import CIFAR10
from torch.nn import Module
from torch.nn import Sequential, Conv2d, MaxPool2d, ReLU, Linear
from d_cnn.utils import train


class VggLite(Module, ABC):

    def __init__(self):
        super(VggLite, self).__init__()
        self.feature = Sequential(
            Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
            ReLU(True),
            MaxPool2d(kernel_size=(2, 2), stride=(2, 2), dilation=(1, 1)),

            Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
            ReLU(True),
            MaxPool2d(kernel_size=(2, 2), stride=(2, 2), dilation=(1, 1)),

            Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
            ReLU(True),
            Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
            ReLU(True),
            MaxPool2d(kernel_size=(2, 2), stride=(2, 2), dilation=(1, 1)),

            Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
            ReLU(True),
            Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
            ReLU(True),
            MaxPool2d(kernel_size=(2, 2), stride=(2, 2), dilation=(1, 1)),

            Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
            ReLU(True),
            Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
            ReLU(True),
            MaxPool2d(kernel_size=(2, 2), stride=(2, 2), dilation=(1, 1))
        )

        self.classifier = Sequential(
            Linear(512, 100),
            ReLU(True),
            Linear(100, 10)
        )

    def forward(self, x):
        x = self.feature(x)
        x = x.view(x.shape[0], -1)
        x = self.classifier(x)
        return x


def data_tf(x):
    x = np.array(x, dtype='float32') / 255
    x = (x - 0.5) / 0.5  # 标准化,这个技巧之后会讲到
    x = x.transpose((2, 0, 1))  # 将 channel 放到第一维,只是 pytorch 要求的输入方式
    x = torch.from_numpy(x)
    return x


train_set = CIFAR10('../data', train=True, transform=data_tf, download=True)
train_data = DataLoader(train_set, batch_size=64, shuffle=True)
test_set = CIFAR10('../data', train=False, transform=data_tf, download=True)
test_data = DataLoader(test_set, batch_size=128, shuffle=False)

net = VggLite()
optimizer = torch.optim.SGD(net.parameters(), lr=1e-1)
criterion = nn.CrossEntropyLoss()

train(net, train_data, test_data, 20, optimizer, criterion)

5. 学习率衰减

# 定义一个优化器 单组参数
optimizer = torch.optim.SGD(net.parameters(), lr=0.01, weight_decay=1e-4)
# 多组参数
optim.SGD([{'params': model.base.parameters()},
           {'params': model.classifier.parameters(), 'lr': 1e-3}], 
            lr=1e-2, momentum=0.9)
# 打印优化器的参数
print('learning rate: {}'.format(optimizer.param_groups[0]['lr']))
print('weight decay: {}'.format(optimizer.param_groups[0]['weight_decay']))
learning rate: 0.01
weight decay: 0.0001

所以可以在循环过程中指定优化器的 lr 值来衰减学习率

# 单组参数时 直接更改
optimizer.param_groups[0]['lr'] = 1e-5
# 多组参数时 使用循环更改
for param_group in optimizer.param_groups:
    param_group['lr'] = 1e-5

6. 正则化

L2正则化

# 通过添加 weight_decay 设置L2正则
optimizer = torch.optim.SGD(net.parameters(), lr=0.01, weight_decay=1e-4) 

7.数据增强

from PIL import Image
from torchvision import transforms as tfs

’‘’
常用的数据增强方法如下:
1.对图片进行一定比例缩放
2.对图片进行随机位置的截取
3.对图片进行随机的水平和竖直翻转
4.对图片进行随机角度的旋转
5.对图片进行亮度、对比度和颜色的随机变化
‘’‘
im = Image.open('./cat.png')

# 随机比例缩放
new_im = tfs.Resize((100, 200))(im)

# 随机裁剪
random_im1 = tfs.RandomCrop(100)(im) # 100 x 100
random_im2 = tfs.RandomCrop((150, 100))(im) # 100 x 100
center_im = tfs.CenterCrop(100)(im) # 中心 100 x 100
# 随机尺寸裁剪后 ,缩放到定义大小 150 x 150
random_im3 = tfs.RandomSizedCrop(150)(im)

# 随机翻转
h_filp = tfs.RandomHorizontalFlip()(im) # 随机水平翻转
v_flip = tfs.RandomVerticalFlip()(im)   # 随机竖直翻转

# 随机角度旋转
rot_im = tfs.RandomRotation(45)(im)

# 亮度、对比度和颜色的变化
# 亮度
bright_im = tfs.ColorJitter(brightness=1)(im) # 随机从 0 ~ 2 之间亮度变化,1 表示原图
# 对比度
contrast_im = tfs.ColorJitter(contrast=1)(im) # 随机从 0 ~ 2 之间对比度变化,1 表示原图
# 颜色
color_im = tfs.ColorJitter(hue=0.5)(im) # 随机从 -0.5 ~ 0.5 之间对颜色变化

# 使用 torchvision.transforms.Compose() 组合变换
im_aug = tfs.Compose([
    tfs.Resize(120),
    tfs.RandomHorizontalFlip(),
    tfs.RandomCrop(96),
    tfs.ColorJitter(brightness=0.5, contrast=0.5, hue=0.5)
])

im_aug(im)

8.数据标准化

猜你喜欢

转载自blog.csdn.net/koibiki/article/details/85114197
今日推荐