pytorch 入门笔记

11 篇文章 0 订阅
1 篇文章 0 订阅

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.数据标准化

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值