Pytorch實戰-logistic 迴歸二元分類程式碼詳細註釋

湯姆魚發表於2019-12-27

                  Pytorch實戰-logistic 迴歸二元分類程式碼詳細註釋

SCDN部落格:https://blog.csdn.net/weixin_41923658 
知乎:https://www.zhihu.com/people/Mister-Yu2019/activities 
簡書:https://www.jianshu.com/u/d17d68ac2c8c 
微信公眾號:「湯姆魚」 

-------------------------------------手動分割線-------------------------------------------

1、logistic 迴歸介紹 

logistic 迴歸是一種廣義線性迴歸 (generalized linear model),與多重線性迴歸分析有很多相同之處。它們的模型形式基本上相同,都具有 wx+b,其中 w 和 b 是待求引數,其區別在於他們的因變數不同,多重線性迴歸直接將 wx+b 作為因變數,即 y=wx+b,而 logistic 迴歸則通過函式L 將 wx+b 對應一個隱狀態 p, p = L(wx+b), 然後根據 p 與 1-p 的大小決定變數的值。如果 L 是logistc 函式,就是 logistic 迴歸,如果 L是多項式函式就是多項式回說的更通俗一點,就是 logistc 迴歸會線上性迴歸後再加一層 logistic 函式的呼叫。 logistic 迴歸主要是進行二分類預測,我們在啟用函式時候講到過 Sigmod 函式, Sigmod 函式是最常見的 logistc 函式為 Sigmod 函式的輸出的是是對於 0-1 之間的概率值,當概率大於 0.5預測為 1,小於 0.5 預測為 0。 

2、資料集

德國信用資料集:UCI German Credit
archive.ics.uci.edu/ml/machine-…

3、程式碼實戰

# 匯入相關的包

import torch # torch 是一種科學計算框架
import torch.nn as nn # torch.nn 神經網路的介面
import numpy as np # numpy 科學計算的軟體包
torch.__version__ # 檢視 torch 的版本複製程式碼


# 使用 numpy 的 load 方法讀取資料

data = np.loadtxt("german.data-numeric")複製程式碼

注:
numpy 中的 loadtxt() 函式可以用來讀取檔案,主要是 txt 檔案;


# 對資料做一下歸一化處理

n, l = data.shape
for j in range(l-1):
meanVal = np.mean(data[:, j])
stdVal = np.std(data[:, j])
data[:, j] = (data[:, j]-meanVal) / stdVal複製程式碼

注:

  • n, l = data.shape --讀取 data 的大小;n 代表行數,l 代表列數

例項:

Pytorch實戰-logistic 迴歸二元分類程式碼詳細註釋

  • data[:, j] --讀取 data 所有行的 j 列的數

例項:

Pytorch實戰-logistic 迴歸二元分類程式碼詳細註釋

  • meanVal = np.mean(data[:, j]) # 求 data 所有行 j 列所有數的平均值 
  • stdVal = np.std(data[:, j]) # 求 data 所有行 j 列所有數的方差 
  • data[:, j] = (data[:, j]-meanVal)/stdVal # 歸一化 


# 打亂資料

np.random.shuffle(data)複製程式碼

注: 

shuffle() 方法將序列的所有元素隨機排序,但 shuffle() 是不能直接訪問的,需要匯入 random 模組,然後通過 random 靜態物件呼叫該方法。


 # 區分訓練集和測試集 

由於這裡沒有驗證集,所以我們直接使用測試集的準確度作為評判好壞的標準 

區分規則:900條用於訓練,100條作為測試訓練 

train_data = data[: 900, : l-1] # 訓練試集
train_lab = data[: 900, l-1] -1 # 訓練標籤
test_data = data[900: , : l-1] # 測試集
test_lab = data[900: , l-1] - 1 # 測試標籤複製程式碼

注意:
這裡為什麼需要在 label 中 -1 呢?
開啟原始資料看一下就明白了,主要原因是原始的資料標籤範圍是1和2,而在程式碼中使用的是sigmoid函式,其對應的範圍是 0-1,因此需要把原始的 label-1.

# 定義模型

class LR(nn.Module):
def __init__(self): # 建構函式
super(LR,self).__init__() # 繼承父類的構造方法,等價於 LR.__init__(self)
self.fc = nn.Linear(24, 2)
 
# 定義前向傳播函式
def forward(self,x):
out = self.fc(x)
out = torch.sigmoid(out)
return out複製程式碼

注: nn.Linear(24, 2) --- 對輸入的資料進行線性變換 y = x + b 

原型: torch.nn.Linear(in_features, out_features, bias=True) 

引數: in_features -- 輸入樣本資料的大小 

out_features -- 輸出樣本資料的大小; 

bias -- 如果設定為 False,則該圖層將不會學習加法偏差。預設值:True 

參考 :https://pytorch.org/docs/master/nn.html#torch.nn.Linear


 # 測試集上的準確率

def test(pred,lab):
t = pred.max(-1)[1] == lab
return torch.mean(t.float())複製程式碼

注:

  • pred.max(-1) --- 表示取 pred 每一行的最大值;
  • Pred.max(-1)[1] --- 表示取 pred 每一行最大值的索引;

Pytorch實戰-logistic 迴歸二元分類程式碼詳細註釋

例項:

Pytorch實戰-logistic 迴歸二元分類程式碼詳細註釋

參考:https://blog.csdn.net/jzwong/article/details/103267516 

  • t = pred.max(-1)[1] == lab --- 返回的是一個長度為樣本個數的 0,1 向量 torch.mean(t.float()) --- 準確率的定義,其實就是計算 1 佔整個樣本的比率 


 # 設定

net = LR() # 類的例項化,建立一個例項
criterion = nn.CrossEntropyLoss() # 使用 CrossEntropyLoss 損失
optm = torch.optim.Adam(net.parameters()) # Adam 優化
epochs = 1000 # 訓練 1000 次複製程式碼


# 開始訓練

for i in range(epochs):
# 指定模型為訓練模式,計算梯度
net.train()
# 輸入值都需要轉換成 torch 的Tensor
x = torch.from_numpy(train_data).float()
y = torch.from_numpy(train_lab).long()
y_hat = net(x)
loss = criterion(y_hat, y) # 計算損失
optm.zero_grad() # 前一步的損失清零
loss.backward() # 反向傳播
optm.step() # 優化
if (i + 1) % 100 == 0: # 這裡我們每 100 次輸出相關的資訊
# 指定模型為計算模式
net.eval()
test_in = torch.from_numpy(test_data).float()
test_l = torch.from_numpy(test_lab).float()
test_out = net(test_in)
# 使用我們的測試函式計算準確率
accu = test(test_out, test_l)
print("Epoch:{}, Loss:{:.4f}, Accurary:{:.2f}".format(i+1, loss.item(),accu))複製程式碼

準確率:

Pytorch實戰-logistic 迴歸二元分類程式碼詳細註釋


相關文章