婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 基于PyTorch實現(xiàn)一個簡單的CNN圖像分類器

基于PyTorch實現(xiàn)一個簡單的CNN圖像分類器

熱門標簽:地圖標注面積 小蘇云呼電話機器人 佛山400電話辦理 朝陽手機外呼系統(tǒng) 儋州電話機器人 北京電銷外呼系統(tǒng)加盟 所得系統(tǒng)電梯怎樣主板設(shè)置外呼 北瀚ai電銷機器人官網(wǎng)手機版 市場上的電銷機器人

pytorch中文網(wǎng):https://www.pytorchtutorial.com/
pytorch官方文檔:https://pytorch.org/docs/stable/index.html

一. 加載數(shù)據(jù)

Pytorch的數(shù)據(jù)加載一般是用torch.utils.data.Dataset與torch.utils.data.Dataloader兩個類聯(lián)合進行。我們需要繼承Dataset來定義自己的數(shù)據(jù)集類,然后在訓練時用Dataloader加載自定義的數(shù)據(jù)集類。

1. 繼承Dataset類并重寫關(guān)鍵方法

pytorch的dataset類有兩種:Map-style datasets和Iterable-style datasets。前者是我們常用的結(jié)構(gòu),而后者是當數(shù)據(jù)集難以(或不可能)進行隨機讀取時使用。在這里我們實現(xiàn)Map-style dataset。
繼承torch.utils.data.Dataset后,需要重寫的方法有:__len__與__getitem__方法,其中__len__方法需要返回所有數(shù)據(jù)的數(shù)量,而__getitem__則是要依照給出的數(shù)據(jù)索引獲取對應(yīng)的tensor類型的Sample,除了這兩個方法以外,一般還需要實現(xiàn)__init__方法來初始化一些變量。話不多說,直接上代碼。

'''
包括了各種數(shù)據(jù)集的讀取處理,以及圖像相關(guān)處理方法
'''
from torch.utils.data import Dataset
import torch
import os
import cv2
from Config import mycfg
import random
import numpy as np


class ImageClassifyDataset(Dataset):
    def __init__(self, imagedir, labelfile, classify_num, train=True):
    	'''
    	這里進行一些初始化操作。
    	'''
        self.imagedir = imagedir
        self.labelfile = labelfile
        self.classify_num = classify_num
        self.img_list = []
        # 讀取標簽
        with open(self.labelfile, 'r') as fp:
            lines = fp.readlines()
            for line in lines:
                filepath = os.path.join(self.imagedir, line.split(";")[0].replace('\\', '/'))
                label = line.split(";")[1].strip('\n')
                self.img_list.append((filepath, label))
        if not train:
            self.img_list = random.sample(self.img_list, 50)

    def __len__(self):
        return len(self.img_list)
        
    def __getitem__(self, item):
	    '''
	    這個函數(shù)是關(guān)鍵,通過item(索引)來取數(shù)據(jù)集中的數(shù)據(jù),
	    一般來說在這里才將圖像數(shù)據(jù)加載入內(nèi)存,之前存的是圖像的保存路徑
	    '''
        _int_label = int(self.img_list[item][1])	# label直接用0,1,2,3,4...表示不同類別
        label = torch.tensor(_int_label,dtype=torch.long)
        img = self.ProcessImgResize(self.img_list[item][0])
        return img, label

    def ProcessImgResize(self, filename):
    	'''
    	對圖像進行一些預處理
    	'''
        _img = cv2.imread(filename)
        _img = cv2.resize(_img, (mycfg.IMG_WIDTH, mycfg.IMG_HEIGHT), interpolation=cv2.INTER_CUBIC)
        _img = _img.transpose((2, 0, 1))
        _img = _img / 255
        _img = torch.from_numpy(_img)
        _img = _img.to(torch.float32)
        return _img

有一些的數(shù)據(jù)集類一般還會傳入一個transforms函數(shù)來構(gòu)造一個圖像預處理序列,傳入transforms函數(shù)的一個好處是作為參數(shù)傳入的話可以對一些非本地數(shù)據(jù)集中的數(shù)據(jù)進行操作(比如直接通過torchvision獲取的一些預存數(shù)據(jù)集CIFAR10等等),除此之外就是torchvision.transforms里面有一些預定義的圖像操作函數(shù),可以直接像拼積木一樣拼成一個圖像處理序列,很方便。我這里因為是用我自己下載到本地的數(shù)據(jù)集,而且比較簡單就直接用自己的函數(shù)來操作了。

