機器學習作業---線性回歸


補充:特征歸一化,意義、方法、使用場景

一:單變量線性回歸

(一)導入需要使用的包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

(二)導入數據集

注意:一定要將數據文件放在和程序同一個文件夾中,否則要使用絕對路徑訪問文件。

將csv文件讀入並轉化為數據框DataFrame形式,需要知道路徑,指定哪一行作為表頭,默認為0,即甚至第一行作為表頭,若沒有表頭,則設置參數header=None,並主動指定列的名稱,用列表表示,來添加列名。

6.1101,17.592
5.5277,9.1302
8.5186,13.662
7.0032,11.854
5.8598,6.8233
8.3829,11.886
7.4764,4.3483
8.5781,12
6.4862,6.5987
5.0546,3.8166
5.7107,3.2522
14.164,15.505
5.734,3.1551
8.4084,7.2258
5.6407,0.71618
5.3794,3.5129
6.3654,5.3048
5.1301,0.56077
6.4296,3.6518
7.0708,5.3893
6.1891,3.1386
20.27,21.767
5.4901,4.263
6.3261,5.1875
5.5649,3.0825
18.945,22.638
12.828,13.501
10.957,7.0467
13.176,14.692
22.203,24.147
5.2524,-1.22
6.5894,5.9966
9.2482,12.134
5.8918,1.8495
8.2111,6.5426
7.9334,4.5623
8.0959,4.1164
5.6063,3.3928
12.836,10.117
6.3534,5.4974
5.4069,0.55657
6.8825,3.9115
11.708,5.3854
5.7737,2.4406
7.8247,6.7318
7.0931,1.0463
5.0702,5.1337
5.8014,1.844
11.7,8.0043
5.5416,1.0179
7.5402,6.7504
5.3077,1.8396
7.4239,4.2885
7.6031,4.9981
6.3328,1.4233
6.3589,-1.4211
6.2742,2.4756
5.6397,4.6042
9.3102,3.9624
9.4536,5.4141
8.8254,5.1694
5.1793,-0.74279
21.279,17.929
14.908,12.054
18.959,17.054
7.2182,4.8852
8.2951,5.7442
10.236,7.7754
5.4994,1.0173
20.341,20.992
10.136,6.6799
7.3345,4.0259
6.0062,1.2784
7.2259,3.3411
5.0269,-2.6807
6.5479,0.29678
7.5386,3.8845
5.0365,5.7014
10.274,6.7526
5.1077,2.0576
5.7292,0.47953
5.1884,0.20421
6.3557,0.67861
9.7687,7.5435
6.5159,5.3436
8.5172,4.2415
9.1802,6.7981
6.002,0.92695
5.5204,0.152
5.0594,2.8214
5.7077,1.8451
7.6366,4.2959
5.8707,7.2029
5.3054,1.9869
8.2934,0.14454
13.394,9.0551
5.4369,0.61705
ex1data1.txt
path = 'ex1data1.txt'
data = pd.read_csv(path,header=None,names=['Population','Profit'])
data.head() #數據預覽

data.describe()  #查看數據描述,包括計數,平均值,標准差,最大最小值,分位數...

(三)數據可視化 

data.plot(kind='scatter',x='Population',y="Profit",figsize=(12,8))
plt.show()

由圖可知,數據集存在一定的線性關系。

(四)創建代價函數

首先,我們將創建一個以參數θ為特征函數的代價函數

def computeCost(X,y,theta): #輸入X是列向量,y也是列向量,theta是行向量 inner = np.power(((X*theta.T)-y),2) #X乘以theta的轉置就是假設函數   return np.sum(inner)/(2*len(X)) #求得代價函數

舉例:

補充:numpy中關於*和dot的區別

對於上面的X*theta.T,我們使用了“*”運算符,進行了矩陣乘法操作。但是我們如果將*當作矩陣乘法,那么我們必須保證兩邊操作數類型是matrix矩陣類型。另外dot也可以實現矩陣乘法,但是它要求傳參是ndarray類型,並且兩個數組保持第一個矩陣列數等於第二個矩陣行數。

