零基礎一步一步pytorch實現Logistic regression邏輯回歸編程教程


為什么我們需要了解Logistic regression邏輯回歸?

因為神經網絡的一個神經元就是Logistic regression邏輯回歸。

Logistic regression(LR)邏輯回歸是什么?

它就是套一個概率分布模型上去。什么是模型?模型就是一個函數比如:f(x)=ax+b。至於邏輯回歸套的那個概率分布模型是什么稍后再說,先說套概率分布模型上去有什么用?假如需要判斷樣本x是屬於A類還是屬於B類。在前面提到了模型就是一個函數,概率分布模型就是輸入一個樣本數據x,函數輸出它屬於A類的概率。邏輯回歸只能分出兩種類。x屬於A類的概率大於0.5那就我們可以認為當前樣本屬於A類,如果概率小於0.5那就認為它屬於B類。

那么邏輯回歸套的是什么函數呢?答: f ( x ) = 1 1 + e w T x f(x) = \frac{1}{1+e^{-w^Tx}} 。其中 w w 是待求解的參數,不同的數據是不一樣的。那我們怎么根據當前已有的數據調整得到最優的參數 w w ?答:用梯度下降。
如果你對梯度下降不理解可以參考這兩篇文章:
易懂的神經網絡理論到實踐(1):單個神經元+隨機梯度下降學習邏輯與規則
{高中生能看懂的}梯度下降是個啥?

pytorch編程實踐

本文的實踐會先介紹使用的數據是什么。然后介紹如何檢驗自己程序是否正確。然后介紹如何用pytorch的反向傳播求導(求導結果是否正確可以我們自己手動計算下來檢驗),並用這個導數實現梯度下降。然后介紹如何我們自己求導實現梯度下降(我們自己寫的導數是否計算正確檢驗方法1是可以用前面反向傳播求導結果檢驗2是我們自己手動計算看程序運行結果是否正確)。

使用pytorch自帶的自動求導工具求導,然后實現梯度下降

大家一定要注意機器學習必備下面那幾個步驟。寫程序一定要對這些步驟爛熟於心。

  1. 加載數據
  2. 輸入樣本計算模型的輸出
  3. 計算損失函數對參數w的導數(梯度)
  4. 梯度下降調節參數w
  5. 重復2-4

1.加載數據

首先我們需要加載數據,這次我們想實現的是讓邏輯回歸識別邏輯異或(兩個數字相同那就是0,兩個數字不同那就是1)。
所以數據(前面兩個數字)與標簽(最后那個數字)是:

1 1 0
1 0 1
0 1 0
0 0 1

現在我們用代碼實現加載數據

# -*- coding:utf-8 -*-
import torch
import numpy as np
''' 用邏輯回歸實現異或功能 '''
# 加載數據
data = torch.tensor([[1,1],[1,0],[0,1],[0,0]],dtype=torch.float)
label = torch.tensor([[0,1,1,0]],dtype=torch.float).t()

計算模型的輸出

前面提到了邏輯回歸的模型是 f ( x ) = 1 1 + e w T x f(x) = \frac{1}{1+e^{-w^Tx}} 。我們首先需要先初始化參數w。然后輸入一個樣本x,然后根據公式 f ( x ) = 1 1 + e w T x f(x) = \frac{1}{1+e^{-w^Tx}} 計算模型輸出。接下來我們用代碼實現它。很多同學不知道自己代碼寫的對不對,大家只需要自己算一下結果,然后看看程序輸出是否符合自己計算結果

# -*- coding:utf-8 -*-
import torch
import numpy as np
''' 用邏輯回歸實現異或功能 '''
# 加載數據
data = torch.tensor([[1,1],[1,0],[0,1],[0,0]],dtype=torch.float)
label = torch.tensor([[0,1,1,0]],dtype=torch.float).t()
w = torch.tensor([1,1],dtype=torch.float, requires_grad=True)

# 加載一個數據,代入到公式中
i = 0
x = data[i]
#f = 1/[1+e^(-wx)]
f = 1/(1+torch.pow(np.e,-x.dot(w)))
print(f) # 輸出tensor(0.8808)

利用pytorch反向傳播自動求導工具計算損失函數對參數w的導數

我們需要告訴pytorch損失函數,然后讓它根據損失函數對參數w求導。接下來我們用代碼實現。()

# -*- coding:utf-8 -*-
import torch
import numpy as np
''' 用邏輯回歸實現異或功能 '''
# 加載數據
data = torch.tensor([[1,1],[1,0],[0,1],[0,0]],dtype=torch.float)
label = torch.tensor([[0,1,1,0]],dtype=torch.float).t()
w = torch.tensor([1,1],dtype=torch.float,requires_grad=True)


# 加載一個數據,代入到公式中
i = 0
x = data[i]
#f = 1/[1+e^(-wx)]
f = 1/(1+torch.pow(np.e,-x.dot(w)))
print(f) # 輸出tensor(0.8808)

loss = (f-label[i])**2 
print(loss)# 輸出:tensor([0.7758])
loss.backward() # 使用反向傳播求損失函數對參數w的導數值
print(w.grad) # 損失函數對w的導數值tensor([0.1850, 0.1850])

利用反向傳播的導數實現梯度下降

# -*- coding:utf-8 -*-
import torch
import numpy as np
''' 用邏輯回歸實現異或功能 '''
# 加載數據
data = torch.tensor([[1,1],[1,0],[0,1],[0,0]],dtype=torch.float)
label = torch.tensor([[0,1,1,0]],dtype=torch.float).t()
w = torch.tensor([1,1],dtype=torch.float,requires_grad=True)


# 加載一個數據,代入到公式中
i = 0
x = data[i]
#f = 1/[1+e^(-wx)]
f = 1/(1+torch.pow(np.e,-x.dot(w)))
print(f) # 輸出tensor(0.8808)

loss = (f-label[i])**2 
print(loss)# 輸出:tensor([0.7758])
loss.backward() # 使用反向傳播求損失函數對參數w的導數值
print(w.grad) # 損失函數對w的導數值tensor([0.1850, 0.1850])

learning_rate = 1e-2
w = w - learning_rate*w.grad
print('更新后的參數w',w)#更新后的參數w tensor([0.9982, 0.9982])

我們自己手動計算導數,並實現梯度下降

# -*- coding:utf-8 -*-
import torch
import numpy as np
''' 用邏輯回歸實現異或功能 '''
# 加載數據
data = torch.tensor([[1,1],[1,0],[0,1],[0,0]],dtype=torch.float)
label = torch.tensor([[0,1,1,0]],dtype=torch.float).t()
w = torch.tensor([1,1],dtype=torch.float,requires_grad=True)


# 加載一個數據,代入到公式中
i = 0
x = data[i]
#f = 1/[1+e^(-wx)]
f = 1/(1+torch.pow(np.e,-x.dot(w)))
print(f) # 輸出tensor(0.8808)

#loss = (f-label[i])**2 
# 計算損失函數loss對w的導數
# 我們把e^(-wx)這部分先存到一個變量里面
e_wx = torch.pow(np.e,-x.dot(w))
dloss_dw = 2*(f-label[i])*x*e_wx/(1+e_wx)**2
print(dloss_dw)
learning_rate = 1e-2
w = w - learning_rate*dloss_dw
print('更新后的參數w',w)#更新后的參數w tensor([0.9982, 0.9982])


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM