task0101.線性回歸
優化函數 - 隨機梯度下降
當模型和損失函數形式較為簡單時,上面的誤差最小化問題的解可以直接用公式表達出來。這類解叫作解析解(analytical solution)。本節使用的線性回歸和平方誤差剛好屬於這個范疇。然而,大多數深度學習模型並沒有解析解,只能通過優化算法有限次迭代模型參數來盡可能降低損失函數的值。這類解叫作數值解(numerical solution)。
在求數值解的優化算法中,小批量隨機梯度下降(mini-batch stochastic gradient descent)在深度學習中被廣泛使用。它的算法很簡單:先選取一組模型參數的初始值,如隨機選取;接下來對參數進行多次迭代,使每次迭代都可能降低損失函數的值。在每次迭代中,先隨機均勻采樣一個由固定數目訓練數據樣本所組成的小批量(mini-batch)β,然后求小批量中數據樣本的平均損失有關模型參數的導數(梯度),最后用此結果與預先設定的一個正數的乘積作為模型參數在本次迭代的減小量。
讀取數據時的一段代碼理解
def data_iter(batch_size, features, labels):
num_examples = len(features)
indices = list(range(num_examples))
random.shuffle(indices) # random read 10 samples
for i in range(0, num_examples, batch_size):
j = torch.LongTensor(indices[i: min(i + batch_size, num_examples)]) # the last time may be not enough for a whole batch
yield features.index_select(0, j), labels.index_select(0, j)
測試
In [1]: num_examples = 20
In [2]: indices = list(range(num_examples))
In [3]: indices
Out[3]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
In [4]: random.shuffle(indices)
In [5]: import random
In [6]: random.shuffle(indices)
In [7]: indices
Out[7]: [8, 16, 15, 18, 14, 10, 0, 7, 2, 3, 4, 9, 12, 6, 17, 13, 5, 11, 19, 1]
In [9]: batch_size = 4
In [10]: for i in range(0, num_examples, batch_size):
...: print(i)
...:
0
4
8
12
16
- 問題:隨便選了課程代碼中的幾個小細節,考考大家,有沒有人來回答一下~
- torch.mm 和 torch.mul 的區別?
- torch.manual_seed(1)的作用?
- optimizer.zero_grad()的作用?
- 答:
(1)torch.mm是矩陣相乘,torch.mul是按元素相乘
(2)設置隨機種子,使實驗結果可以復現
(3)使梯度置零,防止不同batch得到的梯度累加
課后習題
一個圖片解釋
In [12]: import numpy as np
In [13]: y = np.array([1,2,3,4,5,7,8])
In [14]: y.shape
Out[14]: (7,)
In [16]: import torch
In [17]: y = torch.Tensor(y)
In [18]: y.view(-1)
Out[18]: tensor([1., 2., 3., 4., 5., 7., 8.])
In [19]: y.view((-1,1))
Out[19]:
tensor([[1.],
[2.],
[3.],
[4.],
[5.],
[7.],
[8.]])
In [20]: y.view((7,1))
Out[20]:
tensor([[1.],
[2.],
[3.],
[4.],
[5.],
[7.],
[8.]])
In [22]: 0.5* (1/3)*((2.33-3.14)**2 + (1.07 - 0.98)**2 + (1.23 - 1.32)**2)
Out[22]: 0.11205000000000001
task0102.softmax與分類模型
- 這里特征個數d = 4, q = 3(對應輸出o(i)的個數或者截距b(i)的個數), W是4×3型,b是1×3型
- 交叉熵損失函數原理詳解
- 代碼片段解讀
def accuracy(y_hat, y):
return (y_hat.argmax(dim=1) == y).float().mean().item()
- 代碼分析
In [23]: y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])^M
...: y = torch.LongTensor([0, 2]) # 真實的標簽值
In [24]: y.view(-1, 1)
Out[24]:
tensor([[0],
[2]])
In [25]: y_hat.gather(1, y.view(-1, 1))
Out[25]:
tensor([[0.1000],
[0.5000]])
In [26]: y_hat.argmax(dim=1)
Out[26]: tensor([2, 2])
In [27]: (y_hat.argmax(dim=1) == y)
Out[27]: tensor([0, 1], dtype=torch.uint8) # 第一個預測錯誤,所以值為0,第二個預測正確,所以值為1
In [28]: (y_hat.argmax(dim=1) == y).float()
Out[28]: tensor([0., 1.])
In [29]: (y_hat.argmax(dim=1) == y).float().mean()
Out[29]: tensor(0.5000)
In [30]: (y_hat.argmax(dim=1) == y).float().mean().item()
Out[30]: 0.5
2個樣本里面只對了一個樣本(即最后一個),第一個真實值為標簽0,但是y_hat將其預測為標簽2。
總結
softmax的常數不變性引發的思考:
神經網絡中的全部權重同時擴大或減小相同的倍數,softmax分類輸出概率不變,交叉熵不變。
因此有必要對神經網絡的權重進行正則化,防止權重太大
線性回歸:預測連續值,損失函數通常用均方根
SoftMax回歸:預測離散值,用於分類,損失函數通常用交叉熵,softMax這一步主要用於歸一化,得到概率分布
SoftMax對輸出層進行歸一化的原因:
1、輸出層的輸出值的范圍不確定,難以直觀上判斷這些值的意義。
2、由於真實標簽是離散值,這些離散值與不確定范圍的輸出值之間的誤差難以衡量。
交叉熵損失函數 只考慮正確類別的預測概率
課后習題
task0103.多層感知機
-
softmax知識點回顧
-
多層感知機基本知識
-
關於激活函數的選擇
ReLu函數是一個通用的激活函數,目前在大多數情況下使用。但是,ReLU函數只能在隱藏層中使用。
用於分類器時,sigmoid函數及其組合通常效果更好。由於梯度消失問題,有時要避免使用sigmoid和tanh函數。
在神經網絡層數較多的時候,最好使用ReLu函數,ReLu函數比較簡單計算量少,而sigmoid和tanh函數計算量大很多。
在選擇激活函數的時候可以先選用ReLu函數如果效果不理想可以嘗試其他激活函數。
課后習題
- 知識點補充
(1). PyTorch 的 backward 為什么有一個 grad_variables 參數? - Towser的文章 - 知乎
https://zhuanlan.zhihu.com/p/29923090
假設 x 經過一番計算得到 y,那么 y.backward(w) 求的不是 y 對 x 的導數,而是 l = torch.sum(y*w) 對 x 的導數。w 可以視為 y 的各分量的權重,也可以視為遙遠的損失函數 l 對 y 的偏導數。也就是說,不一定需要從計算圖最后的節點 y 往前反向傳播,從中間某個節點 n 開始傳也可以,只要你能把損失函數 l 關於這個節點的導數 dl/dn 記錄下來,n.backward(dl/dn) 照樣能往前回傳,正確地計算出損失函數 l 對於節點 n 之前的節點的導數。特別地,若 y 為標量,w 取默認值 1.0,才是按照我們通常理解的那樣,求 y 對 x 的導數。
(2). 詳解Pytorch 自動微分里的(vector-Jacobian product) - mathmad的文章 - 知乎 【推薦看看】
https://zhuanlan.zhihu.com/p/65609544