舉例:

X_3 = np.array([[1,2],[3,4],[5,6]])
tt = np.array([[2,3]])

print(X_3.dot(tt.T))
print(np.matrix(X_3)*np.matrix(tt).T)

 

(五)雖說我們是單變量線性回歸,但是我們還是存在一個x_0,全為1,使得我們存在一個常數θ_0

因此,我們需要在訓練集中添加一列x_0,以便我們可以使用向量化的解決方案來計算代價和梯度。在訓練集左側插入一列全為1的列,以便計算。

即設置x_0=1,loc=0,name=ones,values=1.

data.insert(0,'Ones',1)

(六)進行變量初始化

cols = data.shape[1]    #獲取列數   shape[0]是行數
X = data.iloc[:,0:cols-1]   #獲取數據集
y = data.iloc[:,cols-1:cols]    #獲取標簽值---目標變量

觀察X訓練集和y目標變量是否正確:

         原始數據data:             X數據集:    y目標變量:

                  

(七)代價函數中傳參X,y應該是numpy矩陣,才可以直接計算

由(六)中獲取的數據類型是DataFrame類型,因此,我們需要進行類型轉換。同時還需要初始化theta,即把theta所有元素都設置為0

X = np.matrix(X.values)
y = np.matrix(y.values)
theta = np.matrix(np.array([0,0]))  #theta是一個(1,2)矩陣

代價函數測試:

computeCost(X,y,theta)

(八)批量梯度下降

當x_0=1時,兩個式子可以合並

def gradientDescennt(X,y,theta,alpha,iters): #iters是迭代次數 alpha是步長 temp = np.matrix(np.zeros(theta.shape)) #構建零值矩陣,暫存theta parameters = int(theta.ravel().shape[1]) #ravel計算需要求解的參數個數 功能將多維數組降至一維 cost = np.zeros(iters) #構建iters個0的數組 for i in range(iters): #進行迭代 error = (X*theta.T)-y #獲取差值 for j in range(parameters): #更新theta_j term = np.multiply(error,X[:,j]) #乘以x_i 因為x_0等於1,所以這個式包含theta_0,theta_1 temp[0,j] = theta[0,j] - (alpha/len(X))*np.sum(term) #更新theta_j theta = temp #更新全部theta值 cost[i] = computeCost(X,y,theta) #更新代價值 return theta, cost

這里設置:步長alpha = 0.01  迭代次數iters = 1000

g,cost = gradientDescennt(X,y,theta,alpha,iters)    #獲取迭代后的theta值,和代價最小值

print(g,cost[-1])  #cost[-1]就是我們最后的最小代價值

(九)可以用我們擬合過的theta值---g,計算訓練模型的代價參數(可以省略)

computeCost(X,y,g)

(十)繪制線性模型以及數據,觀察擬合程度

#進行繪圖
x = np.linspace(data.Population.min(),data.Population.max(),100)    #抽取100個樣本
f = g[0,0]+(g[0,1]*x)   #線性函數,利用x抽取的等距樣本繪制線性直線

fig, ax = plt.subplots(figsize=(12,8))    #返回圖表以及圖表相關的區域,為空代表繪制區域為111--->一行一列圖表,選中第一個
ax.plot(x,f,'r',label="Prediction") #繪制直線
ax.scatter(data.Population,data.Profit,label='Training Data')    #繪制散點圖
ax.legend(loc=4)    #顯示標簽位置  給圖加上圖例  'lower right'  : 4,
ax.set_xlabel("Population")
ax.set_ylabel("Profit")
ax.set_title("Predicted Profit vs Population Size")
plt.show()

繪制代價圖---代價總是降低的:

