Pytorch_Part2_データモジュール

A、データローダーおよびデータセット

ここに画像を挿入説明

1.データローダー

ここに画像を挿入説明

エポック:すべてのトレーニングサンプルはエポックと呼ばれ、モデルに入力されています

反復:反復と呼ばれるモデルに入力のサンプル数、

BATCHSIZE:バッチサイズ、決定エポックどのように多くのイテレーション

サンプルの総数:87、BATCHSIZE:8

1エポック= 10繰り返し?drop_last =真

1エポック= 11繰り返し?drop_last =偽

2.データセット

ここに画像を挿入説明
人民元バイナリ例:に従ってRMB_data 8:1:1は、列車、テスト、有効な3つのグループに基づくデータセットの構築に分かれています

class RMBDataset(Dataset):
    def __init__(self, data_dir, transform=None):
        """
        rmb面额分类任务的Dataset
        :param data_dir: str, 数据集所在路径
        :param transform: torch.transform,数据预处理
        """
        self.label_name = {"1": 0, "100": 1}
        self.data_info = self.get_img_info(data_dir)  # data_info存储所有图片路径和标签,在DataLoader中通过index读取样本
        self.transform = transform

    def __getitem__(self, index):
        path_img, label = self.data_info[index]
        img = Image.open(path_img).convert('RGB')     # 0~255

        if self.transform is not None:
            img = self.transform(img)   # 在这里做transform,转为tensor等等

        return img, label

    def __len__(self):
        return len(self.data_info)

    @staticmethod
    def get_img_info(data_dir):
        data_info = list()
        for root, dirs, _ in os.walk(data_dir):
            # 遍历类别
            for sub_dir in dirs:
                img_names = os.listdir(os.path.join(root, sub_dir))
                img_names = list(filter(lambda x: x.endswith('.jpg'), img_names))

                # 遍历图片
                for i in range(len(img_names)):
                    img_name = img_names[i]
                    path_img = os.path.join(root, sub_dir, img_name)
                    label = rmb_label[sub_dir]
                    data_info.append((path_img, int(label)))

        return data_info

データセットとデータローダーの例:
ここに画像を挿入説明

# ============================ step 1/5 数据 ============================

split_dir = os.path.join("..", "..", "rmb_split")
train_dir = os.path.join(split_dir, "train")
valid_dir = os.path.join(split_dir, "valid")

norm_mean = [0.485, 0.456, 0.406]
norm_std = [0.229, 0.224, 0.225]

train_transform = transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.RandomCrop(32, padding=4),	
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),
])	

valid_transform = transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),
])

# 构建MyDataset实例
train_data = RMBDataset(data_dir=train_dir, transform=train_transform)
valid_data = RMBDataset(data_dir=valid_dir, transform=valid_transform)

# 构建DataLoder
train_loader = DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)	# 每一个epoch样本顺序不同
valid_loader = DataLoader(dataset=valid_data, batch_size=BATCH_SIZE)

ここに画像を挿入説明ここに画像を挿入説明ここに画像を挿入説明

第二に、前処理画像--transform

ここに画像を挿入説明

torchvision.transforms: 一般的な画像前処理方法

  • のデータセンター
  • データ標準化
  • スケーリング
  • 切り取ります
  • 回転
  • 転倒
  • 充填
  • ノイズを追加します
  • グレースケール変換
  • 線形変換
  • アフィン変換
  • 明度、彩度、コントラスト変換

画像強調:データの豊富なセットは、モデルの汎化能力を向上させます

# 对图像进行有序的组合与包装
train_transform = transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.RandomCrop(32, padding=4),	# 随机裁剪
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),	# 标准化
])	

valid_transform = transforms.Compose([
    transforms.Resize((32, 32)),	# 验证时不需要进行图像增强
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),
])

ここに画像を挿入説明ここに画像を挿入説明
標準化は、収束モデルをスピードアップすることができます!

三、画像強調を変換(A)

また、トレーニングを変換するために設定されている拡張データ、データの増幅、として知られているデータ拡張は、トレーニングは豊か、よりので、モデルの一般設定しました。