2. 使用Dataloader加載數(shù)據(jù)

實例化自定義的數(shù)據(jù)集類ImageClassifyDataset后,將其傳給DataLoader作為參數(shù),得到一個可遍歷的數(shù)據(jù)加載器。可以通過參數(shù)batch_size控制批處理大小,shuffle控制是否亂序讀取,num_workers控制用于讀取數(shù)據(jù)的線程數(shù)量。

from torch.utils.data import DataLoader
from MyDataset import ImageClassifyDataset

dataset = ImageClassifyDataset(imagedir, labelfile, 10)
dataloader = DataLoader(dataset, batch_size=5, shuffle=True,num_workers=5)
for index, data in enumerate(dataloader):
	print(index)	# batch索引
	print(data)		# 一個batch的{img,label}

二. 模型設(shè)計

在這里只討論深度學習模型的設(shè)計,pytorch中的網(wǎng)絡(luò)結(jié)構(gòu)是一層一層疊出來的,pytorch中預定義了許多可以通過參數(shù)控制的網(wǎng)絡(luò)層結(jié)構(gòu),比如Linear、CNN、RNN、Transformer等等具體可以查閱官方文檔中的torch.nn部分。
設(shè)計自己的模型結(jié)構(gòu)需要繼承torch.nn.Module這個類,然后實現(xiàn)其中的forward方法,一般在__init__中設(shè)定好網(wǎng)絡(luò)模型的一些組件,然后在forward方法中依據(jù)輸入輸出順序拼裝組件。

'''
包括了各種模型、自定義的loss計算方法、optimizer
'''
import torch.nn as nn


class Simple_CNN(nn.Module):
    def __init__(self, class_num):
        super(Simple_CNN, self).__init__()
        self.class_num = class_num
        self.conv1 = nn.Sequential(
            nn.Conv2d(		# input: 3,400,600
                in_channels=3,
                out_channels=8,
                kernel_size=5,
                stride=1,
                padding=2
            ),
            nn.Conv2d(
                in_channels=8,
                out_channels=16,
                kernel_size=5,
                stride=1,
                padding=2
            ),
            nn.AvgPool2d(2),  # 16,400,600 --> 16,200,300
            nn.BatchNorm2d(16),
            nn.LeakyReLU(),
            nn.Conv2d(
                in_channels=16,
                out_channels=16,
                kernel_size=5,
                stride=1,
                padding=2
            ),
            nn.Conv2d(
                in_channels=16,
                out_channels=8,
                kernel_size=5,
                stride=1,
                padding=2
            ),
            nn.AvgPool2d(2),  # 8,200,300 --> 8,100,150
            nn.BatchNorm2d(8),
            nn.LeakyReLU(),
            nn.Conv2d(
                in_channels=8,
                out_channels=8,
                kernel_size=3,
                stride=1,
                padding=1
            ),
            nn.Conv2d(
                in_channels=8,
                out_channels=1,
                kernel_size=3,
                stride=1,
                padding=1
            ),
            nn.AvgPool2d(2),  # 1,100,150 --> 1,50,75
            nn.BatchNorm2d(1),
            nn.LeakyReLU()
        )
        self.line = nn.Sequential(
            nn.Linear(
                in_features=50 * 75,
                out_features=self.class_num
            ),
            nn.Softmax()
        )

    def forward(self, x):
        x = self.conv1(x)
        x = x.view(-1, 50 * 75)
        y = self.line(x)
        return y

上面我定義的模型中包括卷積組件conv1和全連接組件line,卷積組件中包括了一些卷積層,一般是按照{(diào)卷積層、池化層、激活函數(shù)}的順序拼接,其中我還在激活函數(shù)之前添加了一個BatchNorm2d層對上層的輸出進行正則化以免傳入激活函數(shù)的值過小(梯度消失)或過大(梯度爆炸)。
在拼接組件時,由于我全連接層的輸入是一個一維向量,所以需要將卷積組件中最后的50 × 75 50\times 7550×75大小的矩陣展平成一維的再傳入全連接層(x.view(-1,50*75))

三. 訓練

實例化模型后,網(wǎng)絡(luò)模型的訓練需要定義損失函數(shù)與優(yōu)化器,損失函數(shù)定義了網(wǎng)絡(luò)輸出與標簽的差距,依據(jù)不同的任務(wù)需要定義不同的合適的損失函數(shù),而優(yōu)化器則定義了神經(jīng)網(wǎng)絡(luò)中的參數(shù)如何基于損失來更新,目前神經(jīng)網(wǎng)絡(luò)最常用的優(yōu)化器就是SGD(隨機梯度下降算法) 及其變種。
在我這個簡單的分類器模型中,直接用的多分類任務(wù)最常用的損失函數(shù)CrossEntropyLoss()以及優(yōu)化器SGD。

self.cnnmodel = Simple_CNN(mycfg.CLASS_NUM)
self.criterion = nn.CrossEntropyLoss()	# 交叉熵,標簽應(yīng)該是0,1,2,3...的形式而不是獨熱的
self.optimizer = optim.SGD(self.cnnmodel.parameters(), lr=mycfg.LEARNING_RATE, momentum=0.9)

訓練過程其實很簡單,使用dataloader依照batch讀出數(shù)據(jù)后,將input放入網(wǎng)絡(luò)模型中計算得到網(wǎng)絡(luò)的輸出,然后基于標簽通過損失函數(shù)計算Loss,并將Loss反向傳播回神經(jīng)網(wǎng)絡(luò)(在此之前需要清理上一次循環(huán)時的梯度),最后通過優(yōu)化器更新權(quán)重。訓練部分代碼如下:

for each_epoch in range(mycfg.MAX_EPOCH):
            running_loss = 0.0
            self.cnnmodel.train()
            for index, data in enumerate(self.dataloader):
                inputs, labels = data
                outputs = self.cnnmodel(inputs)
                loss = self.criterion(outputs, labels)

                self.optimizer.zero_grad()	# 清理上一次循環(huán)的梯度
                loss.backward()	# 反向傳播
                self.optimizer.step()	# 更新參數(shù)
                running_loss += loss.item()
                if index % 200 == 199:
                    print("[{}] loss: {:.4f}".format(each_epoch, running_loss/200))
                    running_loss = 0.0
            # 保存每一輪的模型
            model_name = 'classify-{}-{}.pth'.format(each_epoch,round(all_loss/all_index,3))
            torch.save(self.cnnmodel,model_name)	# 保存全部模型

四. 測試

測試和訓練的步驟差不多,也就是讀取模型后通過dataloader獲取數(shù)據(jù)然后將其輸入網(wǎng)絡(luò)獲得輸出,但是不需要進行反向傳播的等操作了。比較值得注意的可能就是準確率計算方面有一些小技巧。

acc = 0.0
count = 0
self.cnnmodel = torch.load('mymodel.pth')
self.cnnmodel.eval()
for index, data in enumerate(dataloader_eval):
	inputs, labels = data   # 5,3,400,600  5,10
	count += len(labels)
	outputs = cnnmodel(inputs)
	_,predict = torch.max(outputs, 1)
	acc += (labels == predict).sum().item()
print("[{}] accurancy: {:.4f}".format(each_epoch, acc / count))

我這里采用的是保存全部模型并加載全部模型的方法,這種方法的好處是在使用模型時可以完全將其看作一個黑盒,但是在模型比較大時這種方法會很費事。此時可以采用只保存參數(shù)不保存網(wǎng)絡(luò)結(jié)構(gòu)的方法,在每一次使用模型時需要讀取參數(shù)賦值給已經(jīng)實例化的模型:

torch.save(cnnmodel.state_dict(), "my_resnet.pth")
cnnmodel = Simple_CNN()
cnnmodel.load_state_dict(torch.load("my_resnet.pth"))

結(jié)語

