日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

机器学习入门学习笔记:(2.2)线性回归python程序实现

發布時間:2025/3/21 python 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 机器学习入门学习笔记:(2.2)线性回归python程序实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??上一篇博客中,推導了線性回歸的公式,這次試著編程來實現它。(機器學習入門學習筆記:(2.1)線性回歸理論推導 )
??我們求解線性回歸的思路有兩個:一個是直接套用上一篇博客最后推導出來的公式;另一個是使用梯度下降法來求解極值。如果數據量很大不建議采用第一個,采用后者能更有效地減小計算量。這篇博客后面的程序也采用的是后者。
??事先聲明,這篇博客是我自己的學習筆記,代碼參考了《機器學習實戰》一書,小部分代碼有所修改。代碼以及數據集我打包上傳好了,感興趣的可以下載下來看看:
線性邏輯回歸代碼
(今天才發現csdn下載居然沒有了0分資源,最少都要1分,有點坑啊)

??代碼不難,簡要介紹下,程序中有注釋。
??按照順序將代碼加入logRegres.py。

導入數據集

# 導入數據集 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
  • 創建了列表dataMat和labelMat,分別用于存儲特征變量對應的值和標簽對應的值;
  • 數據集存放在testSet.txt,從中讀取數據;
  • 逐行讀取,遍歷所有行;讀取的每一行做一下分割,每行的最后一個數據是標簽,前面的都是特征向量的數據。將其分開后,分別加入列表dataMat和labelMat中。

激勵函數

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

??我在以前的博客中介紹了激勵函數的概念。(機器學習入門學習筆記:(1)BP神經網絡原理推導及程序實現 )
??如果只考慮兩個類的情況下,我們的結果可以用0或1來表示,這種函數叫做階躍函數。但是由于階躍函數存在一個0到1的跳變的過程,這會導致不可導、不光滑,有時在數學上難以處理。所以我們采用sigmoid函數來代替激勵函數,以便能在數學上更易處理。
??直接給出sigmoid的公式,不做贅述了:
??

梯度上升法

??通常我們更多地接觸到的是梯度下降法,這兩種方法本質都是一樣的。由于梯度是變化最快的方向,梯度下降法就是向最快的方向減小,而梯度上升法就是增大,最后兩者分別收斂于局部最小值和局部最大值。
??什么時候用梯度下降法或者是梯度上升法呢?具體問題具體分析,如果我們用的是一個誤差函數,我們希望這個誤差盡可能小,那么就選擇梯度下降法了,很簡單的邏輯。

# 梯度上升法 def gradAscent(dataMatIn, classLabels):# 轉換為numpy矩陣數據類型dataMatrix = mat(dataMatIn)labelMat = mat(classLabels).transpose()# 預設初始參數m, n = shape(dataMatrix)# 求出矩陣大小alpha = 0.001 # 步長maxCycles = 500 # 迭代500次# 使用梯度上升找到最優值weights = ones((n, 1)) # 權值for k in range(maxCycles):h = sigmoid(dataMatrix*weights)error = labelMat - hweights = weights + alpha * dataMatrix.transpose() * errorreturn weights

??首先,輸入的兩個參數dataMatIn和classLabels默認是列表類型,后面要使用numpy進行矩陣運算,所以調用numpy的mat()函數將其轉換為numpy下的矩陣數據類型;
??然后預設一些相關的參數,步長不宜太大,迭代次數設為500次;
??接著就是迭代了,不斷更新權值,使用如下公式:

??上面這個是梯度上升的公式,如果是梯度下降的公式把加號改成減號就行。
??關于算法推導這里不做贅述,我以前在其他博客中也有有關梯度下降法的介紹。梯度下降法和梯度上升法本質上是一樣的。(四旋翼姿態解算——梯度下降法理論推導 )
??算法不難,也可以自行查閱相關資料。
??只是看公式的話還是有點懵,梯度上升法的偽代碼如下:

初始化權值,使所有回歸系數為1 重復n次(n表示迭代次數): 計算整個數據集的梯度使用alpha(步長)*gradient(梯度)套上面公式更新回歸系數的向量 返回回歸系數

??跟給出的代碼中對一對,就很容易搞懂了。在命令行測試一下看看:

??另外還有一點,我們看看代碼不難發現,可以很輕易地將這段程序改成梯度下降法,也就是將程序中的梯度更新代碼的幾個符號改一下,結果還是一樣的。

畫出邊界

??只是得到了參數還不夠直觀,我們接著使用matplotlib來是數據可視化。

# 畫出數據集和logistic回歸的最佳你和直線的函數 def plotBestFit(weights):import matplotlib.pyplot as pltdataMat, 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()

??調用庫,沒什么好說的。無非就是把點全部畫出來,最后又畫了一條邊界。

??權值返回來是一個numpy的矩陣類型,我們要先調用getA()方法將其轉換為數組類型。


??分類結果挺不錯的,只有很少的點被分錯了。

隨機梯度上升

??前面使用的梯度上升法也叫作批量梯度上升法(batch gradient ascent),它每一次更新回歸系數時都要遍歷整個數據集,如果數據集很大,計算量也會非常大。
那么一個改進方法就是一次僅僅使用一個樣本點來更新回歸系數,這個方法叫隨機梯度上升法。
??隨機梯度上升法的偽代碼:

所有回歸系數初始化為1 遍歷數據中的每個樣本:計算樣本的梯度使用alpha(步長)*gradient(梯度)套上面公式更新回歸系數的向量 返回回歸系數值

??編寫代碼:

# 隨機梯度上升算法 def stocGradAscent(dataMatIn, classLabels):# 轉換為numpy矩陣數據類型dataMatrix = mat(dataMatIn)labelMat = mat(classLabels).transpose()m,n = shape(dataMatrix)alpha = 0.01weights = ones((n, 1))for i in range(m):h = sigmoid(sum(dataMatrix[i] * weights))error = labelMat[i] - hweights = weights + alpha *dataMatrix[i].transpose() * error return weights

??這部分代碼大體上跟前面梯度上升法是一樣的,不做贅述。唯一的區別就是,沒有了迭代次數,這里是遍歷了整個數據集,使用每個樣本來對參數進行更新而不是每個樣本都計算一遍。

??測試一下:


??結果不太好,我們還需要修改程序。

改進算法

# 改進的隨機梯度上升算法 def stocGradAscent_optimized(dataMatIn, classLabels, numIter=150):# 轉換為numpy矩陣數據類型dataMatrix = mat(dataMatIn)labelMat = mat(classLabels).transpose()m, n = shape(dataMatrix)weights = ones((n, 1))for j in range(numIter):dataIndex = range(m)for i in range(n):alpha = 4 / (1.0 + j + i) + 0.01randIndex = int(random.uniform(0, len(dataIndex)))h = sigmoid(sum(dataMatrix[randIndex] * weights))error = classLabels[randIndex] - hweights = weights + alpha * dataMatrix[randIndex].transpose() * errordel(dataIndex[randIndex])return weights
  • 首先,步長alpha不再是一個常數,隨著迭代次數的增大不斷減小。步長alpha的值后面還加了一個0.01,因為不能讓它趨近于0,如果趨近于0了新數據的更新也幾乎沒有作用,乘積都是0。
  • 然后,這里樣本選取不再是按照默認順序選取了。隨機選取數據集進行更新, 反復迭代多次。

試試看結果:


??效果跟批量梯度下降差不多了,但是隨機梯度下降的計算量要少很多。這里使用的默認迭代次數只有150次。

測試算法

從疝氣病癥預測病馬死亡的概率:

分析特征變量

def classifyVector(inX, weights):prob = sigmoid(sum(inX * weights))if prob > 0.5:return 1else:return 0

??以回歸系數和輸入的特征變量計算對應的sigmoid函數的值,如果大于0.5,就預測為1;如果小于0.5, 就預測為0。

測試結果

def colicTest():# 打開測試集和數據集frTrain = open('horseColicTraining.txt')frTest = open('horseColicTest.txt')# 導入訓練集的特征變量和標簽trainingSet = []trainingLabels = []for line in frTrain.readlines():currentLine = line.strip().split('\t')lineArr = []for i in range(21):lineArr.append(float(currentLine[i]))trainingSet.append(lineArr)trainingLabels.append(float(currentLine[21]))# 使用優化過后的隨機梯度上升法計算權重trainWeights = stocGradAscent_optimized(trainingSet, trainingLabels, 1200)# 導入測試集,并檢驗效果errorCount = 0numTestVec = 0for line in frTest.readlines():numTestVec += 1currentLine = line.strip().split('\t')lineArr = []for i in range(21):lineArr.append(float(currentLine[i]))if int(classifyVector(array(lineArr), trainWeights)) != int(currentLine[21]):errorCount += 1errorRate = float(errorCount) / numTestVecprint('The error rate of this test is : %f'%errorRate)return errorRate

??直接調用前面寫好的函數了,不多說了。

??調用colicTest()10次,比較結果:

def multiTest():numTests = 10errorSum = 0for k in range(numTests):errorSum += colicTest()print('After %d iterations the average error rate is: %f'%(numTests, errorSum/float(numTests)))

總結

以上是生活随笔為你收集整理的机器学习入门学习笔记:(2.2)线性回归python程序实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。