ここに画像を挿入説明ここに画像を挿入説明

1.カット

ここに画像を挿入説明
ここに画像を挿入説明

  • padding_mode:塗りつぶしモード、4つのモードがあります
    • 1、定数:充填して画素値を設定します
    • 図2に示すように、エッジ:画像のエッジ画素によって決定された画素値
    • 3反映:ミラーは、ピクセルは、例えば、最後の画像ではなく、充填される:[1,2,3,4]→[3,2,1,2,3,4,3,2]
    • 4、対称:ミラーが充填され、最後の画素の画像、例えば:[1,2,3,4]→[2,1,1,2,3,4,4,3]
    • 充填:充填する時定数を、画素値
      ここに画像を挿入説明

2.フリップと回し

ここに画像を挿入説明
ここに画像を挿入説明
中心=(0,0)#は、左上隅を回転させます

、センターのためだけの左上隅を回転させ、失われた情報を復元する方法を拡張していません

四つは、イメージインテンシファイア(II)に変換します

1.画像変換

ここに画像を挿入説明
ときpadding_modeの鏡像、フィル無効

ここに画像を挿入説明
ここに画像を挿入説明
ここに画像を挿入説明ここに画像を挿入説明
ここに画像を挿入説明

テンソル上で直接動作します。

transforms.ToTensor()
transforms.RandomErasing(p=1, scale=(0.02,0.33), ratio=(0.5,1), value=(254/255,0,0))

前記限り、値が文字列、ランダムな色であるとして、
ここに画像を挿入説明

変換操作2

ここに画像を挿入説明

3.カスタム変換

ここに画像を挿入説明

class AddPepperNoise(object):
    """增加椒盐噪声
    Args:
        snr (float): Signal Noise Rate
        p (float): 概率值,依概率执行该操作
    """

    def __init__(self, snr, p=0.9):
        assert isinstance(snr, float) or (isinstance(p, float))
        self.snr = snr
        self.p = p

    def __call__(self, img):
        """
        Args:
            img (PIL Image): PIL Image
        Returns:
            PIL Image: PIL image.
        """
        if random.uniform(0, 1) < self.p:
            img_ = np.array(img).copy()
            h, w, c = img_.shape
            signal_pct = self.snr
            noise_pct = (1 - self.snr)
            mask = np.random.choice((0, 1, 2), size=(h, w, 1), p=[signal_pct, noise_pct/2., noise_pct/2.])
            mask = np.repeat(mask, c, axis=2)
            img_[mask == 1] = 255   # 盐噪声:白
            img_[mask == 2] = 0     # 椒噪声:黑
            return Image.fromarray(img_.astype('uint8')).convert('RGB')
        else:
            return img

4.戦闘

原理:トレーニングセットとテストセットが近づいてみよう

  • 空間的位置:翻訳
  • :グレースケール、カラーディザリング
  • 形状:アフィン変換
  • シーンコンテキスト:閉塞、充填
  • ......
    ここに画像を挿入説明
    ここに画像を挿入説明
    ここに画像を挿入説明

オリジナルの分析は、主な問題は、グレースケールに直接入力画像の色合いです

train_transform = transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.RandomCrop(32, padding=4),
    transforms.RandomGrayscale(p=1),
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),
])

出典:

# -*- coding: utf-8 -*-
"""
# @file name  : RMB_data_augmentation.py
# @author     : tingsongyu
# @date       : 2019-09-16 10:08:00
# @brief      : 人民币分类模型数据增强实验
"""
import os
import random
import numpy as np
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
import torch.optim as optim
from matplotlib import pyplot as plt
from model.lenet import LeNet
from tools.my_dataset import RMBDataset
from tools.common_tools import transform_invert


def set_seed(seed=1):
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)


set_seed()  # 设置随机种子
rmb_label = {"1": 0, "100": 1}

# 参数设置
MAX_EPOCH = 10
BATCH_SIZE = 16
LR = 0.01
log_interval = 10
val_interval = 1

# ============================ step 1/5 数据 ============================

split_dir = os.path.join("..", "rmb_split")
train_dir = os.path.join(split_dir, "train")
valid_dir = os.path.join(split_dir, "valid")

norm_mean = [0.485, 0.456, 0.406]
norm_std = [0.229, 0.224, 0.225]

train_transform = transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.RandomCrop(32, padding=4),
    transforms.RandomGrayscale(p=1),
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),
])


valid_transform = transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.RandomGrayscale(p=1),
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),
])

# 构建MyDataset实例
train_data = RMBDataset(data_dir=train_dir, transform=train_transform)
valid_data = RMBDataset(data_dir=valid_dir, transform=valid_transform)

# 构建DataLoder
train_loader = DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
valid_loader = DataLoader(dataset=valid_data, batch_size=BATCH_SIZE)

# ============================ step 2/5 模型 ============================

net = LeNet(classes=2)
net.initialize_weights()

# ============================ step 3/5 损失函数 ============================
criterion = nn.CrossEntropyLoss()                                                   # 选择损失函数

# ============================ step 4/5 优化器 ============================
optimizer = optim.SGD(net.parameters(), lr=LR, momentum=0.9)                        # 选择优化器
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)     # 设置学习率下降策略

# ============================ step 5/5 训练 ============================
train_curve = list()
valid_curve = list()

for epoch in range(MAX_EPOCH):

    loss_mean = 0.
    correct = 0.
    total = 0.

    net.train()
    for i, data in enumerate(train_loader):

        # forward
        inputs, labels = data
        outputs = net(inputs)

        # backward
        optimizer.zero_grad()
        loss = criterion(outputs, labels)
        loss.backward()

        # update weights
        optimizer.step()

        # 统计分类情况
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).squeeze().sum().numpy()

        # 打印训练信息
        loss_mean += loss.item()
        train_curve.append(loss.item())
        if (i+1) % log_interval == 0:
            loss_mean = loss_mean / log_interval
            print("Training:Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
                epoch, MAX_EPOCH, i+1, len(train_loader), loss_mean, correct / total))
            loss_mean = 0.

    scheduler.step()  # 更新学习率

    # validate the model
    if (epoch+1) % val_interval == 0:

        correct_val = 0.
        total_val = 0.
        loss_val = 0.
        net.eval()
        with torch.no_grad():
            for j, data in enumerate(valid_loader):
                inputs, labels = data
                outputs = net(inputs)
                loss = criterion(outputs, labels)

                _, predicted = torch.max(outputs.data, 1)
                total_val += labels.size(0)
                correct_val += (predicted == labels).squeeze().sum().numpy()

                loss_val += loss.item()

            valid_curve.append(loss_val)
            print("Valid:\t Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
                epoch, MAX_EPOCH, j+1, len(valid_loader), loss_val, correct / total))


train_x = range(len(train_curve))
train_y = train_curve

train_iters = len(train_loader)
valid_x = np.arange(1, len(valid_curve)+1) * train_iters*val_interval # 由于valid中记录的是epochloss,需要对记录点进行转换到iterations
valid_y = valid_curve

plt.plot(train_x, train_y, label='Train')
plt.plot(valid_x, valid_y, label='Valid')

plt.legend(loc='upper right')
plt.ylabel('loss value')
plt.xlabel('Iteration')
plt.show()

# ============================ inference ============================

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
test_dir = os.path.join(BASE_DIR, "test_data")

test_data = RMBDataset(data_dir=test_dir, transform=valid_transform)
valid_loader = DataLoader(dataset=test_data, batch_size=1)

for i, data in enumerate(valid_loader):
    # forward
    inputs, labels = data
    outputs = net(inputs)
    _, predicted = torch.max(outputs.data, 1)

    rmb = 1 if predicted.numpy()[0] == 0 else 100

    img_tensor = inputs[0, ...]  # C H W
    img = transform_invert(img_tensor, train_transform)
    plt.imshow(img)
    plt.title("LeNet got {} Yuan".format(rmb))
    plt.show()
    plt.pause(0.5)
    plt.close()

おすすめ

転載: www.cnblogs.com/RyanSun17373259/p/12575945.html