天天看點

原創:機器學習代碼練習(一、回歸)

吳恩達老師在coursea上的機器學習課程的作業是OCTAVE(matlab)做的,當時python還不怎麼流行,現在吳恩達老師也用python了,我把原課程作業用python重新寫了一遍,并放在我的github上。(黃海廣)

本文是第一部分,回歸作業的重構。

機器學習練習 1 - 回歸

單變量線性回歸

代碼修改并注釋:黃海廣

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt      
path = 'data/ex1data1.txt'#這裡讀取原始作業的資料
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])
data.head()      

資料長這樣:

原創:機器學習代碼練習(一、回歸)

看下資料長什麼樣子:

data.plot(kind='scatter', x='Population', y='Profit', figsize=(8,6))
plt.show()      
原創:機器學習代碼練習(一、回歸)

現在讓我們使用梯度下降來實作線性回歸,以最小化成本函數。

首先,我們将建立一個代價函數:

原創:機器學習代碼練習(一、回歸)

其中:

def computeCost(X, y, theta):
    inner = np.power(((X * theta.T) - y), 2)# (m,n) @ (n, 1) -> (n, 1)
# return np.sum(inner) / (2 * len(X))
    return np.sum(inner) / (2 * X.shape[0])      

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

data.insert(0, 'Ones', 1)
data.head()      
原創:機器學習代碼練習(一、回歸)
# set X (training data) and y (target variable)
cols = data.shape[1]
X = data.iloc[:,:cols-1]#X是所有行,去掉最後一列
y = data.iloc[:,cols-1:]#X是所有行,最後一列      

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

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

看下次元:

X.shape, theta.shape, y.shape      

輸出:

((97, 2), (1, 2), (97, 1))      

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

computeCost(X, y, theta)      
32.072733877455676      

batch gradient decent(批量梯度下降)

原創:機器學習代碼練習(一、回歸)
def gradientDescent(X, y, theta, alpha, iters):
    temp = np.matrix(np.zeros(theta.shape))
    parameters = int(theta.ravel().shape[1])
    cost = np.zeros(iters)
    
    for i in range(iters):
        error = (X * theta.T) - y
        for j in range(parameters):
            term = np.multiply(error, X[:,j])
            temp[0,j] = theta[0,j] - ((alpha / len(X)) * np.sum(term))
        theta = temp
        cost[i] = computeCost(X, y, theta)
    return theta, cost      

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

alpha = 0.01
iters = 1000      

現在讓我們運作梯度下降算法來将我們的參數theta合于訓練集。

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

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

computeCost(X, y, g)      
4.515955503078912      

現在我們來繪制線性模型以及資料,直覺地看出它的拟合。

x = np.linspace(data.Population.min(), data.Population.max(), 100)
#np.linspace在指定的間隔内傳回均勻間隔的數字。
f = g[0, 0] + (g[0, 1] * x)
fig, ax = plt.subplots(figsize=(10,6))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Traning Data')
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()      
原創:機器學習代碼練習(一、回歸)

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

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()      
原創:機器學習代碼練習(一、回歸)

多變量線性回歸

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

path = 'data/ex1data2.txt'
data2 = pd.read_csv(path, header=None, names=['Size', 'Bedrooms', 'Price'])
data2.head()      
原創:機器學習代碼練習(一、回歸)

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

data2 = (data2 - data2.mean()) / data2.std()
data2.head()      
原創:機器學習代碼練習(一、回歸)

現在我們重複第1部分的預處理步驟,并對新資料集運作線性回歸程式。

# 添加一列
data2.insert(0, 'Ones', 1)

# 設定X和y
cols = data2.shape[1]
X2 = data2.iloc[:,0:cols-1]
y2 = data2.iloc[:,cols-1:cols]

# 轉為矩陣并且初始化theta
X2 = np.matrix(X2.values)
y2 = np.matrix(y2.values)
theta2 = np.matrix(np.array([0,0,0]))

g2, cost2 = gradientDescent(X2, y2, theta2, alpha, iters)
# 得到模型誤差
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()      
原創:機器學習代碼練習(一、回歸)

normal equation(正規方程)

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

 。 假設我們的訓練集特征矩陣為 X(包含了

)并且我們的訓練集結果為向量 y,則利用正規方程解出向量 

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

,則:

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

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

正規方程:不需要選擇學習率 α,一次計算得出,需要計算

,如果特征數量 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.89578088],
        [ 1.19303364]])      

備注:

代碼和資料都在:

​​https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/tree/master/code/ex1-linear%20regression​​

參考:

​​https://www.coursera.org/course/ml​​

原創:機器學習代碼練習(一、回歸)

關于本站

繼續閱讀