1. Logistic回歸的概念
1.1 簡(jiǎn)介
logistic回歸又稱logistic回歸分析,是一種廣義的線性回歸分析模型,常用于數(shù)據(jù)挖掘,疾病自動(dòng)診斷,經(jīng)濟(jì)預(yù)測(cè)等領(lǐng)域。例如,探討引發(fā)疾病的危險(xiǎn)因素,并根據(jù)危險(xiǎn)因素預(yù)測(cè)疾病發(fā)生的概率等。以胃癌病情分析為例,選擇兩組人群,一組是胃癌組,一組是非胃癌組,兩組人群必定具有不同的體征與生活方式等。因此因變量就為是否胃癌,值為“是”或“否”,自變量就可以包括很多了,如年齡、性別、飲食習(xí)慣、幽門螺桿菌感染等。自變量既可以是連續(xù)的,也可以是分類的。然后通過(guò)logistic回歸分析,可以得到自變量的權(quán)重,從而可以大致了解到底哪些因素是胃癌的危險(xiǎn)因素。同時(shí)根據(jù)該權(quán)值可以根據(jù)危險(xiǎn)因素預(yù)測(cè)一個(gè)人患癌癥的可能性。(摘自百度百科“Logistic回歸”詞條)
1.2 主要用途
- 尋找導(dǎo)致某種情況的主要因素,比如尋找導(dǎo)致肺癌的主要致癌因素;
- 預(yù)測(cè),例如根據(jù)logistic回歸模型預(yù)測(cè)在不同自變量的情況下,判斷導(dǎo)致肺癌的概率有多大;
- 判別,類似預(yù)測(cè),例如判斷在不同自變量下,判斷一個(gè)人有多大可能性屬于肺癌。
1.3 Logistic回歸的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
計(jì)算代價(jià)不高,易于理解和實(shí)現(xiàn)。
缺點(diǎn)
容易欠擬合,分類精度可能不高。
1.4 相關(guān)知識(shí)
- 海維賽德階躍函數(shù)
- Sigmoid函數(shù)
為了實(shí)現(xiàn)Logistic回歸分類器,我們可以在每個(gè)特征上都乘以一個(gè)回歸系數(shù),然后把所有的結(jié)果值相加,將這個(gè)總和代入Sigmoid函數(shù)中,進(jìn)而得到一個(gè)范圍在0~1之間的數(shù)值。任何大于0.5的數(shù)據(jù)被分為1類,小于0.5的數(shù)據(jù)被分為0類。
確定了分類器的函數(shù)形式后,現(xiàn)在的問(wèn)題就變成了如何求解最佳回歸系數(shù)。
2. 基于最優(yōu)化方法的最佳回歸系數(shù)確定
2.1 梯度上升法
基本思想:要找到某函數(shù)的最大值,最好的方法是沿著該函數(shù)的梯度方向探尋。
梯度的定義:梯度是一個(gè)表示某一函數(shù)在某點(diǎn)處的方向?qū)?shù)沿著該方向取最大值的向量,函數(shù)在該點(diǎn)處沿著該方向(即梯度的方向)變化最快,變化率最大。
與梯度上升算法相應(yīng)的還有梯度下降算法,梯度上升用來(lái)求函數(shù)的最大值,而梯度下降用來(lái)求函數(shù)的最小值。
梯度上升算法的偽代碼如下:
每個(gè)回歸系數(shù)初始化為1
重復(fù)R次:
計(jì)算整個(gè)數(shù)據(jù)集的梯度
使用步長(zhǎng) * 梯度更新回歸系數(shù)的向量
返回回歸系數(shù)
編寫梯度上升法的代碼:
from numpy import *
def loadDataSet():
'''
加載testSet.txt中的數(shù)據(jù)
'''
dataMat = []
labelMat = []
fr = open('testSet.txt')
for line in fr.readlines():
lineArr = line.strip().split()
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
labelMat.append(int(lineArr[2]))
return dataMat,labelMat
loadSet()函數(shù)的功能是打開文本testSet.txt并逐行讀取,每行前兩個(gè)值分別是X1和X2,第三個(gè)值是數(shù)據(jù)對(duì)應(yīng)的類別標(biāo)簽。
def sigmoid(inX):
'''
定義sigmoid函數(shù)
'''
return 1.0/(1+exp(-inX))
# 梯度上升算法
def gradAscent(dataMatIn, classLabels):
dataMatrix = mat(dataMatIn) #轉(zhuǎn)換為numpy矩陣數(shù)據(jù)類型
labelMat = mat(classLabels).transpose() #轉(zhuǎn)換為numpy矩陣數(shù)據(jù)類型
m,n = shape(dataMatrix)
alpha = 0.001 # alpha是向目標(biāo)移動(dòng)的步長(zhǎng)
maxCycles = 500 # maxcycles是迭代次數(shù)
weights = ones((n,1)) # 初始化回歸系數(shù)
for k in range(maxCycles):
h = sigmoid(dataMatrix*weights) # 矩陣相乘
error = (labelMat - h) # 向量減法
weights = weights + alpha * dataMatrix.transpose()* error # 矩陣相乘
return weights
測(cè)試算法:
dataArr,labelMat = loadDataSet()
print(gradAscent(dataArr,labelMat))
# 打印回歸系數(shù)
matrix([[ 4.12414349],
[ 0.48007329],
[-0.6168482 ]])
2.2 隨機(jī)梯度上升算法
梯度上升法在每次更新回歸系數(shù)時(shí)都需要遍歷整個(gè)數(shù)據(jù)集,隨著樣本數(shù)和特征數(shù)的增長(zhǎng),梯度上升法的復(fù)雜度會(huì)變得很高,一種改進(jìn)方法是一次僅用一個(gè)樣本點(diǎn)來(lái)更新回歸系數(shù),該方法稱為隨機(jī)梯度上升算法。
隨機(jī)梯度上升算法的偽代碼如下:
所有回歸系數(shù)初始化為1
對(duì)數(shù)據(jù)集中每個(gè)樣本
計(jì)算該樣本的梯度
使用 步長(zhǎng) * 梯度更新回歸系數(shù)值
返回回歸系數(shù)值
接下來(lái)對(duì)隨機(jī)梯度上升算法做一個(gè)簡(jiǎn)單實(shí)現(xiàn):
def stocGradAscent0(dataMatrix, classLabels):
'''
隨機(jī)梯度上升算法的簡(jiǎn)單實(shí)現(xiàn)
'''
m,n = shape(dataMatrix)
alpha = 0.01
weights = ones(n) #初始化所有回歸系數(shù)為1
for i in range(m):
h = sigmoid(sum(dataMatrix[i]*weights))
error = classLabels[i] - h # h和error都是標(biāo)量
weights = weights + alpha * error * dataMatrix[i]
return weights
上面對(duì)隨機(jī)梯度上升算法做了一個(gè)簡(jiǎn)單的實(shí)現(xiàn),可以看出,隨機(jī)梯度上升算法和梯度上升法很相像,但隨機(jī)梯度上升算法的變量h和error都是數(shù)值,不是向量,而且隨機(jī)梯度上升算法中沒有矩陣的轉(zhuǎn)換過(guò)程。
優(yōu)化算法的優(yōu)劣主要看其是否收斂,而上面的簡(jiǎn)單實(shí)現(xiàn)需要大量迭代才會(huì)使得回歸系數(shù)收斂,為此,接下來(lái)做個(gè)改進(jìn):
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
'''
隨機(jī)梯度上升算法改進(jìn)版
'''
m,n = shape(dataMatrix)
weights = ones(n) #initialize to all ones
for j in range(numIter):
dataIndex = range(m)
for i in range(m):
alpha = 4/(1.0+j+i)+0.0001 #步長(zhǎng)在每次迭代時(shí)都會(huì)調(diào)整
randIndex = int(random.uniform(0,len(dataIndex))) #隨機(jī)選取樣本來(lái)更新回歸系數(shù)
h = sigmoid(sum(dataMatrix[randIndex]*weights))
error = classLabels[randIndex] - h
weights = weights + alpha * error * dataMatrix[randIndex]
del(dataIndex[randIndex])
return weights
改進(jìn)版中主要有兩個(gè)地方改進(jìn):
- 步長(zhǎng)在每次迭代時(shí)都會(huì)調(diào)整,避免數(shù)據(jù)波動(dòng)或高頻波動(dòng);
- 隨機(jī)選取樣本來(lái)更新回歸系數(shù),減少周期性的波動(dòng)。
2.3 用Logistic回歸進(jìn)行分類
使用Logistic回歸進(jìn)行分類的方法就是把測(cè)試集上每個(gè)特征向量乘以最優(yōu)化算法得來(lái)的回歸系數(shù),再將該乘積結(jié)果求和代入Sigmoid函數(shù)中即可,大于0.5就預(yù)測(cè)類別標(biāo)簽為1,否則為0.
3. scikit-learn中的邏輯回歸
from sklearn.linear_model import LogisticRegression