至此整個流程就說完了,是一個小白級的圖像分類任務(wù)流程,因為前段時間一直在做android方面的事,所以有點生疏了,就寫了這篇博客記錄一下,之后應(yīng)該還會寫一下seq2seq以及image caption任務(wù)方面的模型構(gòu)造與訓練過程,完整代碼之后也會統(tǒng)一放到github上給大家做參考。

以上就是基于PyTorch實現(xiàn)一個簡單的CNN圖像分類器的詳細內(nèi)容,更多關(guān)于PyTorch實現(xiàn)CNN圖像分類器的資料請關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:
  • pytorch實現(xiàn)textCNN的具體操作
  • Pytorch mask-rcnn 實現(xiàn)細節(jié)分享
  • Pytorch 使用CNN圖像分類的實現(xiàn)
  • pytorch實現(xiàn)CNN卷積神經(jīng)網(wǎng)絡(luò)
  • 用Pytorch訓練CNN(數(shù)據(jù)集MNIST,使用GPU的方法)
  • PyTorch CNN實戰(zhàn)之MNIST手寫數(shù)字識別示例
  • PyTorch上實現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)CNN的方法
  • CNN的Pytorch實現(xiàn)(LeNet)

標簽:江蘇 金融催收 商丘 龍巖 酒泉 定西 云南 寧夏

巨人網(wǎng)絡(luò)通訊聲明:本文標題《基于PyTorch實現(xiàn)一個簡單的CNN圖像分類器》,本文關(guān)鍵詞  基于,PyTorch,實現(xiàn),一個,簡單,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《基于PyTorch實現(xiàn)一個簡單的CNN圖像分類器》相關(guān)的同類信息!
  • 本頁收集關(guān)于基于PyTorch實現(xiàn)一個簡單的CNN圖像分類器的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    欧美人狂配大交3d怪物一区| 色综合天天综合给合国产| 欧美影院一区二区三区| 免费高清不卡av| 国产精品久久久久久久久果冻传媒 | 国产欧美精品一区aⅴ影院| 91精品国产91久久综合桃花| 久久先锋影音av鲁色资源网| 国产亚洲欧美日韩在线一区| 免费观看日韩电影| 国产黑丝在线一区二区三区| 欧美日韩在线播放一区| 91麻豆精品国产无毒不卡在线观看 | 成人午夜电影网站| 亚洲丝袜制服诱惑| 欧美不卡一二三| 欧美中文字幕一区二区三区亚洲 | 国产视频在线观看一区二区三区| 国产福利精品一区| 国产精品青草久久| 国产高清精品网站| 亚洲二区在线视频| 日本电影欧美片| 一区二区三区日韩欧美| 亚洲男女毛片无遮挡| 美女视频黄a大片欧美| 国产一区日韩二区欧美三区| 中文字幕中文字幕一区二区| 欧美日韩性生活| 亚洲成人7777| 亚洲综合小说图片| 欧美亚洲国产一区二区三区va| 在线观看一区二区精品视频| 成人av电影在线网| 欧美伦理影视网| 精品999久久久| 国产精品一级片| 同产精品九九九| 国产精品白丝在线| 国产欧美视频一区二区| 欧美国产丝袜视频| 久久久九九九九| 久久综合九色综合欧美98| 国产女人水真多18毛片18精品视频| 精品国产成人系列| 久久久三级国产网站| 久久综合九色综合欧美亚洲| 国产精品第四页| 亚洲欧美日韩国产综合| 久久在线观看免费| 99精品偷自拍| 欧美在线视频日韩| 在线观看一区日韩| 精品国产自在久精品国产| 欧美mv日韩mv国产网站app| 日韩精品一区二区三区四区视频| 91国偷自产一区二区使用方法| 日韩一区国产二区欧美三区| 欧美电视剧在线观看完整版| 精品美女一区二区三区| 国产农村妇女精品| 国产日韩欧美在线一区| 最新久久zyz资源站| 亚洲日穴在线视频| 久久99九九99精品| 成年人网站91| 欧美精品电影在线播放| 久久久99免费| 日韩理论片在线| 日日骚欧美日韩| 国产在线视频一区二区| 欧美日韩国产天堂| 久久综合九色综合欧美就去吻 | 天天av天天翘天天综合网 | 久久久久久久网| 午夜a成v人精品| 国产成人小视频| 成人小视频在线| 久久看人人爽人人| 亚洲综合在线观看视频| 久久爱www久久做| 一本一道久久a久久精品综合蜜臀| 久久久精品国产免费观看同学| 亚洲精品国产一区二区精华液 | 精品在线一区二区三区| 男女男精品视频网| 欧美日韩国产在线播放网站| 国产婷婷一区二区| 亚洲国产日韩a在线播放| 亚洲国产日韩综合久久精品| 一本到高清视频免费精品| 欧美电影精品一区二区| 亚洲精品乱码久久久久久久久| 精品中文av资源站在线观看| 精品欧美乱码久久久久久| 亚洲青青青在线视频| 国产一区二区三区免费| 在线视频综合导航| 亚洲综合精品久久| av欧美精品.com| 久久久www成人免费毛片麻豆| 亚洲va欧美va天堂v国产综合| 精品影视av免费| 欧美丰满一区二区免费视频| 亚洲精品一二三| 久久电影国产免费久久电影 | 91久久久免费一区二区| 一本色道久久综合精品竹菊| 亚洲欧美日韩在线| 成人综合婷婷国产精品久久免费| 欧美一区二区三区白人| 亚洲一区二区不卡免费| 7777精品伊人久久久大香线蕉| 亚洲欧美综合另类在线卡通| 国产在线播精品第三| 日韩一本二本av| 亚洲精品中文字幕乱码三区| 91在线观看污| 亚洲视频图片小说| 国产精品一区二区免费不卡| 精品国产三级电影在线观看| 免费精品视频最新在线| 在线观看不卡视频| 裸体健美xxxx欧美裸体表演| 欧美一级片在线看| 美女网站色91| 色综合天天综合在线视频| 亚洲一区二区在线免费看| 99这里只有久久精品视频| 一区二区高清视频在线观看| www.欧美精品一二区| 五月激情丁香一区二区三区| 久久影院视频免费| 欧美午夜精品一区二区蜜桃| 国产呦萝稀缺另类资源| 一区二区三区免费看视频| 久久一夜天堂av一区二区三区| 在线亚洲免费视频| 成人在线视频一区| 青青草伊人久久| 一区二区三区蜜桃| 中文字幕精品一区| 日韩一区二区三区免费观看| 色婷婷亚洲精品| 国产99精品视频| 免费不卡在线视频| 亚洲国产欧美在线人成| 国产精品欧美精品| 欧美大片在线观看一区| 欧美性大战久久久久久久蜜臀 | 欧美在线影院一区二区| 国产一区二区成人久久免费影院| 亚洲欧美日韩国产另类专区 | 亚洲欧美福利一区二区| 日韩欧美一卡二卡| 在线观看网站黄不卡| 福利一区福利二区| 精品一区二区在线观看| 天堂成人国产精品一区| 一片黄亚洲嫩模| 亚洲精品视频观看| 国产欧美视频在线观看| 久久久青草青青国产亚洲免观| 欧美一级高清大全免费观看| 日本二三区不卡| 欧美在线视频全部完| 在线亚洲欧美专区二区| 日本精品视频一区二区| 91亚洲精品久久久蜜桃网站| av激情综合网| 成人免费av在线| 成人app下载| av一区二区三区在线| 高清日韩电视剧大全免费| 丰满白嫩尤物一区二区| 国产成人8x视频一区二区| 国产在线乱码一区二区三区| 国产在线一区观看| 国产成人在线网站| 国产91综合网| 风间由美性色一区二区三区| 不卡av在线免费观看| 99久久精品国产导航| 一本久久综合亚洲鲁鲁五月天 | 欧美在线免费播放| 欧美色网一区二区| 欧美日韩一区二区电影| 欧美美女一区二区三区| 日韩一区国产二区欧美三区| 久久亚洲一区二区三区四区| 国产午夜精品福利| 亚洲欧洲国产专区| 亚洲影院理伦片| 理论电影国产精品| 国产99精品在线观看| 一本色道久久综合亚洲91| 欧美日韩大陆一区二区| 精品国产免费视频| 国产精品视频你懂的| 亚洲一区二区五区|