1. 程式人生 > >吳恩達機器學習作業Python實現(一):線性迴歸

吳恩達機器學習作業Python實現(一):線性迴歸

單變數線性迴歸

在本部分的練習中,您將使用一個變數實現線性迴歸,以預測食品卡車的利潤。假設你是一家餐館的執行長,正在考慮不同的城市開設一個新的分店。該連鎖店已經在各個城市擁有卡車,而且你有來自城市的利潤和人口資料。
您希望使用這些資料來幫助您選擇將哪個城市擴充套件到下一個城市。

%matplotlib inline

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

匯入資料,並檢視

path =  'ex1data1.txt'
# names新增列名,header用指定的行來作為標題,若原無標題且指定標題則設為None
data = pd.read_csv(path, header=None, names=['Population', 'Profit']) data.head()

image.png

data.describe()

image.png

在開始任何任務之前,通過視覺化來理解資料通常是有用的。
對於這個資料集,您可以使用散點圖來視覺化資料,因為它只有兩個屬性(利潤和人口)。
(你在現實生活中遇到的許多其他問題都是多維度的,不能在二維圖上畫出來。)

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

output_7_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θ(x)=θTX=θ0x0+θ1x1+θ2x2+...+θnxn{{h}_{\theta }}\left( x \right)={{\theta }^{T}}X={{\theta }_{0}}{{x}_{0}}+{{\theta }_{1}}{{x}_{1}}+{{\theta }_{2}}{{x}_{2}}+...+{{\theta }_{n}}{{x}_{n}}

計算代價函式 J(θ)J(\theta)

def computeCost(X, y, theta):
    inner = np.power(((X * theta.T) -  y), 2)
    return np.sum(inner) / (2 * len(X))

讓我們在訓練集中新增一列,以便我們可以使用向量化的解決方案來計算代價和梯度。

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

現在我們來做一些變數初始化。

取最後一列為 y,其餘為 X

# set X (training data) and y (target variable)
cols = data.shape[1]  # 列數
X = data.iloc[:,0:cols-1]  # 取前cols-1列,即輸入向量
y = data.iloc[:,cols-1:cols] # 取最後一列,即目標向量

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

X.head()  # head()是觀察前5行
y.head()

注意:這裡我使用的是matix而不是array,兩者基本通用。

但是matrix的優勢就是相對簡單的運算子號,比如兩個矩陣相乘,就是用符號*,但是array相乘不能這麼用,得用方法.dot()
array的優勢就是不僅僅表示二維,還能表示3、4、5…維,而且在大部分Python程式裡,array也是更常用的。

兩者區別:

  1. 對應元素相乘:matrix可以用np.multiply(X2,X1),array直接X1*X2
  2. 點乘:matrix直接X1*X2,array可以 X1@X2 或 X1.dot(X2) 或 np.dot(X1, X2)

代價函式是應該是numpy矩陣,所以我們需要轉換X和Y,然後才能使用它們。 我們還需要初始化theta。

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

theta 是一個(1,2)矩陣

np.array([[0,0]]).shape 
# (1, 2)

看下維度,確保計算沒問題

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

計算初始代價函式的值 (theta初始值為0).

computeCost(X, y, theta) # 32.072733877455676

##batch gradient decent(批量梯度下降)

J(θ)=12mi=1m(hθ(x(i))y(i))2 J\left( \theta \right)=\frac{1}{2m}\sum\limits{i=1}^{m}{{{\left( {{h}{\theta }}\left( {{x}^{(i)}} \right)-{{y}^{(i)}} \right)}^{2}}}

其中:
hθ(x)=θTX=θ0x0+θ1x1+θ2x2+...+θnxn {{h}_{\theta }}\left( x \right)={{\theta }^{T}}X={{\theta }_{0}}{{x}_{0}}+{{\theta }_{1}}{{x}_{1}}+{{\theta }_{2}}{{x}_{2}}+...+{{\theta }_{n}}{{x}_{n}}
優化:
θj:=θjαθjJ(θ) {{\theta }_{j}}:={{\theta }_{j}}-\alpha \frac{\partial }{\partial {{\theta }_{j}}}J\left( \theta \right)

θj:=θjα1mi=1m(hθ(x(i))y(i))xj(i) \theta_j:=\theta_j-\alpha\frac{1}{m}\sum^{m}_{i=1}(h_\theta(x^{(i)}) - y^{(i)})x_j^{(i)}
使用 vectorization同時更新所有的 θ,可以大大提高效率

X.shape, theta.shape, y.shape, X.shape[0]
# ((97, 2), (1, 2), (97, 1), 97)
def gradientDescent(X, y, theta, alpha, epoch):
    """reuturn theta, cost"""
    
    temp = np.matrix(np.zeros(theta.shape))  # 初始化一個 θ 臨時矩陣(1, 2)
    parameters = int(theta.flatten().shape[1])  # 引數 θ的數量
    cost = np.zeros(epoch)  # 初始化一個ndarray,包含每次epoch的cost
    m = X.shape[0]  # 樣本數量m
    
    for i in range(epoch):
        # 利用向量化一步求解
        temp =theta - (alpha / m) * (X * theta.T - y).T * X
        
# 以下是不用Vectorization求解梯度下降
#         error = (X * theta.T) - y  # (97, 1)
        
#         for j in range(parameters):
#             term = np.multiply(error, X[:,j])  # (97, 1)
#             temp[0,j] = theta[0,j] - ((alpha / m) * np.sum(term))  # (1,1)
            
         theta = temp
         cost[i] = computeCost(X, y, theta)
        
    return theta, cost

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

alpha = 0.01
epoch = 1000

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

final_theta, cost = gradientDescent(X, y, theta, alpha, epoch)

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

computeCost(X, y, final_theta)

現在我們來繪製線性模型以及資料,直觀地看出它的擬合。

np.linspace()在指定的間隔內返回均勻間隔的數字。

x = np.linspace(data.Population.min(), data.Population.max(), 100)  # 橫座標
f = final_theta[0, 0] + (final_theta[0, 1] * x)  # 縱座標,利潤

fig, ax = plt.subplots(figsize=(6,4))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data['Population'], data.Profit, label='Traning Data')
ax.legend(loc=2)  # 2表示在左上角
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()

image.png

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

fig, ax = plt.subplots(figsize=(8,4))
ax.plot(np.arange(epoch), cost, 'r')  # np.arange()返回等差陣列
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()

image.png

##多變數線性迴歸

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

path =  'ex1data2.txt'
data2 = pd.read_csv(path, names=['Size', 'Bedrooms', 'Price'])
data2.head()

image.png

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

data2 = (data2 - data2.mean()) / data2.std()
data2.head()

image.png

現在我們重複第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, epoch)

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

我們也可以快速檢視這一個的訓練程序。

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

image.png

我們也可以使用scikit-learn的線性迴歸函式,而不是從頭開始實現這些演算法。 我們將scikit-learn的線性迴歸演算法應用於第1部分的資料,並看看它的表現。

from sklearn import linear_model
model = linear_model.LinearRegression()
model.fit(X, y)

scikit-learn model的預測表現

x = np.array(X[:, 1].A1)
f = model.predict(X).flatten()

fig, ax = plt.subplots(figsize=(8,5))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.