神經(jīng)網(wǎng)絡(luò)實(shí)驗(yàn)代碼 | PyTorch系列(二十七)
點(diǎn)擊上方“AI算法與圖像處理”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)

推薦
這個(gè)系列很久沒有更新了,最新有小伙伴反饋官網(wǎng)的又更新了,因此,我也要努力整理一下。這個(gè)系列在CSDN上挺受歡迎的,希望小伙伴無論對你現(xiàn)在是否有用,請幫我分享一下,后續(xù)會(huì)弄成電子書,幫助更多人!
歡迎來到這個(gè)神經(jīng)網(wǎng)絡(luò)編程系列。 在本文中,我們將編寫一個(gè)RunBuilder類,該類將允許我們使用不同的參數(shù)生成多個(gè)運(yùn)行。
使用RunBuilder類
本文以及本系列最后幾節(jié)的目的是使自己處于能夠有效地嘗試我們所構(gòu)建的訓(xùn)練過程的位置。因此,我們將擴(kuò)展在超參數(shù)實(shí)驗(yàn)中該情節(jié)涉及的內(nèi)容。我們將使那里看到的更加干凈。
我們將構(gòu)建一個(gè)名為RunBuilder的類。但是,在介紹如何構(gòu)建類之前。讓我們看看它將允許我們做什么。我們將從import 開始。
from collections import OrderedDictfrom collections import namedtuplefrom itertools import product
我們正在從 collections 中導(dǎo)入OrderedDict和namedtuple,并且正在從itertools中導(dǎo)入一個(gè)名為product的函數(shù)。這個(gè)product()函數(shù)是我們上次看到的函數(shù),它在給定多個(gè)列表輸入的情況下計(jì)算笛卡爾乘積。
好的。這是RunBuilder類,它將構(gòu)建用于定義運(yùn)行的參數(shù)集??吹饺绾问褂煤?,我們將看到它的工作原理。
class RunBuilder():def get_runs(params):Run = namedtuple('Run', params.keys())runs = []for v in product(*params.values()):runs.append(Run(*v))return runs
關(guān)于使用此類的主要注意事項(xiàng)是它具有一個(gè)稱為get_runs()的靜態(tài)方法。該方法將為我們提供基于傳入?yún)?shù)構(gòu)建的運(yùn)行結(jié)果。
現(xiàn)在定義一些參數(shù)。
params = OrderedDict( ?????????????lr?=?[.01,?.001],????????????batch_size?=?[1000,?10000])
在這里,我們在字典中定義了一組參數(shù)和值。我們有一組要嘗試的學(xué)習(xí)率和一組批batch的大小。當(dāng)我們說“嘗試”時(shí),是指我們要針對字典中的每個(gè)學(xué)習(xí)率和每個(gè)批次大小進(jìn)行一次訓(xùn)練。
要獲得這些運(yùn)行,我們只需調(diào)用RunBuilder類的get_runs()函數(shù),并傳入我們要使用的參數(shù)即可。
runs = RunBuilder.get_runs(params)runs[Run(lr=0.01, batch_size=1000),Run(lr=0.01, batch_size=10000),Run(lr=0.001, batch_size=1000),Run(lr=0.001, batch_size=10000)]
很好,我們可以看到RunBuilder類已經(jīng)構(gòu)建并返回了四個(gè)運(yùn)行的列表。這些運(yùn)行中的每一個(gè)都有學(xué)習(xí)率和定義運(yùn)行的batch大小。
我們可以通過索引到列表來訪問單個(gè)運(yùn)行,如下所示:
run = runs[0]runRun(lr=0.01, batch_size=1000)
注意運(yùn)行輸出的字符串表示形式。此字符串表示形式是由Run tuple類為我們自動(dòng)生成的,如果我們想將運(yùn)行統(tǒng)計(jì)信息寫到TensorBoard或任何其他可視化程序的磁盤上,則可以使用該字符串唯一標(biāo)識(shí)運(yùn)行。
另外,由于run is object是具有命名屬性的元組,因此我們可以使用點(diǎn)表示法訪問值,如下所示:
> print(run.lr, run.batch_size)0.01 1000
最后,由于運(yùn)行列表是Python可迭代的,因此我們可以像這樣干凈地迭代運(yùn)行:
for run in runs:print(run, run.lr, run.batch_size)
輸出:
Run(lr=0.01, batch_size=1000) 0.01 1000Run(lr=0.01, batch_size=10000) 0.01 10000Run(lr=0.001, batch_size=1000) 0.001 1000Run(lr=0.001, batch_size=10000) 0.001 10000
要添加其他值,我們要做的就是將它們添加到原始參數(shù)列表中,如果我們想添加其他類型的參數(shù),我們要做的就是添加它。新參數(shù)及其值將自動(dòng)變?yōu)榭稍谶\(yùn)行中使用。運(yùn)行的字符串輸出也將更新。
兩個(gè)參數(shù):
params = OrderedDict(lr = [.01, .001],batch_size = [1000, 10000])runs = RunBuilder.get_runs(params)runs
輸出:
[Run(lr=0.01, batch_size=1000),Run(lr=0.01, batch_size=10000),Run(lr=0.001, batch_size=1000),Run(lr=0.001, batch_size=10000)]
三個(gè)參數(shù):
params = OrderedDict(lr = [.01, .001],batch_size = [1000, 10000],device = ["cuda", "cpu"])runs = RunBuilder.get_runs(params)runs
輸出:
[Run(lr=0.01, batch_size=1000, device='cuda'),Run(lr=0.01, batch_size=1000, device='cpu'),Run(lr=0.01, batch_size=10000, device='cuda'),Run(lr=0.01, batch_size=10000, device='cpu'),Run(lr=0.001, batch_size=1000, device='cuda'),Run(lr=0.001, batch_size=1000, device='cpu'),Run(lr=0.001, batch_size=10000, device='cuda'),Run(lr=0.001, batch_size=10000, device='cpu')]
當(dāng)我們在訓(xùn)練過程中嘗試不同的值時(shí),此功能將使我們能夠更好地控制。
讓我們看看如何構(gòu)建此RunBuilder類。
編碼 RunBuilder類
我們需要具備的第一件事就是我們想要嘗試的參數(shù)和值字典。
params = OrderedDict(lr = [.01, .001],batch_size = [1000, 10000])
接下來,我們從字典中獲得鍵列表。
> params.keys()odict_keys(['lr', 'batch_size'])
然后,我們從字典中獲取值列表。
> params.values()odict_values([[0.01, 0.001], [1000, 10000]])
有了這兩個(gè)功能之后,我們只需檢查一下它們的輸出,以確保我們了解它們。完成后,我們將使用這些鍵和值進(jìn)行下一步操作。我們將從鍵開始。
Run = namedtuple('Run', params.keys())該行創(chuàng)建一個(gè)名為Run的新元組子類,該子類具有命名字段。這個(gè)Run類用于封裝每次運(yùn)行的數(shù)據(jù)。此類的字段名稱由傳遞給構(gòu)造函數(shù)的名稱列表設(shè)置。首先,我們傳遞類名。然后,我們傳遞字段名,在本例中,我們傳遞字典中的鍵列表。
現(xiàn)在我們有了一個(gè)用于運(yùn)行的類,我們準(zhǔn)備創(chuàng)建一些類。
runs = []for v in product(*params.values()):runs.append(Run(*v))
首先,我們創(chuàng)建一個(gè)名為runs的列表。然后,我們使用itertools中的product()函數(shù)使用字典中每個(gè)參數(shù)的值來創(chuàng)建笛卡爾乘積。這給了我們一組定義運(yùn)行的有序?qū)ΑN覀儽闅v所有這些,將運(yùn)行添加到每個(gè)運(yùn)行的列表中。
對于笛卡爾乘積中的每個(gè)值,我們都有一個(gè)有序的元組。笛卡爾積為我們提供了每個(gè)訂購對,因此我們擁有所有可能的訂購對,其學(xué)習(xí)率和批量大小均如此。當(dāng)將元組傳遞給Run構(gòu)造函數(shù)時(shí),我們使用*運(yùn)算符告訴構(gòu)造函數(shù)接受元組值作為與元組本身相反的參數(shù)。
最后,我們將此代碼包裝在RunBuilder類中。
class RunBuilder():def get_runs(params):Run = namedtuple('Run', params.keys())runs = []for v in product(*params.values()):runs.append(Run(*v))return runs
由于get_runs()方法是靜態(tài)的,因此我們可以使用類本身來調(diào)用它。我們不需要該類的實(shí)例。
現(xiàn)在,這使我們可以通過以下方式更新我們的訓(xùn)練代碼:
之前:
for lr, batch_size, shuffle in product(*param_values):comment = f' batch_size={batch_size} lr={lr} shuffle={shuffle}'# Training process given the set of parameters
之后
for run in RunBuilder.get_runs(params):comment = f'-{run}'# Training process given the set of parameters
什么是笛卡爾積?
您知道笛卡爾積嗎?像生活中的許多事物一樣,笛卡爾積是一個(gè)數(shù)學(xué)概念。笛卡爾積是二進(jìn)制運(yùn)算。該操作將兩組作為參數(shù),并返回第三組作為輸出。讓我們看一個(gè)通用的數(shù)學(xué)示例。
假設(shè) X ?是一個(gè)集合。
假設(shè) Y 是一個(gè)集合。
兩組之間的笛卡爾積表示為:X * Y。集合X和集合Y的笛卡爾積被定義為所有有序?qū)Φ募蠈Γ▁, y), x∈X ?和 y∈Y。這可以用以下方式表示:

這種表示笛卡爾乘積的輸出的方式稱為集合生成器符號(hào)。很酷。所以X *Y ?是所有有序?qū)Φ募希▁, y), x∈X ?和 y∈Y。
計(jì)算X*Y
我們執(zhí)行以下操作:對于每個(gè)x∈X ?和 y∈Y,我們收集相應(yīng)的對(x, y)。結(jié)果集合給我們的是所有有序?qū)Φ募?/span>
這是用Python表達(dá)的具體示例:
X = {1,2,3}Y = {1,2,3}{ (x,y) for x in X for y in Y }
輸出:
{(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)}注意數(shù)學(xué)代碼是多么強(qiáng)大。它包括所有的情況。也許你注意到這可以通過使用for循環(huán)迭代來實(shí)現(xiàn),就像這樣:
X = {1,2,3}Y = {1,2,3}cartesian_product = set()for x in X:for y in Y:cartesian_product.add((x,y))cartesian_product
輸出:
{(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)}結(jié)束好了,現(xiàn)在我們知道它是如何工作的了,我們可以繼續(xù)使用它。
文章中內(nèi)容都是經(jīng)過仔細(xì)研究的,本人水平有限,翻譯無法做到完美,但是真的是費(fèi)了很大功夫,希望小伙伴能動(dòng)動(dòng)你性感的小手,分享朋友圈或點(diǎn)個(gè)“在看”,支持一下我?^_^
英文原文鏈接是:
https://deeplizard.com/learn/video/NSKghk0pcco



加群交流
歡迎小伙伴加群交流,目前已有交流群的方向包括:AI學(xué)習(xí)交流群,目標(biāo)檢測,秋招互助,資料下載等等;加群可掃描并回復(fù)感興趣方向即可(注明:地區(qū)+學(xué)校/企業(yè)+研究方向+昵稱)

