邏輯回歸的原理與實踐

1.學習目標

  • 了解邏輯回歸的理論
  • 掌握邏輯回歸sklearn函數調用使用並將其運用到鳶尾花數據集預測

2.邏輯回歸的應用

邏輯回歸模型廣泛用於各個領域,包括機器學習,大多數醫學領域和社會科學。例如,最初由Boyd 等人開發的創傷和損傷嚴重度評分(TRISS)被廣泛用於預測受傷患者的死亡率,使用邏輯回歸 基於觀察到的患者特徵(年齡,性別,體重指數,各種血液檢查的結果等)分析預測發生特定疾病(例如糖尿病,冠心病)的風險。邏輯回歸模型也用於預測在給定的過程中,系統或產品的故障的可能性。還用於市場營銷應用程式,例如預測客戶購買產品或中止訂購的傾向等。在經濟學中它可以用來預測一個人選擇進入勞動力市場的可能性,而商業應用則可以用來預測房主拖欠抵押貸款的可能性。

邏輯回歸模型現在同樣是很多分類演算法的基礎組件,比如 分類任務中基於GBDT演算法+LR邏輯回歸實現的信用卡交易反欺詐,CTR(點擊通過率)預估等,其好處在於輸出值自然地落在0到1之間,並且有概率意義。模型清晰,有對應的概率學理論基礎。它擬合出來的參數就代表了每一個特徵(feature)對結果的影響。也是一個理解數據的好工具。但同時由於其本質上是一個線性的分類器,所以不能應對較為複雜的數據情況。很多時候我們也會拿邏輯回歸模型去做一些任務嘗試的基準線。

3.邏輯回歸原理簡介

邏輯回歸,該模型的輸出變數範圍始終在 0 和 1 之間。

邏輯回歸模型的假設是:
image.png
其中: X 代表特徵向量 g 代表邏輯函數(logistic function)是一個常用的邏輯函數為 S 形函數(Sigmoid function),公式為:
image.png
該函數的影像為:
image.png
image.png的作用是,對於給定的輸入變數,根據選擇的參數計算輸出變數=1 的可能性(estimated probablity)即
image.png
例如,如果對於給定的?,通過已經確定的參數計算得出image.png,則表示有 70%的幾率?為正向類,相應地?為負向類的幾率為 1-0.7=0.3。

image.png
在邏輯回歸中,我們預測:
image.png時,預測 y = 1。
image.png時,預測 y = 0 。
根據上面繪製出的 Sigmoid函數 影像,我們知道當
z = 0 時 g(z) = 0.5
z > 0 時 g(z) > 0.5
z < 0 時 g(z) < 0.5
image.png ,即:
image.png時,預測 y = 1
image.png時,預測 y = 0

因為各個觀測樣本之間相互獨立,那麼它們的聯合分布為各邊緣分布的乘積。得到似然函數為
image.png
接下來我們的目的就是求解似然函數的最大值,對上式兩邊取對數,得到
image.png
所以,我們就可以構造Loss Functionl如下式
image.png
加上-1/m,求解image.png的最小值,也就是求解似然函數的最大值,主要是為了方便後面的梯度下降法。所以使用梯度下降法求解,其更新函數為
image.png

image.png

4.Demo實踐

  • Step1:庫函數導入
##  基礎函數庫
import numpy as np 

## 導入畫圖庫
import matplotlib.pyplot as plt
import seaborn as sns

## 導入邏輯回歸模型函數
from sklearn.linear_model import LogisticRegression
  • Step2:訓練模型
##Demo演示LogisticRegression分類

## 構造數據集
x_fearures = np.array([[-1, -2], [-2, -1], [-3, -2], [1, 3], [2, 1], [3, 2]])
y_label = np.array([0, 0, 0, 1, 1, 1])

## 調用邏輯回歸模型
lr_clf = LogisticRegression()

## 用邏輯回歸模型擬合構造的數據集
lr_clf = lr_clf.fit(x_fearures, y_label) #其擬合方程為 y=w0+w1*x1+w2*x2
  • Step3:模型參數查看
##查看其對應模型的w
print('the weight of Logistic Regression:', lr_clf.coef_)
##查看其對應模型的w0
print('the intercept(w0) of Logistic Regression:', lr_clf.intercept_)
##the weight of Logistic Regression:[[0.73462087 0.6947908]]
##the intercept(w0) of Logistic Regression:[-0.03643213]
  • Step4:數據和模型可視化
## 可視化構造的數據樣本點
plt.figure()
plt.scatter(x_fearures[:, 0], x_fearures[:, 1], c=y_label, s=50, cmap='viridis')
plt.title('Dataset')
plt.show()

image.png

# 可視化決策邊界
plt.figure()
plt.scatter(x_fearures[:, 0], x_fearures[:, 1], c=y_label, s=50, cmap='viridis')
plt.title('Dataset')

nx, ny = 200, 100
x_min, x_max = plt.xlim()
y_min, y_max = plt.ylim()
x_grid, y_grid = np.meshgrid(np.linspace(x_min, x_max, nx), np.linspace(y_min, y_max, ny))

z_proba = lr_clf.predict_proba(np.c_[x_grid.ravel(), y_grid.ravel()])
z_proba = z_proba[:, 1].reshape(x_grid.shape)
plt.contour(x_grid, y_grid, z_proba, [0.5], linewidths=2., colors='blue')

plt.show()

image.png

### 可視化預測新樣本

plt.figure()
## new point 1
x_fearures_new1 = np.array([[0, -1]])
plt.scatter(x_fearures_new1[:, 0], x_fearures_new1[:, 1], s=50, cmap='viridis')
plt.annotate(s='New point 1', xy=(0, -1), xytext=(-2, 0), color='blue', arrowprops=dict(arrowstyle='-|>', connectionstyle='arc3', color='red'))

## new point 2
x_fearures_new2 = np.array([[1, 2]])
plt.scatter(x_fearures_new2[:, 0], x_fearures_new2[:, 1], s=50, cmap='viridis')
plt.annotate(s='New point 2', xy=(1,2), xytext=(-1.5, 2.5), color='red', arrowprops=dict(arrowstyle='-|>', connectionstyle='arc3', color='red'))

## 訓練樣本
plt.scatter(x_fearures[:, 0], x_fearures[:, 1], c=y_label, s=50, cmap='viridis')
plt.title('Dataset')

# 可視化決策邊界
plt.contour(x_grid, y_grid, z_proba, [0.5], linewidths=2., colors='blue')

plt.show()

image.png

  • Step5:模型預測
##在訓練集和測試集上分布利用訓練好的模型進行預測
y_label_new1_predict = lr_clf.predict(x_fearures_new1)
y_label_new2_predict = lr_clf.predict(x_fearures_new2)
print('The New point 1 predict class:\n', y_label_new1_predict)
print('The New point 2 predict class:\n', y_label_new2_predict)
##由於邏輯回歸模型是概率預測模型(前文介紹的p = p(y=1|x,\theta)),所有我們可以利用predict_proba函數預測其概率
y_label_new1_predict_proba = lr_clf.predict_proba(x_fearures_new1)
y_label_new2_predict_proba = lr_clf.predict_proba(x_fearures_new2)
print('The New point 1 predict Probability of each class:\n', y_label_new1_predict_proba)
print('The New point 2 predict Probability of each class:\n', y_label_new2_predict_proba)
##TheNewpoint1predictclass:
##[0]
##TheNewpoint2predictclass:
##[1]
##TheNewpoint1predictProbabilityofeachclass:
##[[0.695677240.30432276]]
##TheNewpoint2predictProbabilityofeachclass:
##[[0.119839360.88016064]]

可以發現訓練好的回歸模型將X_new1預測為了類別0(判別面左下側),X_new2預測為了類別1(判別面右上側)。其訓練得到的邏輯回歸模型的概率為0.5的判別面為上圖中藍色的線。

5.基於鳶尾花(iris)數據集的邏輯回歸分類實踐

在實踐的最開始,我們首先需要導入一些基礎的函數庫包括:numpy (Python進行科學計算的基礎軟體包),pandas(pandas是一種快速,強大,靈活且易於使用的開源數據分析和處理工具),matplotlib和seaborn繪圖。

  • Step1:函數庫導入
##  基礎函數庫
import numpy as np 
import pandas as pd

## 繪圖函數庫
import matplotlib.pyplot as plt
import seaborn as sns

