機器學習實戰(5):Logistic回歸
來自專欄半仙數據分析之路
第5章: Logistic回歸
- 優點:計算代價不高,易於理解和實現。
- 缺點:容易欠擬合,分類精度可能不高。
- 適用數據類型:數值型和標稱型數據。
Charles Xiao:邏輯回歸和SVM的區別是什麼?各適用於解決什麼問題?
邏輯回歸
通常遇到缺值的情況,我們會有幾種常見的處理方式
- 如果缺值的樣本佔總數比例極高,我們可能就直接捨棄了,作為特徵加入的話,可能反倒帶入noise,影響最後的結果了
- 如果缺值的樣本適中,而該屬性非連續值特徵屬性(比如說類目屬性),那就把NaN作為一個新類別,加到類別特徵中
- 如果缺值的樣本適中,而該屬性為連續值特徵屬性,有時候我們會考慮給定一個step(比如這裡的age,我們可以考慮每隔2/3歲為一個步長),然後把它離散化,之後把NaN作為一個type加到屬性類目中。
- 有些情況下,缺失的值個數並不是特別多,那我們也可以試著根據已有的值,擬合一下數據,補充上。
9.1 模型係數關聯分析
親,你以為結果提交上了,就完事了?
我不會告訴你,這只是萬里長征第一步啊(淚牛滿面)!!!這才剛擼完baseline model啊!!!還得優化啊!!!看過Andrew Ng老師的machine Learning課程的同學們,知道,我們應該分析分析模型現在的狀態了,是過/欠擬合?,以確定我們需要更多的特徵還是更多數據,或者其他操作。我們有一條很著名的learning curves對吧。
不過在現在的場景下,先不著急做這個事情,我們這個baseline系統還有些粗糙,先再挖掘挖掘。
- 首先,Name和Ticket兩個屬性被我們完整捨棄了(好吧,其實是因為這倆屬性,幾乎每一條記錄都是一個完全不同的值,我們並沒有找到很直接的處理方式)。
- 然後,我們想想,年齡的擬合本身也未必是一件非常靠譜的事情,我們依據其餘屬性,其實並不能很好地擬合預測出未知的年齡。再一個,以我們的日常經驗,小盆友和老人可能得到的照顧會多一些,這樣看的話,年齡作為一個連續值,給一個固定的係數,應該和年齡是一個正相關或者負相關,似乎體現不出兩頭受照顧的實際情況,所以,說不定我們把年齡離散化,按區段分作類別屬性會更合適一些。
*********************************************************************
5.1 基於Logistic 回歸和Sigmoid 函數的分類
Sigmoid函數
Sigmoid函數在不同坐標尺度下的兩條曲線圖。當x為0時,Sigmoid函數值為0.5。隨著x的增大,對應的Sigmoid值將逼近於1;而隨著x的減小,Sigmoid值將逼近於0。如果橫坐標刻度足夠大,Sigmoid函數看起來很像一個階躍函數。
為了實現Logistic回歸分類器,我們可以在每個特徵上都乘以一個回歸係數,然後把所有的結果值相加,將這個總和代入Sigmoid函數中,進而得到一個範圍在0~1之間的數值。任何大於0.5的數據被分入1類,小於0.5即被歸入0類。
5.2 基於最優化方法的最佳回歸係數確定
它表示將這兩個數值向量對應元素相乘,然後全部加起來即得到z值。其中的向量x是分類器的輸入數據,向量w也就是我們要找到的最佳參數。
5.2.1 梯度上升法
思想:要找到某函數的最大值,最好的方法是沿著該函數的梯度方向探尋。如果梯度記為?,則函數f(x,y)的梯度由下式表示:
偏微分方程,在該點有定義,且可微分。
5.2.2 訓練演算法:使用梯度上升找到最佳參數
#導出numpy所有from numpy import * 定義函數,獲得txt文件的特徵和標籤,存儲至dataMat和labelMat集合中。def loadDataSet(): #定義空集合 dataMat = []; labelMat = [] #讀取txt文件 fr = open(testSet.txt) #for循環逐行讀取 for line in fr.readlines(): # strip()去除字元串空格和換行字元,split()按空格和換行字元分開 lineArr = line.strip().split() #加入到dataMat,第一個值設置為1.0 dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) #求類別標籤 labelMat.append(int(lineArr[2])) return dataMat,labelMat
sigmoid(),確定分類
#定義sigmoid(),確定分類def sigmoid(inX): z=1.0/(1+exp(-inX)) return z
mat()函數:numpy一維數組array轉化為矩陣
定義函數gradAscent(),transpose() 矩陣轉置函數,mat()函數list轉化為martix,數組轉為矩陣.dataMat里存放的是特徵,但是第一列都為1.0,實際上為100*3的矩陣LabelMat里存放的是類別標籤,1*100的行向量def gradAscent(dataMat,labelMat): # 將列錶轉化為矩陣 dataMatrix = mat(dataMat) # 將列錶轉化為矩陣 ,且進行轉置 labelMat = mat(labelMat).transpose() #計算dataMatrix行數m,列數n m,n = shape(dataMatrix) #目標移動步長 alpha = 0.001 #迭代次數 maxCycles = 500 #權重初始化為1 weights = ones((n,1)) for k in range(maxCycles): #注意,這裡h是一個m*1的列向量 h = sigmoid(dataMatrix*weights) #求得誤差 error = (labelMat - h) #更新權重 weights = weights + alpha * dataMatrix.transpose()* error #matrix mult return weights
調用函數
dataMat,labelMat=loadDataSet()gradAscent(dataMat,labelMat)
print(dataMat數據類型是,type(dataMat))print(labelMat數據類型是,type(labelMat))
5.2.3 分析數據:畫出決策邊界
get()將矩陣轉化為一維數組array,與mat()作用相反
#導入數據包import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport warningswarnings.filterwarnings(ignore)%matplotlib inline
繪製決策邊界線
#繪製決策邊界線def plotBestFit(weights): 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() fig.set_size_inches(12,8) #設置畫紙 ax=fig.add_subplot(111) ax.scatter(xcord1,ycord1,color=red,marker=*) ax.scatter(xcord2,ycord2,color=green,marker=s) x=arange(-3,3,0.1) #x=arange(-3,3,0.1) y= (-weights[0]-weights[1]*x)/weights[2] #ax.plot(x,y) ax.plot(x,y) plt.xlabel(X1) plt.ylabel(X2) plt.title(決策邊界線) plt.grid(False) plt.show() return xcord1, ycord1,xcord2, ycord2, y
調用函數
weights=gradAscent(dataMat,labelMat)#getA()將矩陣轉化為一維數組,與mat()作用相反plotBestFit(weights.getA())
5.2.4 訓練演算法:隨機梯度上升
def stocGradAscent0(dataMat,labelMat): m,n=shape(dataMat) #目標移動步長 alpha=0.01 #設置初始權重為1,array([1., 1., 1.])list weights=ones(n) for i in range(m): #dtaMat[i]是(1*n)array; #weights是(m,)array; #dataMat[i]*weights,必須是array結構,乘積是一個數值 #h是數值 h=sigmoid(sum(dataMat[i]*weights)) #labelMat是(m=m2,)array-list error=labelMat[i]-h weights=weights+alpha*error*dataMat[i] return weights,m,n,h,error
調用函數
from numpy import *#reload(logRegres)dataArr,labelMat=loadDataSet()#weights=stocGradAscent0(dataMat,labelMat)value=stocGradAscent0(array(dataMat),labelMat)value
5.3 示例:從疝氣病症預測病馬的死亡率
5.4 本章小結
參考資料
Logistic回歸及梯度上升演算法 - CSDN博客
《機器學習實戰》--logistic回歸 - CSDN博客
python中mat()函數 - CSDN博客
python--zeros函數和ones函數 - chamie - 博客園
python 學習筆記(1)--numpy數組轉置 - CSDN博客
數組與矩陣的區別 Python - CSDN博客
推薦閱讀:
※BP神經網路演算法:將參數矩陣向量化
※gradient descent計算流程和注意事項
※斯坦福公開課-機器學習筆記 1
※Mac tensorflow 的安裝
※高斯過程簡介