第8章 多项式回归与模型泛化
問題:線性回歸要求假設我們的數據背后存在線性關系;
,?如果將x的平方理解成一個特征,x理解成另一個特征;本來只有一個特征x,現在看成有兩個特征的數據集,多了一個特征,就是x的平方,其實式子本身依然是一個線性回歸的式子,但是從x?的角度來看,也就是所謂的非線性方程,這樣的方式就叫做多項式回歸
?PCA降維,多項式回歸提升維度
?
, import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_errornp.random.seed(666) x=np.random.uniform(-3.0,3.0,size=100) X=x.reshape(-1,1) y=0.5*x**2+x+2+np.random.normal(0,1,size=100)from sklearn.pipeline import Pipeline from sklearn.preprocessing import PolynomialFeatures from sklearn.preprocessing import StandardScaler def PolynomialRegression(degree):return Pipeline([("poly", PolynomialFeatures(degree=degree)),("std_scaler", StandardScaler()),("lin_reg", LinearRegression())]) poly2_reg=PolynomialRegression(degree=2) poly2_reg.fit(X,y) y2_predict=poly2_reg.predict(X) mean_squared_error(y,y2_predict) plt.scatter(x,y) plt.plot(np.sort(x),y2_predict[np.argsort(x)],color='r') plt.show()# 不同的degree poly10_reg=PolynomialRegression(degree=10) poly10_reg.fit(X,y) y10_predict=poly10_reg.predict(X) mean_squared_error(y,y10_predict)plt.scatter(x,y) plt.plot(np.sort(x),y10_predict[np.argsort(x)],color='r') plt.show() # degree=100 poly100_reg=PolynomialRegression(degree=100) poly100_reg.fit(X,y) y100_predict=poly100_reg.predict(X) mean_squared_error(y,y100_predict)plt.scatter(x,y) plt.plot(np.sort(x),y100_predict[np.argsort(x)],color='r') plt.show() 不同的degree?
?機器學習主要解決的問題其實是過擬合的問題。
泛化能力:由此及彼的能力(根據已知的訓練數據得到的這條曲線,可是這條曲線在面對新的數據的時候它的能力卻非常弱,也就是泛化能力差)
我們要訓練這個模型為的不是最大程度的擬合這些點,而是為了獲得一個可以預測的模型,當有了新的數據的時候,我們的模型可以給出很好的解答。
所以,我們去衡量我們的模型對于這個訓練的數據它的擬合程度有多好是沒有意義的,我們真正需要的是能夠衡量我們的得到的這個模型的泛化能力有多好。
因此使用訓練數據集和測試數據集
?如果使用訓練數據獲得的的這個模型面對測試數據也能獲得很好的結果的話,我們就說這個模型的泛化能力就是很強的!!!但是如果面對測試數據集它的效果很差的話,那么的的泛化能力就是很弱的,多半我們就遭遇了過擬合
模型的復雜度:不同的模型代表的意思不同
KNN:K越小,模型越復雜;K=1,最復雜
多項式回歸:階數越大,degree越大,模型越復雜
,
?
, ,?通過學習曲線也可以看到模型的過擬合和欠擬合
?學習曲線:隨著訓練樣本的逐漸增多,算法訓練出的模型的表現能力
import numpy as np import matplotlib.pyplot as plt np.random.seed(666) x=np.random.uniform(-3.0,3.0,size=100) X=x.reshape(-1,1) y=0.5*x**2+x+2+np.random.normal(0,1,size=100)from sklearn.model_selection import train_test_split X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=10)from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error train_score=[] test_score=[] for i in range(1,76):lin_reg=LinearRegression()lin_reg.fit(X_train[:i],y_train[:i]) # 依次取訓練數據、測試數據的前i個元素y_train_predict=lin_reg.predict(X_train[:i])train_score.append(mean_squared_error(y_train[:i],y_train_predict))y_test_predict=lin_reg.predict(X_test)test_score.append(mean_squared_error(y_test,y_test_predict))plt.plot([i for i in range(1,76)],np.sqrt(train_score),label="train") plt.plot([i for i in range(1,76)],np.sqrt(test_score),label="test") plt.legend() plt.show()# 封裝成函數 def plot_learning_curve(algo,X_train,X_test,y_train,y_test):train_score=[]test_score=[]for i in range(1,len(X_train)+1):algo.fit(X_train[:i],y_train[:i])y_train_predict=algo.predict(X_train[:i])train_score.append(mean_squared_error(y_train[:i],y_train_predict))y_test_predict=algo.predict(X_test)test_score.append(mean_squared_error(y_test,y_test_predict))plt.plot([i for i in range(1,len(X_train)+1)],np.sqrt(train_score),label="train")plt.plot([i for i in range(1,len(X_train)+1)],np.sqrt(test_score),label="test")plt.legend()plt.axis([0,len(X_train)+1,0,4])plt.show() plot_learning_curve(LinearRegression(),X_train,X_test,y_train,y_test)# 使用多項式回歸 from sklearn.pipeline import Pipeline from sklearn.preprocessing import PolynomialFeatures from sklearn.preprocessing import StandardScaler def PolynomialRegression(degree):return Pipeline([("poly", PolynomialFeatures(degree=degree)),("std_scaler", StandardScaler()),("lin_reg", LinearRegression())])poly2_reg=PolynomialRegression(degree=2) plot_learning_curve(poly2_reg,X_train,X_test,y_train,y_test)poly2_reg=PolynomialRegression(degree=20) # 過擬合 plot_learning_curve(poly2_reg,X_train,X_test,y_train,y_test) 學習曲線,
,?
,?
,一定程度上圍繞著測試數據集打轉,也就是說我們在想辦法找到一組參數,這組參數使得我們用訓練數據集獲得的模型在測試數據集上的效果最好,但是由于測試數據集是已知的,我們相當于在針對這組測試數據集調參,那么它也有可能產生過擬合的情況,也就是說我們得到的這個模型針對這個測試數據集過擬合了解決方法:將整個數據分成三部分:訓練數據集、驗證數據集(validation?test)、測試數據集(將驗證數據集當成之前的測試數據集)
, import numpy as np from sklearn import datasetsdigits=datasets.load_digits() # 手寫識別數據 X=digits.data y=digits.target # 測試train_test_split from sklearn.model_selection import train_test_split X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.4,random_state=666) from sklearn.neighbors import KNeighborsClassifierbest_score, best_p, best_k = 0, 0, 0 for k in range(2, 11):for p in range(1, 6):knn_clf = KNeighborsClassifier(weights="distance", n_neighbors=k, p=p)knn_clf.fit(X_train, y_train)knn_clf.score(X_test, y_test)score = knn_clf.score(X_test, y_test)if score > best_score:best_score, best_p, best_k = score, p, kprint("Best K=", best_k) print("Best P=", best_p) print("Best Score", best_score)# 使用交叉驗證 from sklearn.model_selection import cross_val_score knn_clf=KNeighborsClassifier() cross_val_score(knn_clf,X_train,y_train,cv=3) best_score, best_p, best_k = 0, 0, 0 for k in range(2, 11):for p in range(1, 6):knn_clf = KNeighborsClassifier(weights="distance", n_neighbors=k, p=p)scores = cross_val_score(knn_clf, X_train, y_train, cv=3)score = np.mean(scores)if score > best_score:best_score, best_p, best_k = score, p, kprint("Best K=", best_k) print("Best P=", best_p) print("Best Score", best_score)best_knn_clf=KNeighborsClassifier(weights="distance",n_neighbors=2,p=2) # 選用剛剛找到的最好的參數 best_knn_clf.fit(X_train,y_train) best_knn_clf.score(X_test,y_test) # 對于模型完全沒有見過的test# 回顧網格搜索 from sklearn.model_selection import GridSearchCV # cv:就是交叉驗證的意思,cross_validation param_grid = [{'weights': ['distance'],'n_neighbors': [ i for i in range(2,11)],'p':[i for i in range(1,6)]} ] grid_search=GridSearchCV(knn_clf,param_grid,verbose=1,cv=3,n_jobs=-1) #n_jobs=-1的時候,表示cpu里的所有core進行工作(cv:交叉驗證,默認3) grid_search.fit(X_train,y_train) grid_search.best_score_grid_search.best_params_cross_val_score(knn_clf,X_train,y_train,cv=5) 驗證數據集與交叉驗證 ,
?留一法:訓練數據集有m個樣本,就分成m份;每次都將m-1份樣本用于訓練,然后去看預測那剩下的一個樣本預測的準不準,將這些結果綜合起來來進行評均,作為衡量我們當前參數下這個模型對應的預測的準確度
?偏差方差平衡:Bias?Variance?Trade?off
, ,
?導致較高方差:是模型太過復雜,沒有完全的學習到這個問題的實質,而學習到了很多的噪音
,?
,?
,?高方差:泛化能力差
解決方差:模型的正則化
?
,?α:新的超參數
這種正則化的方式又叫做嶺回歸
import numpy as np import matplotlib.pyplot as plt np.random.seed(42) x=np.random.uniform(-3.0,3.0,size=100) X=x.reshape(-1,1) y=0.5*x+3+np.random.normal(0,1,size=100)plt.scatter(x,y) plt.show()from sklearn.pipeline import Pipeline from sklearn.preprocessing import PolynomialFeatures from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LinearRegression def PolynomialRegression(degree):return Pipeline([("poly", PolynomialFeatures(degree=degree)),("std_scaler", StandardScaler()),("lin_reg", LinearRegression())]) from sklearn.model_selection import train_test_split np.random.seed(666) X_train,X_test,y_train,y_test=train_test_split(X,y)from sklearn.metrics import mean_squared_error poly_reg=PolynomialRegression(degree=20) poly_reg.fit(X_train,y_train) y_predict=poly_reg.predict(X_test) mean_squared_error(y_test,y_predict)X_plot=np.linspace(-3,3,100).reshape(100,1) y_plot=poly_reg.predict(X_plot) plt.scatter(x,y) plt.plot(X_plot[:,0],y_plot,color='r') plt.axis([-3,3,0,6]) plt.show()def plot_model(model):X_plot=np.linspace(-3,3,100).reshape(100,1)y_plot=model.predict(X_plot)plt.scatter(x,y)plt.plot(X_plot[:,0],y_plot,color='r')plt.axis([-3,3,0,6])plt.show()plot_model(poly_reg)# 使用嶺回歸 from sklearn.linear_model import Ridgedef RidgeRegression(degree,alpha):return Pipeline([("poly", PolynomialFeatures(degree=degree)),("std_scaler", StandardScaler()),("ridge_reg", Ridge(alpha=alpha))]) ridge1_reg=RidgeRegression(20,0.0001) ridge1_reg.fit(X_train,y_train) y1_predict=ridge1_reg.predict(X_test) mean_squared_error(y_test,y1_predict) plot_model(ridge1_reg)ridge2_reg=RidgeRegression(20,1) ridge2_reg.fit(X_train,y_train) y2_predict=ridge2_reg.predict(X_test) mean_squared_error(y_test,y2_predict) plot_model(ridge2_reg)ridge3_reg=RidgeRegression(20,100) ridge3_reg.fit(X_train,y_train) y3_predict=ridge3_reg.predict(X_test) mean_squared_error(y_test,y3_predict) plot_model(ridge3_reg) 嶺回歸
?另外一種模型正則化的方式:LASSO Regularization
, import numpy as np import matplotlib.pyplot as plt np.random.seed(42) x=np.random.uniform(-3.0,3.0,size=100) X=x.reshape(-1,1) y=0.5*x+3+np.random.normal(0,1,size=100) plt.scatter(x,y) plt.show()from sklearn.pipeline import Pipeline from sklearn.preprocessing import PolynomialFeatures from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LinearRegression def PolynomialRegression(degree):return Pipeline([("poly", PolynomialFeatures(degree=degree)),("std_scaler", StandardScaler()),("lin_reg", LinearRegression())])from sklearn.model_selection import train_test_split np.random.seed(666) X_train,X_test,y_train,y_test=train_test_split(X,y)from sklearn.metrics import mean_squared_error poly_reg=PolynomialRegression(degree=20) poly_reg.fit(X_train,y_train) y_predict=poly_reg.predict(X_test) mean_squared_error(y_test,y_predict)def plot_model(model):X_plot=np.linspace(-3,3,100).reshape(100,1)y_plot=model.predict(X_plot)plt.scatter(x,y)plt.plot(X_plot[:,0],y_plot,color='r')plt.axis([-3,3,0,6])plt.show()plot_model(poly_reg)# LASSO from sklearn.linear_model import Lasso def LassoRegression(degree,alpha):return Pipeline([("poly", PolynomialFeatures(degree=degree)),("std_scaler", StandardScaler()),("ridge_reg", Lasso(alpha=alpha))]) lasso1_reg=LassoRegression(20,0.01) lasso1_reg.fit(X_train,y_train)y1_predict=lasso1_reg.predict(X_test) mean_squared_error(y_test,y1_predict)plot_model(lasso1_reg)# 增大α lasso2_reg=LassoRegression(20,0.1) lasso2_reg.fit(X_train,y_train)y2_predict=lasso2_reg.predict(X_test) mean_squared_error(y_test,y2_predict)plot_model(lasso2_reg) LASSO Regression ,
?
? ? ,? ???
,?
,???
,?
總結
以上是生活随笔為你收集整理的第8章 多项式回归与模型泛化的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 第9章 逻辑回归
- 下一篇: 第10章 评价分类结果
