Pytorch深度學習之神經網絡合成(pytorch實現神經網絡)
理解神經網絡的基本組成部分,如張量、張量運算和梯度遞減等,對構造復雜的神經網絡至關重要。本章將構建首個神經網絡的Hello world程序,并涵蓋以下主題:
安裝PyTorch;
實現第一個神經網絡;
劃分神經網絡的功能模塊;
介紹張量、變量、Autograd、梯度和優化器等基本構造模塊;
使用PyTorch加載數據。
2.1 安裝PyTorch
PyTorch可以作為Python包使用,用戶可以使用pip或conda來構建,或者從源代碼構建。本書推薦使用Anaconda Python 3發行版。要安裝Anaconda,請參考Anaconda官方文檔。所有示例將在本書的GitHub存儲庫中以Jupyter Notebook的形式提供。強烈建議使用Jupyter Notebook,因為它允許進行交互。如果已經安裝了Anaconda Python,那么可以繼續PyTorch安裝的后續步驟。
基于GPU的Cuda 8版安裝:
基于GPU的Cuda 7.5版安裝:
非GPU版的安裝:
在本書寫作時,PyTorch還不支持Windows,所以可以嘗試使用虛擬機或Docker鏡像。
2.2 實現第一個神經網絡
下面給出本書介紹的第一個神經網絡,它將學習如何將訓練示例(即輸入數組)映射成目標(即輸出數組)。假設我們為最大的在線公司之一Wondermovies工作(該公司按需提供視頻服務),訓練數據集包含了表示用戶在平臺上觀看電影的平均時間的特征,網絡將據此預測每個用戶下周使用平臺的時間。這是個假想出來的用例,不需要深入考慮。構建解決方案的主要分解活動如下。
準備數據:get_data函數準備輸入和輸出張量(數組)。
創建學習參數:get_weights函數提供以隨機值初始化的張量,網絡通過優化這些參數來解決問題。
網絡模型:simple_network函數應用線性規則為輸入數據生成輸出,計算時先用權重乘以輸入數據,再加上偏差(y
=wx
+b
)。 -?損失:loss_fn函數提供了評估模型優劣的信息。 -?優化器:optimize函數用于調整初始的隨機權重,并幫助模型更準確地計算目標值。
如果大家剛接觸機器學習,不用著急,到本章結束時將會真正理解每個函數的作用。下面這些從PyTorch代碼抽取出來的函數,有助于更容易理解神經網絡。我們將逐個詳細討論這些函數。前面提到的分解活動對大多數機器學習和深度學習問題而言都是相同的。接下來的章節會探討為改進各項功能從而構建實際應用的各類技術。
神經網絡的線性回歸模型如下:
{-:-}y
=?__w__x
+b
用PyTorch編碼如下:
到本章結束時,你會了解到每個函數的作用。
2.2.1 準備數據
PyTorch提供了兩種類型的數據抽象,稱為張量和變量。張量類似于numpy中的數組,它們也可以在GPU上使用,并能夠改善性能。數據抽象提供了GPU和CPU的簡易切換。對某些運算,我們會注意到性能的提高,以及只有當數據被表示成數字的張量時,機器學習算法才能理解不同格式的數據。張量類似Python數組,并可以改變大小。例如,圖像可以表示成三維數組(高,寬,通道(RGB)),深度學習中使用最多5個維度的張量表示也很常見。一些常見的張量如下:
標量(0維張量);
向量(1維張量);
矩陣(2維張量);
3維張量;
切片張量;
4維張量;
5維張量;
GPU張量。
包含一個元素的張量稱為標量。標量的類型通常是FloatTensor或LongTensor。在本書寫作時,PyTorch還沒有特別的0維張量。因此,我們使用包含一個元素的一維張量表示:
向量只不過是一個元素序列的數組。例如,可以使用向量存儲上周的平均溫度:
大多數結構化數據都可以表示成表或矩陣。我們使用波士頓房價(Boston House Prices)的數據集,它包含在Python的機器學習包scikit-learn中。數據集是一個包含了506個樣本或行的numpy數組,其中每個樣本用13個特征表示。Torch提供了一個工具函數from_numpy(),它將numpy數組轉換成torch張量,其結果張量的形狀為506行×13列:
當把多個矩陣累加到一起時,就得到了一個3維張量。3維張量可以用來表示類似圖像這樣的數據。圖像可以表示成堆疊到一起的矩陣中的數字。一個圖像形狀的例子是(224,224,3),其中第一個數字表示高度,第二個數字表示寬度,第三個表示通道數(RGB)。我們來看看計算機是如何識別大熊貓的,代碼如下:
由于顯示大小為(224,224,3)的張量會占用本書的很多篇幅,因此將把圖2.1所示的圖像切片成較小的張量來顯示。
圖2.1 顯示的圖像
張量的一個常見操作是切片。舉個簡單的例子,我們可能選擇一個張量的前5個元素,其中張量名稱為sales。我們使用一種簡單的記號sales[:slice_index],其中slice_index表示要進行切片的張量位置:
對熊貓圖像做些更有趣的處理,比如只選擇一個通道時熊貓圖像的樣子,以及如何選擇熊貓的面部。
下面,只選擇熊貓圖像的一個通道:
輸出如圖2.2所示。
圖2.2
現在裁剪圖像,假設要構造一個熊貓的面部檢測器,我們只需要熊貓圖像的面部部分。我們來裁剪張量圖像,讓它只包含熊貓面部。
輸出如圖2.3所示。
另一個常見的例子是需要獲取張量的某個特定元素:
第5章在討論使用卷積神經網絡構建圖像分類器時,將再次用到圖像數據。
圖2.3
PyTorch的大多數張量運算都和NumPy運算非常類似。
4維張量類型的一個常見例子是批圖像。為了可以更快地在多樣例上執行相同的操作,現代的CPU和GPU都進行了專門優化,因此,處理一張或多張圖像的時間相差并不大。因而,同時使用一批樣例比使用單樣例更加常見。對批大小的選擇并不一目了然,它取決于多個因素。不使用更大批尺寸或完整數據集的主要因素是GPU的內存限制,16、32和64是通常使用的批尺寸。
舉例來說,加載一批64×224×224×3的貓咪圖片,其中64表示批尺寸或圖片數量,兩個224分別表示高和寬,3表示通道數:
可能必須使用5維張量的一個例子是視頻數據。視頻可以劃分為幀,例如,熊貓玩球的長度為30秒的視頻,可能包含30幀,這可以表示成形狀為(1×30×224×224×3)的張量。一批這樣的視頻可以表示成形狀為(32×30×224×224×3)的張量——例中的30表示每個視頻剪輯中包含的幀數,32表示視頻剪輯的個數。
我們已學習了如何用張量表示法表示不同形式的數據。有了張量格式的數據后,要進行一些常見運算,比如加、減、乘、點積和矩陣乘法等。所有這些操作都可以在CPU或GPU上執行。PyTorch提供了一個名為cuda()的簡單函數,將張量從CPU復制到GPU。我們來看一下其中的一些操作,并比較矩陣乘法運算在CPU和GPU上的性能差異。
張量的加法運算用如下代碼實現:
對于張量矩陣乘法,我們比較一下代碼在CPU和GPU上的性能。所有張量都可以通過調用cuda()函數轉移到GPU上。
GPU上的乘法運算運行如下:
加、減和矩陣乘法這些基礎運算可以用于構建復雜運算,如卷積神經網絡(CNN)和遞歸神經網絡(RNN),本書稍后的章節將進行相關講解。
深度學習算法經常可以表示成計算圖。圖2.4所示為一個在示例中構建的變量計算圖的簡單例子。
圖2.4 變量計算圖
在圖2.4所示的計算圖中,每個小圓圈表示一個變量,變量形成了一個輕量封裝,將張量對象、梯度,以及創建張量對象的函數引用封裝起來。圖2.5所示為Variable類的組件。
圖2.5 Variable類
梯度是指loss函數相對于各個參數(W
,?b
)的變化率。例如,如果a
的梯度是2,那么a
值的任何變化都會導致Y
值變為原來的兩倍。如果還不清楚,不要著急——大多數數深度學習框架都會為我們代為計算梯度值。本章中,我們將學習如何使用梯度來改善模型的性能。
除了梯度,變量還引用了創建它的函數,相應地也就指明了每個變量是如何創建的。例如,變量a帶有的信息表明它是由X和W的積生成的。
讓我們看個例子,創建變量并檢查梯度和函數引用:
在上面的例子中,我們在變量上調用了backward操作來計算梯度。默認情況下,變量的梯度是none。
變量中的grad_fn指向了創建它的函數。變量被用戶創建后,就像例子中的x一樣,其函數引用為None。對于變量y,它指向的函數引用是MeanBackward。
屬性Data用于獲取變量相關的張量。
2.2.2 為神經網絡創建數據
第一個神經網絡中的get_data函數創建了兩個變量:x和y,尺寸為(17, 1)和(17)。我們看函數內部的構造:
在前面神經網絡的例子中,共有兩個學習參數:w和b,還有兩個不變的參數:x和y。我們已在get_data函數中創建了變量x和y。學習參數使用隨機值初始化并創建,其中參數require_grad的值設為True,這與變量x和y不同,變量x和y創建時require_grad的值是False。初始化學習參數有不同的方法,我們將在后續章節探索。下面列出的是get_weights函數代碼:
前面的代碼大部分是一目了然的,其中torch.randn函數為任意給定形狀創建隨機值。
使用PyTorch變量定義了輸入和輸出后,就要構建模型來學習如何將輸入映射到輸出。在傳統的編程中,我們手動編寫具有不同邏輯的函數代碼,將輸入映射到輸出。然而,在深度學習和機器學習中,是通過把輸入和相關的輸出展示給模型,讓模型完成函數的學習。我們的例子中,在線性關系的假定下,實現了嘗試把輸入映射為輸出的簡單神經網絡。線性關系可以表示為y
=?wx
b
,其中w
和b
是學習參數。網絡要學習w
和b
的值,這樣wx
b
才能更加接近真實的y
。圖2.6是訓練集和神經網絡要學習的模型的示意圖。
圖2.6 輸入數據點
圖2.7表示和輸入數據點擬合的線性模型。
圖2.7 擬合數據點的線性模型
圖中的深灰(藍)色線表示網絡學習到的模型。
現在已經有了實現網絡所需的所有參數(x、w、b和y),我們對w和x做矩陣乘法,然后,再把結果與b求和,這樣就得到了預測值y。函數實現如下:
PyTorch在torch.nn中提供了稱為層(layer)的高級抽象,層將負責多數常見的技術都需要用到的后臺初始化和運算工作。這里使用低級些的操作是為了理解函數內部的構造。在第5章和第6章中,將用PyTorch抽象出來的層來構建復雜的神經網絡或函數。前面的模型可以表示為torch.nn層,如下:
我們已經計算出了y值,接下來要了解模型的性能,必須通過loss函數評估。
由于我們的學習參數w和b以隨機值開始,產生的結果y_pred,必和真實值y相去甚遠。因此,需要定義一個函數,來告知模型預測值和真實值的差距。由于這是一個回歸問題,我們使用稱為誤差平方和(也稱為和方差,SSE)的損失函數。我們對y的預測值和真實值之差求平方。SSE有助于模型評估預測值和真實值的擬合程度。torch.nn庫中有不同的損失函數,如均方差(又稱方差,MSE)損失和交叉熵損失。但是在本章,我們自己來實現loss函數:
除了計算損失值,我們還進行了backward操作,計算出了學習參數w和b的梯度。由于我們會不止一次使用loss函數,因此通過調用grad.data.zero_()方法來清除前面計算出的梯度值。在第一次調用backward函數的時候,梯度是空的,因此只有當梯度不為None時才將梯度值設為0。
前面例子中的算法使用隨機的初始權重來預測目標,并計算損失,最后調用loss變量上的backward函數計算梯度值。每次迭代都在整個樣例集合上重復整個過程。在多數的實際應用中,每次迭代都要對整個數據集的一個小子集進行優化操作。損失值計算出來后,用計算出的梯度值進行優化,以讓損失值降低。優化器通過下面的函數實現:
學習率是一個超參數,可以讓用戶通過較小的梯度值變化來調整變量的值,其中梯度指明了每個變量(w和b)需要調整的方向。
不同的優化器,如Adam、RmsProp和SGD,已在torch.optim包中實現好。后面的章節中,我們將使用這些優化器來降低損失或提高準確率。
2.2.3 加載數據
為深度學習算法準備數據本身就可能是件很復雜的事情。PyTorch提供了很多工具類,工具類通過多線程、數據增強和批處理抽象出了如數據并行化等復雜性。本章將介紹兩個重要的工具類:Dataset類和DataLoader類。為了理解如何使用這些類,我們從Kaggle網站()上拿到Dogs vs. Cats數據集,并創建可以生成PyTorch張量形式的批圖片的數據管道。
任何自定義的數據集類,例如Dogs數據集類,都要繼承自PyTorch的數據集類。自定義的類必須實現兩個函數:__len__(self)和__getitem__(self,idx)。任何和Dataset類表現類似的自定義類都應和下面的代碼類似:
在init方法中,將進行任何需要的初始化。例如在本例中,讀取表索引和圖片的文件名。__len__(self)運算負責返回數據集中的最大元素個數。__getitem__ (self, idx)運算根據每次調用時的idx返回對應元素。下面的代碼實現了DogsAndCatsDataset類。
在定義了DogsAndCatsDataset類后,可以創建一個對象并在其上進行迭代,如下面的代碼所示。
在單個的數據實例上應用深度學習算法并不理想。我們需要一批數據,現代的GPU都對批數據的執行進行了性能優化。DataLoader類通過提取出大部分復雜度來幫助創建批數據。
DataLoader類位于PyTorch的utils類中,它將數據集對象和不同的取樣器聯合,如SequentialSampler和RandomSampler,并使用單進程或者多進程的的迭代器,為我們提供批量圖片。取樣器是為算法提供數據的不同策略。下面是使用DataLoader處理Dogs vs. Cats數據集的例子。
imgs包含一個形狀為(32, 224, 224, 3)的張量,其中32表示批尺寸。
PyTorch團隊也維護了兩個有用的庫,即torchvision和torchtext,這兩個庫基于Dataset和DataLoader類構建。我們將在相關章節使用它們。
2.3 小結
本章中,我們學習了PyTorch提供的多個數據結構和操作,并使用PyTorch的基礎組成模塊實現了幾個組件。在數據準備上,我們創建了供算法使用的張量。我們的網絡架構是一個可預測用戶使用Wondermovies平臺的平均小時數的模型。我們使用loss函數檢查模型的性能,并使用optimize函數調整模型的學習參數,從而改善平臺性能。
我們也了解了PyTorch如何通過抽象出數據并行化和數據增強的復雜度,讓創建數據管道變得更簡單。
下一章將深入探討神經網絡和深度學習算法的原理。我們將學習PyTorch內置的用于構建網絡架構、損失函數和優化器的幾個模塊,也將演示如何在真實數據集上使用它們。
本文轉載自異步社區
神經網絡 深度學習 機器學習
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。