本次我們選擇鳶花數據(iris)進行方法的嘗試訓練,該數據集一共包含5個變數,其中4個特徵變數,1個目標分類變數。共有150個樣本,目標變數為花的類別其都屬於鳶尾屬下的三個亞屬,分別是山鳶尾 (Iris-setosa),變色鳶尾(Iris-versicolor)和維吉尼亞鳶尾(Iris-virginica)。包含的三種鳶尾花的四個特徵,分別是花萼長度(cm)、花萼寬度(cm)、花瓣長度(cm)、花瓣寬度(cm),這些形態特徵在過去被用來識別物種。

變數 描述
sepal length 花萼長度(cm)
sepal width 花萼寬度(cm)
petal length 花瓣長度(cm)
petal width 花瓣寬度(cm)
target 鳶尾的三個亞屬類別,’setosa'(0), ‘versicolor'(1), ‘virginica'(2)
  • Step2:數據讀取/載入
##我們利用sklearn中自帶的iris數據作為數據載入,並利用Pandas轉化為DataFrame格式
from sklearn.datasets import load_iris
data = load_iris() #得到數據特徵
iris_target = data.target #得到數據對應的標籤
iris_features = pd.DataFrame(data=data.data, columns=data.feature_names) #利用Pandas轉化為DataFrame格式
  • Step3:數據資訊簡單查看
##利用.info()查看數據的整體資訊
iris_features.info()

##<class'pandas.core.frame.DataFrame'>
##RangeIndex:150entries,0to149
##Datacolumns(total4columns):
###ColumnNon-NullCountDtype
##----------------------------
##0sepallength(cm)150non-nullfloat64
##1sepalwidth(cm)150non-nullfloat64
##2petallength(cm)150non-nullfloat64
##3petalwidth(cm)150non-nullfloat64
##dtypes:float64(4)
##memoryusage:4.8KB
##進行簡單的數據查看,我們可以利用.head()頭部.tail()尾部
iris_features.head()
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
0 5.1 3.5 1.4
1 4.9 3.0 1.4
2 4.7 3.2 1.3
3 4.6 3.1 1.5
4 5.0 3.6 1.4
iris_features.tail()
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
145 6.7 3.0 5.2
146 6.3 2.5 5.0
147 6.5 3.0 5.2
148 6.2 3.4 5.4
149 5.9 3.0 5.1
##其對應的類別標籤為,其中0,1,2分別代表'setosa','versicolor','virginica'三種不同花的類別

iris_target


##array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,


##0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,


##0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,


##1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,


##1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,


##2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,


##2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2])
##利用value_counts函數查看每個類別數量

pd.Series(iris_target).value_counts()

##2    50

##1    50

##0    50

##dtype:int64
##對於特徵進行一些統計描述

iris_features.describe()
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
count 150.000000 150.000000 150.000000
mean 5.843333 3.057333 3.758000
std 0.828066 0.435866 1.765298
min 4.300000 2.000000 1.000000
25% 5.100000 2.800000 1.600000
50% 5.800000 3.000000 4.350000
75% 6.400000 3.300000 5.100000
max 7.900000 4.400000 6.900000

從統計描述中我們可以看到不同數值特徵的變化範圍。

  • **Step4:**可視化描述
## 合併標籤和特徵資訊
iris_all = iris_features.copy() ##進行淺拷貝,防止對於原始數據的修改
iris_all['target'] = iris_target
## 特徵與標籤組合的散點可視化
sns.pairplot(data=iris_all, diag_kind='hist', hue= 'target')
plt.show()

image.png
從上圖可以發現,在2D情況下不同的特徵組合對於不同類別的花的散點分布,以及大概的區分能力。

for col in iris_features.columns:
    sns.boxplot(x='target', y=col, saturation=0.5, palette='pastel', data=iris_all)
    plt.title(col)
    plt.show()

image.png
image.png
image.png
image.png
利用箱型圖我們也可以得到不同類別在不同特徵上的分布差異情況。

# 選取其前三個特徵繪製三維散點圖
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')

iris_all_class0 = iris_all[iris_all['target'] == 0].values
iris_all_class1 = iris_all[iris_all['target'] == 1].values
iris_all_class2 = iris_all[iris_all['target'] == 2].values
# 'setosa'(0), 'versicolor'(1), 'virginica'(2)
ax.scatter(iris_all_class0[:, 0], iris_all_class0[:, 1], iris_all_class0[:, 2], label='setosa')
ax.scatter(iris_all_class1[:, 0], iris_all_class1[:, 1], iris_all_class1[:, 2], label='versicolor')
ax.scatter(iris_all_class2[:, 0], iris_all_class2[:, 1], iris_all_class2[:, 2], label='virginica')
plt.legend()

