1、演算法簡介

本文的重點放在演算法的工程實現上,關於演算法的原理不具體展開,logistic迴歸演算法很簡單,可以看看Andrew Ng的視訊:https://class.coursera.org/ml-007,也可以看看一些寫得比較好的博文:洞庭之子的博文。下面我只列出一些個人認為重要的點。.

迴歸的概念:假設有一些資料點,我們用一條直線對這些點進行擬合,這個擬合過程就稱作迴歸。

logistic迴歸演算法之所以稱作“logistic”,是因為它運用了logistic函式,即sigmoid函式

logistic迴歸演算法一般用於二分類問題(當然也可以多類別,後面會講)。

logistic迴歸的演算法思想:


用上面的圖來分析,每個O或X代表一個特徵向量,這裡是二維的,可以寫成x=(x1,x2)。

用logistic迴歸進行分類的主要思想就是根據現有資料集,對分類邊界建立迴歸公式,拿上面這個圖來說,就是根據這些OOXX,找出那條直線的公式:Θ0*x0+Θ1*x1+Θ2*x2=Θ0+Θ1*x1+Θ2*x2=0  (x0=1)。

因為上圖是二維的,所以引數Θ=(Θ0,Θ1, Θ2),分類邊界就由這個(Θ0,Θ1, Θ2)確定,對於更高維的情況也是一樣的,所以無論二維三維更高維,分類邊界可以統一表示成f(x)=ΘT*x  (ΘT表示Θ的轉置)。

對於分類邊界上的點,代入分類邊界函式就得到f(x)=0,同樣地,對於分類邊界之上的點,代入得到f(x)>0,對於分類邊界之下的點,代入得到f(x)f(x)大於0或者小於0來分類了。

logistic迴歸的最後一步就是將f(x)作為輸入,代入Sigmoid函式,當f(x)>0時,sigmoid函式的輸出就大0.5,且隨著f(x)趨於正無窮,sigmoid函式的輸出趨於1。當f(x)0時,sigmoid函式的輸出就小於0.5,且隨著f(x)趨於負無窮,sigmoid函式的輸出趨於0。

所以我們要尋找出最佳引數Θ,使得對於1類別的點x,f(x)趨於正無窮,對於0類別的點x,f(x)趨於負無窮(實際程式設計中不可能正/負無窮,只要足夠大/小即可)。

總結一下思緒,logistic迴歸的任務就是要找到最佳的擬合引數。下圖的g(z)即sigmoid函式,跟我上面講的一樣,將f(x)=ΘT*x作為g(z)的輸入。

以上就是logistic迴歸的思想,重點在於怎麼根據訓練資料求得最佳擬合引數Θ?這可以用最優化演算法來求解,比如常用的梯度上升演算法,關於梯度上升演算法這裡也不展開,同樣可以參考上面推薦的博文。

所謂的梯度,就是函式變化最快的方向,我們一開始先將引數Θ設為全1,然後在演算法迭代的每一步裡計算梯度,沿著梯度的方向移動,以此來改變引數Θ,直到Θ的擬合效果達到要求值或者迭代步數達到設定值。Θ的更新公式:

alpha是步長,一系列推導後:

這個公式也是下面寫程式碼所用到的。

後話:理解logistic迴歸之後可以發現,其實它的本質是線性迴歸,得到ΘT*x的過程跟線性迴歸是一樣的,只不過後面又將ΘT*x作為logistic函式的輸入,然後再判斷類別。

2、工程例項

 logistic迴歸一般用於二分類問題,比如判斷一封郵件是否為垃圾郵件,判斷照片中的人是男是女,預測一場比賽輸還是贏……當然也可以用於多分類問題,比如k類別,就進行k次logistic迴歸。

我的前一篇文章:kNN演算法__手寫識別 講到用kNN演算法識別數字0~9,這是個十類別問題,如果要用logistic迴歸,

得做10次logistic迴歸,第一次將0作為一個類別,1~9作為另外一個類別,這樣就可以識別出0或非0。同樣地可以將1作為一個類別,0、2~9作為一個類別,這樣就可以識別出1或非1……..

本文的例項同樣是識別數字,但為了簡化,我只選出0和1的樣本,這是個二分類問題。下面開始介紹實現過程:

(1)工程檔案說明

在我的工程檔案目錄下,有訓練樣本集train和測試樣本集test,原始碼檔案命名為logistic regression.py

訓練樣本集train和測試樣本集test裡面只有0和1樣本:

 logistic regression.py實現的功能:從train裡面讀取訓練資料,然後用梯度上升演算法訓練出引數Θ,接著用引數Θ來預測test裡面的測試樣本,同時計算錯誤率。

(2)原始碼解釋

 loadData(direction)函式

實現的功能就是從資料夾裡面讀取所有訓練樣本,每個樣本(比如0_175.txt)裡有32*32的資料,程式將32*32的資料整理成1*1024的向量,這樣從每個txt檔案可以得到一個1*1024的特徵向量X,而其類別可以從檔名“0_175.txt”裡擷取0出來。因此,從train資料夾我們可以獲得一個訓練矩陣m*1024和一個類別向量m*1,m是樣本個數。

程式碼裡面用到python os模組裡的listdir(),用於從資料夾裡讀取所有檔案,返回的是列表。
python裡的open()函式用於開啟檔案,之後用readline()一行行讀取
  • sigmoid(inX)函式
  • gradAscent(dataArray,labelArray,alpha,maxCycles)函式

用梯度下降法計算得到迴歸係數,alpha是步長,maxCycles是迭代步數。

用到numpy裡面的mat,矩陣型別。shape()用於獲取矩陣的大小。

這個函式返回引數向量Θ,即權重weigh

  • classfy(testdir,weigh)函式

分類函式,根據引數weigh對測試樣本進行預測,同時計算錯誤率

  • digitRecognition(trainDir,testDir,alpha=0.07,maxCycles=10)函式

整合上面的所有函式,呼叫這個函式進行數字識別,alpha和maxCycles有預設形參,這個可以根據實際情況更改。

用loadData函式從train裡面讀取訓練資料,接著根據這些資料,用gradAscent函式得出引數weigh,最後就可以用擬合引數weigh來分類了。

3、試驗結果

工程檔案可以到這裡下載:github地址

執行logistic regression.py,採用預設形參:alpha=0.07,maxCycles=10,看下效果,錯誤率0.0118

改變形參,alpah=0.01,maxCycles=50,看下效果,錯誤率0.0471

這兩個引數可以根據實際情況調整