1. 線性模型
給定 \(d\) 個屬性描述的示例 \(\boldsymbol{x} = (x_1; x_2; ...; x_d)\),其中 \(x_i\) 為 \(\boldsymbol{x}\) 在第 \(i\) 個屬性上的取值,線性模型(linear model)試圖學得一個通過屬性的線性組合來進行預測的函數,即:
使用向量形式為:
其中 \(\boldsymbol{w} = (w_1;w_2;...;w_d)\),表達了各屬性在預測中的重要性。
2. 線性回歸
給定數據集 \(D = \lbrace(\boldsymbol{x}_1,{y}_1), (\boldsymbol{x}_2,{y}_2), ..., (\boldsymbol{x}_m,{y}_m)\rbrace\),其中 \(\boldsymbol{x}_i = (x_{i1}; x_{i2}; ...; x_{id})\),\(y_i \in \mathbb{R}\)。線性回歸(linear regression)試圖學得一個能盡可能准確地預測真實輸出標記的線性模型,即:
2.1 一元線性回歸
先只考慮輸入屬性只有一個的情況,\(D = \lbrace({x}_1,{y}_1), ({x}_2,{y}_2), ..., ({x}_m,{y}_m)\rbrace\),\(x_i \in \mathbb{R}\)。對離散屬性,若屬性值存在序(order)關系,可通過連續化將其轉化為連續值。
如”高度“屬性的取值“高”、“中”、“低”,可轉化為\(\{1.0, 0.5, 0.0\}\)。
若不存在序關系,則假定有 \(k\) 種可能的屬性值,將其轉化為 \(k\) 維向量。
如“瓜類”屬性的取值有“冬瓜”、“西瓜”、“南瓜”,可轉化為 \((0,0,1),(0,1,0),(1,0,0)\)。
線性回歸試圖學得:
為使 \(f(x_i)\simeq y_i\),即:使 \(f(x)\) 與 \(y\) 之間的差別最小化。
考慮回歸問題的常用性能度量——均方誤差(亦稱平方損失(square loss)),即讓均方誤差最小化:
\(w^*,b^*\) 表示 \(w\) 和 \(b\) 的解。
均方誤差對應了歐幾里得距離,簡稱歐氏距離(Euclidean distance)。
基於均方誤差最小化來進行模型求解的方法稱為最小二乘法(least square method)。在線性回歸中,就是試圖找到一條直線,使得所有樣本到直線上的歐氏距離之和最小。
下面需要求解 \(w\) 和 \(b\) 使得 \(E_{(w,b)} = \sum\limits_{i=1}^m(y_i-wx_i-b)^2\) 最小化,該求解過程稱為線性回歸模型的最小二乘參數估計(parameter estimation)。
\(E_{(w,b)}\) 為關於 \(w\) 和 \(b\) 的凸函數,當它關於 \(w\) 和 \(b\) 的導數均為 \(0\) 時,得到 \(w\) 和 \(b\) 的最優解。將 \(E_{(w,b)}\) 分別對 \(w\) 和 \(b\) 求導數得:
令式子 (2.4) 和 (2.5) 為 \(0\) 得到 \(w\) 和 \(b\) 的最優解的閉式(closed-form)解:
其中 \(\overline{x} = \frac{1}{m}\sum\limits_{i=1}^m x_i\) 為 \(x\) 的均值。
其他解法:
\[方差\ var(x) = \frac{\sum\limits_{i=1}^m(x_i-\bar{x})^2}{m-1} \]\[協方差\ cov(x,y) = \frac{\sum_\limits{i=1}^m (x_i-\overline{x})(y_i-\overline{y})}{n-1} \]\[w = \frac{cov(x,y)}{var(x)} = \frac{\sum_\limits{i=1}^m (x_i-\overline{x})(y_i-\overline{y})}{\sum\limits_{i=1}^m (x_i-\overline{x})^2} \]\[b = \bar{y} - w\bar{x} \]
3. 一元線性回歸的Python實現
現有如下訓練數據,我們希望通過分析披薩的直徑與價格的線性關系,來預測任一直徑的披薩的價格。
其中 Diameter
為披薩直徑,單位為“英寸”;Price
為披薩價格,單位為“美元”。
3.1 使用 stikit-learn
3.1.1 導入必要模塊
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
3.1.2 使用 Pandas 加載數據
pizza = pd.read_csv("pizza.csv", index_col='Id')
pizza.head() # 查看數據集的前5行
3.1.3 快速查看數據
我們可以使用 matplotlib 畫出數據的散點圖,x 軸表示披薩直徑,y 軸表示披薩價格。
def runplt():
plt.figure()
plt.title("Pizza price plotted against diameter")
plt.xlabel('Diameter')
plt.ylabel('Price')
plt.grid(True)
plt.xlim(0, 25)
plt.ylim(0, 25)
return plt
dia = pizza.loc[:,'Diameter'].values
price = pizza.loc[:,'Price'].values
print(dia)
print(price)
plt = runplt()
plt.plot(dia, price, 'k.')
plt.show()
[ 6 8 10 14 18]
[ 7. 9. 13. 17.5 18. ]
3.1.4 使用 stlearn 創建模型
model = LinearRegression() # 創建模型
X = dia.reshape((-1,1))
y = price
model.fit(X, y) # 擬合
X2 = [[0], [25]] # 取兩個預測值
y2 = model.predict(X2) # 進行預測
print(y2) # 查看預測值
plt = runplt()
plt.plot(dia, price, 'k.')
plt.plot(X2, y2, 'g-') # 畫出擬合曲線
plt.show()
[ 1.96551724 26.37284483]
這里 fit()
方法學得了一元線性回歸模型 \(f(x) = wx+b\),這里 \(x\) 指披薩的直徑,\(f(x)\) 為預測的披薩的價格。
fit()
的第一個參數 X 為 shape(樣本個數,屬性個數) 的數組或矩陣類型的參數,代表輸入空間;
第二個參數 y 為 shape(樣本個數,) 的數組類型的參數,代表輸出空間。
3.1.5 模型評估
成本函數(cost function)也叫損失函數(lost function),用來定義模型與觀測值的誤差。
模型預測的價格和訓練集數據的差異稱為訓練誤差(training error)也稱殘差(residuals)。
plt = runplt()
plt.plot(dia, price, 'k.')
plt.plot(X2, y2, 'g-')
# 畫出殘差
yr = model.predict(X)
for index, x in enumerate(X):
plt.plot([x, x], [y[index], yr[index]], 'r-')
plt.show()
根據最小二乘法,要得到更高的性能,就是讓均方誤差最小化,而均方誤差就是殘差平方和的平均值。
print("均方誤差為: %.2f" % np.mean((model.predict(X)-y) ** 2))
均方誤差為: 1.75
3.2 手動實現
3.2.1 計算 w 和 b
\(w\) 和 \(b\) 的最優解的閉式(closed-form)解為:
其中 \(\overline{x} = \frac{1}{m}\sum\limits_{i=1}^m x_i\) 為 \(x\) 的均值。
或
下面使用 Python 計算 \(w\) 和 \(b\) 的值:
# 法一:
# w = np.sum(price * (dia - np.mean(dia))) / (np.sum(dia**2) - (1/dia.size) * (np.sum(dia))**2)
# b = (1 / dia.size) * np.sum(price - w * dia)
#法二:
variance = np.var(dia, ddof=1) # 計算方差,doff為貝塞爾(無偏估計)校正系數
covariance = np.cov(dia, price)[0][1] # 計算協方差
w = covariance / variance
b = np.mean(price) - w * np.mean(dia)
print("w = %f\nb = %f" % (w, b))
y_pred = w * dia + b
plt = runplt()
plt.plot(dia, price, 'k.') # 樣本點
plt.plot(dia, y_pred, 'b-') # 手動求出的線性回歸模型
plt.plot(X2, y2, 'g-.') # 使用LinearRegression.fit()求出的模型
plt.show()
w = 0.976293
b = 1.965517
可以看到兩條直線重合,我們求出的回歸模型與使用庫求出的回歸模型相同。
3.2.2 功能封裝
將上述代碼封裝成類:
class LinearRegression:
"""
擬合一元線性回歸模型
Parameters
----------
x : shape 為(樣本個數,)的 numpy.array
只有一個屬性的數據集
y : shape 為(樣本個數,)的 numpy.array
標記空間
Returns
-------
self : 返回 self 的實例.
"""
def __init__(self):
self.w = None
self.b = None
def fit(self, x, y):
variance = np.var(x, ddof=1) # 計算方差,doff為貝塞爾(無偏估計)校正系數
covariance = np.cov(x, y)[0][1] # 計算協方差
self.w = covariance / variance
self.b = np.mean(y) - w * np.mean(x)
# self.w = np.sum(y * (x - np.mean(x))) / (np.sum(x**2) - (1/x.size) * (np.sum(x))**2)
# self.b = (1 / x.size) * np.sum(y - self.w * x)
return self
def predict(self, x):
"""
使用該線性模型進行預測
Parameters
----------
x : 數值 或 shape 為(樣本個數,)的 numpy.array
屬性值
Returns
-------
C : 返回預測值
"""
return self.w * x + self.b
使用:
# 創建並擬合模型
model = LinearRegression()
model.fit(dia, price)
x2 = np.array([0, 25]) # 取兩個預測值
y2 = model.predict(x2) # 進行預測
print(y2) # 查看預測值
runplt()
plt.plot(dia, price, 'b.')
plt.plot(x2, y2, 'y-') # 畫出擬合
plt.show()
[ 1.96551724 26.37284483]
此文原創禁止轉載,轉載文章請聯系博主並注明來源和出處,謝謝!
作者: Raina_RLN https://www.cnblogs.com/raina/