keras還是pytorch?完整的pytorch回歸分類任務(wù)訓(xùn)練流程

前言
相信在2023年入門深度學(xué)習(xí)方向的同學(xué),面對(duì)眾多成熟的深度學(xué)習(xí)框架,尤其是pytorch、TensorFlow、keras這三個(gè)使用率較高的框架,很容易犯起選擇困難癥。
我首先是通過(guò)kaggle的深度學(xué)習(xí)教程入門的,一般來(lái)說(shuō),一些入門級(jí)別的深度學(xué)習(xí)教程,即從概念到多層感知機(jī),基本都是用keras,然而隨著學(xué)習(xí)的深入,keras的高層API特性似乎反而成為了學(xué)習(xí)上的阻礙,因此我隨后轉(zhuǎn)向了pytorch
下面我就基于使用keras和pytorch入門深度學(xué)習(xí)的使用感受和訓(xùn)練過(guò)程,通過(guò)回歸和分類兩種任務(wù)來(lái)說(shuō)明
使用體驗(yàn)
首先,從使用體驗(yàn)上,個(gè)人認(rèn)為兩種框架各自有自己的優(yōu)點(diǎn)。
Keras

keras的API非常人性化,封裝的很到位,基本可以從sklearn無(wú)縫銜接過(guò)來(lái),而且基本不需要糾結(jié)輸入輸出,特別是卷積操作
keras很適合快速驗(yàn)證想法,不需要過(guò)于執(zhí)著于內(nèi)部實(shí)現(xiàn)和繁雜的代碼編寫,例如在每層可以方便的進(jìn)行正則化,提供激活函數(shù),初始化參數(shù)
keras的可視化非常方便,自帶進(jìn)度條,
keras的功能實(shí)現(xiàn)很方便,比如動(dòng)態(tài)調(diào)整學(xué)習(xí)率、早停法、checkpoint都只要在fit方法中加入對(duì)應(yīng)callback函數(shù)即可
下面我用自己之前寫的一段多層感知機(jī)的代碼作為演示
可以看出keras總體架構(gòu)大概服從一下的思路
確定驗(yàn)證策略并分割數(shù)據(jù)集:確定驗(yàn)證策略,例如交叉驗(yàn)證或留出法。將數(shù)據(jù)集分割為訓(xùn)練集和驗(yàn)證集。
設(shè)置超參數(shù):選擇批次大?。╞atch size)和學(xué)習(xí)率(learning rate)等超參數(shù)。
創(chuàng)建Sequential模型:創(chuàng)建一個(gè)Sequential對(duì)象,作為模型的容器。
添加網(wǎng)絡(luò)架構(gòu):將每個(gè)網(wǎng)絡(luò)架構(gòu)按順序添加到Sequential模型中。
配置網(wǎng)絡(luò)架構(gòu):對(duì)于每個(gè)網(wǎng)絡(luò)架構(gòu),選擇適當(dāng)?shù)募せ詈瘮?shù)、正則化方法和參數(shù)初始化等。
編譯模型:使用compile方法編譯模型,指定損失函數(shù)和優(yōu)化策略。
訓(xùn)練模型:使用fit方法將模型與訓(xùn)練集進(jìn)行訓(xùn)練,指定訓(xùn)練的輪數(shù)(epochs)和批次大小。
預(yù)測(cè)結(jié)果:使用predict方法對(duì)新樣本進(jìn)行預(yù)測(cè)。
Pytorch
pytorch的框架更復(fù)雜一些,對(duì)于網(wǎng)絡(luò)結(jié)構(gòu)的把控會(huì)有更好的認(rèn)識(shí)
pytorch提供了更多的自定義空間,可以加入更多自己的想法和需求,例如我想創(chuàng)建一個(gè)比較特殊的損失函數(shù)(比如對(duì)于預(yù)測(cè)成癌癥的結(jié)果取更大損失),或者特殊的讀取批次方法(比如每次讀取時(shí)進(jìn)行某種轉(zhuǎn)換)
使用pytorch的人越來(lái)越多,在復(fù)現(xiàn)別人的代碼上具有一些優(yōu)勢(shì)
總而言之就是,個(gè)人認(rèn)為keras適合前期入門,快速掌握概念并進(jìn)行代碼實(shí)現(xiàn)。而pytorch適合進(jìn)一步學(xué)習(xí),更深層次的理解整個(gè)神經(jīng)網(wǎng)絡(luò)是如何架構(gòu)起來(lái)的
打個(gè)比方吧,keras就像一個(gè)很方便的mod整合包,提供給用戶的是一個(gè)個(gè)已經(jīng)高度完備的建材,用戶只需要知道這些建材怎么搭配,哪個(gè)要放在哪里就好了。
而pytorch更像是一個(gè)原滋原味的原材料工廠,用戶必須指定每個(gè)建材的規(guī)格大小,指定怎么入料出料,詳細(xì)的產(chǎn)品質(zhì)量把控策略
因此從宏觀來(lái)看,雖然在代碼編寫上麻煩了一點(diǎn),但整體上對(duì)整個(gè)網(wǎng)絡(luò)的運(yùn)行有更好的把控,可以避免很多因“黑箱”造成的問(wèn)題,例如梯度消失和爆炸、loss不合理、網(wǎng)絡(luò)不合理等

