[英]Matrix preprocessing for linear regression
目前尚不清楚為什么在使用sklearn.linear_model.LinearRegression
之前必須標准化數據集。 對於我來說,尚不清楚為什么歸一化原始數據仍必須導致正確的結果。 作為測試,我准備了一些數據集:
import numpy as np
import pandas as pd
size = 700
data['x_1'] = x_1
data['x_2'] = x_2
data['y'] = map(lambda i : x_1[i]*7.5 - 2*x_2[i] + noise[i], range(size))
哪里:
noise = np.random.normal(0,1,size)
x_1 = np.random.normal(5,2,size)
x_2 = np.random.normal(2,1,size)
然后,我嘗試使用帶有經過改組和標准化的矩陣的LinearRegression查找系數:
from sklearn.preprocessing import scale
from sklearn.utils import shuffle
df_shuffled = shuffle(data, random_state=123)
X = scale(df_shuffled[df_shuffled.columns[:-1]])
y = df_shuffled["y"]
結果如下:
linear_regressor.fit(X,y)
(14.951827073780766, 'x_1')
(-1.9171042297858722, 'x_2')
之后,我重復了所有不使用scale()函數的步驟,並得到了更好的結果:
(7.5042271168341887, 'x_1')
(-1.9835960918124507, 'x_2')
這是一個例外還是我犯了一些錯誤?
標准化並不是線性回歸的真正要求。 這是一個示例,在該示例中,我將數據拆分為訓練/測試拆分,然后對測試進行預測。
>>> df = pd.DataFrame({'x_1': np.random.normal(0, 1, size), 'x_2': np.random.normal(2, 1, size)})
>>> df['y'] = map(lambda i: df['x_1'][i] * 7.5 - 2 * df['x_2'][i] + np.random.normal(0, 1, size)[i], range(size))
>>> lr = LinearRegression()
>>> X_scaled = scale(df[['x_1', 'x_2']])
>>> X_ns = df[['x_1', 'x_2']]
>>> y = df['y']
>>> train_X_scaled = X_scaled[:-100]
>>> test_X_scaled = X_scaled[-100:]
>>> train_X_ns = X_ns[:-100]
>>> test_X_ns = X_ns[-100:]
>>> train_y = y[:-100]
>>> test_y = y[-100:]
>>> lr.fit(train_X_scaled, train_y)
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
>>> lr.coef_
array([ 7.38189303, -2.04137514])
>>> lr.predict(test_X_scaled)
array([ -5.12130597, -21.58547658, -10.59483732, -10.56241312,
-16.88790301, 0.61347437, -7.28207791, -9.37464865,
-5.12411501, -14.79287322, -9.84583896, 0.61183408,
-9.00695481, -0.42201284, -20.50254306, 0.1984764 ,
-9.57419381, 1.39035118, 9.66405865, -10.18972252,
-8.76733834, -7.33179222, -10.53075411, 0.51671133,
3.65140463, -16.86740729, 7.86837224, 4.61310894,
-3.80289123, -11.92948864, -6.55643999, -10.77231532,
1.97181141, 15.75089958, 2.71987359, -5.49740398,
-6.59654793, -6.39042298, -8.86057313, 12.63031921,
-8.05054779, -11.04476828, -3.70610232, -4.81986166,
-3.09909457, 10.3576317 , -6.48789854, -4.05243726,
-4.11076559, -9.21957658, -4.36368549, 2.13365208,
-19.24153319, 6.52751487, -3.48801127, 2.01989782,
-1.00673834, -10.33590131, -9.25592347, -16.91433355,
3.58685085, -6.30149903, -2.23264539, 6.86114404,
8.33602945, -14.25656579, -22.24380384, -14.50287259,
-6.64710009, -17.40421316, -12.7734427 , -3.76204612,
-0.05843445, -5.0349674 , -6.86404519, -6.8523112 ,
-14.9479788 , 1.6120415 , -6.24457762, -7.11712009,
-5.57018237, -2.89811595, -5.44008672, 8.19302959,
-1.78437334, -19.32108323, 1.00091276, 4.79161569,
1.65685676, -8.68406543, 7.27219645, -2.90941943,
2.4613977 , 2.94533763, -6.35486958, -1.01281799,
2.13959957, -6.73934486, -1.65493937, 13.2605013 ])
>>> lr.fit(train_X_ns, train_y)
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
>>> lr.coef_
array([ 7.52554825, -1.98783572])
>>> lr.predict(test_X_ns)
array([ -5.12130597, -21.58547658, -10.59483732, -10.56241312,
-16.88790301, 0.61347437, -7.28207791, -9.37464865,
-5.12411501, -14.79287322, -9.84583896, 0.61183408,
-9.00695481, -0.42201284, -20.50254306, 0.1984764 ,
-9.57419381, 1.39035118, 9.66405865, -10.18972252,
-8.76733834, -7.33179222, -10.53075411, 0.51671133,
3.65140463, -16.86740729, 7.86837224, 4.61310894,
-3.80289123, -11.92948864, -6.55643999, -10.77231532,
1.97181141, 15.75089958, 2.71987359, -5.49740398,
-6.59654793, -6.39042298, -8.86057313, 12.63031921,
-8.05054779, -11.04476828, -3.70610232, -4.81986166,
-3.09909457, 10.3576317 , -6.48789854, -4.05243726,
-4.11076559, -9.21957658, -4.36368549, 2.13365208,
-19.24153319, 6.52751487, -3.48801127, 2.01989782,
-1.00673834, -10.33590131, -9.25592347, -16.91433355,
3.58685085, -6.30149903, -2.23264539, 6.86114404,
8.33602945, -14.25656579, -22.24380384, -14.50287259,
-6.64710009, -17.40421316, -12.7734427 , -3.76204612,
-0.05843445, -5.0349674 , -6.86404519, -6.8523112 ,
-14.9479788 , 1.6120415 , -6.24457762, -7.11712009,
-5.57018237, -2.89811595, -5.44008672, 8.19302959,
-1.78437334, -19.32108323, 1.00091276, 4.79161569,
1.65685676, -8.68406543, 7.27219645, -2.90941943,
2.4613977 , 2.94533763, -6.35486958, -1.01281799,
2.13959957, -6.73934486, -1.65493937, 13.2605013 ])
分數也相同:
>>> lr.fit(train_X_ns, train_y)
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
>>> lr.score(test_X_ns, test_y)
0.9829300206380267
>>> lr.fit(train_X_scaled, train_y)
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
>>> lr.score(test_X_scaled, test_y)
0.9829300206380267
那么為什么要標准化呢? 因為它沒有傷害。 在管道中,您可能需要添加其他步驟,例如群集或PCA,這需要擴展。 請記住,如果要應用縮放,則還希望將其應用到評分數據集。 在這種情況下,必須使用StandardScaler,因為它具有fit
和transform
。 在我的示例中,我使用了scale
因為在拆分之前我將其同時應用於訓練和測試。 但是,在現實生活中,您的未來數據是未知的,因此您想使用StandardScaler
基於從訓練集中找到的mu和std進行轉換。
sklearn.preprocessing.scale()
通過減去均值( mu
)除以標准差( sigma
)來轉換變量:
x_scaled = (x - mu) / sigma
在您的情況下, x1
的mu
和sigma
值分別為5和2。 因此稱比例,將從每個x1
減去5,然后除以2。
移位不會影響線性回歸系數,而只會改變截距。 但是規模不同。 如果x1和y之間的關系由下式給出:
y = a*x1 # where the coefficient a is a constant
然后將x1
除以2,那么您需要將系數加倍以保持相同的關系。
在此示例中, x2
的sigma
為1,因此sigma
。
不縮放的系數/截距:
linear_regressor = LinearRegression()
linear_regressor.fit(X,y)
print(linear_regressor.coef_)
print(linear_regressor.intercept_)
#[ 7.48676034 -1.99400201]
#0.0253066229528
使用縮放:
X_scaled = scale(df_shuffled[df_shuffled.columns[:-1]])
linear_regressor2 = LinearRegression()
linear_regressor2.fit(X_scaled,y)
print(linear_regressor2.coef_)
print(linear_regressor2.intercept_)
#[ 14.90368565 -1.94029573]
#33.7451724511
在第二種情況下,您將獲得x1
和x2
縮放版本的系數並進行截距。
這不是問題或錯誤。 這意味着如果您使用擬合的模型進行預測,則只需對新數據應用相同的轉換即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.