線性回歸,核技巧和線性核
在這篇文章中,我想展示一個(gè)有趣的結(jié)果:線性回歸與無(wú)正則化的線性核ridge回歸是等價(jià)的。
這里實(shí)際上涉及到很多概念和技術(shù),所以我們將逐一介紹,最后用它們來(lái)解釋這個(gè)說(shuō)法。
首先我們回顧經(jīng)典的線性回歸。然后我將解釋什么是核函數(shù)和線性核函數(shù),最后我們將給出上面表述的數(shù)學(xué)證明。
線性回歸
經(jīng)典的-普通最小二乘或OLS-線性回歸是以下問(wèn)題:
Y是一個(gè)長(zhǎng)度為n的向量,由線性模型的目標(biāo)值組成
β是一個(gè)長(zhǎng)度為m的向量:這是模型必須“學(xué)習(xí)”的未知數(shù)
X是形狀為n行m列的數(shù)據(jù)矩陣。我們經(jīng)常說(shuō)我們有n個(gè)向量記錄在m特征空間中
我們的目標(biāo)是找到使平方誤差最小的值
這個(gè)問(wèn)題實(shí)際上有一個(gè)封閉形式的解,被稱(chēng)為普通最小二乘問(wèn)題。解決方案是:
一旦解已知,就可以使用擬合模型計(jì)算新的y值給定新的x值,使用:
讓我們用scikit-learn來(lái)驗(yàn)證我上面的數(shù)學(xué)理論:使用sklearn線性回歸器,以及基于numpy的回歸:
%matplotlib qt
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
np.random.seed(0)
n = 100
X_ = np.random.uniform(3, 10, n).reshape(-1, 1)
beta_0 = 2
beta_1 = 2
true_y = beta_1 * X_ + beta_0
noise = np.random.randn(n, 1) * 0.5 # change the scale to reduce/increase noise
y = true_y + noise
fig, axes = plt.subplots(1, 2, squeeze=False, sharex=True, sharey=True, figsize=(18, 8))
axes[0, 0].plot(X_, y, "o", label="Input data")
axes[0, 0].plot(X_, true_y, '--', label='True linear relation')
axes[0, 0].set_xlim(0, 11)
axes[0, 0].set_ylim(0, 30)
axes[0, 0].legend()
# f_0 is a column of 1s
# f_1 is the column of x1
X = np.c_[np.ones((n, 1)), X_]
beta_OLS_scratch = np.linalg.inv(X.T @ X) @ X.T @ y
lr = LinearRegression(
fit_intercept=False, # do not fit intercept independantly, since we added the 1 column for this purpose
).fit(X, y)
new_X = np.linspace(0, 15, 50).reshape(-1, 1)
new_X = np.c_[np.ones((50, 1)), new_X]
new_y_OLS_scratch = new_X @ beta_OLS_scratch
new_y_lr = lr.predict(new_X)
axes[0, 1].plot(X_, y, 'o', label='Input data')
axes[0, 1].plot(new_X[:, 1], new_y_OLS_scratch, '-o', alpha=0.5, label=r"OLS scratch solution")
axes[0, 1].plot(new_X[:, 1], new_y_lr, '-*', alpha=0.5, label=r"sklearn.lr OLS solution")
axes[0, 1].legend()
fig.tight_layout()
print(beta_OLS_scratch)
print(lr.coef_)
可以看到,2種方法的結(jié)果是相同的
[[2.12458946]
[1.99549536]]
[[2.12458946 1.99549536]]
這兩種方法給出了相同的結(jié)果
核技巧 Kernel-trick
現(xiàn)在讓我們回顧一種稱(chēng)為內(nèi)核技巧的常用技術(shù)。
我們最初的問(wèn)題(可以是任何類(lèi)似分類(lèi)或回歸的問(wèn)題)存在于輸入數(shù)據(jù)矩陣X的空間中,在m個(gè)特征空間中有n個(gè)向量的形狀。有時(shí)在這個(gè)低維空間中,向量不能被分離或分類(lèi),所以我們想要將輸入數(shù)據(jù)轉(zhuǎn)換到高維空間??梢允止ね瓿?,創(chuàng)建新特性。但是隨著特征數(shù)量的增長(zhǎng),數(shù)值計(jì)算也將增加。
核函數(shù)的技巧在于使用設(shè)計(jì)良好的變換函數(shù)——通常是T或——從一個(gè)長(zhǎng)度為m的向量x創(chuàng)建一個(gè)長(zhǎng)度為m的新向量x ',這樣我們的新數(shù)據(jù)具有高維數(shù),并且將計(jì)算負(fù)荷保持在最低限度。
為了達(dá)到這個(gè)目的,函數(shù)必須滿足一些性質(zhì),使得新的高維特征空間中的點(diǎn)積可以寫(xiě)成對(duì)應(yīng)輸入向量的函數(shù)——核函數(shù):
這意味著高維空間中的內(nèi)積可以表示為輸入向量的函數(shù)。也就是說(shuō)我們可以在高維空間中只使用低維向量來(lái)計(jì)算內(nèi)積。這就是核技巧:可以從高維空間的通用性中獲益,而無(wú)需在那里進(jìn)行任何計(jì)算。
唯一的條件是我們只需要在高維空間中做點(diǎn)積。
實(shí)際上有一些強(qiáng)大的數(shù)學(xué)定理描述了產(chǎn)生這樣的變換和/或這樣的核函數(shù)的條件。
以下是一個(gè)核函數(shù)示例:
kernel從m維空間創(chuàng)建m^2維空間的第一個(gè)例子是使用以下代碼:
在核函數(shù)中添加一個(gè)常數(shù)會(huì)增加維數(shù),其中包含縮放輸入特征的新特征:
下面我們要用到的另一個(gè)核函數(shù)是線性核函數(shù):
所以恒等變換等價(jià)于用一個(gè)核函數(shù)來(lái)計(jì)算原始空間的內(nèi)積。
實(shí)際上還有很多其他有用的核,比如徑向核(RBF)核或更一般的多項(xiàng)式核,它們可以創(chuàng)建高維和非線性特征空間。我們這里再簡(jiǎn)單介紹一個(gè)在線性回歸環(huán)境中使用RBF核計(jì)算非線性回歸的例子:
import numpy as np
from sklearn.kernel_ridge import KernelRidge
import matplotlib.pyplot as plt
np.random.seed(0)
X = np.sort(5 * np.random.rand(80, 1), axis=0)
y = np.sin(X).ravel()
y[::5] += 3 * (0.5 - np.random.rand(16))
# Create a test dataset
X_test = np.arange(0, 5, 0.01)[:, np.newaxis]
# Fit the KernelRidge model with an RBF kernel
kr = KernelRidge(
kernel='rbf', # use RBF kernel
alpha=1, # regularization
gamma=1, # scale for rbf
)
kr.fit(X, y)
y_rbf = kr.predict(X_test)
# Plot the results
fig, ax = plt.subplots()
ax.scatter(X, y, color='darkorange', label='Data')
ax.plot(X_test, y_rbf, color='navy', lw=2, label='RBF Kernel Ridge Regression')
ax.set_title('Kernel Ridge Regression with RBF Kernel')
ax.legend()
線性回歸中的線性核
如果變換將x變換為(x)那么我們可以寫(xiě)出一個(gè)新的線性回歸問(wèn)題
注意維度是如何變化的:線性回歸問(wèn)題的輸入矩陣從[nxm]變?yōu)閇nxm '],因此系數(shù)向量從長(zhǎng)度m變?yōu)閙 '。
這就是核函數(shù)的訣竅:當(dāng)計(jì)算解'時(shí),注意到X '與其轉(zhuǎn)置的乘積出現(xiàn)了,它實(shí)際上是所有點(diǎn)積的矩陣,它被稱(chēng)為核矩陣
線性核化和線性回歸
最后,讓我們看看這個(gè)陳述:在線性回歸中使用線性核是無(wú)用的,因?yàn)樗韧跇?biāo)準(zhǔn)線性回歸。
線性核通常用于支持向量機(jī)的上下文中,但我想知道它在線性回歸中的表現(xiàn)。
為了證明這兩種方法是等價(jià)的,我們必須證明:
使用beta的第一種方法是原始線性回歸,使用beta '的第二種方法是使用線性核化方法。我們可以用上面的矩陣性質(zhì)和關(guān)系來(lái)證明這一點(diǎn):
我們可以使用python和scikit learn再次驗(yàn)證這一點(diǎn):
%matplotlib qt
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
np.random.seed(0)
n = 100
X_ = np.random.uniform(3, 10, n).reshape(-1, 1)
beta_0 = 2
beta_1 = 2
true_y = beta_1 * X_ + beta_0
noise = np.random.randn(n, 1) * 0.5 # change the scale to reduce/increase noise
y = true_y + noise
fig, axes = plt.subplots(1, 2, squeeze=False, sharex=True, sharey=True, figsize=(18, 8))
axes[0, 0].plot(X_, y, "o", label="Input data")
axes[0, 0].plot(X_, true_y, '--', label='True linear relation')
axes[0, 0].set_xlim(0, 11)
axes[0, 0].set_ylim(0, 30)
axes[0, 0].legend()
# f_0 is a column of 1s
# f_1 is the column of x1
X = np.c_[np.ones((n, 1)), X_]
beta_OLS_scratch = np.linalg.inv(X.T @ X) @ X.T @ y
lr = LinearRegression(
fit_intercept=False, # do not fit intercept independantly, since we added the 1 column for this purpose
).fit(X, y)
new_X = np.linspace(0, 15, 50).reshape(-1, 1)
new_X = np.c_[np.ones((50, 1)), new_X]
new_y_OLS_scratch = new_X @ beta_OLS_scratch
new_y_lr = lr.predict(new_X)
axes[0, 1].plot(X_, y, 'o', label='Input data')
axes[0, 1].plot(new_X[:, 1], new_y_OLS_scratch, '-o', alpha=0.5, label=r"OLS scratch solution")
axes[0, 1].plot(new_X[:, 1], new_y_lr, '-*', alpha=0.5, label=r"sklearn.lr OLS solution")
axes[0, 1].legend()
fig.tight_layout()
print(beta_OLS_scratch)
print(lr.coef_)
總結(jié)
在這篇文章中,我們回顧了簡(jiǎn)單線性回歸,包括問(wèn)題的矩陣公式及其解決方案。
然后我們介紹了了核技巧,以及它如何允許我們從高維空間中獲益,并且不需要將低維數(shù)據(jù)實(shí)際移動(dòng)到這個(gè)計(jì)算密集型空間。
最后,我證明了線性回歸背景下的線性核實(shí)際上是無(wú)用的,它對(duì)應(yīng)于簡(jiǎn)單的線性回歸。