fig, ax = plt.subplots()    #返回圖表以及圖表相關的區域,為空代表繪制區域為111--->一行一列圖表,選中第一個
ax.plot(np.arange(iters),cost,'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title("Error vs. Training Epoch")
plt.show()

(十一)全部代碼

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

def computeCost(X,y,theta): #輸入X是列向量,y也是列向量,theta是行向量
    inner = np.power(((X*theta.T)-y),2) #X乘以theta的轉置就是假設函數
    return np.sum(inner)/(2*len(X)) #求得代價函數

def gradientDescennt(X,y,theta,alpha,iters):    #iters是迭代次數
    temp = np.matrix(np.zeros(theta.shape)) #構建零值矩陣,暫存theta
    parameters = int(theta.ravel().shape[1])    #ravel計算需要求解的參數個數   功能將多維數組降至一維
    cost = np.zeros(iters) #構建iters個0的數組

    for i in range(iters):  #進行迭代
        error = (X*theta.T)-y   #獲取差值
        for j in range(parameters): #更新theta_j
            term = np.multiply(error,X[:,j])    #乘以x_i  因為x_0等於1,所以這個式包含theta_0,theta_1
            temp[0,j] = theta[0,j] - (alpha/len(X))*np.sum(term)    #更新theta_j

        theta = temp    #更新全部theta值
        cost[i] = computeCost(X,y,theta)    #更新代價值

    return theta, cost

path = 'E:\Python\MachineLearning\ex1data1.txt'
data = pd.read_csv(path,header=None,names=['Population','Profit'])
data.insert(0,'Ones',1)

cols = data.shape[1]    #獲取列數   shape[0]是行數
X = data.iloc[:,0:cols-1]   #獲取數據集
y = data.iloc[:,cols-1:cols]    #獲取標簽值---目標變量

X = np.matrix(X.values)
y = np.matrix(y.values)
theta = np.matrix(np.array([0,0]))

alpha = 0.01
iters = 1000

g,cost = gradientDescennt(X,y,theta,alpha,iters)    #獲取迭代后的theta值,和代價最小值

#進行繪圖
fig, ax = plt.subplots()    #返回圖表以及圖表相關的區域,為空代表繪制區域為111--->一行一列圖表,選中第一個
ax.plot(np.arange(iters),cost,'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title("Error vs. Training Epoch")
plt.show()
# x = np.linspace(data.Population.min(),data.Population.max(),100)    #抽取100個樣本
# f = g[0,0]+(g[0,1]*x)   #線性函數,利用x抽取的等距樣本繪制線性直線
#
# fig, ax = plt.subplots()    #返回圖表以及圖表相關的區域,為空代表繪制區域為111--->一行一列圖表,選中第一個
# ax.plot(x,f,'r',label="Prediction") #繪制直線
# ax.scatter(data.Population,data.Profit,label='Training Data')    #繪制散點圖
# ax.legend(loc=4)    #顯示標簽位置
# ax.set_xlabel("Population")
# ax.set_ylabel("Profit")
# ax.set_title("Predicted Profit vs Population Size")
# plt.show()

# print(g,cost[-1])
# print(computeCost(X,y,g))
# data.plot(kind='scatter',x='Population',y="Profit",figsize=(12,8))
# plt.show()
View Code

二:多變量線性回歸

該練習包括一個房屋價格數據集,其中包含兩個變量(房屋大小、卧室數量)和目標(房子價格)。

2104,3,399900
1600,3,329900
2400,3,369000
1416,2,232000
3000,4,539900
1985,4,299900
1534,3,314900
1427,3,198999
1380,3,212000
1494,3,242500
1940,4,239999
2000,3,347000
1890,3,329999
4478,5,699900
1268,3,259900
2300,4,449900
1320,2,299900
1236,3,199900
2609,4,499998
3031,4,599000
1767,3,252900
1888,2,255000
1604,3,242900
1962,4,259900
3890,3,573900
1100,3,249900
1458,3,464500
2526,3,469000
2200,3,475000
2637,3,299900
1839,2,349900
1000,1,169900
2040,4,314900
3137,3,579900
1811,4,285900
1437,3,249900
1239,3,229900
2132,4,345000
4215,4,549000
2162,4,287000
1664,2,368500
2238,3,329900
2567,4,314000
1200,3,299000
852,2,179900
1852,4,299900
1203,3,239500
ex1data2.txt

(一)讀取數據

path = 'E:\Python\MachineLearning\ex1data2.txt'
data = pd.read_csv(path,header=None,names=['Size','Bedrooms','Price'])

(二)特征歸一化(新增預處理步驟)

有時不同特征之間數組的絕對值差距比較大。10000+,0.000+導致數值較大的將數值較小的特征掩蓋掉,並且會影響算法收斂的速度。

這里采用標准差標准化: x =(x - u)/σ    u是均值   σ是標准差

data = (data-data.mean())/data.std()

 

(三)其他步驟同一,需要修改維度

def computeCost(X,y,theta): #輸入X是列向量,y也是列向量,theta是行向量
    inner = np.power(((X*theta.T)-y),2) #X乘以theta的轉置就是假設函數
    return np.sum(inner)/(2*len(X)) #求得代價函數

def gradientDescennt(X,y,theta,alpha,iters):    #iters是迭代次數
    temp = np.matrix(np.zeros(theta.shape)) #構建零值矩陣,暫存theta
    parameters = int(theta.ravel().shape[1])    #ravel計算需要求解的參數個數   功能將多維數組降至一維
    cost = np.zeros(iters) #構建iters個0的數組

    for i in range(iters):  #進行迭代
        error = (X*theta.T)-y   #獲取差值
        for j in range(parameters): #更新theta_j
            term = np.multiply(error,X[:,j])    #乘以x_i  因為x_0等於1,所以這個式包含theta_0,theta_1
            temp[0,j] = theta[0,j] - (alpha/len(X))*np.sum(term)    #更新theta_j

        theta = temp    #更新全部theta值
        cost[i] = computeCost(X,y,theta)    #更新代價值

    return theta, cost
代價函數和梯度下降法
data.insert(0,'Ones',1)

cols = data.shape[1]    #獲取列數   shape[0]是行數
X = data.iloc[:,0:cols-1]   #獲取數據集
y = data.iloc[:,cols-1:cols]    #獲取標簽值---目標變量

X = np.matrix(X.values)
y = np.matrix(y.values)
theta = np.matrix(np.array([0,0,0]))

alpha = 0.01
iters = 1000

g,cost = gradientDescennt(X,y,theta,alpha,iters)    #獲取迭代后的theta值,和代價最小值

(四)查看代價函數收斂圖

#進行繪圖
fig, ax = plt.subplots()    #返回圖表以及圖表相關的區域,為空代表繪制區域為111--->一行一列圖表,選中第一個
ax.plot(np.arange(iters),cost,'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title("Error vs. Training Epoch")
plt.show()

多變量也是隨着迭代次數的增加,他的訓練誤差也是逐漸減小。

三:補充正規方程求θ

(一)求解θ

正規方程是通過求解下面的方程來找出使得代價函數最小的參數的:

假設我們的訓練集特征矩陣為 X(包含了x_0=1)並且我們的訓練集結果為向量 y,則利用正規方程解出向量 θ:

上標T代表矩陣轉置,上標-1 代表矩陣的逆。 

(二)梯度下降與正規方程的比較:

梯度下降:

  需要選擇學習率α,需要多次迭代,當特征數量n大時也能較好適用,適用於各種類型的模型

正規方程:

  不需要選擇學習率α,一次計算得出,需要計算,如果特征數量n較大則運算代價大,因為矩陣逆的計算時間復雜度為O(n3),通常來說當n小於10000 時還是可以接受的,只適用於線性模型,不適合邏輯回歸模型等其他模型

# 正規方程
def normalEqn(X, y):
    theta = np.linalg.inv(X.T@X)@X.T@y#X.T@X等價於X.T.dot(X)
    return theta
final_theta2=normalEqn(X, y)#感覺和批量梯度下降的theta的值有點差距
final_theta2

梯度下降得到的結果是matrix([[-3.24140214, 1.1272942 ]])和上面得到的值有出入。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM