1. 程式人生 > >使用牛頓法確定邏輯斯諦迴歸(Logistic Regression)最佳迴歸係數

使用牛頓法確定邏輯斯諦迴歸(Logistic Regression)最佳迴歸係數

邏輯斯諦迴歸

在邏輯斯諦迴歸中,因為使用梯度上升(gradient ascent)收斂較慢,固本文采用牛頓法(Newton’s Method)進行引數求解,試驗發現通常迭代10次左右就可達到收斂,而梯度上升法則需要迭代上百甚至上千次,當然實際的迭代次數也要視實際資料而定。

牛頓法

牛頓法與梯度下降法的功能一樣,都是最優化的常用方法。
對於一個函式,如果要求函式值為0時的值,如圖所示:


先隨機選一個點,然後求出該點的切線,即導數,延長切線與橫軸相交,以相交時的的值作為下一次迭代的值,更新規則如下


對於邏輯斯諦迴歸,需要求的是似然函式L(θ)的最大值,當L(θ)的導數L’(θ)為0時即為L(θ)的最大值,即求L’(θ)=0的引數,則可使用牛頓法進行求解,此時引數更新規則為


使用牛頓法的另一個好處是不需要像梯度法一樣指定學習率(即步長)。但是牛頓法需要對二階導(Hessian矩陣)進行求逆,不過隨著擬牛頓法(BFGS)以及限域擬牛頓法(LBFGS)的提出,大大減少了求逆的計算量,不過在本文還是使用牛頓法進行引數求解。

牛頓法求解邏輯斯諦迴歸引數

迭代中需要進行的主要步驟包括如下:

(1)   初始化引數θ

(2)   獲取資料x

(3)   對資料進行預測h

(4)   得到對數似然函式L(θ)

(5)   根據L(θ)計算梯度g

(6)   根據L(θ)計算Hessian矩陣H

(7)   更新引數θ

具體計算

(1)   初始化θ=(b, θ(1), θ

(2), …, θ(n))T,初始時θ=(0, 0, 0, …, 0)T

(2)   獲取x=(1, x(1), x(2), …, x(n))T,其中x(1)到x(n)為資料的n個特徵的值

(3)   使用邏輯斯諦函式計算預測值h

 

(4)   得到似然函式


對數似然函式為


(5)   根據L(θ)計算梯度,一個維度的梯度計算公式為


n+1維的梯度向量為


(6)   根據L(θ)計算Hessian矩陣H,其中j行k列的值為


(n+1)*(n+1)的Hessian矩陣為


(7)   更新引數θθ = θ – H-1 g

本文使用的迭代規則是求出m個樣本的梯度g以及Hessian矩陣H,對m個g和H求平均,然後更新θ

,虛擬碼:

while(iterNum)                       //迭代次數
{
<span style="white-space:pre">	</span>for i range(1,m)                 //m個樣本
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>(2) (3) (4) (5) (6)      //具體計算的步驟標號
	}
	g = (1/m)g
	H = (1/m)H
	θ = θ – H-1g
	iterNum--
}

測試

測試效果如下:


tie dai ma

依賴包括numpy庫和matplotlib庫。

程式碼比較亂,因為開始時並沒有使用numpy庫,所以向量的點積、相加等計算都是自己實現的。後來使用牛頓法需要求矩陣逆,自己偷懶不想寫,所以用了numpy。中間還有一些計算本來可以使用numpy中的方法直接進行計算,但可能是對矩陣的初始化方法不對,始終無法用numpy計算矩陣乘法,無奈只能自己用笨方法進行計算。程式碼較亂,做好瞎眼準備,ready! go!

# -*- coding: gb18030 -*-
__author__ = 'jinyu'
from numpy import *
import math
 
