一、線性迴歸
線性迴歸一般用來做連續值的預測,預測的結果爲一個連續值。因訓練時學習樣本不僅要提供學習的特徵向量X,而且還要提供樣本的實際結果(標記label),所以它是一種有監督學習。其中
線性迴歸需要學習得到的是一個映射關係
在線性迴歸中,假定輸入X和輸出y之間具有線性相關的關係。
例如當特徵向量
當情況複雜時,考慮
其中,爲了在映射函數hΘ(X)中保留常數項,令
當給定一個訓練集數據的情況,可以通過某個算法,學習出來一個線性的映射函數
二、損失函數
在需要通過學習得到的映射函數
那怎麼得到所需的特徵係數向量?怎麼保證得到的特徵係數向量是足夠好?這裏會有一個評判標準:損失函數。
根據特徵向量係數
其中
爲了得到預測值
三、梯度下降算法求解
批量隨機梯度下降BGD
在上面,找到了一個特徵係數向量
對於損失函數
梯度下降就是一個不斷地最小化損失函數的過程。從圖像上來看,先初始化
這個不斷迭代的過程猶如一個不斷下山的過程,我們可以得到圖中關於
當
對於特徵向量係數
對下山迭代公式進行展開,可得到具體求得
其中,
當學習率
一般情況下,
其他梯度下降算法
a. 批量梯度下降算法BGD中,
這樣訓練速度會隨着樣本數量
b. 隨機梯度下降法SGD:利用每個樣本的損失函數對
隨機梯度下降算法通過每個樣本來迭代更新一次,當一些訓練樣本爲噪聲樣本時,會導致SGD並不是向着整體最優化方向迭代。因此SGD算法在解空間的搜索比較盲目,但在大體上是往着最優值方向移動的。
c. 小批量梯度下降法MBGD:MBGD是前面兩個算法SGD和BGD的一個折中,既要保證算法的計算速度,又要保證參數訓練的最優性,每次需要計算一小批量樣本的彙總誤差來進行梯度下降。MBGD對
上式設置的一個batch大小爲 10 個訓練樣本,不同的任務所設置的batch大小也有所不同,可把 batch的大小可看一個超參數。
梯度下降的注意
在使用梯度下降求解最優化的解時,要注意對特徵進行歸一化,這樣可以提升模型的收斂速度。考慮兩維的情況:假如樣本只有兩個特徵時,一個特徵取值於 100 到 1000 之間,另一個特徵取值於0到1之間,可在
可得到一個個窄長的類橢圓等高線,導致在梯度下降時不斷地走“之”路線,增長了迭代時間。
若對特徵進行歸一化後,每個特徵之間具有相近的尺度,在
四、過渡到多項式迴歸
通過上面的線性迴歸,我們可以得到一個線性的映射函數
對於
這樣一來,
五、過擬合的正則化
當我們的損失函數
當我們的損失函數
對於過擬合問題,可以使用 正則化 的方法,即在原來的損失函數
無正則化時的損失函數:
L1正則化下的損失函數:
L2正則化下的損失函數:
L1正則化、L2正則化也稱爲Lasso正則化、Ridge正則化,其中
正則化後的損失函數不僅要最小化預測值與樣本點實際值間的差距了,還得最小化參數向量
正則化後,不僅要求
L1正則化往往會使得一些
六、最小二乘法求解
根據特徵向量係數
其中
由最小二乘法,令
因此可得:
當
上述的
由最小二乘法,令
可得到
其中
七、代碼示例
- 在sklearn的房價數據上使用線性迴歸,多項式迴歸:
from sklearn import datasets
boston = datasets.load_boston() # 加載房價數據
X = boston.data
y = boston.target
print X.shape
print y.shape
(506L, 13L)
(506L,)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y ,test_size = 1/3.,random_state = 8)
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
# 線性迴歸
lr = LinearRegression(normalize=True,n_jobs=2)
scores = cross_val_score(lr,X_train,y_train,cv=10,scoring='neg_mean_squared_error') #計算均方誤差
print scores.mean()
lr.fit(X_train,y_train)
lr.score(X_test,y_test)
-24.4294227766
0.6922002690740765
from sklearn.preprocessing import PolynomialFeatures
# 多項式迴歸
for k in range(1,4):
lr_featurizer = PolynomialFeatures(degree=k) # 用於產生多項式 degree:最高次項的次數
print '-----%d-----' % k
X_pf_train = lr_featurizer.fit_transform(X_train)
X_pf_test = lr_featurizer.transform(X_test)
pf_scores = cross_val_score(lr,X_pf_train,y_train,cv=10,scoring='neg_mean_squared_error')
print pf_scores.mean()
lr.fit(X_pf_train,y_train)
print lr.score(X_pf_test,y_test)
print lr.score(X_pf_train,y_train)
-----1-----
-24.4294227766
0.692200269074
0.755769163218
-----2-----
-22.7848754621
0.833095620158
0.93821030015
-----3-----
-6325.76073853
-16.550355583
1.0
當 k=1 時,迴歸爲線性迴歸;當 k=2 時,迴歸爲多項式迴歸,模型的效果比線性迴歸要好一點。
當 k=3 時,已經出現過擬合現象,模型在訓練集上得分很高,然而在驗證集上得分很低,從交叉驗證的得分結果也可以看得出來
# 正則化解決k=3的過擬合現象
lr_featurizer = PolynomialFeatures(degree=3) # 用於產生多項式 degree:最高次項的次數
X_pf_train = lr_featurizer.fit_transform(X_train)
X_pf_test = lr_featurizer.transform(X_test)
# LASSO迴歸:
from sklearn.linear_model import Lasso
for a in range(0,0.0005):
print '----%f-----'% a
lasso = Lasso(alpha=a,normalize=True)
pf_scores = cross_val_score(lasso,X_pf_train,y_train,cv=10,scoring='neg_mean_squared_error')
print pf_scores.mean()
lasso.fit(X_pf_train,y_train)
print lasso.score(X_pf_test,y_test)
print lasso.score(X_pf_train,y_train)
----0.000000-----
-29.3011407539
D:\Users\cxm\Anaconda2\lib\site-packages\ipykernel\__main__.py:15: UserWarning: With alpha=0, this algorithm does not converge well. You are advised to use the LinearRegression estimator
0.768272379891
0.965488575704
----0.000500-----
-11.2829107107
0.837992634283
0.943520416421
對比 alpha=0 和 alpha = 0.0005的情況,發現Lasso正則化處理後,模型的評價會提高很多。
# 正則化解決k=3的過擬合現象
lr_featurizer = PolynomialFeatures(degree=3) # 用於產生多項式 degree:最高次項的次數
X_pf_train = lr_featurizer.fit_transform(X_train)
X_pf_test = lr_featurizer.transform(X_test)
from sklearn.linear_model import Ridge
# 嶺迴歸
for a in [0,0.005]:
print '----%f-----'% a
ridge = Ridge(alpha=a,normalize=True)
pf_scores = cross_val_score(ridge,X_pf_train,y_train,cv=10,scoring='neg_mean_squared_error')
print pf_scores.mean()
ridge.fit(X_pf_train,y_train)
print ridge.score(X_pf_test,y_test)
print ridge.score(X_pf_train,y_train)
----0.000000-----
-6143.74385842
-16.4626220878
1.0
----0.005000-----
-14.0438948376
0.823709164706
0.948990485145
對比 alpha=0 和 alpha = 0.0005的情況,發現Ridge正則化處理後,模型的評價會提高很多。
- tensorflow實現正則化解決過擬合現象
from sklearn.datasets import load_boston
from sklearn.metrics import mean_squared_error
X_data = load_boston().data
Y_data = load_boston().target.reshape(-1,1)
print (X_data.shape,Y_data.shape)
((506, 13), (506, 1))
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_data, Y_data ,test_size = 1/3.,random_state = 8)
from sklearn.preprocessing import PolynomialFeatures
pl_featurizer = PolynomialFeatures(degree=2) # 用於產生多項式 degree:最高次項的次數
X_train = pl_featurizer.fit_transform(X_train)
X_test = pl_featurizer.transform(X_test)
print X_train.shape
(337, 105)
import tensorflow as tf
X = tf.placeholder(tf.float32,[None,105])
Y = tf.placeholder(tf.float32,[None,1])
tf_W_L1 = tf.Variable(tf.zeros([105,1]))
tf_b_L1 = tf.Variable(tf.zeros([1,1]))
pred = tf.matmul(X,tf_W_L1)+tf_b_L1
print pred
Tensor("add_6:0", shape=(?, 1), dtype=float32)
# L1正則化:
loss = tf.reduce_mean(tf.pow(pred-Y,2))*0.5 +0.001*tf.reduce_sum(tf_W_L1)
train_step = tf.train.AdamOptimizer(0.01).minimize(loss)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(20000):
sess.run(train_step,feed_dict={X:X_train,Y: y_train})
if(i%10000==0):
print mean_squared_error(y_train,pred.eval(feed_dict={X:X_train}).flatten().reshape(-1,1))
print 'test mse: '
print mean_squared_error(y_test,pred.eval(feed_dict={X:X_test}).flatten().reshape(-1,1))
42669456.628
10.4569020596
test mse:
15.7365063927