機器學習-線性回歸+回歸算法的評價指標


線性回歸

  • 回歸問題的目標值是連續性的值,而分類問題的目標值是離散型的值。
  • 回歸處理的問題為預測:
    • 預測房價
    • 銷售額的預測
    • 設定貸款額度
    • 總結:上述案例中,可以根據事物的相關特征預測出對應的結果值
  • 線性回歸在生活中的映射(現實生活中就有線性回歸):生活案例【預測學生的期末成績】:
    • 期末成績的制定:0.7*考試成績+0.3平時成績,則該例子中,特征值為考試成績和平時成績,目標值為總成績。從此案例中大概可以感受到
      • 回歸算法預測出來的結果其實就是經過相關的算法計算出來的結果值!
      • 每一個特征需要有一個權重的占比,這個權重的占比明確后,則就可以得到最終的計算結果,也就是獲取了最終預測的結果了。
        • 那么這個特征對應的權重如何獲取或者如何制定呢?
#現在有一組售房的數據
import numpy as np
import pandas
from pandas import DataFrame
import matplotlib.pylab as plt
dic = {
    '面積':[55,76,80,100,120,150],
    '售價':[110,152,160,200,240,300]
}
df = DataFrame(data=dic)
df
  • 需要對售房數據的分布情況進行展示
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['FangSong'] # 指定默認字體
mpl.rcParams['axes.unicode_minus'] = False # 解決保存圖像是負號'-'顯示為方塊的問題

plt.scatter(df['面積'],df['售價'])
plt.xlabel('面積')
plt.ylabel('售價')
plt.title('面積和價錢的分布圖')

問題:假如現在有一套房子,面積為76.8平米,那么這套房子應該賣多少錢呢?也就是如何預測該套房子的價錢呢?

  • 上圖中散點的分布情況就是面積和價錢這兩個值之間的關系,那么如果該關系可以用一個走勢的直線來表示的話,那么是不是就可以通過這條走勢的直線預測出新房子的價格呢?
#忽略代碼只看繪制出的圖
plt.scatter(df['面積'],df['售價'])
plt.xlabel('面積')
plt.ylabel('售價')
plt.title('面積和價錢的分布圖')
plt.scatter(np.linspace(0,180,num=100),np.linspace(0,180,num=100)*2,alpha=0.3)
  • 上圖中發現,該直線是穿過了所有的散點,那么如果已有的散點的分布沒有這么規律的話,這條直線就無法穿過所有散點,怎么辦呢?
    • 先不考慮,我們先來研究目前這種簡單的情況!
 
  • 散點的趨勢:
    • 在上圖中使用了一條直線來表示了房子的價格和面子對應的分布趨勢,那么該趨勢找到后,就可以基於該趨勢根據新房子的面積預測出新房子的價格。
  • 線性回歸的作用:
    • 就是找出特征和目標之間存在的某種趨勢!!!在二維平面中,該種趨勢可以用一條線段來表示。
  • 該趨勢使用什么表示呢?---》線性方程:
    • 在數學中,線性方程y = wx就可以表示一條唯一的直線。那么在上述售房數據中,面積和價格之間的關系(二倍的關系)其實就可以映射成
      • 價格 = 2 * 面積 ==》y=2x,這個方程就是價格和面積的趨勢!也就是說根據該方程就可以進行新房子價格的預測
    • 標准的線性方程式為:y = wx + b,w為斜率,b為截距。那么如果用線性方程表示房價和面積的趨勢的話,這個b是否需要帶上呢?
 

