前幾天剛學完吳恩達老師的機器學習課程,然后嘗試著去完成課后的編程作業,在這里分享一下ex1其中的單變數線性回歸的心得,
這一版是使用的非向量化的方式去編程,
我會把每行代碼的作用給大家解釋清楚,讓大家可以更好地理解整個線性回歸的程序,
大家在運行下面的代碼時候要注意:
①首先pip install 好需要用到的庫和包,
②txt的路徑要寫好,如果不會寫相對路徑的直接復制粘貼絕對路徑也可以,不過要注意//和\的區別,
③請手動在ex1data1.txt的第一行加入features這一個單詞,(這主要是因為我對pandas用的不熟,不會加列名,下一篇向量化的代碼詳解中,就沒有這么蠢啦)
好啦 請閱讀代碼+注釋吧 會讓你對線性回歸有一個新的理解的~
from matplotlib import pyplot as plt
import pandas as pd
import random
import numpy as np
#匯入包 pyplot是用來畫圖的 pandas用來讀取資料處理資料的
# random用來生成亂數 numpy是用來做矩陣運算的
# 這一版代碼中 用的是非向量化的方式 所以匯入了numpy但是沒有用到
#首先我們了解一下步驟:
#step1:假設函式:hx=theta0 + theta1 * x 并初始化theta0與theta1
#step2:cost函式:(hx-y)^2/ 求m項的和 再除以2m m是指資料的條數
#step3:如果cost函式求出來的值 也就是model error模型誤差太大 就進行梯度下降
#step4:梯度下降:theta0=theta0-學習率*導數項
# theta1=theta1-學習率*導數項
# 導數項為 (hx-y)*xi 求m項的和 并除以m m是指資料的條數
# 對于theta0來說 相當于theta0*x0 x0=1 所以導數項就等于
# (hx-y)*x0 ---> (hx-y)*1
# 對于theta1來說 導數項就等于
# (hx-y)*x
#所以梯度下降的公式可以寫成:theta0=theta0-學習率*(hx-y)*1
# theta1=theta1-學習率*(hx-y)*x
#然后重復進行step1 2 3 4 直至收斂
#上面的就是進行線性回歸的基本流程 下面非向量化代碼的詳細解釋
#由于是我第一次寫讀取檔案的代碼 程序很繁瑣 顯得很蠢 在向量化代碼中改的很簡單了
df = pd.read_table("ex1data1.txt")#使用pandas的readtable的方法讀取txt檔案
features = []#創建一個features串列用來存盤資料
#!!!!這里需要注意 因為原始資料中 沒有列名 而且資料之間使用“,”隔開,當時我不知道讀取資料時可以加上列名,所以手動在txt檔案開頭加了一行 features
#在向量化代碼中 讀取資料會變得更簡單
for row in df.itertuples(index=True, name='Pandas'):
features.append(getattr(row, "features")) #遍歷資料的每一行,將列名為features的資料加入features串列中
# print(features)
x1 = []
x2 = []#創建兩個串列用來存盤使用“,”分開的資料 其中x1對應著上面線性回歸流程中的x x2對應著y
for elements in features:
elements = elements.split(",")
# print(elements[0],elements[1])
x1.append(float(elements[0]))
x2.append(float(elements[1]))
#遍歷features中的每個元素 其實每個元素的形式為“x1,x2”如“5.11,65.25”這樣
#使用split按照“,”將每個元素分成兩部分 第一部分存入x1串列 第二部分存入x2串列
plt.scatter(x1, x2)#使用散點圖畫出資料的分布
plt.show()
#到此我們就取出了x1 x2 并把他們存入了不同的串列以備后用 下面就開始線性回歸的步驟啦
#——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
theta0, theta1,= random.randrange(-1, 1), random.randrange(-1, 1)#初始化theta0,theta1,機器學習課程中講的也可以設定為0
x0 = [1 for i in range(97)]#其實上面提取資料只提取了x 對于theta1而言也就是x1 還有真實值y 但 對于theta0來說 雖然式子中只有theta0 其實相當于都乘了一個x0
#只不過x0都是1 所以這里也用了一個串列來表示x0
modelError = 0#設定模型誤差 以備后用 其實就是(hx-y)^2 后面會回圈m次 累加
learningRate = 0.001#設定學習率
sumModelError = 1000#設定總的模型誤差 也就是代價 是上面累加完的modelError 然后再除以2m
lastSumModelError=10000#設定上一次的模型誤差 可能你不懂這是用來干什么的 后面會詳細解釋的 先跳過這個變數也可以
derivative0=0 #設定theta0的導數項為0 用于后面進行累加
derivative1=0 #設定theta1的導數項為0 用于后面進行累加
#上面我設定了很多變數為0 用于累加 如果沒有編程經驗的可能不懂 就像求和需要設定一個sum=0 然后sum+=i一樣 這是一種很小白的做法 可是對于第一次寫線性回歸我只會這么做了 哈哈
sumModelError_arr=[]#設定總的模型誤差 也就是總的代價 總的損失(如果只聽了機器學習這一門課可能不知道什么是損失,再繼續聽吳恩達的深度學習就懂啦)用于存入迭代程序中的代價,用于以后畫圖
derivative0_arr=[]#設定theta0的導數項的陣列用于存入迭代程序中的導數項,用于以后畫圖
derivative1_arr=[]#設定theta1的導數項的陣列用于存入迭代程序中的導數項,用于以后畫圖
minus=1#這是設定的一個變數用來判斷迭代到底該什么時候停止 minus=上一次的總的代價-這一次的總的代價
for j in range(0,10000000):#先設定一個很大很大的迭代次數 這里設定了10000000
if minus>0.0001:#這個判斷的意思是 如果上一次的總的代價-這一次的總的代價 >0.0001 就繼續迭代 如果小于等于 就說明已經收斂了 就不停止迭代了
for i in range(0, len(x0)):#回圈m次 m是資料條數 相當于每次都按順序取不同的資料 第一條 第二條
derivative0 += ((theta0 * x0[i] + theta1 * x1[i]) - x2[i]) * x0[i]#theta0的導數項 還記得我們上面流程中的公式么?
# 對于theta0來說 相當于theta0*x0 x0=1 所以導數項就等于
# (hx-y)*x0 ---> (hx-y)*1
derivative1 += ((theta0 * x0[i] + theta1 * x1[i]) - x2[i]) * x1[i]#theta1的導數項
# 對于theta1來說 導數項就等于
# (hx-y)*x
modelError += ((theta0 * x0[i] + theta1 * x1[i]) - x2[i]) *((theta0 * x0[i] + theta1 * x1[i]) - x2[i])
#每一項的誤差 代價 損失 這三種叫法都可以 然后累加
#(hx-y)^2/ 求m項的和
derivative0 = derivative0 / len(x0)#導數項還需除以m
# print(j, i, derivative0)
derivative1 = derivative1 / len(x0)#導數項還需除以m
# print(j, i, derivative1)
#導數項為 (hx-y)*xi 求m項的和 并除以m m是指資料的條數
temp0 = theta0 - learningRate * derivative0#計算新的theta0
# print("derivative1", derivative1)
temp1 = theta1 - learningRate * derivative1#計算新的theta1
#梯度下降:theta0 = theta0 - 學習率 * 導數項
# theta1=theta1-學習率*導數項
#之所以使用temp0 temp1是因為需要同步更新 我記得當時寫的時候是按照吳恩達課程上給的偽代碼寫的 現在回過頭寫注釋 感覺直接賦值給theta0 theta1好像也可以
theta0 = temp0
theta1 = temp1
# print(theta0,theta1)
sumModelError = modelError / (2 * len(x0))#計算總的代價 就多了一個除以2m
sumModelError1=lastSumModelError
minus = sumModelError1 - sumModelError
lastSumModelError=sumModelError
modelError=0# 上面四行代碼都是為了計算上一次的代價-下一次的代價所做的準備 主要是邏輯關系有點難想明白 你按照上面四行去賦值 自己思考一下順序就懂啦
# print("derivative0",derivative0,"derivative1",derivative1)
# print("sumModelError",sumModelError)
sumModelError_arr.append(sumModelError)#把這一次的總代價加入到串列中
derivative0_arr.append(derivative0)#把這一次theta0的導數項加入到串列中
derivative1_arr.append(derivative1)#把這一次theta1的導數項加入到串列中
#print(minus)
#看到這里 你已經完成了一次回圈程序啦 如果到這里minus(我們上面用四行代碼設定的)還滿足>0.0001這個要求的話 就會一直回圈迭代下去
#如果不滿足 就會跳到下面的else中 break 停止回圈啦
else:
break
plt.plot(sumModelError_arr,color="blue")
plt.show()#畫圖 畫的圖就是總的損失 或者說 總的代價隨迭代次數的變化 最后會看到會收斂到一個值 然后線性回歸就大功告成啦
#這是我的第一次寫關于機器學習的文章 有什么不足請評論區留言啦 代碼很繁瑣 在下一篇 單變數線性回歸(向量化)的代碼中會很變得很簡潔的啦
下一篇文章應該是吳恩達 機器學習 ex1 單變數線性回歸代碼詳解(向量化寫法)超級適合小白看
如果以你覺得我寫的文章幫助了你 請多多關注和評論區留言喲
你的支持是我寫文章的動力!
以后還會陸續更新其他有關機器學習和深度學習的文章,超級詳細的喲!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/234253.html
標籤:python
