目录
1.linear_model.LogisticRegression
1.1 重要参数 penalty & C
1.1.1 正则化
1.1.2 逻辑回归中的特征工程
1.2 重要参数 max_iter
1.3 二元回归与多元回归:重要参数solver & multi_class
首先来看一下sklearn中逻辑回归的类:
1.linear_model.LogisticRegression class sklearn.linear_model.LogisticRegression ( penalty=’l2’ , dual=False , tol=0.0001 , C=1.0 , fifit_intercept=True , intercept_scaling=1 , class_weight=None , random_state=None , solver=’warn’ , max_iter=100 , multi_class=’warn’ , verbose=0 , warm_start=False , n_jobs=None ) 下面根据类中的各种重要参数进行讨论。常用的有L1正则化和L2正则化两种选项 penalty可以输入l1或者l2,从而告诉模型想用哪一种正则化方式,默认是l2;
C是正则化强度的倒数,大于0的浮点数,默认1.0,C越小,损失函数会越小,模型对损失函数的惩罚越重,正则化的效力越强,参数会逐渐被压缩得越来越小。
L1正则化会将参数压缩为0,L2正则化只会让参数尽量小,不会取到0。
下面看看L1正则化和L2正则化的差别:
from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer #乳腺癌数据集
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
data = load_breast_cancer()
X = data.data
y = data.target
data.data.shape
lrl1 = LR(penalty="l1",solver="liblinear",C=0.5,max_iter=1000)
lrl2 = LR(penalty="l2",solver="liblinear",C=0.5,max_iter=1000)
#逻辑回归的重要属性coef_,查看每个特征所对应的参数
lrl1 = lrl1.fit(X,y)
print(lrl1.coef_)
print((lrl1.coef_ != 0).sum(axis=1)) #可返回不为0的系数个数,等于=返回true;不等于返回false
lrl2 = lrl2.fit(X,y)
print(lrl2.coef_) #l2不压缩特征,所有特征都有系数
打印L1正则化和L2正则化后每个参数的系数:
下面探索哪种正则化效果更好:
l1 = [] #保存l1训练的结果
l2 = []
l1test = []
l2test = []
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3,random_state=420)
for i in np.linspace(0.05,1,19):
lrl1 = LR(penalty="l1",solver="liblinear",C=i,max_iter=1000)
lrl2 = LR(penalty="l2",solver="liblinear",C=i,max_iter=1000)
lrl1 = lrl1.fit(Xtrain,Ytrain)
l1.append(accuracy_score(lrl1.predict(Xtrain),Ytrain))
l1test.append(accuracy_score(lrl1.predict(Xtest),Ytest))
lrl2 = lrl2.fit(Xtrain,Ytrain)
l2.append(accuracy_score(lrl2.predict(Xtrain),Ytrain))
l2test.append(accuracy_score(lrl2.predict(Xtest),Ytest))
#设置中文字体
import matplotlib.font_manager as fm
my_font=fm.FontProperties(fname="/System/Library/Fonts/PingFang.ttc")
graph = [l1,l2,l1test,l2test]
color = ["green","black","lightgreen","gray"]
label = ["L1","L2","L1test","L2test"]
plt.figure(figsize=(6,6))
for i in range(len(graph)):
plt.plot(np.linspace(0.05,1,19),graph[i],color[i],label=label[i])
plt.legend(loc=4) #图例的位置在哪里?4表示,右下角
plt.xlabel('C 的取值',fontproperties=my_font)
plt.ylabel('模型准确度',fontproperties=my_font)
plt.show()
上图显示两种正则化方式的模型在训练集表现都很好
随着C的逐渐变大,正则化的强度越来越小,模型在训练集和测试集上的表现都呈上升趋势,直到C=0.8左右,训练集上的表现依然在走高,但模型在未知数据集上的表现开始下跌,这时候就是出现了过拟合,在实际使用时,基本就默认使用l2正则化,如果感觉到模型的效果不好,那就换L1试试看。
- 为什么不用PCA
推荐使用高效的嵌入法embedded
from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import SelectFromModel
data = load_breast_cancer()
data.data.shape
LR_ = LR(solver="liblinear",C=0.9,random_state=420)
print(cross_val_score(LR_,data.data,data.target,cv=10).mean())
X_embedded = SelectFromModel(LR_,norm_order=1).fit_transform(data.data,data.target)
print(X_embedded.shape)
cross_val_score(LR_,X_embedded,data.target,cv=10).mean()
看看结果,特征数量被减小到个位数,并且模型的效果却没有下降太多,如果我们要求不高,在这里其实就可以停下了。
想让模型效果更好,有两种调节方式:
(1)调节SelectFromModel中的threshold
只要调整threshold的值(画出threshold的学习曲线),就可以观察不同的threshold下模型的效果如何变化。
一旦调整threshold,就不是在使用L1正则化选择特征,而是使用模型的属性.coef_中生成的各个特征的系数来选择。
coef_虽然返回的是特征的系数,但是系数的大小和决策树中的feature_ importances_以及降维算法中的可解释性方差explained_vairance_概念相似,其实都是衡量特征的重要程度和贡献度的,因此SelectFromModel中的参数threshold可以设置为coef_的阈值,即可以剔除系数小于threshold中输入的数字的所有特征。
fullx = []
fsx = []
threshold = np.linspace(0,abs((LR_.fit(data.data,data.target).coef_)).max(),20)
k=0 #abs代表对里面的系数取绝对值
for i in threshold:
X_embedded = SelectFromModel(LR_,threshold=i).fit_transform(data.data,data.target)
fullx.append(cross_val_score(LR_,data.data,data.target,cv=5).mean())
fsx.append(cross_val_score(LR_,X_embedded,data.target,cv=5).mean())
print((threshold[k],X_embedded.shape[1]))
k+=1
plt.figure(figsize=(20,5))
plt.plot(threshold,fullx,label="full")
plt.plot(threshold,fsx,label="feature selection")
plt.xticks(threshold)
plt.xlabel('threshold 的取值',fontproperties=my_font)
plt.ylabel('模型交叉验证得分',fontproperties=my_font)
plt.legend()
plt.show()
然而,这种方法其实是比较无效的
当threshold越来越大,被删除的特征越来越多,模型的效果也越来越差,模型效果最好的情况下需要保证有17个以上的特征。
这对于现实情况来说,是一种无效的降维
(2)调逻辑回归的类LR_
第二种调整方法,是调逻辑回归的类LR_,通过画C的学习曲线来实现:
fullx = []
fsx = []
C=np.arange(0.01,10.01,0.5)
for i in C:
LR_ = LR(solver="liblinear",C=i,random_state=420)
fullx.append(cross_val_score(LR_,data.data,data.target,cv=10).mean())
X_embedded = SelectFromModel(LR_,norm_order=1).fit_transform(data.data,data.target)
fsx.append(cross_val_score(LR_,X_embedded,data.target,cv=10).mean())
print(max(fsx),C[fsx.index(max(fsx))])
plt.figure(figsize=(20,5))
plt.plot(C,fullx,label="full")
plt.plot(C,fsx,label="feature selection")
plt.xticks(C)
plt.legend()
plt.show()
继续细化学习曲线
#细化学习曲线
fullx = []
fsx = []
C=np.arange(6.05,7.05,0.005)
for i in C:
LR_ = LR(solver="liblinear",C=i,random_state=420)
fullx.append(cross_val_score(LR_,data.data,data.target,cv=10).mean())
X_embedded = SelectFromModel(LR_,norm_order=1).fit_transform(data.data,data.target)
fsx.append(cross_val_score(LR_,X_embedded,data.target,cv=10).mean())
print(max(fsx),C[fsx.index(max(fsx))])
plt.figure(figsize=(20,5))
plt.plot(C,fullx,label="full")
plt.plot(C,fsx,label="feature selection")
plt.xticks(C)
plt.legend()
plt.show()
验证模型效果:
降维前:
#验证模型效果:降维之前
LR_ = LR(solver="liblinear",C=6.069999999999999,random_state=420)
cross_val_score(LR_,data.data,data.target,cv=10).mean()
#0.9473057644110275
后:
#验证模型效果:降维之后
LR_ = LR(solver="liblinear",C=6.069999999999999,random_state=420)
X_embedded = SelectFromModel(LR_,norm_order=1).fit_transform(data.data,data.target)
cross_val_score(LR_,X_embedded,data.target,cv=10).mean()
print("降维后数据集结构为:",X_embedded.shape) #(569, 11)
1.2 重要参数 max_iter
关于max_iter设置成多少可以达到较好的效果,通过学习曲线展示:
l2 = [] #训练集上的测试结果
l2test = [] #测试集上测试结果
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3,random_state=420)
for i in np.arange(1,201,10):
lrl2 = LR(penalty="l2",solver="liblinear",C=0.9,max_iter=i)
lrl2 = lrl2.fit(Xtrain,Ytrain)
l2.append(accuracy_score(lrl2.predict(Xtrain),Ytrain))
l2test.append(accuracy_score(lrl2.predict(Xtest),Ytest))
graph = [l2,l2test]
color = ["black","gray"]
label = ["L2","L2test"]
plt.figure(figsize=(20,5))
for i in range(len(graph)):
plt.plot(np.arange(1,201,10),graph[i],color[i],label=label[i])
plt.legend(loc=4)
plt.xticks(np.arange(1,201,10))
plt.xlabel('max_iter')
plt.ylabel('cv结果',fontproperties=my_font)
plt.show()
#使用属性.n_iter_来调用本次求解中真正实现的迭代次数
lr = LR(penalty="l2",solver="liblinear",C=0.9,max_iter=100).fit(Xtrain,Ytrain)
print(lr.n_iter_) #24
1.3 二元回归与多元回归:重要参数solver & multi_class
把某种分类类型都看作1,其余的分类类型都为0值,这种方法被称为"一对多"(One-vs-rest),简称OvR,在sklearn中表示为“ovr"
又或者,我们可以把 好几个分类类型划为1,剩下的几个分类类型划为0值,这是一种”多对多“(Many-vs-Many)的方法,简称MvM,在 sklearn中表示为"Multinominal"
每种方式都配合L1或L2正则项来使用。
在sklearn中,使用参数multi_class来告诉模型,我们的预测标签是ovr还是MvM
看看鸢尾花数据集上,multinomial和ovr的区别:
from sklearn.datasets import load_iris
iris = load_iris()
print(iris.target)
for multi_class in ('multinomial', 'ovr'):
clf = LR(solver='sag', max_iter=100, random_state=42,
multi_class=multi_class).fit(iris.data, iris.target)
print("training score : %.3f (%s)" % (clf.score(iris.data, iris.target), multi_class))
#training score : 0.987 (multinomial)
#training score : 0.960 (ovr)
结果是多对多的效果更好
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)