吳恩達老師在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
關于本站