深度之眼_Week2 編程作業1_梯度下降

機器學習作業 1 - 線性迴歸

1.單變量線性迴歸

導入需要使用的包

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

導入數據集。提醒大家:一定要把數據文件ex1data1.txt放在和程序同一個文件夾裏,否則需要使用絕對路徑訪問文件
將csv文件讀入並轉化爲數據框形式,路徑,指定哪一行作爲表頭。默認設置爲0(即第一行作爲表頭),如果沒有表頭的話,要修改參數,設置header=None,
指定列的名稱,用列表表示。一般我們沒有表頭,即header=None時,這個用來添加列名
在默認情況下,head命令顯示文件的頭5行內容

path =  'ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])
data.head()  #預覽數據
Population Profit
0 6.1101 17.5920
1 5.5277 9.1302
2 8.5186 13.6620
3 7.0032 11.8540
4 5.8598 6.8233

對於數值數據,結果的索引將包括計數,平均值,標準差,最小值,最大值以及較低的百分位數和50。默認情況下,較低的百分位數爲25,較高的百分位數爲75.50百分位數與中位數相同。

data.describe()
Population Profit
count 97.000000 97.000000
mean 8.159800 5.839135
std 3.869884 5.510262
min 5.026900 -2.680700
25% 5.707700 1.986900
50% 6.589400 4.562300
75% 8.578100 7.046700
max 22.203000 24.147000

數據可視化,繪製散點圖 kind: 取值爲 line 或者 scatter, 後者爲默認值 圖像大小

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

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-YA2zXIlR-1579357526501)(output_9_0.png)]

現在讓我們使用梯度下降來實現線性迴歸,以最小化成本函數。 以下代碼示例中實現的方程在“練習”文件夾中的“ex1.pdf”中有詳細說明。

首先,我們將創建一個以參數θ爲特徵函數的代價函數
J(θ)=12mi=1m(hθ(x(i))y(i))2J\left( \theta \right)=\frac{1}{2m}\sum\limits_{i=1}^{m}{{{\left( {{h}_{\theta }}\left( {{x}^{(i)}} \right)-{{y}^{(i)}} \right)}^{2}}}
其中:\[{{h}{\theta }}\left( x \right)={{\theta }^{T}}X={{\theta }{0}}{{x}{0}}+{{\theta }{1}}{{x}{1}}+{{\theta }{2}}{{x}{2}}+…+{{\theta }{n}}{{x}_{n}}\]

np.power(x1,x2)數組的元素分別求n次方。x2可以是數字,也可以是數組,但是x1和x2的列數要相同

def computeCost(X, y, theta):
    # your code here  (appro ~ 2 lines)
    inner = np.power(((X*theta.T)-y),2)
    return np.sum(inner)/(2*len(X))

讓我們在訓練集中添加一列,以便我們可以使用向量化的解決方案來計算代價和梯度。在訓練集的左側插入一列全爲“1”的列,以便計算即x0=1
loc爲0,name爲ones,value爲1.

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

現在我們來做一些變量初始化。.shape[0] 爲第一維的長度,shape[1] 爲第二維的長度理解列.pandas中利用.iloc選取數據iloc’,’ 前的部分標明選取的行,‘,’後的部分標明選取的列 此時三列了

# set X (training data) and y (target variable)
cols = data.shape[1]
X = data.iloc[:,0:cols-1]#X是所有行,去掉最後一列
y = data.iloc[:,cols-1:cols]

觀察下 X (訓練集) and y (目標變量)是否正確.

X.head()#head()默認是觀察前5行
Ones Population
0 1 6.1101
1 1 5.5277
2 1 8.5186
3 1 7.0032
4 1 5.8598
y.head()
Profit
0 17.5920
1 9.1302
2 13.6620
3 11.8540
4 6.8233

代價函數是應該是numpy矩陣,所以我們需要轉換X和Y,然後才能使用它們。 我們還需要初始化theta,即把theta所有元素都設置爲0.

X = np.matrix(X.values)
y = np.matrix(y.values)
# your code here  (appro ~ 1 lines)
theta = np.matrix(np.array([0,0]))

theta 是一個(1,2)矩陣

theta
matrix([[0, 0]])

看下維度

X.shape, theta.shape, y.shape
((97, 2), (1, 2), (97, 1))

計算代價函數 (theta初始值爲0).

computeCost(X, y, theta)
32.072733877455676

2.batch gradient decent(批量梯度下降)

θj:=θjαθjJ(θ){{\theta }_{j}}:={{\theta }_{j}}-\alpha \frac{\partial }{\partial {{\theta }_{j}}}J\left( \theta \right)

def gradientDescent(X, y, theta, alpha, iters):
    temp = np.matrix(np.zeros(theta.shape)) #構建零值矩陣
    parameters = int(theta.ravel().shape[1])# ravel計算需要求解的參數個數 功能將多維數組降至一維
    cost = np.zeros(iters) #構建iters個0的數組
    
    for i in range(iters):
        # your code here  (appro ~ 1 lines)
        error = (X * theta.T) - y
        for j in range(parameters):
            # your code here  (appro ~ 2 lines)
            term = np.multiply(error, X[:,j])#計算兩矩陣(hθ(x)-y)x
            temp[0,j] = theta[0,j] - ((alpha / len(X)) * np.sum(term))
            
        # your code here  (appro ~ 2 lines)    
        theta = temp
        cost[i] = computeCost(X, y, theta)
        
    return theta, cost