image.png

 
  • 是否帶上b,得具體情況具體分析。y=wx,如果x為0,則y必定為0,那就意味着趨勢對應的直線必過坐標系的原點(0,0),如果帶上b值,則直線不過原點(除非b=0)。如果上有圖的趨勢直線過原點的話,趨勢就會不准。加b的目的是為了使得趨勢對應的直線更加具有通用性!!!(最好加上b 就算過原點也不過就是b=0)  
 
  • 思考:上述的線性方程y=wx+b其中x為特征y為目標,這種方程作為線性關系模型的預測依據的話是否可以滿足所有的預測場景呢?
    • 如果現在房價受影響的因素不光是面積了,加入了采光率和樓層了,那么就意味着特征變成了3種。在原始的線性方程y=wx+b中只可以有一個特征,則該方程不具備通用性。
    • 標准線性關系模型為:
      • 售價 = (w1面積+w2采光率+w3樓層)+ b==》y = (w1x1w2x2+wn*xn)+b
        • w又叫做權重。
        • b可以變換成w0*x0,x0=1
          • y = w0x0+w1x1+w2x2+wnxn
        • 權重向量(行向量):w0,w1,...wn
          • 行向量的轉置就是列向量。行向量是一個 n×1 的矩陣,即矩陣由一個含有n個元素的行所組成。
        • 行向量乘以行向量的轉置為一個常數!!!

 

線性回歸:

  • 找出特征和特征權重之間的一種組合,從而來預測對應的結果!!!
    • 線性方程式:image.png
 

矩陣基礎:是大多數算法的基礎,非常重要

  • 矩陣和數組的區別:
    • 數據可以是任意維度的
    • 矩陣必須是二維的
  • 矩陣滿足了一些特定的需求:
    • 矩陣乘法:(m行,b列)*(b行,n列)==(m行,n列)image.png

 

x = np.array([[1,2],[3,4],[5,6]])
y = np.array([[1,1,1],[2,2,2]])
display(x,y)
np.dot(x,y)

ws = np.array([[2,2,2,2]]) #每個特征的權重
xs = np.array([[55,66,77,88],[35,46,97,118]])#兩組特征
display(ws.T,xs)
np.dot(xs,ws.T)

 

  • 問題:真實結果和預測結果是否會存在誤差?
    • 如果房價預測案例中,特征與目標之間的分布規律不是線性的,那是否還可以使用一條直線表示特征和目標之間的趨勢呢?
      • 可以,只要保證直線距離所有的散點距離最近,則該直線還是可以在一定程度上表示非線性分布散點之間的分布規律。但是該規律會存在誤差!
      • image.png
 

image.png

  • 答:在多數的預測中都會和真實值存在一定的誤差!
 
  • 誤差存在,那我們如何處理誤差呢?在處理誤差之前,我們必須先要知道一個回歸算法的特性:
    • 回歸算法是一個迭代算法。所謂的迭代就好比是系統版本的迭代,迭代后的系統要比迭代前的系統更好。
      • 當開始訓練線性回歸模型的時候,是逐步的將樣本數據帶入模型對其進行訓練的。
      • 訓練開始時先用部分的樣本數據訓練模型生成一組w和b,對應的直線和數據對應散點的誤差比較大,通過不斷的帶入樣本數據訓練模型會逐步的迭代不好(誤差較大)的w和b從而使得w和b的值更加的精准。
    • 官方解釋:迭代是重復反饋過程的活動,其目的通常是為了逼近所需目標或結果。每一次對過程的重復稱為一次“迭代”,而每一次迭代得到的結果會作為下一次迭代的初始值。
 
  • 誤差的處理方法:
    • 通俗點來說,回歸算法就是在不斷的自身迭代的減少誤差來使得回歸算法的預測結果可以越發的逼近真實結果!!!
 
  • 如何不斷迭代的減少誤差呢?
    • 通過【損失函數】來表示誤差image.png
      • yi:為第i個訓練樣本的真實值
      • hw(xi):預測值
        • 誤差的大小和我們線性回歸方程中的哪個系數有直系的關聯呢?
 
  • 損失函數也可以表示為:image.png
 
  • 因此得知誤差的大小線性回歸方程中的系數w是有直系關聯的
    • w(權重)的不同會導致誤差大小的不同
    • 那么最終的問題就轉化成了,【如何去求解方程中的w使得誤差可以最小】
 
  • L0,L1和L2范式:
    • L0是指向量中非0的元素的個數。
    • L1是指向量中各個元素絕對值之和。
    • L2是指向量各元素的平方和然后求平方根
 
  • L2范式:
    • 這個損失函數代表了向量yi-y^i 的L2范式的平方結果,L2范式的本質是就是歐式距離,即是兩個向量上的每個點對應相減后的平方和再開平方,我們現在只實現了向量上每個點對應相減后的平方和,並沒有開方,所以我們的損失函數是L2范式,即歐式距離的平方結果。
 

