1 What is Machine-learning?
- Tom Mitchell: 機器學習是指一個程序從經驗E(計算機與自己進行上萬次的對弈)中學習解決某項任務T(玩跳棋),進行某一項性能度量P(贏跳棋的概率),通過P測定在T上的表現因經驗E而提高。
2 Machine learning algorithm:
1、Supervised learning:
定義:
給出一些數據集與正確的答案(‘right answers’ given/Regression/Classification)希望計算機進行預測,並得出“正確答案”。比如:房子的大小與對應的房價,然後讓計算機可以擬合出一條線,得出更多正確的答案
Regression:
Classification:
練習題:
- 問題一:我有大量相同貨物的庫存,想要預測在下面三週會賣出多少件?(連續變量:Regression)
- 問題二:讓計算機去測試一下用戶的賬戶,確定每個賬戶是被攻擊或被破壞了(分類變量:Classification)
2、Unsupervised learning:
定義:
給計算機一組數據,沒有答案,讓計算機幫我們看看這組數據當中有沒有什麼規律或者數據是否存在不同的蔟(下圖爲聚類:Google新聞將費別相同的新聞進行分類)
練習:
答案:2、3
2 迴歸算法:
1、代價函數
我們的目標就是要求得最小的代價函數數!
上面的幾張圖片展示出了代價函數與擬合線準確性的關係,當代價函數越小,也就是越接近中心,那麼擬合線的準確性就會越高。
那麼如何能夠找到最小的代價函數呢?
我們應使得下面的hypothesis函數(下面簡稱h函數)與x所對應的實際值y越接近!
又因爲h函數是由兩個未知參數所控制的,那我們的目標就轉變爲找到最優的這兩個未知參數,使得h函數能夠和y非常的接近。
要實現這個,那就要使用梯度下降算法了!
2、梯度下降算法
Batch-gradient descent:
其中:=符號表示賦值而非等於(也就是說每次都會更新一個值)
首先解釋求求偏導部分:
- 求偏導的目的基本上可以說取這個紅點的切線,就是這樣一條紅色的直線,剛好與函數相切於這一點,讓我們看看這條紅色直線的斜率,就是這條剛好與函數曲線相切的這條直線,這條直線的斜率正好是這個三角形的高度除以這個水平長度,現在,這條線有一個正斜率,也就是說它有正導數,因此,我得到的新的θ_1,θ_1更新後等於θ_1減去一個正數乘以a,也就是說θ_1變小了,j也就會變小,進一步的向j的最小點逼近。
- 同樣的,當我們所求的爲負斜率,我們的θ_1就會變大,也會向j的最小點逼近(可以把這個偏導當作是一個自動的方向盤,它總是確保行駛的方向向j的最小點去逼近)
- 而alpha就是步長,也可以稱作是學習速率,alpha過小會使得車開的很慢,alpha過大會使得車開的太快,可能會跨過那個最小點。
- 觀察下圖,在那個紫色的點初始化,如果我更新一步梯度下降,那麼我可能會到達綠色的點,因爲這個點的導數(斜率)是相當陡的。如果我再更新一步,你會發現我的導數,也是沒那麼陡的,到達下一個紅色的點。隨着我接近最低點,我的導數越來越接近零,所以,梯度下降一步後,新的導數會變小一點點。然後我想再梯度下降一步,在這個綠點,我自然會用一個稍微跟剛纔在那個品紅點時比,再小一點的一步,到了新的紅色點,更接近全局最低點了,因此這點的導數會比在綠點時更小。所以,我再進行一步梯度下降時,我的導數項是更小的,θ_1更新的幅度就會更小。所以隨着梯度下降法的運行,你移動的幅度會自動變得越來越小,直到最終移動幅度非常小,你會發現,已經收斂到局部極小值。
假設我們只有一個特徵變量,那麼此時我們的代價函數的偏導數是這樣的:
可以寫成這樣:
3、多變量梯度下降:
從上面的公式當中我們可以看到,我們由n+1個參數,n個特徵變量。通常爲了簡化,我們會設x0=1,這樣我們就有了n+1個參數和n+1個變量了。
因此我們就可以做向量的乘法了。
4、梯度下降縮放:
當我們的特徵值取值範圍相差比較大的時候,比如我們有兩個特徵,一個是房子的大小,一個是房間數,這時我們會發現我們的這兩個特徵取值範圍是比較大的,在計算代價函數的時候圖像就會像下面那樣,非常的高細,要走很多步纔會到最優點。
通常我們可以採用縮放法:
或是:
5、確定迭代次數
因爲梯度下降算法收斂所需要的迭代次數根據模型的不同而不同,我們無法預知,如果迭代次數太少就難以得到最優的解,如果過多就會造成過多的計算。通常可以通過繪圖來計算。
6、多項式迴歸
有時,我們的一次項模型可能無法非常準確的擬合我們的數據,因此,我們可能會去採用其他多項式來使得模型更合適。
也可以使用:
7、正規方程:
通過下面方程可以計算參數:
注:當正規方程中矩陣出現不可逆時,我們通常採用剔除線性相關的兩個特徵的其中一個;或是使用np.linalg.pinv()
3 實戰:
- 數據:
我們的數據有兩個特徵變量,我們設x爲population,y爲profit
- 觀察數據分佈情況:
import tensorflow as tf
import numpy as np
from matplotlib import pyplot as plt
import pandas as pd
def loadData(file_name):
"""讀取數據
Param:
file_name:文件存放路徑
return dataset_x,dataset_y"""
dataset = pd.read_csv(file_name,names=['population','profit'])
dataset_x = dataset['population']
dataset_y = dataset['profit']
return dataset_x,dataset_y
def Show():
file_name = 'E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex1-linear regression/ex1data1.txt'
dataset_x,dataset_y = loadData(file_name)
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
plt.figure(figsize=(20,10),dpi=70)
plt.scatter(dataset_x,dataset_y,color='orange',s=60)
plt.xlabel('Population',fontsize=12,fontweight='bold')
plt.ylabel('Profit',fontsize=12,fontweight='bold')
plt.title('Data Distribution',fontsize=16,fontweight='bold')
plt.show()
if __name__=='__main__':
Show()
- 定義一個函數,將x,y分佈取出:
def get_x(data):
"""插入一列x0=1,並且輸出narray型的X
Params:
data:讀取的數據
return:
narray型的X"""
data_x = data['population'] #取出x的數據
n = data_x.shape[0] #獲取行數
x0 = pd.DataFrame({'X0':np.ones(n)})
#新建一個DataFrame列表用來concat(注:concat不能用narray直接組合)
X = pd.concat([x0,data_x],axis=1)
return np.array(X)
def get_y(data):
Y = data['profit']
return np.array(Y)
- 計算代價函數:
def j(X,Y,weight):
"""計算代價函數
Params:
X:get_x返回的數據
Y:get_y返回的數據
weight:初始化的未知參數
return:
j_:對應的代價函數"""
m = X.shape[0]
inner = X@weight - Y #@想當與矩陣乘法
square_sum = inner.T @inner #.T相當於轉置
j_ = square_sum/(2*m)
return j_
if __name__=='__main__':
X = get_x(data)
Y = get_y(data)
n = X.shape[1]
weight=np.zeros(n)
j_=j(X,Y,weight)
print(j_)
結果爲:
- 計算梯度下降函數:
def gradDscent(X,Y,weight):
m=X.shape[0]
inner = X.T @(X@weight-Y)
return inner/m
- 批量梯度下降:
def batch_gradient_decent(weight,X,Y,epoch,alpha=0.01):
"""批量梯度下降,獲取最優參數,和代價函數列表來確定合適的迭代次數
Params:
weight:初始化的參數
X:get_x返回的數據
Y:get_y返回的數據
epoch:迭代次數
alpha:步長
return:
j_:存放所有代價函數值的列表
weight_:最優參數"""
j_ = [j(X,Y,weight)] #新建一個列表
m,n = X.shape
weight_ = weight.copy() #複製一個以防混淆
for i in range(epoch): #進入迭代
weight_ = weight_ - alpha*gradDscent(X,Y,weight_)
j_.append(j(X,Y,weight_))
return j_,weight_
結合:
import tensorflow as tf
import numpy as np
from matplotlib import pyplot as plt
import pandas as pd
def get_x(data):
"""插入一列x0=1,並且輸出narray型的X
Params:
data:讀取的數據
return:
narray型的X"""
data_x = data['population'] #取出x的數據
n = data_x.shape[0] #獲取行數
x0 = pd.DataFrame({'X0':np.ones(n)})
#新建一個DataFrame列表用來concat(注:concat不能用narray直接組合)
X = pd.concat([x0,data_x],axis=1)
return np.array(X)
def get_y(data):
Y = data['profit']
return np.array(Y)
def j(X,Y,weight):
"""計算代價函數
Params:
X:get_x返回的數據
Y:get_y返回的數據
weight:初始化的未知參數
return:
j_:對應的代價函數"""
m = X.shape[0]
inner = X@weight - Y #@想當與矩陣乘法
square_sum = inner.T @inner #.T相當於轉置
j_ = square_sum/(2*m)
return j_
def gradDscent(X,Y,weight):
m=X.shape[0]
inner = X.T @(X@weight-Y)
return inner/m
def batch_gradient_decent(weight,X,Y,epoch,alpha=0.01):
"""批量梯度下降,獲取最優參數,和代價函數列表來確定合適的迭代次數
Params:
weight:初始化的參數
X:get_x返回的數據
Y:get_y返回的數據
epoch:迭代次數
alpha:步長
return:
j_:存放所有代價函數值的列表
weight_:最優參數"""
j_ = [j(X,Y,weight)] #新建一個列表
m,n = X.shape
weight_ = weight.copy() #複製一個以防混淆
for i in range(epoch): #進入迭代
weight_ = weight_ - alpha*gradDscent(X,Y,weight_)
j_.append(j(X,Y,weight_))
return j_,weight_
if __name__ == '__main__':
data = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex1-linear regression/ex1data1.txt',names=['population','profit'])
X=get_x(data)
Y=get_x(data)
n = X.shape[1]
weight = np.zeros(n)
j_,weight_=batch_gradient_decent(weight,X,Y,300,alpha=0.01)
Y = np.arange(401)
plt.plot(Y,j_)
plt.show()
- 畫出擬合線:
b = weight_[0]#獲得截距
m = weight_[1]#獲得斜率
y = data.population*m+b
plt.scatter(data.population,data.profit,color = 'red',label='Training data')
plt.plot(data.population,y,color='orange',label='Prediction')
plt.legend(loc=2)
plt.show()