參考資料
<PYTHON_MACHINE_LEARNING> chapter3
A Tour of Machine Learning
Classifers Using Scikit-learn
引言
在我們進行分類的時,所取樣本中的特征值一般都分布在實數域,但是我們想得到的往往是一個在 [0,1] 中的類似概率的值。 或者這么說,為了讓特征值之間不會因為相差過大而造成干擾,比如,只有一個特征取值特別大,但是其他取值很小的時候, 我們需要對數據進行歸一化。 即我們需要用一個從R 到 [0,1] 的單射來先處理特征值矩陣,然后再進行機器學習。當所用的映射是 sigmoid函數的時候,我們管這樣的機器學習算法叫做邏輯回歸。
PS:邏輯回歸是用來分類的!!!不是用來做線性回歸的! sigmoid 函數的反函數叫做 logit 函數, 這就是邏輯回歸 logistic regression 的來歷,跟邏輯沒啥關系......
sigmoid 函數
這個函數的特點就是一條S型的定義域在 R 中, 值域在 [0,1] 中的函數
同時它也代表 y=1的概率, y=0 的概率為 1-phi(z)
畫一下圖來說明一下
#! /usr/bin/python <br> # -*-coding: utf8 -*-
import matplotlib.pyplot as plt
import numpy as np
def sigmoid(z):
return 1.0/(1.0+np.exp(-z))
z = np.arange(-10,10,0.1)
p = sigmoid(z)
plt.plot(z,p)
#畫一條豎直線,如果不設定x的值,則默認是0
plt.axvline(x=0, color='k')
plt.axhspan(0.0, 1.0,facecolor='0.7',alpha=0.4)
# 畫一條水平線,如果不設定y的值,則默認是0
plt.axhline(y=1, ls='dotted', color='0.4')
plt.axhline(y=0, ls='dotted', color='0.4')
plt.axhline(y=0.5, ls='dotted', color='k')
plt.ylim(-0.1,1.1)
#確定y軸的坐標
plt.yticks([0.0, 0.5, 1.0])
plt.ylabel('$\phi (z)$')
plt.xlabel('z')
ax = plt.gca()
ax.grid(True)
plt.show()
邏輯回歸算法 logistic regression
- 基本原理
邏輯回歸算法跟Adaline 線性自適應算法很類似,區別只不過是把激活函數從**恒同映射 y = z ** 換成了 y = sigmoid(z)
- 邏輯回歸中的損失函數
回憶一下在梯度下降模型 Adaline 中應用到的損失函數 cost function 平方差函數
這是線性回歸的一種損失函數
但是對于S型的sigmoid函數,這樣的定義在 y 趨近-1,1 的時候會特別接近零
對于邏輯回歸 logistic regression 損失函數是這樣定義的
對數似然損失函數(交叉熵)
Ps: 一下所有的 log 其實都是 ln
這個損失函數是怎么來的呢? 極大似然法
先定義似然函數(每個樣本都認為是獨立的):
似然函數可以看成條件概率
關于似然函數的概念可以參考kevinGao的博客
http://www.cnblogs.com/kevinGaoblog/archive/2012/03/29/2424346.html
根據似然函數的概念,令似然函數最大的那個概率就是最合理的。我們想最大化似然函數,但是這個形式還是不夠好看,畢竟是連乘的形式,所以,我們取一下對數
現在好了,我們知道:當 權向量 w 使 l最大的時候, w 最合理
那么我們就定義 J 函數 : J = -l
為了更好的理解,我們看一下單個樣本的損失函數:
以y=1為例,當預測值接近正確值的時候,J 會收斂到 0
- 權值更新
跟梯度下降法一樣,按照公式
經過計算
我們就有了權值更新的公式
居然跟Adaline一模一樣哎
意不意外?驚不驚喜?
這意味著,我們在單獨編寫 LogisticRegression 類的時候,只需要在Adaline類中重新定義一下激勵函數 phi 就可以了
實踐
我們再上一章 sklearn 實現 Perceptron 感知機的基礎上用 Iris 的數據集來實踐一下
__author__ = 'Administrator'
#! /usr/bin/python <br> # -*- coding: utf8 -*-
from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.cross_validation import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
from PDC import plot_decision_regions
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import numpy as np
iris = datasets.load_iris()
x = iris.data[:,[2,3]]
y = iris.target
X_train,X_test,y_train,y_test = train_test_split(
x , y, test_size=0.3, random_state = 0
)
sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)
Ir = LogisticRegression(C=1000.0,random_state=0)
Ir.fit(X_train_std,y_train)
X_combined_std = np.vstack((X_train_std,X_test_std))
y_combined = np.hstack((y_train,y_test))
plot_decision_regions(X=X_combined_std,y=y_combined,
classifier=Ir,
test_idx=range(105,150))
plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.legend(loc='upper left')
plt.savefig('Iris.png')
plt.show()
print(X_test_std[0,:])
a = Ir.predict_proba(X_test_std[0,:])
print(a)
過擬合,欠擬合與正則化
過擬合與欠擬合是機器學習常見的兩個問題
- 過擬合
俗稱想太多。為了很好的擬合訓練集,模型使用了太多的參數,變得特別復雜,甚至噪音與誤差都被分成了一類,這樣的模型雖然對訓練集模擬的很好,但是對用來預測的數據集卻特別不可靠,我們說 :這樣的模型 has a high variance (高方差)
-欠擬合
對應的,頭腦太簡單。模型太過簡單以至于對預測用數據集來說也不可靠
我們這這樣的模型 has a high bias (高偏差)
- 正則化 Ruglarization
為了防止過擬合,正則化是一種常用的方法。正則化,簡單地說,就是引入額外的偏差去降低一些極端權值的影響。
最常見的正則化,是 L2正則化,他在損失函數的末尾加上這樣一項
Lambda 被稱為正則化參數
這樣損失函數形式變為:
Ir = LogisticRegression(C=1000.0,random_state=0)
在類 LogisticRegression 中的參數C 來源于支持向量機(SVM)的相關概念, 這里先不作展開
損失函數的最終形式:
- C值對模擬的影響
設置從 -5 到 4 10不同的冪作為C值,我們看一下 權值的影響
weights, params = [], []
for c in list(range(-5,5)):
lr = LogisticRegression(C=10**int(c), random_state=0)
lr.fit(X_train_std, y_train)
weights.append(lr.coef_[1])
params.append(10**c)
weights = np.array(weights)
plt.plot(params, weights[:, 0],label='petal length')
plt.plot(params,weights[:,1],linestyle='--',label='petal width')
plt.ylabel('weight coefficient')
plt.xlabel('C')
plt.legend(loc='upper left')
plt.xscale('log')
plt.show()