機器學習邏輯迴歸模型總結——從原理到sklearn實踐
阿新 • • 發佈:2019-02-17
0x00 基本原理
邏輯迴歸演算法,從名字上看似乎是個迴歸問題,但實際上邏輯迴歸是個典型的分類演算法。
對於分類問題,一般都是一些離散變數,且y的取值如下:
以二元分類問題開始討論,y的取值為“類別1,類別2”,為了表示清楚,這裡使用0和1來表示二元分類中的兩個類別,即y的取值為:
和線性迴歸問題一樣,我們規定假設函式為:
在邏輯迴歸中,實際上對於假設函式,使用了一種邏輯函式的概念,函式如下:
稱為S型函式,或者邏輯函式。取值範圍為(0,1),符合我們上面對假設函式的要求。通常,設定閾值為0.5,如果訓練樣本輸入到假設函式中,得到的值大於0.5,則認為分類為1,否則分類為0:
相應的,我們的損失函式(Cost Function)為:
如果這裡計算折損的形式還是和線性迴歸一樣平方損失函式:
所以在計算折損值的時候,邏輯迴歸中使用了對數損失函式來獲得一個凸函式的J,整理得到的最終損失函式形式如下,其中省略了若干數學推導:
我們再次使用梯度下降演算法來求出最優的引數向量,梯度下降在邏輯迴歸中表現如下:
可能有人發現,這不和線性擬合問題中的梯度下降公式一樣嗎?實際上,由於邏輯迴歸模型中採用了邏輯函式來表示假設函式,所以這兩種模型中的梯度下降表達式是完全不同的兩回事兒。
有了梯度下降演算法,我們就可以使用訓練集來求出最優的引數向量。邏輯迴歸中,為了消除過度擬合問題,有正則化方法,這裡就不再贅述。
0x01 演算法實現
根據Andrew Ng所提供的資料,我們依舊選擇Octave來實現邏輯迴歸演算法。
首先是sigmoid函式(邏輯函式)的表達:
function g = sigmoid(z)
g = zeros (size(z));
g = 1 ./ (1+exp(-z));
end
Cost Function的實現:
function [J, grad] = costFunction(theta, X, y)
% 初始化
m = length(y);
J = 0;
grad = zeros(size(theta));
% 損失函式的計算
temp = sigmoid(X*theta);
temp = temp(:,size(temp, 2));
J = (1/m) * sum((-y.*log(temp))-((1-y).*log(1-temp))) ;
% 損失函式的導數計算
for i=1:size(theta,1),
grad(i) = (1/m) * sum((temp - y).*X(:,i));
end;
end
由於資料中所給的不是直接使用梯度下降演算法,而是使用了Octave中的優化方法來求最優引數向量,所以只需要返回損失函式J和各個損失函式的導數grad
。實際上,如果改成直接使用梯度下降的話,只需要在求grad的過程中,同步更新我們各個引數即可。
預測函式如下,這裡一般選擇閾值為0.5,所以大於0.5的假設函式返回值,我們就判斷類別為1。
function p = predict(theta, X)
m = size(X, 1);
p = zeros(m, 1);
% 計算類別,使用p向量返回
for i=1:m,
prop = sigmoid(X(i,:)*theta) ;
if prop >= 0.5,
p(i) = 1;
end;
end;
end;
0x02 演算法執行
執行演算法,可以看到視覺化的決策邊界:
0x03 sklearn庫實踐
清楚了邏輯迴歸模型的原理,我們使用python進行機器學習演練,使用sklearn機器學習庫,可以很方便地進行實踐。
資料集為學生的兩次考試成績以及是否通過大學申請,我們用邏輯迴歸進行分類,以後給出一個樣本,輸出成功通過大學申請的概率。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.cross_validation import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
from sklearn.metrics import precision_recall_curve, roc_curve, auc
data = pd.read_csv('ex2data1.txt', sep=',', \
skiprows=[2], names=['score1','score2','result'])
score_data = data.loc[:,['score1','score2']]
result_data = data.result
p = 0
for i in xrange(10):
x_train, x_test, y_train, y_test = \
train_test_split(score_data, result_data, test_size = 0.2)
model = LogisticRegression(C=1e9)
model.fit(x_train, y_train)
predict_y = model.predict(x_test)
p += np.mean(predict_y == y_test)
# 繪製圖像
pos_data = data[data.result == 1].loc[:,['score1','score2']]
neg_data = data[data.result == 0].loc[:,['score1','score2']]
h = 0.02
x_min, x_max = score_data.loc[:, ['score1']].min() - .5, score_data.loc[:, ['score1']].max() + .5
y_min, y_max = score_data.loc[:, ['score2']].min() - .5, score_data.loc[:, ['score2']].max() + .5
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
# 繪製邊界和散點
Z = Z.reshape(xx.shape)
plt.pcolormesh(xx, yy, Z, cmap=plt.cm.Paired)
plt.scatter(x=pos_data.score1, y=pos_data.score2, color='black', marker='o')
plt.scatter(x=neg_data.score1, y=neg_data.score2, color='red', marker='*')
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.show()
# 模型表現
answer = model.predict_proba(x_test)[:,1]
precision, recall, thresholds = precision_recall_curve(y_test, answer)
report = answer > 0.5
print(classification_report(y_test, report, target_names = ['neg', 'pos']))
print("average precision:", p/100)
執行結果如下:
畫出了決策邊界之後,就可以看到我們最後的分類結果。
當然也可以使用precision_call_curve
方法自動計算召回率精度等資料:
precision recall f1-score support
neg 0.88 0.88 0.88 8
pos 0.92 0.92 0.92 12
avg / total 0.90 0.90 0.90 20
('average precision:', 0.089999999999999997)
精度達到了90%,模型效果還不錯。
0x04 總結
邏輯迴歸模型實際上是一個典型的監督學習分類演算法,配合sklearn庫可以很方便的進行邏輯迴歸處理。前提是要真正理解邏輯迴歸模型的原理和推導過程。
實戰中,機器學習和資訊保安結合越來越緊密了,所以這也是我為啥開始學習機器學習的原因,就邏輯迴歸而言,完全可以用在防爬檢測,掃描器檢測,惡意URL提取的應用上,實戰的前提是瞭解原理:)