##
# 讀取訓練資料
# #
def loadDataSet(dataFileName):
    dataMat = []
    labelMat = []
    fr = open(dataFileName)
    for line in fr:
        lineArr = line.strip().split()
        dataMat.append([1.0, 10.0*float(lineArr[0]), 10.0*float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
 
    return dataMat, labelMat
##
# sigmod函式
# #
def sigmoid(x):
    return 1.0 / (1+math.exp(-x))
 
##
# 梯度上升法
# #
def gradientAscent(dataMat, labelMat, alpha):
    m = len(dataMat)        #訓練集個數
    n = len(dataMat[0])     #資料特徵緯度
    theta = [0] * n
 
    iter = 1000
    while(iter):
        for i in range(m):
            hypothesis = sigmoid(computeDotProduct(dataMat[i], theta))
            error = labelMat[i] - hypothesis
            gradient = computeTimesVect(dataMat[i], error)
            theta = computeVectPlus(theta, computeTimesVect(gradient, alpha))
        iter -= 1
    return theta
 
##
# 牛頓法
# #
def newtonMethod(dataMat, labelMat, iterNum=10):
    m = len(dataMat)        #訓練集個數
    n = len(dataMat[0])     #資料特徵緯度
    theta = [0.0] * n
 
    while(iterNum):
        gradientSum = [0.0] * n
        hessianMatSum = [[0.0] * n]*n
        for i in range(m):
            try:
                hypothesis = sigmoid(computeDotProduct(dataMat[i], theta))
            except:
                continue
            error = labelMat[i] - hypothesis
            gradient = computeTimesVect(dataMat[i], error/m)
            gradientSum = computeVectPlus(gradientSum, gradient)
            hessian = computeHessianMatrix(dataMat[i], hypothesis/m)
            for j in range(n):
                hessianMatSum[j] = computeVectPlus(hessianMatSum[j], hessian[j])
 
        #計算hessian矩陣的逆矩陣有可能異常,如果捕獲異常則忽略此輪迭代
        try:
            hessianMatInv = mat(hessianMatSum).I.tolist()
        except:
            continue
        for k in range(n):
            theta[k] -= computeDotProduct(hessianMatInv[k], gradientSum)
 
        iterNum -= 1
    return theta
 
##
# 計算hessian矩陣
# #
def computeHessianMatrix(data, hypothesis):
    hessianMatrix = []
    n = len(data)
 
    for i in range(n):
        row = []
        for j in range(n):
            row.append(-data[i]*data[j]*(1-hypothesis)*hypothesis)
        hessianMatrix.append(row)
    return hessianMatrix
 
##
# 計算兩個向量的點積
# #
def computeDotProduct(a, b):
    if len(a) != len(b):
        return False
    n = len(a)
    dotProduct = 0
    for i in range(n):
        dotProduct += a[i] * b[i]
    return dotProduct
 
##
# 計算兩個向量的和
# #
def computeVectPlus(a, b):
    if len(a) != len(b):
        return False
    n = len(a)
    sum = []
    for i in range(n):
        sum.append(a[i]+b[i])
    return sum
 
##
# 計算某個向量的n倍
# #
def computeTimesVect(vect, n):
    nTimesVect = []
    for i in range(len(vect)):
        nTimesVect.append(n * vect[i])
    return nTimesVect
 
def plotBestFit(dataMat, labelMat, weights):
    import matplotlib.pyplot as plt
    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(0.0, 70.0, 0.1)
    y = (-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x, y)
    plt.xlabel('X1'); plt.ylabel('X2');
    plt.show()
 
def classifyVector(inX, weights):
    prob = sigmoid(sum(inX*weights))
    if prob > 0.5: return 1.0
    else: return 0.0
 
def colicTest(tainFileName, testFileName):
    frTrain = open(tainFileName); frTest = open(testFileName)
    trainingSet = []; trainingLabels = []
    for line in frTrain.readlines():
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(21):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[21]))
    trainWeights = newtonMethod(trainingSet, trainingLabels, 10)
    errorCount = 0; numTestVec = 0.0
    for line in frTest.readlines():
        numTestVec += 1.0
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(21):
            lineArr.append(float(currLine[i]))
        if int(classifyVector(array(lineArr), trainWeights))!= int(currLine[21]):
            errorCount += 1
    errorRate = (float(errorCount)/numTestVec)
    print "the error rate of this test is: %f" % errorRate
    return errorRate
 
dataMat, labelMat = loadDataSet("ex4x.dat")
theta = newtonMethod(dataMat, labelMat, 10)
print theta
plotBestFit(dataMat, labelMat, array(theta))
 
#colicTest('horseColicTraining.txt', 'horseColicTest.txt')

程式碼和資料


相關推薦

使用牛頓確定邏輯迴歸Logistic Regression最佳迴歸係數

邏輯斯諦迴歸 在邏輯斯諦迴歸中,因為使用梯度上升(gradient ascent)收斂較慢,固本文采用牛頓法(Newton’s Method)進行引數求解,試驗發現通常迭代10次左右就可達到收斂,而梯度上升法則需要迭代上百甚至上千次,當然實際的迭代次數也要視實際資料而定

樸素貝葉naive bayes邏輯迴歸logistic regression線性迴歸

樸素貝葉斯法實際上學習到生成資料的機制,所以屬於生成模型。條件獨立假設等於是說用於分類的特徵在類確定的條件下都是條件獨立的,但是有的時候會失去一些分類準確性。對於給定的輸入x,通過學習到的模型計算後驗概率分佈,將後驗概率最大的類作為x的類輸出主要是使用貝葉斯公式推導的過程。在

廣義線性迴歸邏輯迴歸 Logistic Regression

廣義線性模型 邏輯斯諦迴歸概念可以認為是屬於廣義線性迴歸的範疇,但它是用來進行分類的。 線性模型的表示式為: f (

邏輯迴歸Logistic regression—《統計學習方法》

邏輯斯諦迴歸(Logistic regression)是統計學習領域的一個經典分類方法,學習李航教授的《統計學習方法》將筆記和一些感悟記錄下來; 1 邏輯斯諦分佈(logistic distribution)   為一個連續型的隨機變數,分佈函式F和密度

【Tensorflow】邏輯迴歸Logistic Regression的簡單實現

Introduction 為了簡單的介紹和講解一下Tensorflow的基本操作, 我決定做一個簡單的邏輯斯特迴歸實現與程式碼講解, 但不太會用Markdown的方式來展現一個JupyterNotebook, 姑且就按照“說明—例項”的方式來解釋逐個程式碼塊好了

機器學習專案實戰--邏輯迴歸Logistic Regression

(一)邏輯迴歸 邏輯迴歸演算法是一種廣義的線性迴歸分析模型, 可用於二分類和多分類問題, 常用於資料探勘、疾病自動診斷、經濟預測等領域。通俗來說, 邏輯迴歸演算法通過將資料進行擬合成一個邏輯函式來預估一個事件出現的概率,因此被稱為邏輯迴歸。因為演算法輸出的為事件發生概率, 所以其輸出值應該在0

機器學習演算法與Python實踐之邏輯迴歸Logistic Regression

#!/usr/bin/python # -*- coding:utf-8 -*- import numpy as np from numpy import * import matplotlib.pyplot as plt #處理資料函式 def loadDataSet():

邏輯迴歸Logistic Regression演算法小結

一、邏輯迴歸簡述:   回顧線性迴歸演算法,對於給定的一些n維特徵(x1,x2,x3,......xn),我們想通過對這些特徵進行加權求和彙總的方法來描繪出事物的最終運算結果。從而衍生出我們線性迴歸的計算公式:        向量化表示式:         &n

機器學習/邏輯迴歸logistic regression/--附python程式碼

個人分類: 機器學習 本文為吳恩達《機器學習》課程的讀書筆記,並用python實現。 前一篇講了線性迴歸,這一篇講邏輯迴歸,有了上一篇的基礎,這一篇的內容會顯得比較簡單。 邏輯迴歸(logistic regression)雖然叫回歸,但他做的事實際上是分類。這裡我們討論二元分類,即只分兩類,y屬於{0,1}。

機器學習之邏輯迴歸logistic regression

概述 邏輯斯蒂迴歸實質是對數機率迴歸(廣義的線性迴歸),是用來解決分類問題的。 其中sigmoid用來解決二分類問題,softmax解決多分類問題,sigmoid是softmax的特殊情況。 數學建模直接針對分類可能性建模。 引數學習可用極大似然估計

Python手擼邏輯迴歸logistic regression

與線性迴歸用於預測連續值不同,邏輯歸回用於分類,原理與線性迴歸類似,定義損失函式,然後最小化損失,得到引數既模型,只不過損失的定義不同。 邏輯迴歸的假設如圖1所示,可以理解為線性迴歸外面套了一層sigmoid函式g(z),sigmoid函式影象如圖2所示,該函式有很好的數學

邏輯迴歸Logistic+Regression經典例項

房價預測 資料集描述 資料共有81個特徵 SalePrice - the property’s sale price in dollars. This is the target variable that you’re trying to pre

邏輯迴歸Logistic Regression

1、總述 邏輯迴歸是應用非常廣泛的一個分類機器學習演算法,它將資料擬合到一個logit函式(或者叫做logistic函式)中,從而能夠完成對事件發生的概率進行預測。 2、由來     要說邏輯迴歸,我們得追溯到線性迴歸,想必大家對線性迴歸都有一定的瞭解,即對於多維空間中存在

邏輯迴歸logistic regression和線性迴歸linear regression

序號 邏輯迴歸 線性迴歸 模型歸類 離散選擇法模型 迴歸分析 數值型別 二元 一元或多元 公式 P(Y=1│X=x)=exp(x'β)/(1+exp(x'β)) 邏輯迴歸 Logit模型(Logit model,也譯作“評定模型”,“分類評定模型”,又作Logistic

機器學習演算法與Python實踐之邏輯迴歸Logistic Regression

Logistic regression (邏輯迴歸)是當前業界比較常用的機器學習方法,用於估計某種事物的可能性。比如某使用者購買某商品的可能性,某病人患有某種疾病的可能性,以及某廣告被使用者點選的可能性等。(注意這裡是:“可能性”,而非數學上的“概率”,logisitc迴

機器學習筆記——logistic迴歸logistic regression

logistic迴歸 logistic迴歸實際上並不是一種迴歸演算法,而是一種分類演算法,意思就是輸出值是離散值(01或者更多類),而它叫這個名字完全是歷史原因。我們可以從下圖看出對於分類問題,如果我們採用傳統的迴歸演算法並不能獲得很好的效果 假設稱述 由於輸出的值是0和1,因此我

線性迴歸logistic regression

單變數線性迴歸 本文以單變數線性迴歸為例,且變數為一次方,多變數只需要增加變數x1,x2······的個數,變數x也可以有更高的次方。 h代表假設函式 theta代表引數 x代表輸入變數 y代表標籤 J代表損失函式 目標即為通過改變引數theta的值,最小化損

對數機率迴歸Logistic Regression總結

對數機率迴歸logistic regression,雖然名字是迴歸,但是實際上它是處理分類問題的演算法。簡單的說迴歸問題和分類問題如下: 迴歸問題:預測一個連續的輸出。 分類問題:離散輸出,比如二分類問題輸出0或1. 邏輯迴歸常用於垃圾郵件分類,天氣預測、

機器學習之邏輯迴歸logistics regression程式碼牛頓實現

      先貼一張圖解釋牛頓法原理:       然後以一道問題為例:       這個問題是《機器學習》周志華版本上的題目,給了西瓜的密度和含糖率資料,判斷西瓜的好壞。資料在程式碼裡。       下面貼一下程式碼: <span style="font-size

機器學習實戰邏輯迴歸LRLogistic Regression

目錄 0. 前言 1. Sigmoid 函式 2. 梯度上升與梯度下降 3. 梯度下降法(Gradient descent) 4. 梯度上升法(Gradient ascent) 5. 梯度下降/上升法的數學推導