機器學習作業 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”中有詳細說明。
首先,我們將創建一個以參數θ爲特徵函數的代價函數
其中:\[{{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(批量梯度下降)
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(正規方程)(選做)
正規方程是通過求解下面的方程來找出使得代價函數最小的參數的: 。
假設我們的訓練集特徵矩陣爲 X(包含了)並且我們的訓練集結果爲向量 y,則利用正規方程解出向量 。
上標T代表矩陣轉置,上標-1 代表矩陣的逆。設矩陣,則:
梯度下降與正規方程的比較:
梯度下降:需要選擇學習率α,需要多次迭代,當特徵數量n大時也能較好適用,適用於各種類型的模型
正規方程:不需要選擇學習率α,一次計算得出,需要計算,如果特徵數量n較大則運算代價大,因爲矩陣逆的計算時間複雜度爲,通常來說當小於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中,我們將看看分類問題的邏輯迴歸。