image.png

 
  • 在這個平方結果下,我們的y和y^分別是我們的真實標簽和預測值,也就是說,這個損失函數實在計算我們的真實標 簽和預測值之間的距離。因此,我們認為這個損失函數衡量了我們構造的模型的預測結果和真實標簽的差異,因此我 們固然希望我們的預測結果和真實值差異越小越好。所以我們的求解目標就可以轉化為:image.png
 
  • SSE&RSS:
    • 其中右下角的2表示向量y-Xw的L2范式,也就是我們的損失函數所代表的含義。在L2范式上開平方,就是我們的損失函數。我們往往稱 呼這個式子為SSE(Sum of Sqaured Error,誤差平方和)或者RSS(Residual Sum of Squares 殘差平方和)。
 
  • 最小二乘法
    • 現在問題轉換成了求解讓RSS 最小化的參數向量w,這種通過最小化真實值和預測值之間的RSS來求解參數的方法叫做最小二乘法。
    • 求解極值(最小值)的第一步往往是求解一階導數並讓一階導數等於0,最小二乘法也不能免俗。因此,我們現在在殘差平方和RSS上對參數向量w求導。
 
  • 首先w表示的是一個列向量(矩陣),我們現在並非是對常數求導,而是對列向量(矩陣)進行求導。矩陣求導的自行掌握即可。
  • 首先將L2范式拆開:image.png
    • 兩個向量(y&Xw)的平方就等於兩個向量的轉置乘以兩個向量本身。
 
  • 處理轉置乘法和減法:image.png
 
  • 然后將上圖的分子進行多項式相乘:image.png
 
  • 然后公式就變相為yTy對w求導,wTXTy對w的求導,yTXw對w的求導,wTXTXw對w的求導。這里的w為列向量(矩陣)則就涉及到對矩陣的求導:
    • 在矩陣求導中如果小a為常數項,A為矩陣則:image.png
      • 由於y是一個列向量,為一階矩陣,那么其本身乘以其轉置為一個常數!
 
  • 分子上的每一項對w進行求導后的結果為:image.png
    • 至此我們就求解出了對w求導的一階導數,接下來讓一階導數為0則就求出了最小誤差下的w的值了。
 

image.png

- -1表示逆矩陣,矩陣*自己的逆矩陣=1
 
  • API
    • 最小二乘(正規方程):from sklearn.linear_model import LinearRegression
 
  • 最小二乘法image.png
  • 這些參數中並沒有一個是必填的,更沒有對我們的模型有不可替代作用的參數。這說明,線性回歸的性能,往往取決於數據本身,而並非是我們的調參能力,線性回歸也因此對數據有着很高的要求。幸運的是,現實中大部分連續型變量之間,都存在着或多或少的線性聯系。所以線性回歸雖然簡單,卻很強大。順便一提,sklearn中的線性回歸可以處理多標簽問題,只需要在fit的時候輸入多維度標簽就可以了。
 
  • normalize參數:如果為True,則會對特征數據進行歸一化處理,如果想對特征數據進行標准化處理則需要在訓練模型前調用相關工具類對其進行標准化處理。
 
  • 使用最小二乘對加利福尼亞房屋進行預測
  • 特征介紹:
    • AveBedrms:該街區平均的卧室數目
    • Population:街區人口
    • AveOccup:平均入住率
    • Latitude:街區的緯度
    • Longitude:街區的經度
    • MedInc:街區住戶收入的中位數
    • HouseAge:房屋使用年數中位數
    • AveRooms:街區平均房屋的數量

 

from sklearn.linear_model import LinearRegression
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split

house = datasets.fetch_california_housing(data_home='./datasets')

#樣本數據提取
feature = house.data
target = house.target

feature.shape
(20640, 8)

#需不需要做特征的預處理
#回歸模型一般情況下不需要做特征的預處理,如果最終模型預測效果不好,可以適當考慮加上預處理

