用Pytorch訓(xùn)練神經(jīng)網(wǎng)絡(luò)
本文目標(biāo)是如何使用Pytorch以盡可能短的方式從圖像中預(yù)測(cè)顏色、填充級(jí)別等連續(xù)屬性。我們將學(xué)習(xí)加載現(xiàn)有網(wǎng)絡(luò),修改它以預(yù)測(cè)特定屬性,并用不到40行代碼(不包括空格)對(duì)其進(jìn)行訓(xùn)練。
Standart神經(jīng)網(wǎng)絡(luò)通常專注于分類問(wèn)題,比如識(shí)別貓和狗。然而,這些網(wǎng)絡(luò)可以很容易地進(jìn)行修改,從圖像中預(yù)測(cè)連續(xù)屬性,如年齡、大小或價(jià)格。
首先,讓我們導(dǎo)入軟件包并定義主要的訓(xùn)練參數(shù):
import numpy as np
import torchvision.models.segmentation
import torch
import torchvision.transforms as tf
Learning_Rate=1e-5
width=height=900
batchSize=1
學(xué)習(xí)率:是訓(xùn)練過(guò)程中梯度下降的步長(zhǎng)。
寬度和高度是用于訓(xùn)練的圖像的尺寸。訓(xùn)練過(guò)程中的所有圖像都將調(diào)整為該大小。
batchSize:是將用于每次訓(xùn)練迭代的圖像數(shù)。
batchSize,width,height將與訓(xùn)練的內(nèi)存需求成比例。根據(jù)硬件的不同,可能需要使用較小的批處理大小來(lái)避免內(nèi)存不足問(wèn)題。
請(qǐng)注意,由于我們只使用單一大小的圖像進(jìn)行訓(xùn)練,因此訓(xùn)練后的網(wǎng)絡(luò)可能僅限于使用這種大小的圖像。
接下來(lái),讓我們創(chuàng)建訓(xùn)練數(shù)據(jù)。我們想做一個(gè)簡(jiǎn)單的演示,所以我們將創(chuàng)建一個(gè)用白色填充到一定高度的圖像。該網(wǎng)絡(luò)的目標(biāo)是預(yù)測(cè)被白色覆蓋的圖像的比例。這可以很容易地用于從真實(shí)圖像預(yù)測(cè)更復(fù)雜的屬性,如其他教程所示。
例如:
在上圖中,我們希望網(wǎng)絡(luò)預(yù)測(cè)為0.47,因?yàn)?7%的圖像填充為白色。在底圖中,我們希望網(wǎng)絡(luò)預(yù)測(cè)0.76,因?yàn)?6%的圖像填充為白色。
在實(shí)際環(huán)境中,你可能會(huì)從文件中加載數(shù)據(jù)。在這里,我們將動(dòng)態(tài)創(chuàng)建它:
def ReadRandomImage():
FillLevel=np.random.random() # Set random fill level
Img=np.zeros([900,900,3],np.uint8) # Create black image
Img[0:int(FillLevel*900),:]=255 # Fill the image
transformImg=tf.Compose([tf.ToPILImage(),
tf.Resize((height,width)),tf.ToTensor(),tf.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))]) # Set image transformation
Img=transformImg(Img) # Transform to pytorch
return Img,F(xiàn)illLevel
在第一部分中,我們創(chuàng)建圖像:
FillLevel=np.random.random() # Set random fill level
Img=np.zeros([900,900,3],np.uint8) # Create black image
Img[0:int(FillLevel*900),:]=255 # Fill the image
第一行選擇0–1之間的隨機(jī)數(shù)作為填充級(jí)別。
Img=np.zeros([900,900,3])創(chuàng)建一個(gè)大小為900X900的矩陣,填充零作為圖像。這相當(dāng)于一個(gè)高度和寬度為900的黑色圖像。圖像有3個(gè)對(duì)應(yīng)于RGB的通道。
接下來(lái),我們用白色填充圖像的頂部,直到填充水平線。
Img[0:int(FillLevel*900),:]=255
現(xiàn)在我們創(chuàng)建了圖像,我們對(duì)其進(jìn)行處理并將其轉(zhuǎn)換為Pytorch格式:
transformImg=tf.Compose([tf.ToPILImage(),
tf.Resize((height,width)),tf.ToTensor(),tf.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))]) # Set image transformation
這定義了一組將應(yīng)用于圖像的變換。這包括轉(zhuǎn)換為PIL格式(轉(zhuǎn)換的標(biāo)準(zhǔn)格式),以及調(diào)整大小和轉(zhuǎn)換為PyTorch格式。
對(duì)于圖像,我們還通過(guò)減去平均值并除以像素強(qiáng)度來(lái)標(biāo)準(zhǔn)化圖像中像素的強(qiáng)度。
對(duì)于我們的簡(jiǎn)單圖像,標(biāo)準(zhǔn)化和大小調(diào)整并不是真正需要的,但這些轉(zhuǎn)換對(duì)于真實(shí)圖像很重要。
接下來(lái),我們將變換應(yīng)用于圖像:
Img=transformImg(Img)
對(duì)于訓(xùn)練,我們需要使用一批圖像。這意味著在4D矩陣中,多個(gè)圖像相互疊加。我們使用以下函數(shù)創(chuàng)建batch:
def LoadBatch(): # Load batch of images
images = torch.zeros([batchSize,3,height,width])
FillLevel = torch.zeros([batchSize])
for i in range(batchSize):
images[i],F(xiàn)illLevel[i]=ReadRandomImage()
return images,F(xiàn)illLevel
第一行創(chuàng)建一個(gè)空的4d矩陣,該矩陣將存儲(chǔ)尺寸為[batchSize,Channel,height,width]的圖像,其中Channel是圖像的層數(shù);這是RGB圖像的3。下一行創(chuàng)建一個(gè)數(shù)組,其中存儲(chǔ)填充級(jí)別。這將作為我們訓(xùn)練的標(biāo)簽。
下一部分使用前面定義的ReadRandomImage函數(shù)將圖像集和填充級(jí)別加載到空矩陣:
for i in range(batchSize):
images[i],F(xiàn)illLevel[i]=ReadRandomImage()
現(xiàn)在我們可以加載數(shù)據(jù)了,是時(shí)候加載神經(jīng)網(wǎng)絡(luò)了:
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
Net = torchvision.models.resnet18(pretrained=True) # Load net
Net.fc = torch.nn.Linear(in_features=512, out_features=1, bias=True)
Net = Net.to(device)
optimizer = torch.optim.Adam(params=Net.parameters(),lr=Learning_Rate)
第一部分是確定計(jì)算機(jī)是否有GPU或CPU。如果有Cuda GPU,訓(xùn)練將在GPU上進(jìn)行:
device = torch.device(‘cuda’) if torch.cuda.is_available() else torch.device(‘cpu’)
對(duì)于任何實(shí)際數(shù)據(jù)集,使用CPU進(jìn)行訓(xùn)練都非常緩慢。
接下來(lái),我們加載用于圖像分類的網(wǎng)絡(luò):
Net = torchvision.models.resnet18(pretrained=True)
torchvision.models包含許多有用的圖像分類模型。Reseet18是一個(gè)輕量級(jí)的分類模型,適用于低資源訓(xùn)練或簡(jiǎn)單的數(shù)據(jù)集。對(duì)于更難的問(wèn)題,最好使用resenet50(請(qǐng)注意,數(shù)字指的是網(wǎng)絡(luò)中的層數(shù))。
通過(guò)設(shè)置pretrained=True,我們?cè)贗magenet數(shù)據(jù)集上加載帶有預(yù)訓(xùn)練權(quán)重的網(wǎng)絡(luò)。
在學(xué)習(xí)新問(wèn)題時(shí),最好從預(yù)訓(xùn)練的模型開(kāi)始,因?yàn)樗试S網(wǎng)絡(luò)使用以前的經(jīng)驗(yàn)并更快地收斂。
我們可以看到我們剛剛通過(guò)print(Net)查看網(wǎng)絡(luò)的所有結(jié)構(gòu)和所有層:
print(Net)
…
…
(avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
(fc): Linear(in_features=512, out_features=1000, bias=True)
這會(huì)按使用順序打印層。
網(wǎng)絡(luò)的最后一層是線性變換,輸入512層,輸出1000層。1000代表輸出類的數(shù)量(這個(gè)網(wǎng)絡(luò)是在圖像網(wǎng)絡(luò)上訓(xùn)練的,圖像網(wǎng)絡(luò)將圖像分為1000個(gè)類中的一個(gè))。
因?yàn)槲覀冎幌腩A(yù)測(cè)一個(gè)值,所以我們想用一個(gè)輸出的新線性層來(lái)代替它:
Net.fc = torch.nn.Linear(in_features=512, out_features=1, bias=True)
公平地說(shuō),這部分是可選的,因?yàn)橐粋(gè)有1000個(gè)輸出通道的網(wǎng)絡(luò)只需忽略999個(gè)通道就可以預(yù)測(cè)一個(gè)值。但這樣更優(yōu)雅。
接下來(lái),我們將網(wǎng)絡(luò)加載到GPU或CPU設(shè)備中:
Net=Net.to(device)
最后,我們加載一個(gè)優(yōu)化器:
optimizer=torch.optim.Adam(params=Net.parameters(),lr=Learning_Rate) # Create adam optimizer
優(yōu)化器將在反向傳播步驟中控制梯度速率。Adam是最快的優(yōu)化器之一。
最后,我們通過(guò)加載數(shù)據(jù)開(kāi)始訓(xùn)練,使用網(wǎng)絡(luò)進(jìn)行預(yù)測(cè):
AverageLoss=np.zeros([50]) # Save average loss for display
for itr in range(2001): # Training loop
images,GTFillLevel=LoadBatch() # Load taining batch
images=torch.a(chǎn)utograd.Variable(images,requires_grad=False).
to(device)
GTFillLevel = torch.a(chǎn)utograd.Variable(GTFillLevel,
requires_grad=False).to(device)
PredLevel=Net(images) # make prediction
首先,我們希望保存訓(xùn)練期間的平均損失;我們創(chuàng)建一個(gè)數(shù)組來(lái)存儲(chǔ)最后50步的損失。
AverageLoss=np.zeros([50])
這將使我們能夠跟蹤網(wǎng)絡(luò)的學(xué)習(xí)情況。
我們將訓(xùn)練2000個(gè)步驟:
for itr in range(2000):
LoadBatch在前面定義,幫助加載一批圖像及其填充級(jí)別。
torch.a(chǎn)utograd.Variable:將數(shù)據(jù)轉(zhuǎn)換成網(wǎng)絡(luò)可以使用的梯度變量。我們?cè)O(shè)置Requires_grad=False,因?yàn)槲覀冎粚⑻荻葢?yīng)用于網(wǎng)絡(luò)的層。to(device) 將張量復(fù)制到對(duì)應(yīng)的設(shè)備(GPU/CPU)。
最后,我們將圖像輸入網(wǎng)絡(luò),得到預(yù)測(cè)結(jié)果。
PredLevel=Net(images)
一旦我們做出預(yù)測(cè),我們可以將其與實(shí)際填充水平進(jìn)行比較,并計(jì)算損失。損失是圖像的預(yù)測(cè)和真實(shí)填充水平之間的絕對(duì)差(L1):
Loss=torch.a(chǎn)bs(PredLevel-GTFillLevel).mean()
請(qǐng)注意,我們不是將損失應(yīng)用于一張圖像,而是應(yīng)用于批次中的多張圖像,因此我們需要將損失的平均值作為單個(gè)數(shù)字。
一旦我們計(jì)算了損失,我們就可以應(yīng)用反向傳播并改變權(quán)重。
Loss.backward() # Backpropogate loss
Optimizer.step() # Apply gradient descent change to wei
在訓(xùn)練期間,我們想看看我們的平均損失是否減少,看看網(wǎng)絡(luò)是否真的學(xué)到了什么。
因此,我們將最后50個(gè)損失值存儲(chǔ)在一個(gè)數(shù)組中,并顯示每個(gè)步驟的平均值:
AverageLoss[itr%50]=Loss.data.cpu().numpy() # Save loss average
print(itr,") Loss=",Loss.data.cpu().numpy(),
'AverageLoss',AverageLoss.mean())
這涵蓋了整個(gè)訓(xùn)練階段,但我們還需要保存經(jīng)過(guò)訓(xùn)練的模型。否則,一旦程序停止,它就會(huì)丟失。
保存很費(fèi)時(shí),所以我們希望大約每200步只做一次:
if itr % 200 == 0:
print(“Saving Model” +str(itr) + “.torch”)
torch.save(Net.state_dict(), str(itr) + “.torch”)
在運(yùn)行這個(gè)腳本大約200步之后,網(wǎng)絡(luò)應(yīng)該會(huì)給出很好的結(jié)果。
總共40行代碼,不包括空格。
訓(xùn)練并保存網(wǎng)絡(luò)后,可以加載網(wǎng)絡(luò)進(jìn)行預(yù)測(cè):
https://github.com/sagieppel/Train-neural-net-to-predict-continuous-property-from-an-image-in-40-lines-of-code-with-PyTorch/blob/main/Infer.py
該腳本加載你之前訓(xùn)練和保存的網(wǎng)絡(luò),并使用它進(jìn)行預(yù)測(cè)。
這里的大部分代碼與訓(xùn)練腳本相同,只有幾處不同:
Net.load_state_dict(torch.load(modelPath)) # Load trained model
從modelPath中的文件加載我們之前訓(xùn)練和保存的網(wǎng)絡(luò)
#Net.eval()
將網(wǎng)絡(luò)從訓(xùn)練模式轉(zhuǎn)換為評(píng)估模式。這主要意味著不會(huì)計(jì)算批次標(biāo)準(zhǔn)化統(tǒng)計(jì)數(shù)據(jù)。
雖然使用它通常是一個(gè)好主意,但在我們的例子中,它實(shí)際上會(huì)降低準(zhǔn)確性,因此我們將在沒(méi)有它的情況下使用網(wǎng)絡(luò)。
with torch.no_grad():
這意味著網(wǎng)絡(luò)運(yùn)行時(shí)沒(méi)有收集梯度。梯度只與訓(xùn)練相關(guān),收集梯度需要大量資源。
感謝閱讀!
原文標(biāo)題 : 用Pytorch訓(xùn)練神經(jīng)網(wǎng)絡(luò)
發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
即日-11.13立即報(bào)名>>> 【在線會(huì)議】多物理場(chǎng)仿真助跑新能源汽車
-
11月28日立即報(bào)名>>> 2024工程師系列—工業(yè)電子技術(shù)在線會(huì)議
-
12月19日立即報(bào)名>> 【線下會(huì)議】OFweek 2024(第九屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會(huì)
-
即日-12.26火熱報(bào)名中>> OFweek2024中國(guó)智造CIO在線峰會(huì)
-
即日-2025.8.1立即下載>> 《2024智能制造產(chǎn)業(yè)高端化、智能化、綠色化發(fā)展藍(lán)皮書(shū)》
-
精彩回顧立即查看>> 【限時(shí)免費(fèi)下載】TE暖通空調(diào)系統(tǒng)高效可靠的組件解決方案
推薦專題
- 1 【一周車話】沒(méi)有方向盤和踏板的車,你敢坐嗎?
- 2 特斯拉發(fā)布無(wú)人駕駛車,還未迎來(lái)“Chatgpt時(shí)刻”
- 3 特斯拉股價(jià)大跌15%:Robotaxi離落地還差一個(gè)蘿卜快跑
- 4 馬斯克給的“驚喜”夠嗎?
- 5 打完“價(jià)格戰(zhàn)”,大模型還要比什么?
- 6 馬斯克致敬“國(guó)產(chǎn)蘿卜”?
- 7 神經(jīng)網(wǎng)絡(luò),誰(shuí)是盈利最強(qiáng)企業(yè)?
- 8 比蘋果偉大100倍!真正改寫人類歷史的智能產(chǎn)品降臨
- 9 諾獎(jiǎng)進(jìn)入“AI時(shí)代”,人類何去何從?
- 10 Open AI融資后成萬(wàn)億獨(dú)角獸,AI人才之爭(zhēng)開(kāi)啟
- 高級(jí)軟件工程師 廣東省/深圳市
- 自動(dòng)化高級(jí)工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級(jí)銷售經(jīng)理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術(shù)專家 廣東省/江門市
- 封裝工程師 北京市/海淀區(qū)
- 結(jié)構(gòu)工程師 廣東省/深圳市