编程实现体会一下正则化 对权重的影响: 不同alpha 下对应的权重: 等比数列 ,正态分布
# from sklearn.datasets import make_regression from sklearn.linear_model import Ridge #L2 正则化 import matplotlib.pyplot as plt plt.rcParams["font.family"] = "serif" #切换成英文字体 #创建回归数据集: X,y,w = make_regression(n_samples= 10 ,n_features= 10 ,coef= True ,random_state= 1 ,bias= 3.5 ) #n_samples :样本数 n_features:样本特征 # coef:是否返回权重,默认是False # random_state 随机种子 表示数据集是否会变动, 0,1 都保持不变 #bias : 偏置项 alpha = np.logspace(-4,4,200) #10^-4 到 10^4 之间的 200数量的等比数列 #用来保存不同alpha 数值下的权重 coefs = [] #创造林回归对象 rig = Ridge() for i in alpha: #岭回归 #赋值不同的alpha rig.set_params(alpha = i) rig.fit(X,y) #将权重添加到列表 coefs.append(rig.coef_) #set 去修改参数 ax = plt.gca() ax.plot(alpha,coefs) ax.set_xscale('log') ax.set_xlabel("alpha") ax.set_ylabel("coefs") #发现当a 很小的时候 权重很大, a 很大的时候 权重 逐渐趋于 0 权重的表达式占据主要部分LASSO 容易产生权重是 0 ridge() 比较稳定 弹性网络介于两者之间
编程演示一下 LASSO 特征选择:
#通过Lasso 实现特征选择 :在a较大下,会出现很多权重为0 from sklearn.datasets import load_boston from sklearn.preprocessing import StandardScaler from sklearn.linear_model import Lasso #流水线 from sklearn.pipeline import Pipeline #导入波士顿数据 X, y = load_boston(return_X_y= True) #流水线 (列表 里面是元组) steps = [("ss",StandardScaler()),("ls",Lasso(alpha = 5))] pipe = Pipeline(steps) pipe.fit(X,y) #获取权重 lasso = pipe.named_steps["ls"] print( lasso.coef_ )权重如下:会发现有很多的为 0 的权重 下面进行特征选择:
from sklearn.feature_selection import SelectFromModel #数字 1 1e-5 表示科学计数法 10^(-5) #estimator : 评估器 ,即SelectFromModel 要进行特征选择的模型 #threshold :阈值 ,当特征权重 小于阈值的时候 丢弃该特征 #prefit 传入的评估器(estimator),是否已经训练过了 ,默认是FALSE 这里我们已经训练过了 ##获取权重 # lasso = pipe.named_steps["ls"] # print( lasso.coef_ ) sfm = SelectFromModel(estimator =lasso ,threshold = 1e-5,prefit =True ) #默认参数X X_transform = sfm.transform(X) print(X_transform) #发现只保留了两列权重 #返回布尔数组,用来表示是否选择 想对应的特征,True 表示选择了 print(sfm.get_support())三种方式解法过拟合问题: 流水线 加循环 ,enumerate
from sklearn.model_selection import train_test_split from sklearn.datasets import load_boston from sklearn.preprocessing import StandardScaler from sklearn.linear_model import Lasso from sklearn.linear_model import ElasticNet #流水线 from sklearn.pipeline import Pipeline #定义数据分布的函数: def true_fun(X) : return np.cos(1.5 * np.pi * X) #定义训练和绘图函数,后面可重复使用 def fit_and_plot(model): np.random.seed(0) x =np.random.rand(50) #在映射函数上面,增加一定的误差(噪声),这样更符合现实中数据的分布 #误差符合正态分布 y = true_fun(x)+np.random.randn(len(x)) *0.1 X = x[:,np.newaxis] #分割数据 X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.5,random_state = 0 ) model.fit(X_train,y_train) #训练集和测试集的得分:R^2 train_score = model.score(X_train,y_train) test_score = model.score(X_test,y_test) #绘制测试集和训练集图像 plt.scatter(X_train,y_train,c = 'g',label = '训练集') plt.scatter(X_test,y_test,c = 'orange',label = '测试集') #绘制回归曲线 s= np.linspace(0,1,100).reshape(-1,1) plt.plot(s,model.predict(s), c= 'r',label = '拟合线') plt.xlabel("x") plt.ylabel("y") plt.xlim(0,1) plt.ylim(-2,2) plt.legend(loc = 'upper center') plt.title(f"训练集R^2: {train_score:.3f} 测试集:{test_score:.3f}") #字体变为中文 plt.rcParams['font.family'] = 'SimHei' plt.figure(figsize= (10,10)) # #构造数据 # x= np.random.rand(50) # y = true_fun(x)+np.random.randn(len(x))*0.1 models = [("线性回归:(无正则话)",LinearRegression()),("l1正则化",Lasso(alpha = 0.02)), ("l2 正则话",Ridge(alpha = 0.02)),("弹性网络",ElasticNet(alpha = 0.02,l1_ratio= 0.5))] #注意对列表继续表里要加enumrate for index,(name,model) in enumerate(models): plt.subplot(2,2,index+1) #这里每次记得+1 因为 一开始是 2,2,0 但是要求是2,2,1 #此处 流水线 省略了一步,所有列表还有一个括号 pipe =Pipeline ( steps=[("Poly",PolynomialFeatures(degree = 15,include_bias = False)),("Model",model)] ) fit_and_plot(pipe) #输出权重 print(model.coef_) print("*"*50)各回归下的输出权重: 可以看懂LASSO 的权重有很多0值,正则化的强度强
那么如何选择合适的a 参数呢 我们可以在给定的一组a 值内选择适合每个回归下的alpha 参数: