回歸(四):logistic回歸

Sigmod函數

logist回歸首先是一種分類方法曼库,作為一種分類方法此衅,它具有一個先驗概率分布:伯努利分布济欢。因此Sigmod函數具有同指數族分布一樣的形式脆贵。

![][equtation1]
[equtation1]: http://latex.codecogs.com/svg.latex?\sigma=\frac{1}{1+{e^{-z}}}

復習:指數組分布有哪些?

  • 伯努利分布(Bernoulli)量蕊;
  • 多項式分布(Multinomial)羡亩;
  • 泊松分布(Poisson);
  • 伽馬分布(gamma)與指數分布(exponential):對有間隔的正數進行建模危融,比如公交車的到站時間問題;
  • β 分布:對小數建模雷袋;
  • Dirichlet 分布:對概率分布進建模吉殃;
  • Wishart 分布:協方差矩陣的分布;
  • 高斯分布(Gaussian)楷怒;

上面這些分布都可以化為Sigmod函數的形式蛋勺,關于這些分布的問題,可以被歸為廣義線性模型鸠删。

Sigmod函數

觀察圖像可知抱完,Sigmod函數看起來表現為一個階躍函數的形式,sigmoid函數是一個良好的閾值函數刃泡。具有如下優(yōu)點:

  • 連續(xù)巧娱,光滑
  • 嚴格單調
  • 關于(0,0.5)中心對稱
  • 對閾值函數f(x)的近似得很良好
             1, x > 0
          /
f(x)= 
         \
             0, x < 0
  • 其導數f'(x)=f(x)*[1-f(x)]碉怔,可以節(jié)約計算時間

我們可以據此給每個特征都乘上一個回歸系數,然后把所有結果相加禁添,將這個總和帶入z撮胧。
![][equtation1]
[equtation1]: http://latex.codecogs.com/svg.latex?\sigma=\frac{1}{1+{e^{-z}}}
其中:
![][equtation2]
[equtation2]: http://latex.codecogs.com/svg.latex?z=w_{0}x_{0}+w_{1}x_{1}+\cdots+w_{n}x_{n}
以向量形式表達就是:
![][equtation3]
[equtation3]: http://latex.codecogs.com/svg.latex?z=w^{T}x
于是我們可以找到一個最佳參數w,盡可能得使分類趨于理想的結果老翘。這種通過訓練數據找到分類界面的方法非常類似于線性回歸芹啥,因此它也被叫做logistc回歸。

神經網絡中的激活函數

Andrew Ng的圖铺峭,靈魂畫手
Ng另外的一個圖

如何確定這個界面墓怀,也就是找到w這組最佳系數,方法同線性回歸類似卫键,有最小二乘傀履、梯度上升等方法,前者不再贅述永罚,這里只說梯度上升(下降)法啤呼。

梯度上升法

首先要聲明的是,梯度上升和梯度下降都是一回事呢袱,只是公式中的假發(fā)需要改為減法官扣,原理都是沿著梯度找局部最優(yōu)。原理在線性回歸中已經寫出來過羞福,就不再贅述了惕蹄,這里只介紹算法。
偽代碼如下:

每個回歸系數初始化為1
重復R次:
    計算整個數據集的梯度
    是有alpha*gradient更新回歸系數的向量
返回回歸系數

代碼實例:
MLR已經替我們把數據已經洗好了治专,首先預覽一下:

-0.017612   14.053064   0
-1.395634   4.662541    1
-0.752157   6.538620    0
-1.322371   7.152853    0
0.423363    11.054677   0
0.406704    7.067335    1

可以看到第一列是x1,第二列為x2,最后一列是類別卖陵。
總之代碼如下:

#  -*-coding:utf-8 -*-
from numpy import *
#數據載入函數
def loadDataSet():
    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

#Sigmoid函數
def sigmoid(inX):
    return 1.0/(1+exp(-inX))

#梯度下降函數
def gradAscent(dataMatIn, classLabels):
    dataMatrix = mat(dataMatIn)             #搞成NumPy矩陣
    labelMat = mat(classLabels).transpose() 
    m,n = shape(dataMatrix)                 #m行n列
    alpha = 0.001                           #定義步長
    maxCycles = 500                         #迭代次數
    weights = ones((n,1))                   #初始化w,一個全是1的列向量
    for k in range(maxCycles):              #循環(huán)固定次數
        h = sigmoid(dataMatrix*weights)     
        #h是一個列向量张峰,維度等于樣本個數泪蔫,該數據有100個
        error = (labelMat - h)              #算個差值
        weights = weights + alpha * dataMatrix.transpose()* error 
        #按照差值的方向調整系數
    return weights

if __name__ == '__main__':
    dataArr, labelMat = loadDataSet()
    weights =  gradAscent(dataArr, labelMat)
    print weights

返回值也可以看一下:

[[ 4.12414349]
 [ 0.48007329]
 [-0.6168482 ]]

當然我們沒有忘記可視化是很重要的,于是我們試著畫個圖看看:

def plotBestFit(weights):
    import matplotlib.pyplot as plt
    dataMat,labelMat=loadDataSet()
    dataArr = array(dataMat)
    n = shape(dataArr)[0] 
    xcord1 = []; ycord1 = []
    xcord2 = []; ycord2 = []
    for i in range(n):
        if int(labelMat[i])== 1:
            xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])
        else:
            xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
    ax.scatter(xcord2, ycord2, s=30, c='green')
    x = arange(-3.0, 3.0, 0.1)
    y = (-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x, y)
    plt.xlabel('X1'); plt.ylabel('X2');
    plt.show()

if __name__ == '__main__':
    dataArr, labelMat = loadDataSet()
    weights =  gradAscent(dataArr, labelMat)
    print weights
    plotBestFit(weights.getA())
    #getA()是np矩陣方法喘批,作為ndarray返回自己

得到下圖:

應該分得挺好的

這個方法好是挺好的撩荣,但因為用了300次乘法,所以不太適用于較大數據饶深,所以我們再來搞個隨機梯度看看餐曹。

隨機梯度上升(Stochastic Gradient)

首先,單純的梯度上升在每次更新w時都需要遍歷整個數據集敌厘,小數據尚可台猴,對于大數據沒什么可行性,對于這種算法我們把它叫做批處理
相對應的饱狂,還有一種算法我們每次更新僅用一個樣本點曹步,這種方法叫做在線學習

偽代碼:

所有回歸系數初始化為1
對數據集中每個樣本
    計算該樣本的梯度
    使用alpha*gradient更新回歸系數值
返回回歸系數值

代碼如下:

def stocGradAscent0(dataMatrix, classLabels):
    m,n = shape(dataMatrix)
    alpha = 0.01
    weights = ones(n)   #初始化w嗡官,一個全是1的行向量
    for i in range(m):
        h = sigmoid(sum(dataMatrix[i]*weights))
        error = classLabels[i] - h
        weights = weights + alpha * error * dataMatrix[i]
    return weights

if __name__ == '__main__':
    weights2 = stocGradAscent0(array(dataArr), labelMat)
    print weights2
    plotBestFit(weights2)

看看返回的w箭窜,好像跟第一個相差很大啊穴张。

[ 1.01702007  0.85914348 -0.36579921]

畫的圖也完全不能接受啊毒坛,肯定是哪里出了問題。

仔細思考一下磅网,這個算法到底哪里出了問題婆咸?原來是步長的問題V褡健!

步長過小尚骄,收斂太慢块差;步長太小,收斂不到局部最優(yōu)解倔丈。

所以我們需要對算法改進一下憨闰,得到有一個動態(tài)步長。

#默認迭代次數是150次需五,可以通過參數修改
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
    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    #隨著迭代步長減小鹉动,但由于常數項不會太小
            randIndex = int(random.uniform(0,len(dataIndex)))#從而保證后面的數據也有一定影響力
            h = sigmoid(sum(dataMatrix[randIndex]*weights))
            error = classLabels[randIndex] - h
            weights = weights + alpha * error * dataMatrix[randIndex]
            del(dataIndex[randIndex])
            #每次從列表中隨機選一個值,然后刪掉
    return weights

最后得到的結果是:

[ 13.10360032   0.65123109  -1.75151716]

好像還能接受宏邮。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末泽示,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子蜜氨,更是在濱河造成了極大的恐慌械筛,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件飒炎,死亡現場離奇詭異埋哟,居然都是意外死亡,警方通過查閱死者的電腦和手機郎汪,發(fā)現死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門赤赊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人怒竿,你說我怎么就攤上這事±┣猓” “怎么了耕驰?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長录豺。 經常有香客問我朦肘,道長饭弓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任媒抠,我火速辦了婚禮弟断,結果婚禮上,老公的妹妹穿的比我還像新娘趴生。我一直安慰自己阀趴,他們只是感情好,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布苍匆。 她就那樣靜靜地躺著刘急,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浸踩。 梳的紋絲不亂的頭發(fā)上叔汁,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天,我揣著相機與錄音检碗,去河邊找鬼据块。 笑死,一個胖子當著我的面吹牛折剃,可吹牛的內容都是我干的另假。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼微驶,長吁一口氣:“原來是場噩夢啊……” “哼浪谴!你這毒婦竟也來了?” 一聲冷哼從身側響起因苹,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤苟耻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后扶檐,有當地人在樹林里發(fā)現了一具尸體凶杖,經...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年款筑,在試婚紗的時候發(fā)現自己被綠了智蝠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡奈梳,死狀恐怖杈湾,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情攘须,我是刑警寧澤漆撞,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響浮驳,放射性物質發(fā)生泄漏悍汛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一至会、第九天 我趴在偏房一處隱蔽的房頂上張望离咐。 院中可真熱鬧,春花似錦奉件、人聲如沸宵蛀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糖埋。三九已至,卻和暖如春窃这,著一層夾襖步出監(jiān)牢的瞬間瞳别,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工杭攻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留祟敛,地道東北人。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓兆解,卻偏偏與公主長得像馆铁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子锅睛,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內容