斯坦福大學機器學習筆記——特徵和多項式迴歸以及正規方程
我們可以舉一個例子來引入多項式迴歸:
比如我們之前遇到的房價問題,對於房價的影響我們假設有兩個特徵,一個是房子的寬度
但是我們可以換一個角度思考,我們完全可以用房子的面積
所以我們在建立模型時,可以對一些特徵進行選擇,選擇特徵的不同所構建的假設不同。
但是我們經常見到的問題,並不是都是能夠線性擬合的,比如下面的資料型別:
顯然上面的資料使用線性擬合,擬合的效果不是特別好,同時若是我們選擇下面形式的擬合方式:
這個形式的擬合方式是二次函式,二次函式擬合上面的資料時,會在對稱軸的右方出現下降的趨勢,所以這種擬合方式也是不合理的,所以我們想到了用到的擬合方式為:
這種假設能夠很好的擬合該資料型別。
對於使用什麼形式的假設比較合適,通常我們需要先觀察資料然後確定準備嘗試怎樣的模型,也就是說模型的確定是由資料來決定的。
上面提到的二次函式和三次函式擬合方式都可以稱為多項式迴歸。
對於多項式的迴歸我們可以將其轉化為線性迴歸的方式進行擬合,若我們另
通過上述方式,我們將多項式迴歸問題轉化為線性問題來求解。
注意:我們採用多項式迴歸時,前面部落格講到的特徵縮放仍然是有必要的。
正規方程:
對於上面的線性迴歸演算法我們都是採用的梯度下降法,使得損失函式最小,而對於線性迴歸演算法還有另外一種使得損失函式最小的方法,那就是正規方程。
正規方程式通過求解下面的方程來找出使得代價函式最小的引數:
假設我們的訓練集特徵矩陣為X(包含
其中,T代表矩陣的轉置,上標-1代表矩陣的逆運算。
舉例來看一下正規方式的使用:
這就是上述每個矩陣的構建方式,然後帶入公式就可以求得待求引數(一般針對矩陣化的程式語言,求逆一般都有現成的函式可以呼叫)。
從求取引數的式子中我們不難發現,當求待求的引數
- 特徵之間不獨立,比如在描述身高時,選取的兩個特徵為米和英尺,因為這兩個之間存在著一種換算關係:1米(m)=3.2808399英尺(ft),所以這兩個特徵不是獨立的,這種情況下,矩陣是不可逆的。
- 當特徵的數量大於訓練集的數量時,正規方程也是不能用的。
當使用正規方程時:
1.首先確定是否有相關的特徵,如果存在相關的特徵,則去除相關特徵;
2.當特徵的數目較多時,可以去除一些不重要的特徵,用少量的特徵表示儘可能多的內容。
下面來比較一下梯度下降法和正規方程的優劣:
梯度下降法的優勢:
1.當特徵的數量比較大時(特徵的數量超過10000),也能夠很好的實現損失函式最小化,同時時間複雜度不是很高;而當特徵的數量比較大時,使用正規方程求解逆運算是非常耗時的,所以此時使用梯度下降法比較合適。
2.梯度下降法適用於所有型別的模型,而正規方程的方法一般只適用於線性模型,不適合邏輯迴歸等其他模型。
正規方程的優勢:
1.當特徵點的數量不是很大時,使用正規方程更加簡答,不需要像梯度下降演算法一樣迭代實現,一次計算就可以得出最優引數。
2.對於梯度演算法來說,效能的好壞還與學習率的設定有關,學習率設定不合適,時間消耗較長,甚至得不到最優解,而正規方程的方法不需要學習率的設定。
基於python的正規方程實現如下所示:
import numpy as np
#從資料集中得到特徵矩陣和標籤向量
def loadDataSet(fileName):
num_fea=len(open(fileName).readline().split(','))-1 #獲得特徵的數量
fr=open(fileName) #開啟檔案
featureArr=[]
labelArr=[]
# 讀取每一行的資料
for line in fr.readlines():
line_fea=[]
line_data=line.strip().split(',') #將每一行的資料按照','分隔開(使用什麼分隔開看資料本身的構成)
line_data.insert(0,'1') #將特徵進行擴充,將特徵矩陣轉化為增廣矩陣的形式
for i in range(num_fea+1):
line_fea.append(float(line_data[i])) #得到每一行的特徵
featureArr.append(line_fea)
labelArr.append(float(line_data[-1])) #得到每一行的標籤
return featureArr,labelArr
def normalEquation(featureArr, labelArr):
featureArr=np.mat(featureArr)
labelArr=np.mat(labelArr).T
xTx = featureArr.T*featureArr
if np.linalg.det(xTx)==0:
print("This matrix is singular, it can't do inverse")
return
ws=(xTx.I)*(featureArr.T*labelArr)
return ws
#主程式
featureArr,labelArr=loadDataSet('ex1data2.txt')
ws=normalEquation(featureArr,labelArr)
print(ws)
matlab實現正規方程的程式碼如下:
clear;
close all;
%% 資料處理和初始化
data = load('ex1data2.txt'); % ex1data.txt中第一列是特徵,第二列是標籤
feature = data(:,1:end-1); % 取出特徵資料
result = data(:,end); % 出標籤資料
[num_sample, num_feature] = size(feature);
feature = [ones(num_sample,1) feature]; % 將特徵進行擴充套件,在原來的基礎上增加一列全為1的矩陣
xTx = feature' * feature;
if det(xTx)==0
sprintf('the matric is a singular, it can not do inverse!')
else
theta = pinv(xTx) * feature' * result;
end
% 測試資料
test_data = [1520 4;5551 3]; %測試資料
[num_test_sample, num_test_feature] = size(test_data); %測試資料的個數
test_data = [ones(num_test_sample,1) test_data]; %測試資料的擴充
test_result = test_data * theta; %測試資料的預測結果
test = feature * theta;
本人菜鳥一枚,有什麼問題歡迎指正。