plt.show()

image.png

  • Step5:利用邏輯回歸模型在二分類上進行訓練和預測
##為了正確評估模型性能,將數據劃分為訓練集和測試集,並在訓練集上訓練模型,在測試集上驗證模型性能。
from sklearn.model_selection import train_test_split
##選擇其類別為0和1的樣本(不包括類別為2的樣本)
iris_features_part = iris_features.iloc[:100]
iris_target_part = iris_target[:100]
##測試集大小為20%,80%/20%分
x_train, x_test, y_train, y_test = train_test_split(iris_features_part, iris_target_part, test_size=0.2, random_state=2020)
##從sklearn中導入邏輯回歸模型
from sklearn.linear_model import LogisticRegression
##定義邏輯回歸模型
clf = LogisticRegression(random_state=0, solver='lbfgs')
##在訓練集上訓練邏輯回歸模型
clf.fit(x_train, y_train)
##查看其對應的w
print('the weight of Logistic Regression:', clf.coef_)

##查看其對應的w0
print('the intercept(w0) of Logistic Regression:', clf.intercept_)
##在訓練集和測試集上分別利用訓練好的模型進行預測
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)
from sklearn import metrics
##利用accuracy(準確度)【預測正確的樣本數目佔總預測樣本數目的比例】評估模型效果
print('The accuracy of the Logistic Regression is:', metrics.accuracy_score(y_train, train_predict))
print('The accuracy of the Logistic Regression is:', metrics.accuracy_score(y_test, test_predict))

##查看混淆矩陣(預測值和真實值的各類情況統計矩陣)
confusion_matrix_result = metrics.confusion_matrix(test_predict, y_test)
print('The confusion matrix result:\n', confusion_matrix_result)

##利用熱力圖對於結果進行可視化
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
plt.xlabel('Predictedlabels')
plt.ylabel('Truelabels')
plt.show()

##The accuracy of the Logistic Regressionis:1.0
##The accuracy of the Logistic Regressionis:1.0
##The confusion matrix result:
##[[9  0]
##[0  11]]

image.png
我們可以發現其準確度為1,代表所有的樣本都預測正確了。

  • Step6:利用邏輯回歸模型在三分類(多分類)上進行訓練和預測
##測試集大小為20%,80%/20%分
x_train, x_test, y_train, y_test = train_test_split(iris_features, iris_target, test_size=0.2, random_state=2020)
##定義邏輯回歸模型
clf = LogisticRegression(random_state=0, solver='lbfgs')
##在訓練集上訓練邏輯回歸模型
clf.fit(x_train, y_train)
##查看其對應的w
print('the weight of Logistic Regression:\n', clf.coef_)
##查看其對應的w0
print('the intercept(w0) of Logistic Regression:\n', clf.intercept_)
##由於這個是3分類,所有我們這裡得到了三個邏輯回歸模型的參數,其三個邏輯回歸組合起來即可實現三分類
##在訓練集和測試集上分布利用訓練好的模型進行預測
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)
##由於邏輯回歸模型是概率預測模型(前文介紹的p=p(y=1|x,\theta)),所有我們可以利用predict_proba函數預測其概率

train_predict_proba = clf.predict_proba(x_train)
test_predict_proba = clf.predict_proba(x_test)

print('The test predict Probability of each class:\n', test_predict_proba)
##其中第一列代表預測為0類的概率,第二列代表預測為1類的概率,第三列代表預測為2類的概率。

##利用accuracy(準確度)【預測正確的樣本數目佔總預測樣本數目的比例】評估模型效果
print('The accuracy of the Logistic Regression is:', metrics.accuracy_score(y_train, train_predict))
print('The accuracy of the Logistic Regression is:', metrics.accuracy_score(y_test, test_predict))
##查看混淆矩陣
confusion_matrix_result = metrics.confusion_matrix(test_predict, y_test)
print('The confusion matrix result:\n', confusion_matrix_result)

##利用熱力圖對於結果進行可視化
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()

##The confusion matrix result:
##[[10  0   0]
##[0   8   2] 
##[0   2   8]]

image.png