詳細(xì)的使用pytorch訓(xùn)練流程:以分類和回歸為例
下面就以分類和回歸為例子,分享一下使用pytorch進(jìn)行訓(xùn)練的一般流程,不管是哪種網(wǎng)絡(luò),基本都可以用這種“堆積木”式的架構(gòu)來(lái)完成
總體流程思路
導(dǎo)入工具包
定義超參數(shù),例如批次大小,初始學(xué)習(xí)率等,可以放在一個(gè)config或者其他配置文件中
創(chuàng)建數(shù)據(jù)集和數(shù)據(jù)讀取器:常用DataLoader,TensorDataset,或繼承自Dataset進(jìn)行自定義數(shù)據(jù)集
創(chuàng)建網(wǎng)絡(luò)類
繼承自nn.Module
初始化網(wǎng)絡(luò)結(jié)構(gòu)
實(shí)現(xiàn)前向傳播方法
(可選)使用.to(device)或者.cuda()將模型放入GPU中
進(jìn)行參數(shù)初始化,并apply到網(wǎng)絡(luò)上
定義損失函數(shù)與優(yōu)化器
損失函數(shù)需要自定義時(shí)繼承自nn.Module
(可選)定義學(xué)習(xí)率調(diào)度器
(可選)使用tensorboard進(jìn)行可視化,創(chuàng)建writer并可視化網(wǎng)絡(luò)結(jié)構(gòu)
from torch.utils.tensorboard import SummaryWriter
writer=SummaryWriter('log')
writer.add_graph(model=model)
開(kāi)始訓(xùn)練并將模型調(diào)到訓(xùn)練模式model.train()
迭代dataloader,讀取訓(xùn)練集的數(shù)據(jù)與標(biāo)簽 for data, label in train_loader
(可選)將數(shù)據(jù)和標(biāo)簽轉(zhuǎn)移到GPU上data, label = data.cuda(), label.cuda()
清零優(yōu)化器梯度optimizer.zero_grad()
把數(shù)據(jù)傳入網(wǎng)絡(luò)output = model(data)
計(jì)算輸出標(biāo)簽與真實(shí)標(biāo)簽的損失loss = criterion(output, label)
反向傳播求梯度loss.backward()
更新參數(shù)optimizer.step()
開(kāi)始驗(yàn)證并將模型調(diào)到驗(yàn)證模式model.eval()
使用上下文管理,不再計(jì)算梯度with torch.no_grad()
迭代dataloader,讀取驗(yàn)證集的數(shù)據(jù)與標(biāo)簽for data, label in val_loader
(可選)將數(shù)據(jù)和標(biāo)簽轉(zhuǎn)移到GPU上data, label = data.cuda(), label.cuda()
把數(shù)據(jù)傳入網(wǎng)絡(luò)output = model(data)
計(jì)算輸出標(biāo)簽與真實(shí)標(biāo)簽的損失loss = criterion(output, label)
(可選)進(jìn)行學(xué)習(xí)率調(diào)度器更新: scheduler.step(val_loss)傳入的是要監(jiān)控的指標(biāo)
(可選)進(jìn)行tensorboard更新指標(biāo),這里我只展示監(jiān)控學(xué)習(xí)曲線、學(xué)習(xí)率和參數(shù)權(quán)重分布
14.(可選)保存模型torch.save(model,'TempModel.pkl')
具體代碼實(shí)現(xiàn)
任務(wù)一:對(duì)加利福利亞房?jī)r(jià)數(shù)據(jù)(20640,8)進(jìn)行回歸任務(wù),預(yù)測(cè)真實(shí)房?jī)r(jià)
工具包導(dǎo)入
超參數(shù)定義
獲取數(shù)據(jù)集
自定義Dataset存儲(chǔ)我們的數(shù)據(jù)
ps:若出現(xiàn)錯(cuò)誤RuntimeError: mixed dtype (CPU): expect input to have scalar type of BFloat16只需將tensor指定dtype設(shè)置為float32,這里發(fā)現(xiàn)有時(shí)候不指定dtype會(huì)出錯(cuò)
分割數(shù)據(jù)集,分別置入我們的Dataset
定義DataLoader
對(duì)于Windows環(huán)境,必須是num_workers=0
一般驗(yàn)證集不設(shè)置打亂數(shù)據(jù)shuffle=False
測(cè)試一下我們是否成功定義了數(shù)據(jù)讀取邏輯
很好!輸出是符合我們的維度要求的
定義網(wǎng)絡(luò)結(jié)構(gòu)
初始化參數(shù)
定義損失函數(shù)和優(yōu)化器
這里我們自定義一個(gè)損失函數(shù),對(duì)于預(yù)測(cè)小于真實(shí)房?jī)r(jià)的結(jié)果,使用MAE,否則使用MSE
優(yōu)化器需要傳入模型的參數(shù)以便其進(jìn)行更新,以及定義的學(xué)習(xí)率
測(cè)試一下自定義的損失函數(shù)是否正常工作
定義學(xué)習(xí)率調(diào)度器
這里我們監(jiān)控驗(yàn)證集上的損失,若五輪沒(méi)有比最優(yōu)的下降,我們就讓學(xué)習(xí)率乘以0.2
使用Tensorboard進(jìn)行可視化訓(xùn)練流程
開(kāi)始訓(xùn)練和驗(yàn)證