初始化一些附加變量 - 學習速率α和要執行的迭代次數。

alpha = 0.01
iters = 1000

現在讓我們運行梯度下降算法來將我們的參數θ適合於訓練集。

g, cost = gradientDescent(X, y, theta, alpha, iters)
g
matrix([[-3.24140214,  1.1272942 ]])

最後,我們可以使用我們擬合的參數計算訓練模型的代價函數(誤差)。

computeCost(X, y, g)
4.515955503078912

現在我們來繪製線性模型以及數據,直觀地看出它的擬合。fig代表整個圖像,ax代表實例

x = np.linspace(data.Population.min(), data.Population.max(), 100)#抽100個樣本
f = g[0, 0] + (g[0, 1] * x)#g[0,0] 代表theta0 , g[0,1] 代表theta1


fig, ax = plt.subplots(figsize=(12,8))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Traning Data')
ax.legend(loc=4)#顯示標籤位置
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wXgnzmMI-1579357526503)(output_38_0.png)]

由於梯度方程式函數也在每個訓練迭代中輸出一個代價的向量,所以我們也可以繪製。 請注意,代價總是降低 - 這是凸優化問題的一個例子。

fig, ax = plt.subplots(figsize=(12,8))
ax.plot(np.arange(iters), cost, 'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-oKcqswrI-1579357526504)(output_40_0.png)]

3.多變量線性迴歸

練習1還包括一個房屋價格數據集,其中有2個變量(房子的大小,臥室的數量)和目標(房子的價格)。 我們使用我們已經應用的技術來分析數據集。

path =  'ex1data2.txt'
data2 = pd.read_csv(path, header=None, names=['Size', 'Bedrooms', 'Price'])
data2.head()
Size Bedrooms Price
0 2104 3 399900
1 1600 3 329900
2 2400 3 369000
3 1416 2 232000
4 3000 4 539900

對於此任務,我們添加了另一個預處理步驟 - 特徵歸一化。 這個對於pandas來說很簡單

如果這個房子價格不歸一化,它的數量級和你輸入值規一化數量級差別太大,幾十萬的數量級和個位小數做迴歸,就不能保證收斂了
預測的y和實際上y幾十萬差的太多了

data2 = (data2 - data2.mean()) / data2.std()
data2.head()
Size Bedrooms Price
0 0.130010 -0.223675 0.475747
1 -0.504190 -0.223675 -0.084074
2 0.502476 -0.223675 0.228626
3 -0.735723 -1.537767 -0.867025
4 1.257476 1.090417 1.595389

現在我們重複第1部分的預處理步驟,並對新數據集運行線性迴歸程序。

# add ones column
data2.insert(0, 'Ones', 1)

# set X (training data) and y (target variable)
cols = data2.shape[1]
X2 = data2.iloc[:,0:cols-1]
y2 = data2.iloc[:,cols-1:cols]

# convert to matrices and initialize theta
X2 = np.matrix(X2.values)
y2 = np.matrix(y2.values)
theta2 = np.matrix(np.array([0,0,0]))

# perform linear regression on the data set
g2, cost2 = gradientDescent(X2, y2, theta2, alpha, iters)

# get the cost (error) of the model
computeCost(X2, y2, g2)
0.13070336960771892

我們也可以快速查看這一個的訓練進程。

fig, ax = plt.subplots(figsize=(12,8))
ax.plot(np.arange(iters), cost2, 'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zJSZCw0W-1579357526506)(output_49_0.png)]

4. normal equation(正規方程)(選做)

正規方程是通過求解下面的方程來找出使得代價函數最小的參數的:θjJ(θj)=0\frac{\partial }{\partial {{\theta }_{j}}}J\left( {{\theta }_{j}} \right)=0
假設我們的訓練集特徵矩陣爲 X(包含了x0=1{{x}_{0}}=1)並且我們的訓練集結果爲向量 y,則利用正規方程解出向量 θ=(XTX)1XTy\theta ={{\left( {{X}^{T}}X \right)}^{-1}}{{X}^{T}}y
上標T代表矩陣轉置,上標-1 代表矩陣的逆。設矩陣A=XTXA={{X}^{T}}X,則:(XTX)1=A1{{\left( {{X}^{T}}X \right)}^{-1}}={{A}^{-1}}

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

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

正規方程:不需要選擇學習率α,一次計算得出,需要計算(XTX)1{{\left( {{X}^{T}}X \right)}^{-1}},如果特徵數量n較大則運算代價大,因爲矩陣逆的計算時間複雜度爲O(n3)O(n3),通常來說當nn小於10000 時還是可以接受的,只適用於線性模型,不適合邏輯迴歸模型等其他模型

np.linalg.inv求逆操作 @相當於dot() ,dot函數可以通過numpy庫調用,也可以由數組實例對象進行調用。a.dot(b) 與 np.dot(a,b)效果相同。

# 正規方程
def normalEqn(X, y):
    # your code here  (appro ~ 1 lines)
    theta = np.linalg.inv(X.T@X)@X.T@y
    return theta
final_theta2=normalEqn(X, y)#感覺和批量梯度下降的theta的值有點差距
final_theta2
matrix([[-3.89578088],
        [ 1.19303364]])
#梯度下降得到的結果是matrix([[-3.24140214,  1.1272942 ]])

在練習2中,我們將看看分類問題的邏輯迴歸。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章