天天看點

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

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

一:單變量線性回歸

(一)導入需要使用的包

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 ]])和上面得到的值有出入。