最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

39 實(shí)戰(zhàn) Kaggle 比賽:圖像分類(CIFAR-10)【動(dòng)手學(xué)深度學(xué)習(xí)v2

2023-08-01 17:27 作者:月蕪SA  | 我要投稿

CIFAR-10經(jīng)典分類實(shí)戰(zhàn)

在實(shí)踐中,圖像數(shù)據(jù)集通常以圖像文件的形式出現(xiàn)。 本節(jié)將從原始圖像文件開(kāi)始,然后逐步組織、讀取并將它們轉(zhuǎn)換為張量格式。

import collections
import math
import os
import shutil
'''shell util是Python的一個(gè)倒騰文件的東西'''
import pandas as pd
import torch
import torchvision
from torch import nn
from d2l import torch as d2l


比賽數(shù)據(jù)集分為訓(xùn)練集和測(cè)試集,其中訓(xùn)練集包含50000張、測(cè)試集包含300000張圖像。 在測(cè)試集中,10000張圖像將被用于評(píng)估,而剩下的290000張圖像將不會(huì)被進(jìn)行評(píng)估,包含它們只是為了防止手動(dòng)標(biāo)記測(cè)試集并提交標(biāo)記結(jié)果。 兩個(gè)數(shù)據(jù)集中的圖像都是png格式,高度和寬度均為32像素并有三個(gè)顏色通道(RGB)。 這些圖片共涵蓋10個(gè)類別:飛機(jī)、汽車、鳥(niǎo)類、貓、鹿、狗、青蛙、馬、船和卡車。為了便于入門,此處提供包含前1000個(gè)訓(xùn)練圖像和5個(gè)隨機(jī)測(cè)試圖像的數(shù)據(jù)集的小規(guī)模樣本。

#@save
d2l.DATA_HUB['cifar10_tiny'] = (d2l.DATA_URL + 'kaggle_cifar10_tiny.zip',
                                '2068874e4b9a9f0fb07ebe0ad2b29754449ccacd')

# 如果使用完整的Kaggle競(jìng)賽的數(shù)據(jù)集,設(shè)置demo為False
demo = True

if demo:
    data_dir = d2l.download_extract('cifar10_tiny')
else:
    data_dir = '../data/cifar-10/'


#@save
def read_csv_labels(fname):
    """讀取fname來(lái)給標(biāo)簽字典返回一個(gè)文件名"""
    with open(fname, 'r') as f:
        # 跳過(guò)文件頭行(列名)
        lines = f.readlines()[1:]
    tokens = [l.rstrip().split(',') for l in lines]
    return dict(((name, label) for name, label in tokens))

labels = read_csv_labels(os.path.join(data_dir, 'trainLabels.csv'))
print('# 訓(xùn)練樣本 :', len(labels))
print('# 類別 :', len(set(labels.values())))


# 訓(xùn)練樣本 : 1000
# 類別 : 10



#@save
def copyfile(filename, target_dir):
    """將文件復(fù)制到目標(biāo)目錄"""
    os.makedirs(target_dir, exist_ok=True)
    shutil.copy(filename, target_dir)

#@save
def reorg_train_valid(data_dir, labels, valid_ratio):
    """將驗(yàn)證集從原始的訓(xùn)練集中拆分出來(lái)"""
    # 訓(xùn)練數(shù)據(jù)集中樣本最少的類別中的樣本數(shù)
    n = collections.Counter(labels.values()).most_common()[-1][1]
    # 驗(yàn)證集中每個(gè)類別的樣本數(shù)
    n_valid_per_label = max(1, math.floor(n * valid_ratio))
    label_count = {}
    for train_file in os.listdir(os.path.join(data_dir, 'train')):
        label = labels[train_file.split('.')[0]]
        fname = os.path.join(data_dir, 'train', train_file)
        copyfile(fname, os.path.join(data_dir, 'train_valid_test',
                                     'train_valid', label))
        if label not in label_count or label_count[label] < n_valid_per_label:
            copyfile(fname, os.path.join(data_dir, 'train_valid_test',
                                         'valid', label))
            label_count[label] = label_count.get(label, 0) + 1
        else:
            copyfile(fname, os.path.join(data_dir, 'train_valid_test',
                                         'train', label))
    return n_valid_per_label


#@save
def reorg_test(data_dir):
    """在預(yù)測(cè)期間整理測(cè)試集,以方便讀取"""
    for test_file in os.listdir(os.path.join(data_dir, 'test')):
        copyfile(os.path.join(data_dir, 'test', test_file),
                 os.path.join(data_dir, 'train_valid_test', 'test',
                              'unknown'))