觀察Tensorboard上的情況
在命令行中輸入tensorboard --logdir=log --port=1145 這里--logdir的參數(shù)為之前的writer=SummaryWriter('log'),--port為端口可以不寫
Ctrl+左鍵進(jìn)入鏈接

觀察我們之前繪制的學(xué)習(xí)曲線
可以看出最終模型趨于收斂,存在一些過(guò)擬合的情況

在網(wǎng)頁(yè)的Graph頁(yè)面中觀察我們的網(wǎng)絡(luò)架構(gòu),可以具體點(diǎn)進(jìn)去看每一層

觀察我們的參數(shù)分布

(與我們的基線模型嶺回歸進(jìn)行對(duì)比)
可以發(fā)現(xiàn)多層感知機(jī)的損失是0.41,而嶺回歸是0.53,表明多層感知機(jī)是優(yōu)于線性模型的
模型保存
任務(wù)二:對(duì)XOR數(shù)據(jù)進(jìn)行分類
具體相同流程不再贅述,這里只展示不相同的地方
讀取數(shù)據(jù)集
我們這里將10%的隨機(jī)數(shù)據(jù)取反

定義網(wǎng)絡(luò)架構(gòu)
這里注意避免踩坑,有些pytorch損失函數(shù)不支持gpu計(jì)算,例如二元交叉熵?fù)p失
定義損失函數(shù)與優(yōu)化器
模型訓(xùn)練與驗(yàn)證

打印我們的決策邊界

結(jié)語(yǔ)
目前為止還是我在入門深度學(xué)習(xí)上,對(duì)不同框架使用的一些感受,在后續(xù)進(jìn)一步學(xué)習(xí)卷積神經(jīng)網(wǎng)絡(luò)和循環(huán)神經(jīng)網(wǎng)絡(luò)后,或許會(huì)有不一樣的感受,這里暫且記錄于此,希望能幫到各位初學(xué)者,并祝大家煉丹成功!
