入門Pytorch(一)——搭建第一個神經網絡

第一步:安裝Pytorch

個人電腦在pip上下載Pytorch報錯,所以使用Anaconda下載,在此再也不贅述。html

第二步:準備數據、構建框架

首先咱們約定嘗試搭建兩層神經網絡,數據量$N=64$,輸入層、隱藏層、輸出層的維度分別是:$d_{in}=1000,H=100,d_{out}=10$python

由於是一個Demo,因此嘗試直接使用一些隨機數據進行測試:網絡

#  64個數據,1000-dim,,中間層100-dim,輸出10-dim
x = torch.randn(N, d_in, requires_grad=True)
y = torch.randn(N, d_out, requires_grad=True)

注意在這個時候須要寫出requires_grad=True,方便後續使用.grad屬性直接計算梯度。app

接下來就是要定義一個模型,這個模型咱們是打算使用兩層的神經網絡,首先在官方的Doc中是這樣定義torch.nn.module的用法的:框架

Base class for all neural network modules.ide

Your models should also subclass this class.函數

查閱Doc,主要有幾個點是應該會用到的:學習

  • torch.nn.module應當是全部神經網絡的基類,而且你要是寫一個神經網絡也應該繼承自此。
  • 若是要應用這個模型到GPU,還可使用.cuda()函數。

對於其中的__init__,就是勾勒出整個模型的框架,咱們首先須要把基類的構造函數進行調用,而後把本模型所須要的函數進行定義,由於咱們想要作兩層的神經網絡,因此分別聲明兩層線性的函數。測試

對於其中的forward,是全部的子類都必須得進行override,表明了前向傳播的逐層映射關係。激活函數咱們約定使用ReLu也就是.clamp(min=0)優化

因此咱們能夠寫成下面這個樣子:

class TwoLayerNet(torch.nn.module):
    #  定義了init和forward就想到於給定了一個模型
    #  init至關於給了這個框架
    def __init__(self, d_in, H, d_out):
        super(TwoLayerNet, self).__init__()
        self.linear1 = nn.Linear(d_in, H)
        self.linear2 = nn.Linear(H, d_out)

    #  forward是定義前向傳播的部分
    def forward(self, x):
        y_pred = self.linear2(self.linear1(x).clamp(min=0))
        return y_pred

第三步:應用模型

前向傳播部分

主要是兩個方面,第一是把上面定義好的框架應用起來,第二是給定學習率和loss function。

# 初始化model
model = TwoLayerNet(d_in, H, d_out)

# 規定loss function
loss_fn = nn.MSELoss(reduction='sum')

# 規定學習率
learning_rate = 1e-4

反向傳播部分

首先,咱們約定反向傳播的模型是SGD這種比較簡單的模型:

optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
loss_list = []  # 爲了畫圖

訓練迭代部分

至此,咱們須要對模型有個直觀認識,對於整個模型而言應當是$x \rightarrow H \rightarrow y_{pred}$爲正向傳播路徑,而損失函數爲:

$$loss = \sqrt{y_{pred}^2-y^2} $$

對於各層神經網絡,我借用網圖來講明一下關係:

timg.jpg

第一層神經網絡是輸入部分:因此權重矩陣$w_1$應該是$d_{in}\times H$的維度,同理,第二層神經網絡輸出權重矩陣應當是$H \times d_{out}$維度。

咱們接下來就是進行訓練迭代,咱們先約定訓練$200$代,觀察收斂效果。

for it in range(200):
    #  forward pass
    y_pred = model(x)

    #  compute loss
    loss = loss_fn(y_pred.float(), y.float())
    print(it, loss.item())
    loss_list.append(loss)

    #  backward pass
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

forward pass部分是把自變量$x$輸入到模型中,而compute loss是計算損失數值,咱們須要注意如下這些點:

  • loss_fn(y_pred.float(), y.float())不能夠寫成loss_fn(y_pred- y),不然會缺失一個target參數
  • loss.item()是用來輸出loss這個tensor包含的數值

backward pass中,咱們須要注意,每次求梯度降低以前,都須要把以前的梯度清零,緣由就是這個梯度若是不被清零,在每次迭代的時候都會被自動疊加,這樣自動疊加的好處是對於一些連鎖的梯度運算的時候更爲方便了,可是對於每一代而言都須要手動進行清零。

第四步:結尾和簡單分析

最後咱們只要簡單的把迭代的圖畫出來便可,效果大概是這樣的:

plt.plot(range(200), loss_list)
plt.show()

Figure_1.png
大概在$10$代附近就已經收斂了,效果仍是蠻不錯的。能夠經過第一次運行的結果調整迭代次數。

下面附上整個代碼:

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
N, d_in, H, d_out = 64, 1000, 100, 10

#  隨機建立一些訓練數據
x = torch.randn(N, d_in, requires_grad=True)
y = torch.randn(N, d_out, requires_grad=True)


class TwoLayerNet(torch.nn.module):
    #  定義了init和forward就想到於給定了一個模型
    #  init至關於給了這個框架
    def __init__(self, D_in, H, D_out):
        super(TwoLayerNet, self).__init__()
        self.linear1 = nn.Linear(D_in, H)
        self.linear2 = nn.Linear(H, D_out)

    #  forward是
    def forward(self, x):
        y_pred = self.linear2(self.linear1(x).clamp(min=0))
        return y_pred


# 初始化model
model = TwoLayerNet(d_in, H, d_out)

# 規定loss function
loss_fn = nn.MSELoss(reduction='sum')

# 規定學習率
learning_rate = 1e-4

#  定義optimizer作優化
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
loss_list = []
for it in range(200):
    #  forward pass
    y_pred = model(x)

    #  compute loss
    loss = loss_fn(y_pred.float(), y.float())
    print(it, loss.item())
    loss_list.append(loss)

    #  backward pass
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

plt.plot(range(200), loss_list)
plt.show()

參考資料

pytorch官方文檔

最好的PyTorch的入門與實戰教程(16小時實戰)

相關文章
相關標籤/搜索