原文鏈接:https://blog.csdn.net/Cowry5/article/details/80174130
吳恩達機器學(xué)習(xí)系列作業(yè)目錄
單變量線性回歸
在本部分的練習(xí)中叉弦,您將使用一個變量實現(xiàn)線性回歸竹观,以預(yù)測食品卡車的利潤舆蝴。假設(shè)你是一家餐館的首席執(zhí)行官缀雳,正在考慮不同的城市開設(shè)一個新的分店。該連鎖店已經(jīng)在各個城市擁有卡車恤浪,而且你有來自城市的利潤和人口數(shù)據(jù)畅哑。
您希望使用這些數(shù)據(jù)來幫助您選擇將哪個城市擴展到下一個城市。
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
導(dǎo)入數(shù)據(jù)水由,并查看
path = 'ex1data1.txt'
# names添加列名荠呐,header用指定的行來作為標(biāo)題,若原無標(biāo)題且指定標(biāo)題則設(shè)為None
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])
data.head()
data.describe()
在開始任何任務(wù)之前砂客,通過可視化來理解數(shù)據(jù)通常是有用的泥张。
對于這個數(shù)據(jù)集,您可以使用散點圖來可視化數(shù)據(jù)鞠值,因為它只有兩個屬性(利潤和人口)媚创。
(你在現(xiàn)實生活中遇到的許多其他問題都是多維度的,不能在二維圖上畫出來彤恶。)
data.plot(kind='scatter', x='Population', y='Profit', figsize=(8,5))
plt.show()
現(xiàn)在讓我們使用梯度下降來實現(xiàn)線性回歸钞钙,以最小化成本函數(shù)。 以下代碼示例中實現(xiàn)的方程在“練習(xí)”文件夾中的“ex1.pdf”中有詳細說明声离。
首先芒炼,我們將創(chuàng)建一個以參數(shù)θ為特征函數(shù)的代價函數(shù)
<nobr aria-hidden="true">J(θ)=12m∑mi=1(hθ(x(i))?y(i))2</nobr>
</article>
J(θ)=2m1?i=1∑m?(hθ?(x(i))?y(i))2
其中:<nobr aria-hidden="true">hθ(x)=θTX=θ0x0+θ1x1+θ2x2+...+θnxn</nobr>
hθ?(x)=θTX=θ0?x0?+θ1?x1?+θ2?x2?+...+θn?xn?
計算代價函數(shù) <nobr aria-hidden="true">J(θ)</nobr>
J(θ)
def computeCost(X, y, theta):
inner = np.power(((X * theta.T) - y), 2)
return np.sum(inner) / (2 * len(X))
讓我們在訓(xùn)練集中添加一列,以便我們可以使用向量化的解決方案來計算代價和梯度术徊。
data.insert(0, 'Ones', 1)
現(xiàn)在我們來做一些變量初始化本刽。
取最后一列為 y,其余為 X
# set X (training data) and y (target variable)
cols = data.shape[1] # 列數(shù)
X = data.iloc[:,0:cols-1] # 取前cols-1列赠涮,即輸入向量
y = data.iloc[:,cols-1:cols] # 取最后一列子寓,即目標(biāo)向量
觀察下 X (訓(xùn)練集) and y (目標(biāo)變量)是否正確.
X.head() # head()是觀察前5行
y.head()
注意:這里我使用的是matix而不是array,兩者基本通用笋除。
但是matrix的優(yōu)勢就是相對簡單的運算符號斜友,比如兩個矩陣相乘,就是用符號*垃它,但是array相乘不能這么用蝙寨,得用方法.dot()
array的優(yōu)勢就是不僅僅表示二維,還能表示3嗤瞎、4、5…維听系,而且在大部分Python程序里贝奇,array也是更常用的。
兩者區(qū)別:
- 對應(yīng)元素相乘:matrix可以用np.multiply(X2,X1)靠胜,array直接X1*X2
- 點乘:matrix直接X1*X2掉瞳,array可以 X1@X2 或 X1.dot(X2) 或 np.dot(X1, X2)
代價函數(shù)是應(yīng)該是numpy矩陣毕源,所以我們需要轉(zhuǎn)換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))
計算初始代價函數(shù)的值 (theta初始值為0).
computeCost(X, y, theta) # 32.072733877455676
batch gradient decent(批量梯度下降)
<nobr aria-hidden="true">J(θ)=12m∑i=1m(hθ(x(i))?y(i))2</nobr>
J(θ)=2m1?∑i=1m(hθ(x(i))?y(i))2
其中:
<nobr aria-hidden="true">hθ(x)=θTX=θ0x0+θ1x1+θ2x2+...+θnxn</nobr>
hθ?(x)=θTX=θ0?x0?+θ1?x1?+θ2?x2?+...+θn?xn?
優(yōu)化:
<nobr aria-hidden="true">θj:=θj?α??θjJ(θ)</nobr>
θj?:=θj??α?θj???J(θ)
<nobr aria-hidden="true">θj:=θj?α1m∑mi=1(hθ(x(i))?y(i))x(i)j</nobr>
θj?:=θj??αm1?i=1∑m?(hθ?(x(i))?y(i))xj(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]) # 參數(shù) θ的數(shù)量
cost = np.zeros(epoch) # 初始化一個ndarray冻璃,包含每次epoch的cost
m = X.shape[0] # 樣本數(shù)量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
初始化一些附加變量 - 學(xué)習(xí)速率α和要執(zhí)行的迭代次數(shù)。
alpha = 0.01
epoch = 1000
現(xiàn)在讓我們運行梯度下降算法來將我們的參數(shù)θ適合于訓(xùn)練集损合。
final_theta, cost = gradientDescent(X, y, theta, alpha, epoch)
最后省艳,我們可以使用我們擬合的參數(shù)計算訓(xùn)練模型的代價函數(shù)(誤差)。
computeCost(X, y, final_theta)
現(xiàn)在我們來繪制線性模型以及數(shù)據(jù)嫁审,直觀地看出它的擬合跋炕。
np.linspace()在指定的間隔內(nèi)返回均勻間隔的數(shù)字。
x = np.linspace(data.Population.min(), data.Population.max(), 100) # 橫坐標(biāo)
f = final_theta[0, 0] + (final_theta[0, 1] * x) # 縱坐標(biāo)律适,利潤
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()
由于梯度方程式函數(shù)也在每個訓(xùn)練迭代中輸出一個代價的向量辐烂,所以我們也可以繪制。 請注意捂贿,線性回歸中的代價函數(shù)總是降低的 - 這是凸優(yōu)化問題的一個例子纠修。
fig, ax = plt.subplots(figsize=(8,4))
ax.plot(np.arange(epoch), cost, 'r') # np.arange()返回等差數(shù)組
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()
多變量線性回歸
練習(xí)1還包括一個房屋價格數(shù)據(jù)集,其中有2個變量(房子的大小眷蜓,臥室的數(shù)量)和目標(biāo)(房子的價格)分瘾。 我們使用我們已經(jīng)應(yīng)用的技術(shù)來分析數(shù)據(jù)集。
path = 'ex1data2.txt'
data2 = pd.read_csv(path, names=['Size', 'Bedrooms', 'Price'])
data2.head()
對于此任務(wù)吁系,我們添加了另一個預(yù)處理步驟 - 特征歸一化德召。 這個對于pandas來說很簡單
data2 = (data2 - data2.mean()) / data2.std()
data2.head()
現(xiàn)在我們重復(fù)第1部分的預(yù)處理步驟,并對新數(shù)據(jù)集運行線性回歸程序汽纤。
# 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
我們也可以快速查看這一個的訓(xùn)練進程上岗。
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()
我們也可以使用scikit-learn的線性回歸函數(shù),而不是從頭開始實現(xiàn)這些算法蕴坪。 我們將scikit-learn的線性回歸算法應(yīng)用于第1部分的數(shù)據(jù)肴掷,并看看它的表現(xiàn)。
from sklearn import linear_model
model = linear_model.LinearRegression()
model.fit(X, y)
scikit-learn model的預(yù)測表現(xiàn)
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.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()
normal equation(正規(guī)方程)
正規(guī)方程是通過求解下面的方程來找出使得代價函數(shù)最小的參數(shù)的:<nobr aria-hidden="true">??θjJ(θj)=0</nobr>
?θj???J(θj?)=0 背传。
假設(shè)我們的訓(xùn)練集特征矩陣為 X(包含了<nobr aria-hidden="true">x0=1</nobr>x0?=1)并且我們的訓(xùn)練集結(jié)果為向量 y呆瞻,則利用正規(guī)方程解出向量 <nobr aria-hidden="true">θ=(XTX)?1XTy</nobr>θ=(XTX)?1XTy 。
上標(biāo)T代表矩陣轉(zhuǎn)置径玖,上標(biāo)-1 代表矩陣的逆痴脾。設(shè)矩陣<nobr aria-hidden="true">A=XTX</nobr>A=XTX,則:<nobr aria-hidden="true">(XTX)?1=A?1</nobr>
(XTX)?1=A?1
梯度下降與正規(guī)方程的比較:
梯度下降:需要選擇學(xué)習(xí)率α梳星,需要多次迭代赞赖,當(dāng)特征數(shù)量n大時也能較好適用滚朵,適用于各種類型的模型
正規(guī)方程:不需要選擇學(xué)習(xí)率α,一次計算得出前域,需要計算<nobr aria-hidden="true">(XTX)?1</nobr>
(XTX)?1辕近,如果特征數(shù)量n較大則運算代價大,因為矩陣逆的計算時間復(fù)雜度為<nobr aria-hidden="true">O(n3)</nobr>O(n3)匿垄,通常來說當(dāng)<nobr aria-hidden="true">n</nobr>
n小于10000 時還是可以接受的移宅,只適用于線性模型,不適合邏輯回歸模型等其他模型
# 正規(guī)方程
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
#梯度下降得到的結(jié)果是matrix([[-3.24140214, 1.1272942 ]])
在練習(xí)2中年堆,我們將看看分類問題的邏輯回歸吞杭。