pytorch菜鳥教程(pytorch 教程)
來源:圖靈社羣
題圖來自Usplash
1 什麼是PyTorch?
PyTorch是與TensorFlow、MXNet、Caffe等平行的深度學習開源框架。2017年初由Facebook首次推出,旨在實現快速,靈活的實驗和高效生產。
PyTorch一經推出,便很快成為人工智慧領域研究人員的熱門選擇。
在深度學習頂級會議ICLR的提交論文中,提及PyTorch的論文數從2017年的87篇激增到2018年的252篇,大有趕超深度學習框架佼佼者TensorFlow之勢。
隨著PyTorch 1.0的問世以及ONNX(Open Neural Network Exchange)深度學習開發生態的逐漸完備,PyTorch無疑成為眾多深度學習框架中最值得期待的明日之星。
PyTorch為什麼會這麼受歡迎?
下面我們簡單總結了4點原因。
1. 簡單、易用、上手快
這一點對於初學者來說是極具吸引力的。
2. 功能強大
從計算機視覺、自然語言處理再到深度強化學習,PyTorch的功能異常強大。而且,如今支援PyTorch、功能強大的包也越來越多,例如Allen NLP和Pyro。
3. Python化程式設計
在諸多深度學習開源框架平臺中,PyTorch恐怕是和Python結合得最好的一個。相比較TensorFlow框架來說,PyTorch將會讓你的程式碼更流暢舒服。
4. 強大的社羣支援
對於一個初學者來說,吸取到前輩的經驗恐怕是最迫切的問題了。儘管PyTorch僅兩歲有餘,但是它的社羣成長飛快。在國內,用PyTorch作為關鍵詞搜尋就能找到大概五六個網路社羣、BBS。各大問答類網站關於PyTorch的問題數目也在持續增多。
PyTorch最大的特點就在於簡單易用,特別適合新手快速掌握。
PyTorch與TensorFlow有什麼區別?
到底哪個框架更適合學習?下面這篇知乎文章或許能幫到你:
《PyTorch還是TensorFlow?這有一份新手深度學習框架選擇指南》
文中對這兩個框架做了簡單的對比,所以在這裡我們就不再說了。PS:技術是發展的,文中的對比非絕對。
2 新手如何入門PyTorch?
其實PyTorch官網提供的的教程資源很全面,我們可以根據下面的步驟進行學習,此步驟來源知乎陳雲的回答,原文地址:
https://www.zhihu.com/question/55720139/answer/147148105
1. PyTorch Tutorials > Deep Learning with PyTorch: A 60 Minute Blitz
60分鐘入門,簡單易懂。
https://pytorch.org/tutorials/
2. PyTorch Examples:
實現一個簡單的例子,加深理解。
https://github.com/pytorch/examples
3. 通讀PyTorch文件:
絕大部分文件都是作者親自寫的,質量很高。
https://pytorch.org/docs/stable/index.html
4. 論壇討論:
論壇很活躍,沒事刷一刷帖可以少走很多彎路。
https://discuss.pytorch.org/
5. 閱讀原始碼
通過閱讀程式碼可以瞭解函式和類的機制,此外它的很多函式,模型,模組的實現方法都如教科書般經典。
其他:PyTorch資源合集:
https://github.com/ritchieng/the-incredible-pytorch
3 PyTorch示例:預測房價
下面我們引入一個例項問題:根據歷史資料預測未來的房價。
我們將實現一個線性迴歸模型,並用梯度下降演算法求解該模型,從而給出預測直線。
這個例項問題是:假如有歷史房價資料,我們應如何預測未來某一天的房價?針對這個問題,我們的求解步驟包括:準備資料、模型設計、訓練和預測。
一、準備資料
按理說,我們需要找到真實的房價資料來進行擬合和預測。簡單起見,我們也可以人為編造一批資料,從而重點關注方法和流程。
首先,我們編造一批假的時間資料。假設我們每隔一個月能獲得一次房價資料,那麼時間資料就可以為0, 1, …,表示第0、1、2……個月份,我們可以由PyTorch的linspace來構造0~100之間的均勻數字作為時間變數x:
x = Variable(torch.linspace(0, 100).type(torch.FloatTensor))
然後,我們再來編造這些時間點上的歷史房價資料。假設它就是在x 的基礎上加上一定的噪聲:
rand = Variable(torch.randn(100)) * 10 y = x rand
這裡的rand 是一個隨機數,滿足均值為0、方差為10 的正態分佈。torch.randn(100)這個命令可以生成100個標準正態分佈隨機數(均值0,方差1)。於是,我們就編造好了歷史房價資料:y。現在我們有了100 個時間點xi(i是下標)和每個時間點對應的房價yi(i是下標)。其中,每一個xi(i是下標), yi(i是下標)稱為一個樣本點。
之後,我們將資料集切分成訓練集和測試集兩部分。所謂訓練集是指訓練一個模型的所有資料,所謂測試集則是指用於檢驗這個訓練好的模型的所有資料。注意,在訓練的過程中,模型不會接觸到測試集的資料。因此,模型在測試集上執行的效果模擬了真實的房價預測環境。
在下面這段程式碼中,:-10 是指從x 變數中取出倒數第10 個元素之前的所有元素;而-10:是指取出x 中最後面的10 個元素。所以,我們就把第0 到90 個月的資料當作訓練集,把後10 個月的資料當作測試集。
x_train = x[: -10] x_test = x[-10 :] y_train = y[: -10] y_test = y[-10 :]
接下來,讓我們對訓練資料點進行視覺化:
import matplotlib.pyplot as plt #匯入畫圖的程式包
plt.figure(figsize=(10,8)) #設定繪製視窗大小為10*8 inch #繪製資料,由於x 和y 都是Variable,需要用data 獲取它們包裹的Tensor,並轉成Numpy plt.plot(x_train.data.numpy(), y_train.data.numpy(), 'o') plt.xlabel('X') #新增X 軸的標註 plt.ylabel('Y') #新增Y 軸的標註 plt.show() #畫出圖形
最終得到的輸出影象如圖1所示。
圖1 人造房價資料的散點圖
通過觀察散點圖,可以看出走勢呈線性,所以可以用線性迴歸來進行擬合。
二、模型設計
我們希望得到一條儘可能從中間穿越這些資料散點的擬合直線。設這條直線方程為:
y=ax b
接下來的問題是,求解出引數a、b 的數值。我們可以將每一個資料點xi(i下標)代入這個方程中,計算出一個ˆyi(i下標),即:
顯然,這個點越靠近yi(i下標)越好。所以,我們只需要定義一個平均損失函式:
並讓它儘可能地小。其中N 為所有資料點的個數,也就是100。由於xi(i下標), yi (i下標)都是固定的數,而只有a 和b 是變數,那麼L 本質上就是a 和b 的函式。所以,我們要尋找最優的a、b 組合,讓L 最小化。
我們可以利用梯度下降法來反覆迭代a 和b,從而讓L 越變越小。梯度下降法是一種常用的數值求解函式最小值的基本方法,它的基本思想就像是盲人下山。這裡要優化的損失函式L(a, b)就是那座山。假設有一個盲人站在山上的某個隨機初始點(這就對應了a 和b 的初始隨機值),他會在原地轉一圈,尋找下降最快的方向來行進。所謂下降的快慢,其實就是L 對a、b 在這一點的梯度(導數);所謂的行進,就是更新a 和b 的值,讓盲人移動到一個新的點。於是,每到一個新的點,盲人就會依照同樣的方法行進,最終停留在讓L 最小的那個點。
我們可以通過下面的迭代計算來實現盲人下山的過程:
α 為一個引數,叫作學習率,它可以調節更新的快慢,相當於盲人每一步的步伐有多大。α 越大,a、b 更新得越快,但是計算得到的最優值L 就有可能越不準。
在計算的過程中,我們需要計算出L 對a、b 的偏導數,利用PyTorch 的backward()可以非常方便地將這兩個偏導數計算出來。於是,我們只需要一步一步地更新a 和b 的數值就可以了。當達到一定的迭代步數之後,最終的a 和b 的數值就是我們想要的最優數值,y=ax b 這條直線就是我們希望尋找的儘可能擬合所有資料點的直線。
三、訓練
接下來,就讓我們將上述思路轉化為PyTorch 程式碼。首先,我們需要定義兩個自動微分變數a 和b:
a = Variable(torch.rand(1), requires_grad = True) b = Variable(torch.rand(1), requires_grad = True)
可以看到,在初始的時候,a 和b 都是隨機取值的。設定學習率:
learning_rate = 0.0001
然後,完成對a 和b 的迭代計算:
for i in range(1000): #計算在當前a、b 條件下的模型預測數值 predictions = a.expand_as(x_train) * x_train b.expand_as(x_train) loss = torch.mean((predictions - y_train) ** 2) #通過與標籤資料y 比較,計算誤差 print('loss:', loss) loss.backward() #對損失函式進行梯度反傳 #利用上一步計算中得到的a 的梯度資訊更新a 中的data 數值 a.data.add_(- learning_rate * a.grad.data) #利用上一步計算中得到的b 的梯度資訊更新b 中的data 數值 b.data.add_(- learning_rate * b.grad.data)#增加這部分程式碼,清空儲存在變數a、b 中的梯度資訊,以免在backward 的過程中反覆不停地累加 a.grad.data.zero_() #清空a 的梯度數值 b.grad.data.zero_() #清空b 的梯度數值
這個迭代計算了1000 步,當然我們可以調節數值。數值越大,迭代時間越長,最終計算得到的a、b 就會越準確。在每一步迭代中,我們首先要計算predictions,即所有點的ˆyi ;然後計算平均誤差函式loss,即前面定義的L;接著呼叫了backward()函式,求L 對所有計算圖中的葉節點(a、b)的導數。於是,這些導數資訊分別儲存在了a.grad 以及b.grad 之中;然後,通過a.data.add_(-learning_rate * a.grad.data)完成對a 數值的更新,也就是a 的數值應該加上一個-learning_rate 乘以剛剛計算得到的L 對a 的偏導數值,b 也進行同樣的處理;最後,在更新完a、b 的數值後,需要清空a 中的梯度資訊(a.grad.data.zero_()),否則它會在下一步迭代的時候自動累加。於是,一步迭代完成。
整個計算過程其實是利用自動微分變數 a 和b 來完成動態計算圖的構建,然後在其上進行梯度反傳的過程。所以,整個計算過程就是在訓練一個廣義的神經網路,a 和b 就是神經網路的引數,一次迭代就是一次訓練。
另外,有以下幾點技術細節值得說明。
- 在計算predictions 時,為了讓a、b 與x 的維度相匹配,我們對a 和b 進行了擴維。我們知道,x_train 的尺寸是(90, 1),而a、b 的尺寸都是1,它們並不匹配。我們可以通過使用expand_as 提升a、b 的尺寸,與x_train 一致。a.expand_as(x_train)的作用是將a的維度調整為和x_train 一致,所以函式的結果是得到一個尺寸為(90, 1)的張量,數值全為a 的數值。
- 不能直接對一個自動微分變數進行數值更新,只能對它的data 屬性進行更新。所以在更新a 的時候,我們是在更新a.data,也就是a 所包裹的張量。
- 在PyTorch中,如果某個函式後面加上了“_”,就表明要用這個函式的計算結果更新當前的變數。例如,a.data.add_(3)的作用是將a.data 的數值更新為a.data 加上3。
最後,將原始的資料散點聯合擬合的直線通過圖形畫出來,如下所示:
x_data = x_train.data.numpy() #將x 中的資料轉換成NumPy 陣列 plt.figure(figsize = (10, 7)) #定義繪圖視窗 xplot, = plt.plot(x_data, y_train.data.numpy(), 'o') #繪製x, y 散點圖 yplot, = plt.plot(x_data, a.data.numpy() * x_data b.data.numpy()) #繪製擬合直線圖 plt.xlabel('X') #給橫座標軸加標註 plt.ylabel('Y') #給縱座標軸加標註 str1 = str(a.data.numpy()[0]) 'x ' str(b.data.numpy()[0]) #將擬合直線的引數a、b 顯示出來 plt.legend([xplot, yplot],['Data', str1]) #繪製圖例 plt.show() #將圖形畫出來
最後得到的影象如圖2所示:
圖2 資料點與擬合曲線
看來我們得到的擬合結果還不錯。
四、預測
最後一步就是進行預測。在測試資料集上應用我們的擬合直線來預測出對應的y,也就是房價。只需要將測試資料的x 值帶入我們擬合好的直線即可:
predictions = a.expand_as(x_test) * x_test b.expand_as(x_test) #計算模型的預測結果 predictions #輸出
最終輸出的預測結果為:
Variable containing: 89.4647 90.4586 91.4525 92.4465 93.4404 94.4343 95.4283 96.4222 97.4162 98.4101 [torch.FloatTensor of size 10]
那麼,預測的結果到底準不準呢?我們不妨把預測數值和實際數值繪製在一起,如下所示:
x_data = x_train.data.numpy() #獲得x 包裹的資料 x_pred = x_test.data.numpy() #獲得包裹的測試資料的自變數 plt.figure(figsize = (10, 7)) #設定繪圖視窗大小 plt.plot(x_data, y_train.data.numpy(), 'o') #繪製訓練資料 plt.plot(x_pred, y_test.data.numpy(), 's') #繪製測試資料 x_data = np.r_[x_data, x_test.data.numpy()] plt.plot(x_data, a.data.numpy() * x_data b.data.numpy()) #繪製擬合資料 plt.plot(x_pred, a.data.numpy() * x_pred b.data.numpy(), 'o') #繪製預測資料 plt.xlabel('X') #更改橫座標軸標註 plt.ylabel('Y') #更改縱座標軸標註 str1 = str(a.data.numpy()[0]) 'x ' str(b.data.numpy()[0]) #圖例資訊 plt.legend([xplot, yplot],['Data', str1]) #繪製圖例 plt.show()
最終得到的影象如圖3 所示:
圖3 擬合曲線及其預測資料
圖中的方塊點表示測試集中實際的房價資料,直線上的圓點則表示在測試集上預測的房價資料。我們還可以計算測試集上的損失函式,來檢驗模型預測的效果,在此不再贅述。
——示例內容節選自《深度學習原理與PyTorch實戰》
10個PyTorch實戰案例
10個實戰示例來源於《深度學習原理與PyTorch實戰》,這是一本系統介紹PyTorch的入門書。全書共12章,前2章是深度學習和PyTorch簡介,後面10章,每章一個實戰示例。
深度學習原理與PyTorch實戰
- 單車預測器——你的第一個神經網路
- 機器也懂感情——中文情緒分類器
- 手寫數字識別器——卷積神經網路
- 寫數字加法機——遷移學習
- 自己的Prisma——影象風格遷移
- 人工智慧造假術——影象生成與對抗學習
- 詞彙的星空——詞向量與Word2Vec
- LSTM作曲機——序列生成模型
- 神經翻譯機——端到端的機器翻譯模型
- AI遊戲高手——深度強化學習
讀完這本書,我們可以輕鬆入門深度學習,學會構造一個影象識別器,生成逼真的圖畫,讓機器理解單詞與文字,讓機器作曲,教會機器玩遊戲,還可以實現一個簡單的機器翻譯系統等。
深度學習原理與PyTorch實戰
——
集智俱樂部 著
—— 集智俱樂部 ——
誕生於2003年,是國內最早的人工智慧社羣之一。經過十幾年的發展,已經逐漸成長為一個深受國內頂尖研究者、科學家、工程師和學生群體熱愛的學術社羣。
在這十幾年間,集智俱樂部舉辦了大大小小400多場講座、讀書會等活動,創作了《科學的極致:漫談人工智慧》和《走近2050:注意力、網際網路與人工智慧》兩本人工智慧科普讀物。
值得一提的是,國內AI領域著名的創業黑馬“Momenta”和“彩雲AI”的創始人及核心成員都來自於集智俱樂部。
全書注重實戰,每章圍繞一個有意思的實戰案例展開,不僅循序漸進地講解了PyTorch的基本使用、神經網路的搭建、卷積神經網路和迴圈神經網路的實現,而且全面深入地介紹了計算機視覺、自然語言處理、遷移學習,以及最新的對抗學習和深度強化學習等前沿技術。
本書資源
本書配有原始碼、習題和視訊課程,讓你輕鬆入門深度學習,快速上手PyTorch。