#數據集的切分
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.2,random_state=2020)

linner = LinearRegression(normalize=True,copy_X=False)
linner.fit(x_train,y_train)
LinearRegression(copy_X
=False, normalize=True) #查看特征的權重系數 linner.coef_
array([ 4.40832770e-01,  9.61642244e-03, -1.14781227e-01,  6.75973842e-01,
       -5.10337874e-06, -3.47558983e-03, -4.19478386e-01, -4.32477249e-01])
#截距 linner.intercept_
-36.77944310594463
feature_names = house.feature_names 

#將系數和特征名稱結合在一起查看
[*zip(feature_names,linner.coef_)]
[('MedInc', 0.44083277039517),
 ('HouseAge', 0.009616422444042433),
 ('AveRooms', -0.11478122746959646),
 ('AveBedrms', 0.675973842315124),
 ('Population', -5.1033787396040516e-06),
 ('AveOccup', -0.003475589832444126),
 ('Latitude', -0.4194783856769445),
 ('Longitude', -0.4324772490416929)]

linner.score(x_test,y_test)
0.6077878946185034
 
        

回歸模型的評價指標

  • 回歸類算法的模型評估一直都是回歸算法中的一個難點,回歸類與分類型算法的模型評估其實是相似的法則— —找真實標簽和預測值的差異。只不過在分類型算法中,這個差異只有一種角度來評判,那就是是否預測到了正確的分類,而在我們的回歸類算法中,我們有兩種不同的角度來看待回歸的效果:
    • 第一,我們是否預測到了正確或者接近正確的數值(因為誤差的存在)。
    • 第二,我們是否擬合到了足夠的信息。(是否模型預測的結果線性和樣本真實的結果的線性更加吻合)
      • 這兩種角度,分別對應着不同的模型評估指標。
 

是否預測到了正確的數值

  • 回憶一下我們的RSS殘差平方和,它的本質是我們的預測值與真實值之間的差異,也就是從一種角度來評估我們回歸的效力,所以RSS既是我們的損失函數,也是我們回歸類模型的模型評估指標之一。但是,RSS有着致命的缺點: 它是一個無界的和,可以無限地大或者無限的小。我們只知道,我們想要求解最小的RSS,從RSS的公式來看,它不能為負,所以 RSS越接近0越好,但我們沒有一個概念,究竟多小才算好,多接近0才算好?為了應對這種狀況,sklearn中使用RSS 的變體,均方誤差MSE(mean squared error)來衡量我們的預測值和真實值的差異:image.png
  • 均方誤差,本質是在RSS的基礎上除以了樣本總量,得到了每個樣本量上的平均誤差。有了平均誤差,我們就可以將平均誤差和我們的標簽的取值范圍(最大值和最小值)在一起比較,以此獲得一個較為可靠的評估依據。(查看這個錯誤有多嚴重)。
    • 因為標簽的最大值和最小值可以表示標簽的一個分部情況,那么將其最大值和最小值和平均誤差比較就可以大概看出在每個樣本上的誤差或者錯誤有多嚴重。
 
  • 在sklearn當中,我們有兩種方式調用這個評估指標:
    • 一種是使用sklearn專用的模型評估模塊metrics里的類mean_squared_error
    • 另一種是調用 交叉驗證的類cross_val_score並使用里面的scoring參數來設置為:neg_mean_squared_error使用均方誤差。

 

from sklearn.metrics import mean_squared_error as MSE
#y_true:測試數據的真實標簽
#y_pred:使用模型對測試集的預測結果
y_pred = linner.predict(x_test)
MSE(y_test,y_pred)

0.5313973307052253

y_test.min(),y_test.max()
(0.14999, 5.00001)

交叉驗證求得的均方誤差為負值

  • 均方誤差的計算公式中求得的均方誤差的值不可能為負。但是sklearn中的參數scoring下,均方誤差作為評判 標准時,卻是計算”負均方誤差“(neg_mean_squared_error)。這是因為sklearn在計算模型評估指標的時候,會考 慮指標本身的性質,均方誤差本身是一種誤差,所以被sklearn划分為模型的一種損失(loss)。在sklearn當中,所有 的損失都使用負數表示,因此均方誤差也被顯示為負數了。真正的均方誤差MSE的數值,其實就是neg_mean_squared_error去掉負號的數字。
