機(jī)器學(xué)習(xí)之Logistic回歸

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 主要用途

  1. 尋找導(dǎo)致某種情況的主要因素,比如尋找導(dǎo)致肺癌的主要致癌因素;
  2. 預(yù)測(cè),例如根據(jù)logistic回歸模型預(yù)測(cè)在不同自變量的情況下,判斷導(dǎo)致肺癌的概率有多大;
  3. 判別,類似預(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):

  1. 步長(zhǎng)在每次迭代時(shí)都會(huì)調(diào)整,避免數(shù)據(jù)波動(dòng)或高頻波動(dòng);
  2. 隨機(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
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容