国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Pytorch自定義數(shù)據(jù)集模型完整訓(xùn)練流程

這篇具有很好參考價(jià)值的文章主要介紹了Pytorch自定義數(shù)據(jù)集模型完整訓(xùn)練流程。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

Pytorch模型自定義數(shù)據(jù)集訓(xùn)練流程

我們以kaggle競賽中的貓狗大戰(zhàn)數(shù)據(jù)集為例搭建Pytorch自定義數(shù)據(jù)集模型訓(xùn)練的完整流程。

1、任務(wù)描述

Cats vs. Dogs(貓狗大戰(zhàn))數(shù)據(jù)集是Kaggle大數(shù)據(jù)競賽某一年的一道賽題,利用給定的數(shù)據(jù)集,用算法實(shí)現(xiàn)貓和狗的識別。 其中包含了訓(xùn)練集和測試集,訓(xùn)練集中貓和狗的圖片數(shù)量都是12500張且按順序排序,測試集中貓和狗混合亂序圖片一共12500張。
下載地址:https://www.kaggle.com/c/dogs-vs-cats/data

Pytorch自定義數(shù)據(jù)集模型完整訓(xùn)練流程

卷積神經(jīng)網(wǎng)絡(luò)(CNN)是一類包含卷積計(jì)算且具有深度結(jié)構(gòu)的前饋神經(jīng)網(wǎng)絡(luò),是深度學(xué)習(xí)的代表算法之一。卷積神經(jīng)網(wǎng)絡(luò)具有表征學(xué)習(xí)能力,能夠按其階層結(jié)構(gòu)對輸入信息進(jìn)行平移不變分類,因此也被稱為“平移不變?nèi)斯ど窠?jīng)網(wǎng)絡(luò)”。
默認(rèn)對圖像分類各種算法已經(jīng)熟悉,卷積、池化、批量歸一化、全連接等各種結(jié)構(gòu)具體細(xì)節(jié)這里不討論,有不懂的可自行學(xué)習(xí)。

2、導(dǎo)入各種需要用到的包

import torch
import torchvision
from torchvision import datasets, transforms
import torch.utils.data
import matplotlib.pyplot as plt
from torch.utils.data import TensorDataset,DataLoader,Dataset
from torch.utils.tensorboard import SummaryWriter
import torch.nn.functional as F
from torch import nn
import numpy as np
import os
import shutil
from PIL import Image
import warnings
warnings.filterwarnings("ignore")

3、分割數(shù)據(jù)集

下載貓狗大戰(zhàn)數(shù)據(jù)集,并解壓。
解壓完成后,通過以下代碼實(shí)現(xiàn)數(shù)據(jù)集預(yù)處理(剔除不能正常打開的圖片,打亂數(shù)據(jù)集等);然后對數(shù)據(jù)集進(jìn)行分割,其中90%的數(shù)據(jù)集作為train訓(xùn)練,另外10%的數(shù)據(jù)集作為test測試。

# 分割數(shù)據(jù)集,將全部數(shù)據(jù)分成0.9的Train和0.1的Test
source_path = r"./kagglecatsanddogs_5340/PetImages/"
# 如果不存在文件夾要新建一個(gè)
if not os.path.exists(os.path.join(source_path, "train")):
    os.mkdir(os.path.join(source_path, "train"))
train_dir = os.path.join(source_path, "train")

if not os.path.exists(os.path.join(source_path, "test")):
    os.mkdir(os.path.join(source_path, "test"))
test_dir = os.path.join(source_path,"test")

## 將Cat和Dog文件夾全部移到train目錄下,然后再從train目錄下移動(dòng)10%到test目錄下
for category_dir in os.listdir(source_path):
    if category_dir not in ["train", "test"]:
        shutil.move(os.path.join(source_path,category_dir), os.path.join(source_path,"train"))
            
## 開始移動(dòng),移動(dòng)前先剔除不能正常打開的圖片
for dir in os.listdir(train_dir):
    category_dir_path = os.path.join(train_dir, dir)
    image_file_list = os.listdir(category_dir_path)   # 取出全部圖片文件
    for file in image_file_list:
        try:
            Image.open(os.path.join(category_dir_path, file))
        except:
            os.remove(os.path.join(category_dir_path, file))
            image_file_list.remove(file)
    np.random.shuffle(image_file_list)
    test_num = int(0.1*len(image_file_list))
 
    #移動(dòng)10%文件到對應(yīng)目錄
    if not os.path.exists(os.path.join(test_dir,dir)):
        os.mkdir(os.path.join(test_dir,dir))
    if len(os.listdir(os.path.join(test_dir,dir))) < test_num:  # 只有未移動(dòng)過才需要移動(dòng),否則每運(yùn)行一次都會(huì)移動(dòng)一下
        for i in range(test_num):
            shutil.move(os.path.join(category_dir_path,image_file_list[i]), os.path.join(test_dir,dir,image_file_list[i]))

4、將數(shù)據(jù)轉(zhuǎn)成pytorch標(biāo)準(zhǔn)的DataLoader輸入格式

1、先對數(shù)據(jù)集進(jìn)行預(yù)處理,包括resize成224*224的尺寸,因?yàn)関gg_net模型需要的輸入尺寸為[N, 224, 224, 3];隨機(jī)翻轉(zhuǎn),隨機(jī)旋轉(zhuǎn)等,另外對數(shù)據(jù)集做Normalize標(biāo)準(zhǔn)化,其中的mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.2]是從ImageNet數(shù)據(jù)集上的百萬張圖片中隨機(jī)抽樣計(jì)算得到的,以上這些內(nèi)容主要是數(shù)據(jù)增強(qiáng),增強(qiáng)模型的泛化性,有更好的預(yù)測效果。
2、然后將預(yù)處理好的數(shù)據(jù)轉(zhuǎn)成pytorch標(biāo)準(zhǔn)的DataLoader輸入格式,。

# 數(shù)據(jù)預(yù)處理
transform = transforms.Compose([
    transforms.RandomResizedCrop(224),# 對圖像進(jìn)行隨機(jī)的crop以后再resize成固定大小
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.2]),  # ImageNet全部圖片的平均值和標(biāo)準(zhǔn)差
    transforms.RandomRotation(20), # 隨機(jī)旋轉(zhuǎn)角度
    transforms.RandomHorizontalFlip(p=0.5), # 隨機(jī)水平翻轉(zhuǎn)
])
 
# 讀取數(shù)據(jù)
root = source_path
train_dataset = datasets.ImageFolder(root + '/train', transform)
test_dataset = datasets.ImageFolder(root + '/test', transform)
 
# 導(dǎo)入數(shù)據(jù)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=16, shuffle=False)

5、導(dǎo)入預(yù)訓(xùn)練模型,并修改分類層

1、定義device,如果有GPU模型訓(xùn)練會(huì)自動(dòng)用GPU訓(xùn)練,否則會(huì)使用CPU;使用GPU訓(xùn)練,只需在模型、數(shù)據(jù)、損失函數(shù)上使用cuda()就行。
2、這邊默認(rèn)對分類圖像算法都熟悉,可以自己構(gòu)建vgg16的完整網(wǎng)絡(luò),在貓狗數(shù)據(jù)集上重新訓(xùn)練。也可以下載預(yù)訓(xùn)練模型,由于原網(wǎng)絡(luò)的分類輸出是1000類別的,但是我們的圖片只有兩類,所以需要修改分類層,讓模型能夠適配我們的訓(xùn)練數(shù)據(jù)集。

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
vgg16 = torchvision.models.vgg16(pretrained=True).to(device)
print(vgg16)

inputs = torch.rand(1, 3, 224, 224)  # 拿一個(gè)隨機(jī)tensor測試一下網(wǎng)絡(luò)的輸出是否滿足預(yù)期
output = vgg16(inputs.to(device))
print("原始VGG網(wǎng)絡(luò)的輸出:",output.size())

# 構(gòu)建新的全連接層
vgg16.classifier = torch.nn.Sequential(torch.nn.Linear(25088, 100),
                                       torch.nn.ReLU(),
                                       torch.nn.Dropout(p=0.5),
                                       torch.nn.Linear(100, 2)).to(device)
inputs = torch.rand(1, 3, 224, 224)
output = vgg16(inputs.to(device))
print("新構(gòu)建的VGG網(wǎng)絡(luò)的輸出:",output.size())

6、開始模型訓(xùn)練

開始模型訓(xùn)練,我們這里只訓(xùn)練全連接分類層,將特征層的梯度requires_grad設(shè)置為False,特征層的參數(shù)將不參與訓(xùn)練。
訓(xùn)練過程中保存效果最好的網(wǎng)絡(luò)模型,以防掉線,可以從斷點(diǎn)開始繼續(xù)訓(xùn)練,同時(shí)也可以用來做預(yù)測。
訓(xùn)練完成后,保存訓(xùn)練好的網(wǎng)絡(luò)和參數(shù),后面可以加載模型做預(yù)測。

writer = SummaryWriter("./logs/model")
loss_func = nn.CrossEntropyLoss().to(device)
learning_rate = 0.0001

#如果我們想只訓(xùn)練模型的全連接層
for param in vgg16.features.parameters():
    param.requires_grad = False
optimizer = torch.optim.Adam(vgg16.parameters(),lr=learning_rate)

## 斷點(diǎn)續(xù)訓(xùn)開始
resume = False
if resume:
    # 恢復(fù)上次的訓(xùn)練狀態(tài)
    print("Resume from checkpoint...")
    checkpoint = torch.load("./models/checkpoint/ckpt_best.pth")
    vgg16.load_state_dict(checkpoint['net'])
    optimizer.load_state_dict(checkpoint['optimizer'])
    
    epoch_ = checkpoint['epoch'] + 1
    #從上次記錄的損失和正確率接著記錄
    loss = checkpoint['loss']
    total_test_loss = checkpoint["total_test_loss"]
    total_acc = checkpoint["total_acc"]
else:
    total_acc = 0.0
    epoch_ = 0

##訓(xùn)練開始
total_train_step = 0
total_test_step = 0
min_acc = 0.0
for epoch in range(epoch_ , 10):
    print("-----------train epoch {} start---------------".format(epoch))
    vgg16.train()
    for data in train_loader:
        optimizer.zero_grad()
        img, label = data
        output = vgg16(img.to(device))
        loss = loss_func(output, label.to(device))
        loss.backward()
        optimizer.step()
        total_train_step += 1
        
        if total_train_step % 10 == 0:
            print("steps: {}, train_loss: {}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss", loss.item(), total_train_step)


    ## 測試開始,看訓(xùn)練效果是否滿足預(yù)期
    total_test_loss = 0
    vgg16.eval()
    with torch.no_grad():
        for data in test_loader:
            optimizer.zero_grad()
            img, label = data
            output = vgg16(img.to(device))
            loss = loss_func(output, label.to(device))
            total_test_loss += loss
            accuary = torch.sum(output.argmax(1) == label.to(device))
            total_acc += accuary
    total_test_step += 1
    val_acc = total_acc.item() / len(test_dataset)
    total_acc = 0.0
    
    ## 保存Acc最小的模型
    if val_acc > min_acc:
        min_acc = val_acc
        torch.save(vgg16.state_dict(), "./models/2classes_vgg16_weight.pth")
        print("測試Acc: {} \n 模型保存成功!".format(min_acc))

    # 保存模型和訓(xùn)練參數(shù)的全相關(guān)信息,方便斷點(diǎn)續(xù)訓(xùn)
    checkpoint = {
        "net": vgg16.state_dict(),
        'optimizer':optimizer.state_dict(),
        "loss": loss,
        "epoch": epoch,
        "total_test_loss": total_test_loss,
        "total_acc": total_acc
    }
    if not os.path.exists("./models/checkpoint"):
        os.mkdir("./models/checkpoint")
    torch.save(checkpoint, './models/checkpoint/ckpt_best.pth')

    print("測試loss: {}".format(total_test_loss.item()))
    print("測試Acc: {}".format(val_acc))
    writer.add_scalar("test_loss", total_test_loss.item(), total_test_step)
    writer.add_scalar("test_Acc", val_acc, total_test_step)
    
torch.save(vgg16.state_dict(), "./models/2classes_vgg16_latest_{}.pth".format(val_acc))

7、利用訓(xùn)好的模型做預(yù)測

拿出一張圖片做預(yù)測,首先導(dǎo)入預(yù)訓(xùn)練模型,同樣改掉分類層,然后導(dǎo)入預(yù)訓(xùn)練權(quán)重,預(yù)測圖片類別,輸出標(biāo)簽值和預(yù)測類別。文章來源地址http://www.zghlxwxcb.cn/news/detail-423360.html

import matplotlib.pyplot as plt
img_path = r"./kagglecatsanddogs_5340/PetImages/test/Cat/1381.jpg"   # 拿出要預(yù)測的圖片
image = Image.open(img_path).convert("RGB")
image.show()
    
vgg16_pred = torchvision.models.vgg16(pretrained=True)
vgg16_pred.classifier = torch.nn.Sequential(torch.nn.Linear(25088, 100),
                                       torch.nn.ReLU(),
                                       torch.nn.Dropout(p=0.5),
                                       torch.nn.Linear(100, 2))

transform = torchvision.transforms.Compose([
    torchvision.transforms.Resize((224,224), interpolation=2),
    torchvision.transforms.ToTensor()
])
vgg16_pred.load_state_dict(torch.load("./models/2classes_vgg16_weight_15_0.9467513434294089.pth", map_location=torch.device('cpu')))
print(vgg16_pred)

image = transform(image)
print(image.size())
image = torch.reshape(image, [1,3,224,224])
vgg16_pred.eval()
with torch.no_grad():
    output = vgg16_pred(image)
# print("預(yù)測值為:",output)
print("預(yù)測標(biāo)簽為:",output.argmax(1).item())
print("預(yù)測動(dòng)物為:",train_dataset.classes[output.argmax(1)])

到了這里,關(guān)于Pytorch自定義數(shù)據(jù)集模型完整訓(xùn)練流程的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包