整合成一個(gè)公式,就變成了如下公式:
成都創(chuàng)新互聯(lián)公司公司2013年成立,是專(zhuān)業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元榮昌做網(wǎng)站,已為上家服務(wù),為榮昌各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話(huà):18980820575
z是一個(gè)矩陣,θ是參數(shù)列向量(要求解的),x是樣本列向量(給定的數(shù)據(jù)集),θ^T表示θ的轉(zhuǎn)置
Sigmoid函數(shù)的輸入記為z,由下面公式得出:
z=w0x0+w1x1+w2x2+...+wnxn
如果采用向量的寫(xiě)法,上述公式可以寫(xiě)成z = wTx,它表示將這兩個(gè)數(shù)值向量對(duì)應(yīng)元素相乘然后
全部加起來(lái)即得到z值。其中的向量x是分類(lèi)器的輸入數(shù)據(jù),向量w也就是我們要找到的最佳參數(shù) (系數(shù)),從而使得分類(lèi)器盡可能地精確。
邏輯回歸的簡(jiǎn)單來(lái)說(shuō),就是根據(jù)數(shù)據(jù)得到的回歸直線(xiàn)方程z=a*x+b方程之后,將z作為sigmoid的輸入使得z的值轉(zhuǎn)化為在0-1之間的值,然后計(jì)算概率,最后根據(jù)sigmod函數(shù)的特點(diǎn)也就是當(dāng)輸入為零的時(shí)候,函數(shù)值為0.5,以0.5為分界線(xiàn)來(lái)劃分?jǐn)?shù)據(jù)的類(lèi)型。
梯度上升算法用來(lái)求函數(shù)的最大值,而梯度下降算法用來(lái)求函數(shù)的最小值。
求一個(gè)函數(shù)的最大值,在數(shù)學(xué)中,是不是通過(guò)對(duì)函數(shù)求導(dǎo),然后算出導(dǎo)數(shù)等于0,或者導(dǎo)數(shù)不存在的位置作為極值,然后如果極值只有一個(gè)開(kāi)區(qū)間內(nèi)是不是極值就是最大值。但是在實(shí)際應(yīng)用中卻不是這么簡(jiǎn)單的去求最大值,而是通過(guò)迭代的方式一步一步向最值點(diǎn)靠近,最后得到最值。這也就是梯度上升法的思想
其中,m為樣本的總數(shù),y(i)表示第i個(gè)樣本的類(lèi)別,x(i)表示第i個(gè)樣本,需要注意的是θ是多維向量,x(i)也是多維向量。
梯度上升迭代公式為:
代碼實(shí)現(xiàn):
import matplotlib.pyplot as plt
import numpy as np
import warnings
warnings.filterwarnings('ignore')
def loadDataSet():
dataMat = [] #創(chuàng)建數(shù)據(jù)列表
labelMat = [] #創(chuàng)建標(biāo)簽列表
fr = open('testSet.txt') #打開(kāi)文件
for line in fr.readlines(): #逐行讀取
lineArr = line.strip().split() #去回車(chē),放入列表
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) #添加數(shù)據(jù)
labelMat.append(int(lineArr[2])) #添加標(biāo)簽
fr.close() #關(guān)閉文件
return dataMat, labelMat #返回
def sigmoid(inX):
return 1.0/(1+np.exp(-inX))
#dataMatIn,它是一個(gè)2維NumPy數(shù)組,每列分別代表每個(gè)不同的特征,每行則代表每個(gè)訓(xùn)練樣本
def gradAscent(dataMatIn,classLabels):
dataMatrix=np.mat(dataMatIn)#轉(zhuǎn)換成numpy的mat
labelMat=np.mat(classLabels).transpose()#為了便于矩陣運(yùn)算,需要將該行向量轉(zhuǎn)換為列向量,做法是將原向量轉(zhuǎn)置,再將它賦值給labelMat
m,n=np.shape(dataMatrix) #返回dataMatrix的大小。m為行數(shù),n為列數(shù)。
alpha=0.001 #向目標(biāo)移動(dòng)的步長(zhǎng)
maxCycles=500 #maxCycles是迭代次數(shù)
weights=np.ones((n,1))#權(quán)重初始化都為1
for k in range(maxCycles):
h=sigmoid(dataMatrix*weights)#梯度上升矢量化公式
error=(labelMat-h)#相當(dāng)于公式中的y(i)-h(x(i))
weights=weights+alpha*dataMatrix.transpose()*error#公式里面的累加在這里使用矩陣相乘來(lái)實(shí)現(xiàn)(矩陣相乘的過(guò)程中先乘再加)
return weights.getA() #返回權(quán)重?cái)?shù)組
def plotBestFit(weights):
dataMat, labelMat = loadDataSet() #加載數(shù)據(jù)集
dataArr = np.array(dataMat) #轉(zhuǎn)換成numpy的array數(shù)組
n = np.shape(dataMat)[0] #數(shù)據(jù)個(gè)數(shù)
xcord1 = []; ycord1 = [] #正樣本
xcord2 = []; ycord2 = [] #負(fù)樣本
for i in range(n): #根據(jù)數(shù)據(jù)集標(biāo)簽進(jìn)行分類(lèi)
if int(labelMat[i]) == 1:
xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2]) #1為正樣本
else:
xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])#0為負(fù)樣本
fig = plt.figure()
ax = fig.add_subplot(111) #添加subplot
ax.scatter(xcord1, ycord1, s = 20, c = 'red', marker = 's',alpha=.5)#繪制正樣本
ax.scatter(xcord2, ycord2, s = 20, c = 'green',alpha=.5) #繪制負(fù)樣本
x = np.arange(-3.0, 3.0, 0.1)
y = (-weights[0] - weights[1] * x) / weights[2]
ax.plot(x, y)
plt.title('BestFit') #繪制title
plt.xlabel('X1'); plt.ylabel('X2') #繪制label
plt.show()
if __name__ == '__main__':
dataMat, labelMat = loadDataSet()
weights = gradAscent(dataMat, labelMat)
plotBestFit(weights)
#plotDataSet()
正常運(yùn)行之前報(bào)了如下錯(cuò)誤AttributeError: partially initialized module ‘matplotlib.cbook’ has no attribute ‘deprecated’ (most likely due to a circular import)
然后就是你安裝的matplotlib版本太高了,可以將以前的版本給卸載了,然后安裝一個(gè)版本較低的matplotlib,然后就可以解決
測(cè)試結(jié)果
總結(jié):代碼運(yùn)行的大致思路如下:
拿到數(shù)據(jù)之后通過(guò)loadDataSet函數(shù)將數(shù)據(jù)的坐標(biāo)和類(lèi)別分別存放在兩個(gè)數(shù)組中
然后通過(guò)拿到的坐標(biāo)數(shù)組和分類(lèi)數(shù)組,首先先將數(shù)組轉(zhuǎn)換為矩陣,方便后面矩陣的運(yùn)算,然后根據(jù)sigmoid函數(shù)將所有數(shù)據(jù)轉(zhuǎn)化為0-1之間的數(shù)據(jù),也即公式中的h(xi)的值,然后用每個(gè)樣本的類(lèi)標(biāo)簽減去梯度上升的矢量值,最后帶入公式算出當(dāng)前的權(quán)重值
繪圖
然后繪圖的時(shí)候定義兩種數(shù)據(jù)類(lèi)型的x坐標(biāo)的數(shù)組和對(duì)應(yīng)的y坐標(biāo)的數(shù)組,然后通過(guò)數(shù)據(jù)集,將每種類(lèi)別對(duì)應(yīng)的x坐標(biāo)和y坐標(biāo)分開(kāi)存入對(duì)應(yīng)的數(shù)組中
然后繪制一張空的面板,添加坐標(biāo)系,然后將每個(gè)同一類(lèi)別的點(diǎn)畫(huà)在面板上,并且同一類(lèi)別的點(diǎn)的顏色相同
最后畫(huà)擬合的直線(xiàn),橫坐標(biāo)的范圍已知,然后取sigmoid 函數(shù)為0。0是兩個(gè)分類(lèi)(類(lèi)別1和類(lèi)別0)的分界處。因此,我們?cè)O(shè)定 0 = w0x0 + w1x1 + w2x2,然后解出X2和X1的關(guān)系式(即分隔線(xiàn)的方程,注意X0=1)。
最后根據(jù)函數(shù)方程和x的值將直線(xiàn)畫(huà)在面板上即可
#改進(jìn)的梯度上升算法
#迭代次數(shù)150是根據(jù)上面的代碼測(cè)試出來(lái)的
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
m,n = np.shape(dataMatrix) #返回dataMatrix的大小。m為行數(shù),n為列數(shù)。
weights = np.ones(n) #參數(shù)初始化
for j in range(numIter):
dataIndex = list(range(m))
for i in range(m):
alpha = 4/(1.0+j+i)+0.01 #降低alpha的大小,每次減小1/(j+i)。
randIndex = int(random.uniform(0,len(dataIndex))) #隨機(jī)選取樣本
h = sigmoid(sum(dataMatrix[randIndex]*weights)) #選擇隨機(jī)選取的一個(gè)樣本,計(jì)算h
error = classLabels[randIndex] - h #計(jì)算誤差
weights = weights + alpha * error * dataMatrix[randIndex] #更新回歸系數(shù)
del(dataIndex[randIndex]) #刪除已經(jīng)使用的樣本
return weights
#2.為改進(jìn)之前查看回歸系數(shù)與迭代次數(shù)的關(guān)系
def gradAscent1(dataMatIn, classLabels):
dataMatrix = np.mat(dataMatIn) #轉(zhuǎn)換成numpy的mat
labelMat = np.mat(classLabels).transpose() #轉(zhuǎn)換成numpy的mat,并進(jìn)行轉(zhuǎn)置
m, n = np.shape(dataMatrix) #返回dataMatrix的大小。m為行數(shù),n為列數(shù)。
alpha = 0.01 #移動(dòng)步長(zhǎng),也就是學(xué)習(xí)速率,控制更新的幅度。
maxCycles = 500 #最大迭代次數(shù)
weights = np.ones((n,1))
weights_array = np.array([])
for k in range(maxCycles):
h = sigmoid(dataMatrix * weights) #梯度上升矢量化公式
error = labelMat - h
weights = weights + alpha * dataMatrix.transpose() * error
weights_array = np.append(weights_array,weights)
weights_array = weights_array.reshape(maxCycles,n)
return weights.getA(),weights_array #將矩陣轉(zhuǎn)換為數(shù)組,并返回
#改進(jìn)之后的
def stocGradAscent(dataMatrix, classLabels, numIter=150):
m,n = np.shape(dataMatrix) #返回dataMatrix的大小。m為行數(shù),n為列數(shù)。
weights = np.ones(n) #參數(shù)初始化
weights_array = np.array([]) #存儲(chǔ)每次更新的回歸系數(shù)
for j in range(numIter):
dataIndex = list(range(m))
for i in range(m):
alpha = 4/(1.0+j+i)+0.01 #降低alpha的大小,每次減小1/(j+i)。
randIndex = int(random.uniform(0,len(dataIndex))) #隨機(jī)選取樣本
h = sigmoid(sum(dataMatrix[randIndex]*weights)) #選擇隨機(jī)選取的一個(gè)樣本,計(jì)算h
error = classLabels[randIndex] - h #計(jì)算誤差
weights = weights + alpha * error * dataMatrix[randIndex] #更新回歸系數(shù)
weights_array = np.append(weights_array,weights,axis=0) #添加回歸系數(shù)到數(shù)組中
del(dataIndex[randIndex]) #刪除已經(jīng)使用的樣本
weights_array = weights_array.reshape(numIter*m,n) #改變維度
return weights,weights_array
測(cè)試結(jié)果
讓我們分析一下。我們一共有100個(gè)樣本點(diǎn),改進(jìn)的隨機(jī)梯度上升算法迭代次數(shù)為150。而上圖顯示次迭代次數(shù)的原因是,使用一次樣本就更新一下回歸系數(shù)。因此,迭代150次,相當(dāng)于更新回歸系數(shù)150*100=次。簡(jiǎn)而言之,迭代150次,更新1.5萬(wàn)次回歸參數(shù)。從上圖左側(cè)的改進(jìn)隨機(jī)梯度上升算法回歸效果中可以看出,其實(shí)在更新2000次回歸系數(shù)的時(shí)候,已經(jīng)收斂了。相當(dāng)于遍歷整個(gè)數(shù)據(jù)集20次的時(shí)候,回歸系數(shù)已收斂。訓(xùn)練已完成。
上圖右側(cè)的梯度上升算法回歸效果,梯度上升算法每次更新回歸系數(shù)都要遍歷整個(gè)數(shù)據(jù)集。從圖中可以看出,當(dāng)?shù)螖?shù)為300多次的時(shí)候,回歸系數(shù)才收斂。湊個(gè)整,就當(dāng)它在遍歷整個(gè)數(shù)據(jù)集300次的時(shí)候已經(jīng)收斂好了。
def classifyVector(inX, weights):
prob = sigmoid(sum(inX*weights))
if prob > 0.5: return 1.0
else: return 0.0
def colicSklearn():
frTrain = open('horseColicTraining.txt') #打開(kāi)訓(xùn)練集
frTest = open('horseColicTest.txt') #打開(kāi)測(cè)試集
trainingSet = []; trainingLabels = []
testSet = []; testLabels = []
for line in frTrain.readlines():#取出訓(xùn)練集中的每一行的所有數(shù)據(jù)
currLine = line.strip().split('\t')#每一行里數(shù)據(jù)的劃分以空格劃分
lineArr = []
for i in range(len(currLine)-1):#遍歷每一行的每個(gè)元素
lineArr.append(float(currLine[i]))#lineArr里存放的就是每一行中所有的數(shù)據(jù)
trainingSet.append(lineArr)#將每一行的數(shù)據(jù)存放在訓(xùn)練集中
trainingLabels.append(float(currLine[-1]))#拿到每一行的最后一列也即數(shù)據(jù)類(lèi)別
for line in frTest.readlines():#取出測(cè)試集中每一行的所有數(shù)據(jù)
currLine = line.strip().split('\t')
lineArr =[]
for i in range(len(currLine)-1):
lineArr.append(float(currLine[i]))
testSet.append(lineArr)
testLabels.append(float(currLine[-1]))
classifier = LogisticRegression(solver='liblinear',max_iter=10).fit(trainingSet, trainingLabels)
test_accurcy = classifier.score(testSet, testLabels) * 100
print('正確率:%f%%' % test_accurcy)
測(cè)試結(jié)果
文章題目:機(jī)器學(xué)習(xí)實(shí)戰(zhàn)-Logistic回歸
URL分享:http://redsoil1982.com.cn/article8/dsogcip.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站建設(shè)、軟件開(kāi)發(fā)、網(wǎng)站維護(hù)、網(wǎng)站導(dǎo)航、品牌網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
網(wǎng)頁(yè)設(shè)計(jì)公司知識(shí)