def reorg_cifar10_data(data_dir, valid_ratio):
    labels = read_csv_labels(os.path.join(data_dir, 'trainLabels.csv'))
    reorg_train_valid(data_dir, labels, valid_ratio)
    reorg_test(data_dir)


在這里,我們只將樣本數(shù)據(jù)集的批量大小設(shè)置為32。 在實(shí)際訓(xùn)練和測(cè)試中,應(yīng)該使用Kaggle競(jìng)賽的完整數(shù)據(jù)集,并將batch_size設(shè)置為更大的整數(shù),例如128。 我們將10%的訓(xùn)練樣本作為調(diào)整超參數(shù)的驗(yàn)證集。

batch_size = 32 if demo else 128
valid_ratio = 0.1
reorg_cifar10_data(data_dir, valid_ratio)


使用圖像增廣來(lái)解決過(guò)擬合的問(wèn)題。例如在訓(xùn)練中,我們可以隨機(jī)水平翻轉(zhuǎn)圖像。 我們還可以對(duì)彩色圖像的三個(gè)RGB通道執(zhí)行標(biāo)準(zhǔn)化。 下面,我們列出了其中一些可以調(diào)整的操作。


transform_train = torchvision.transforms.Compose([
    # 在高度和寬度上將圖像放大到40像素的正方形
    torchvision.transforms.Resize(40),
    # 隨機(jī)裁剪出一個(gè)高度和寬度均為40像素的正方形圖像,
    # 生成一個(gè)面積為原始圖像面積0.64~1倍的小正方形,
    # 然后將其縮放為高度和寬度均為32像素的正方形
    torchvision.transforms.RandomResizedCrop(32, scale=(0.64, 1.0),
                                                   ratio=(1.0, 1.0)),
    torchvision.transforms.RandomHorizontalFlip(),
    torchvision.transforms.ToTensor(),
    # 標(biāo)準(zhǔn)化圖像的每個(gè)通道
    torchvision.transforms.Normalize([0.4914, 0.4822, 0.4465],
                                     [0.2023, 0.1994, 0.2010])])


在測(cè)試期間,我們只對(duì)圖像執(zhí)行標(biāo)準(zhǔn)化,以消除評(píng)估結(jié)果中的隨機(jī)性。


transform_test = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor(),
    torchvision.transforms.Normalize([0.4914, 0.4822, 0.4465],
                                     [0.2023, 0.1994, 0.2010])])


接下來(lái),我們讀取由原始圖像組成的數(shù)據(jù)集,每個(gè)樣本都包括一張圖片和一個(gè)標(biāo)簽。


train_ds, train_valid_ds = [torchvision.datasets.ImageFolder(
    os.path.join(data_dir, 'train_valid_test', folder),
    transform=transform_train) for folder in ['train', 'train_valid']]

valid_ds, test_ds = [torchvision.datasets.ImageFolder(
    os.path.join(data_dir, 'train_valid_test', folder),
    transform=transform_test) for folder in ['valid', 'test']]


在訓(xùn)練期間,我們需要指定上面定義的所有圖像增廣操作。 當(dāng)驗(yàn)證集在超參數(shù)調(diào)整過(guò)程中用于模型評(píng)估時(shí),不應(yīng)引入圖像增廣的隨機(jī)性。 在最終預(yù)測(cè)之前,我們根據(jù)訓(xùn)練集和驗(yàn)證集組合而成的訓(xùn)練模型進(jìn)行訓(xùn)練,以充分利用所有標(biāo)記的數(shù)據(jù)。


train_iter, train_valid_iter = [torch.utils.data.DataLoader(
    dataset, batch_size, shuffle=True, drop_last=True)
    for dataset in (train_ds, train_valid_ds)]

valid_iter = torch.utils.data.DataLoader(valid_ds, batch_size, shuffle=False,
                                         drop_last=True)

test_iter = torch.utils.data.DataLoader(test_ds, batch_size, shuffle=False,
                                        drop_last=False)


定義了?7.6節(jié)中描述的Resnet-18模型。

def get_net():
    num_classes = 10
    net = d2l.resnet18(num_classes, 3)
    return net

loss = nn.CrossEntropyLoss(reduction="none")


定義了模型訓(xùn)練函數(shù)train

注意:這里的lr_period和lr_decay是用于對(duì)learning rate進(jìn)行衰退的超參數(shù)。意思是在lr_period個(gè)輪次后lr將與lr_decay相乘從而衰退。


def train(net, train_iter, valid_iter, num_epochs, lr, wd, devices, lr_period,
          lr_decay):
    trainer = torch.optim.SGD(net.parameters(), lr=lr, momentum=0.9,
                              weight_decay=wd)
    scheduler = torch.optim.lr_scheduler.StepLR(trainer, lr_period, lr_decay)
    num_batches, timer = len(train_iter), d2l.Timer()
    legend = ['train loss', 'train acc']
    if valid_iter is not None:
        legend.append('valid acc')
    animator = d2l.Animator(xlabel='epoch', xlim=[1, num_epochs],
                            legend=legend)
    net = nn.DataParallel(net, device_ids=devices).to(devices[0])
    for epoch in range(num_epochs):
        net.train()
        metric = d2l.Accumulator(3)
        for i, (features, labels) in enumerate(train_iter):
            timer.start()
            l, acc = d2l.train_batch_ch13(net, features, labels,
                                          loss, trainer, devices)
            metric.add(l, acc, labels.shape[0])
            timer.stop()
            if (i + 1) % (num_batches // 5) == 0 or i == num_batches - 1:
                animator.add(epoch + (i + 1) / num_batches,
                             (metric[0] / metric[2], metric[1] / metric[2],
                              None))
        if valid_iter is not None:
            valid_acc = d2l.evaluate_accuracy_gpu(net, valid_iter)
            animator.add(epoch + 1, (None, None, valid_acc))
        scheduler.step()
    measures = (f'train loss {metric[0] / metric[2]:.3f}, '
                f'train acc {metric[1] / metric[2]:.3f}')
    if valid_iter is not None:
        measures += f', valid acc {valid_acc:.3f}'
    print(measures + f'\n{metric[2] * num_epochs / timer.sum():.1f}'
          f' examples/sec on {str(devices)}')


現(xiàn)在,我們可以訓(xùn)練和驗(yàn)證模型了,而以下所有超參數(shù)都可以調(diào)整。 例如,我們可以增加周期的數(shù)量。當(dāng)lr_periodlr_decay分別設(shè)置為4和0.9時(shí),優(yōu)化算法的學(xué)習(xí)速率將在每4個(gè)周期乘以0.9。 為便于演示,我們?cè)谶@里只訓(xùn)練20個(gè)周期。


devices, num_epochs, lr, wd = d2l.try_all_gpus(), 20, 2e-4, 5e-4
lr_period, lr_decay, net = 4, 0.9, get_net()
train(net, train_iter, valid_iter, num_epochs, lr, wd, devices, lr_period,
      lr_decay)


train loss 0.668, train acc 0.781, valid acc 0.453
1022.7 examples/sec on [device(type='cuda', index=0), device(type='cuda', index=1)]


知識(shí)補(bǔ)充:

數(shù)據(jù)增廣方法中,標(biāo)準(zhǔn)化處理normalize函數(shù)中的參數(shù)是從imagenet中得到的,實(shí)際取任何值都可以。影響不大

 # 標(biāo)準(zhǔn)化圖像的每個(gè)通道
    torchvision.transforms.Normalize([0.4914, 0.4822, 0.4465],
                                     [0.2023, 0.1994, 0.2010])])


·weight decay和 lr decay是不同的。

ld是為了使得模型盡快收斂。

wd是為了normalization

ld的設(shè)置最好能使得lr在前期保持一個(gè)較大得值。后期再變小。比較常用的辦法是用cos函數(shù)來(lái)實(shí)現(xiàn)。





39 實(shí)戰(zhàn) Kaggle 比賽:圖像分類(CIFAR-10)【動(dòng)手學(xué)深度學(xué)習(xí)v2的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
长岭县| 文登市| 玛沁县| 邹城市| 观塘区| 台中县| 潞西市| 尼玛县| 阿瓦提县| 聂拉木县| 新乐市| 临夏市| 芒康县| 南宫市| 甘谷县| 来凤县| 邵阳市| 惠州市| 许昌县| 固始县| 罗源县| 平罗县| 永修县| 颍上县| 高陵县| 华池县| 当涂县| 宁强县| 永善县| 九龙坡区| 东莞市| 尉氏县| 长丰县| 定结县| 祁连县| 措勤县| 灵宝市| 大名县| 古浪县| 临西县| 如皋市|