from sklearn.model_selection import cross_val_score
cross_val_score(linner,x_train,y_train,cv=5,scoring='neg_mean_squared_error').mean()
-0.5309250456411233
  • 絕對值誤差(了解)
    • 除了MSE,我們還有與MSE類似的MAE(Mean absolute error,絕對均值誤差):image.png
    • 其表達的概念與均方誤差完全一致,不過在真實標簽和預測值之間的差異外我們使用的是L1范式(絕對值)。現實使 用中,MSE和MAE選一個來使用就好了。
      • 在sklearn當中,我們使用命令
        • from sklearn.metrics import mean_absolute_error來調用MAE,
      • 同時,我們也可以使用交叉驗證中的
        • scoring = "neg_mean_absolute_error", 以此在交叉驗證時調用MAE。
 

是否擬合了足夠的信息

  • 對於回歸類算法而言,只探索數據預測是否准確是不足夠的。除了數據本身的數值大小之外,我們還希望我們的模型能夠捕捉到數據的”規律“,比如數據的分布規律(拋物線),單調性等等。而是否捕獲到這些信息是無法使用MSE來衡量的。image.png
 
  • 來看這張圖,其中紅色線是我們的真實標簽,而藍色線是我們模型預測的值。這是一種比較極端,但的確可能發生的情況。這張圖像上,前半部分的擬合非常成功,看上去我們的真實標簽和我們的預測結果幾乎重合,但后半部分的擬合 卻非常糟糕,模型向着與真實標簽完全相反的方向去了。對於這樣的一個擬合模型,如果我們使用MSE來對它進行判 斷,它的MSE會很小,因為大部分樣本其實都被完美擬合了,少數樣本的真實值和預測值的巨大差異在被均分到每個 樣本上之后,MSE就會很小。但這樣的擬合結果必然不是一個好結果,因為一旦我的新樣本是處於擬合曲線的后半段的,我的預測結果必然會有巨大的偏差,而這不是我們希望看到的。所以,我們希望找到新的指標,除了判斷預測的 數值是否正確之外,還能夠判斷我們的模型是否擬合了足夠多的,數值之外的信息。
  • 在我們學習降維特征選擇的時候,我們提到我們使用方差來衡量數據上的信息量。如果方差越大,代表數據上的信息量越多,而這個信息量(數據潛在的規律)不僅包括了數值的大小,還包括了我們希望模型捕捉的那些規律。為了衡量模型對數據上的信息量的捕捉,我們定義了R2來幫助我們:image.png
 

image.png

 
  • 分母其實可以表示稱為樣本的潛在規律,分子為模型的誤差(損失),那么樣本數據潛在的規律是不變的,則誤差越小則分子分母表達式返回的結果越小,則r2越接近1.
 
  • 可以使用三種方式來調用
    • 一種是直接從metrics中導入r2_score,輸入預測值和真實值后打分。
    • 第二種是直接從 線性回歸LinearRegression的接口score來進行調用。
    • 第三種是在交叉驗證中,輸入"r2"來調用。

 

from sklearn.metrics import r2_score
r2_score(y_test,y_pred)
0.6077878946185034
  • 繪制擬合圖
%matplotlib inline
import matplotlib.pyplot as plt
y_pred = linner.predict(x_test)
plt.plot(range(len(y_test)),sorted(y_test),c="black",label= "y_true")
plt.plot(range(len(y_pred)),sorted(y_pred),c="red",label = "y_predict")
plt.legend()
plt.show()
  • 可見,雖然我們的大部分數據被擬合得比較好,但是圖像的開頭和結尾處卻又着較大的擬合誤差。如果我們在圖像右側分布着更多的數據,我們的模型就會越來越偏離我們真正的標簽。這種結果類似於我們前面提到的,雖然在有限的數據集上將數值預測正確了,但卻沒有正確擬合數據的分布,如果有更多的數據進入我們的模型,那數據標簽被預測錯誤的可能性是非常大的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM