解决模型中方差太大的主要方式:模型正则化(Regularization)
模型正则化主要是限制系数的参数
如多项式回归中方差太大,主要是由于模型太复杂,样本特征前的参数太大
alpha是一个参数,即加入模型正则化的程度,若alpha等于0,则损失函数仍和之前的相同,相当于没有加入模型正则化,若alpha=无穷大,则相当于只考虑了theta的值,此时让损失函数尽可能的小,即此时alpha全为0,此时构造出来的模型去预测值应该是一个 常数。
注意:这里的alpha从1开始,因为theta0并不影响曲线的复杂程度,他只是影响曲线的高低
alpha来调节正则化程度
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
import numpy as np
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt
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)
x_train,x_test,y_train,y_test=train_test_split(X,y,random_state=10)
from sklearn.linear_model import Ridge
#定义岭回归的管道
def ridgeregression(degree,alpha):
return Pipeline([
("poly",PolynomialFeatures(degree=degree)),
("sca_std",StandardScaler()),
("reg",Ridge(alpha=alpha))
])
#多项式回归的管道
def polyregressin(degree):
return Pipeline([
("poly",PolynomialFeatures(degree=degree)),
("sca_std",StandardScaler()),
("reg",LinearRegression())
])
#绘制当前模型的曲线图
def plot_model(model):
x1=np.linspace(-3,3,100).reshape(100,1)
y1=model.predict(x1)
plt.scatter(x,y)
plt.plot(x1[:,0],y1,color='r')
plt.axis([-3,3,0,6])
plt.show()
pip_reg=polyregressin(degree=20)
pip_reg.fit(x_train,y_train)
y_predict=pip_reg10.predict(x_test)
plot_model(pip_reg10)
mean_squared_error(y_test,y_predict)
#让degree=20,alpha=0.001
ridge1_reg=ridgeregression(20,0.001)
ridge1_reg.fit(x_train,y_train)
y1_predict=ridge1_reg.predict(x_test)
plot_model(ridge1_reg)
mean_squared_error(y_test,y1_predict)
ridge2_reg=ridgeregression(20,1)
ridge2_reg.fit(x_train,y_train)
y2_predict=ridge2_reg.predict(x_test)
plot_model(ridge2_reg)
mean_squared_error(y_test,y2_predict)
ridge3_reg=ridgeregression(20,10)
ridge3_reg.fit(x_train,y_train)
y3_predict=ridge3_reg.predict(x_test)
plot_model(ridge3_reg)
mean_squared_error(y_test,y3_predict)
ridge3_reg=ridgeregression(20,100)
ridge3_reg.fit(x_train,y_train)
y3_predict=ridge3_reg.predict(x_test)
plot_model(ridge3_reg)
mean_squared_error(y_test,y3_predict)
ridge4_reg=ridgeregression(20,100000)
ridge4_reg.fit(x_train,y_train)
y4_predict=ridge4_reg.predict(x_test)
plot_model(ridge4_reg)
mean_squared_error(y_test,y4_predict)
通过上述例子,我们可以发现,单只使用多项式回归时,当degree较大时,
方差太大,曲线太复杂,泛化能力弱,此时的mse较大。
当使用岭回归时,不同的alpha值得到的曲线也不同,所以对于不同的数据
我们要测试alpha值来得到更好的模型。
当alpha=较大时,此时theta基本等于0,曲线接近一条直线。
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
import numpy as np
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt
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)
x_train,x_test,y_train,y_test=train_test_split(X,y,random_state=10)
#多项式回归的管道
def polyregressin(degree):
return Pipeline([
("poly",PolynomialFeatures(degree=degree)),
("sca_std",StandardScaler()),
("reg",LinearRegression())
])
#绘制当前模型的曲线图
def plot_model(model):
x1=np.linspace(-3,3,100).reshape(100,1)
y1=model.predict(x1)
plt.scatter(x,y)
plt.plot(x1[:,0],y1,color='r')
plt.axis([-3,3,0,6])
plt.show()
from sklearn.linear_model import Lasso
#定义岭回归的管道
def lassoregression(degree,alpha):
return Pipeline([
("poly",PolynomialFeatures(degree=degree)),
("sca_std",StandardScaler()),
("reg",Lasso(alpha=alpha))
])
pip_reg=polyregressin(degree=20)
pip_reg.fit(x_train,y_train)
y_predict=pip_reg10.predict(x_test)
plot_model(pip_reg10)
mean_squared_error(y_test,y_predict)
lasso1_reg=lassoregression(degree=20,alpha=0.01)
lasso1_reg.fit(x_train,y_train)
y1_predict=lasso1_reg.predict(x_test)
plot_model(lasso1_reg)
mean_squared_error(y_test,y1_predict)
lasso2_reg=lassoregression(degree=20,alpha=1.3)
lasso2_reg.fit(x_train,y_train)
y2_predict=lasso2_reg.predict(x_test)
plot_model(lasso2_reg)
mean_squared_error(y_test,y2_predict)
lasso3_reg=lassoregression(degree=20,alpha=10)
lasso3_reg.fit(x_train,y_train)
y3_predict=lasso3_reg.predict(x_test)
plot_model(lasso3_reg)
mean_squared_error(y_test,y3_predict)
我们可以发现岭回归与lasso的区别:
当degree都为20时
岭回归alpha=100时,它的曲线仍带有弧度但是却没那么复杂了,这证明系数都有在减小。
在lasso中,当alpha=1.3时,虽然去曲线仍然是倾斜的,但是却接近于一条倾斜直线,这证明一部分系数已经变成了0.
具体原因见下方
看其梯度算法,看其是如何变为0求最小值的便可得知。
岭回归:theta是一起减小之后变为0的
lasso是:挑选部分不重要的样本特征使其theta变为0 ,有减少样本特征的作用。
通过岭回归与lasso的比较,我们可以回顾之前的机器学习对应的指标
可以发现,虽然机器学习中有很多名词,但是其基本形式都是类似的
当然也有L0范数,但是L0范数是在mse的基础上求非0theta的最小值,是一个NP问题,多项式复杂程度的非确定性问题,如果theta值很多,则计算很复杂
L0正则可以用L1来取代,因为L1是让有更多的theta为0,可以作为特征选择
弹性网是结合了lasso正则与岭回归的优点,岭回归是让theta都变小,但是lasso是尽快的让theta的某些值变小,一般来说,优先使用岭回归,但是当系数太多时,岭回归计算时间长,但是lasso让某些系数变为0,若这些样本特征是有用的,那么就会造成极大误差,但是lasso计算时间比岭回归短。
弹性网结合了这两者的有点。