机器学习sklearn-逻辑回归

目录

L0范数,L1范数,L2范数

sigmond函数

损失函数

penalty和C参数

逻辑回归中的特征工程 

梯度下降


L0范数,L1范数,L2范数

L0范数是指向量中非0的元素的个数。如果我们用L0范数来规则化一个参数矩阵W的话,就是希望W的大部分元素都是0。

L1范数是指向量中各个元素绝对值之和,也有个美称叫“稀疏规则算子”(Lasso regularization)。

任何的规则化算子,如果他在Wi=0的地方不可微,并且可以分解为一个“求和”的形式,那么这个规则化算子就可以实现稀疏。这说是这么说,W的L1范数是绝对值,|w|在w=0处是不可微。

L1范数和L0范数可以实现稀疏,L1因具有比L0更好的优化求解特性而被广泛应用。

L2范数是指向量各元素的平方和然后求平方根。我们让L2范数的规则项||W||2最小,可以使得W的每个元素都很小,都接近于0,但与L1范数不同,它不会让它等于0,而是接近于0,这里是有很大的区别的哦。而越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象。

制了参数很小,实际上就限制了多项式某些分量的影响很小,这样就相当于减少参数个数。

sigmond函数

Sigmoid 函数是一个 S 型的函数,当自变量 z 趋近正无穷时,因变量 g(z) 趋近于 1 ,而当 z 趋近负无穷时, g(z) 趋近于0 ,它能够将任何实数映射到 (0,1) 区间,使其可用于将任意值函数转换为更适合二分类的函数。
因为这个性质, Sigmoid 函数也被当作是归一化的一种方法,与我们之前学过的 MinMaxSclaer 同理,是属于数据预处理中的“ 缩放 功能,可以将数据压缩到 [0,1] 之内。区别在于, MinMaxScaler 归一化之后,是可以取到0 1 的(最大值归一化后就是 1 ,最小值归一化后就是 0 ),但 Sigmoid 函数只是无限趋近于 0 1

损失函数

损失函数仅仅针对有参数的模型而言,没有参数的模型就不存损失函数,比如KNN,决策树。

损失函数小,模型在训练集上表现优异,拟合充分,参数优秀。
损失函数大,模型在训练集上表现差劲,拟合不足,参数糟糕。
我们追求损失函数的最小值,让模型在训练集上表现最优,可能会引发另一个问题:如果模型在训练集上表示优秀,却在测试集上表现糟糕,模型就会过拟合。虽然逻辑回归和线性回归是天生欠拟合的模型,但我们还是需要控制过拟合的技术来帮助我们调整模型,对逻辑回归中过拟合的控制,通过正则化来实现。

penalty和C参数

机器学习sklearn-逻辑回归_第1张图片

L1 正则化和 L2 正则化虽然都可以控制过拟合,但它们的效果并不相同。当正则化强度逐渐增大(即 C 逐渐变小), 参数的取值会逐渐变小,但L1 正则化会将参数压缩为 0 L2 正则化只会让参数尽量小,不会取到 0
L1 正则化在逐渐加强的过程中,携带信息量小的、对模型贡献不大的特征的参数,会比携带大量信息的、对模型有巨大贡献的特征的参数更快地变成0 ,所以 L1 正则化本质是一个特征选择的过程,掌管了参数的 稀疏性 L1 正则化越强,参数向量中就越多的参数为0 ,参数就越稀疏,选出来的特征就越少,以此来防止过拟合。因此,如果特征量很大,数据维度很高,我们会倾向于使用L1 正则化。由于 L1 正则化的这个性质,逻辑回归的特征选择可以由Embedded嵌入法来完成。
相对的, L2 正则化在加强的过程中,会尽量让每个特征对模型都有一些小的贡献,但携带信息少,对模型贡献不大的特征的参数会非常接近于0 。通常来说,如果我们的主要目的只是为了防止过拟合,选择 L2 正则化就足够了。但是如果选择L2 正则化后还是过拟合,模型在未知数据集上的效果表现很差,就可以考虑 L1 正则化。
而两种正则化下 C 的取值,都可以通过学习曲线来进行调整。
机器学习sklearn-逻辑回归_第2张图片
#比较L1正则化和L2正则化

from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer #导入乳腺癌数据集
from sklearn.model_selection import train_test_split
from sklearn.metrics import  accuracy_score
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

data=load_breast_cancer()
X=data.data
Y=data.target

#实例化
lr_l1=LR(penalty='l1',solver='liblinear',C=0.5,max_iter=1000)
lr_l2=LR(penalty='l2',solver='liblinear',C=0.5,max_iter=1000)
lr_l1=lr_l1.fit(X,Y)
lr_l2=lr_l2.fit(X,Y)

#查看coef_属性 正则化后不为0参数个数
print(lr_l1.coef_)
print((lr_l1.coef_!=0).sum())
print(lr_l2.coef_)
print((lr_l2.coef_!=0).sum())

 绘制参数C的学习曲线

机器学习sklearn-逻辑回归_第3张图片

#绘制逻辑回归参数C学习曲线

from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer #导入乳腺癌数据集
from sklearn.model_selection import train_test_split
from sklearn.metrics import  accuracy_score
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


data = load_breast_cancer()
X = data.data
y = data.target
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3)

l1=[]
l2=[]
l1test=[]
l2test=[]

for i in np.linspace(0.05,1,19):
    lr_l1=LR(penalty='l1',solver='liblinear',C=i,max_iter=1000)
    lr_l2=LR(penalty='l2',solver='liblinear',C=i,max_iter=1000)

    lr_l1=lr_l1.fit(Xtrain,Ytrain)
    l1.append(accuracy_score(lr_l1.predict(Xtrain),Ytrain))
    l1test.append(accuracy_score(lr_l1.predict(Xtest),Ytest))

    lr_l2=lr_l2.fit(Xtrain,Ytrain)
    l2.append(accuracy_score(lr_l2.predict(Xtrain),Ytrain))
    l2test.append(accuracy_score(lr_l2.predict(Xtest),Ytest))

graph = [l1,l2,l1test,l2test]
color = ["green","black","lightgreen","red"]
label = ["L1","L2","L1test","L2test"]

plt.figure(figsize=(20,8),dpi=80)
for i in range(len(graph)):
    plt.plot(np.linspace(0.05,1,19),graph[i],color[i],label=label[i])
plt.xlabel('C')
plt.ylabel('accurancy')
plt.legend(loc='best') 
plt.show()
可见,至少在我们的乳腺癌数据集下,两种正则化的结果区别不大。但随着 C 的逐渐变大,正则化的强度越来越小,模型在训练集和测试集上的表现都呈上升趋势,直到C=0.8 左右,训练集上的表现依然在走高,但模型在未知数据集上的表现开始下跌,这时候就是出现了过拟合。我们可以认为,C 设定为 0.8 会比较好。在实际使用时,基本就默认使用l2 正则化,如果感觉到模型的效果不好,那就换 L1 试试看。

逻辑回归中的特征工程 

说到降维,我们首先想到的是之前提过的高效降维算法, PCA SVD ,遗憾的是,这两种方法大多数时候不适用于逻辑回归。逻辑回归是由线性回归演变而来,线性回归的一个核心目的是通过求解参数来探究特征X 与标签 y 之间的关系,而逻辑回归也传承了这个性质,我们常常希望通过逻辑回归的结果,来判断什么样的特征与分类结果相关,因此我们希望保留特征的原貌。PCA SVD 的降维结果是不可解释的,因此一旦降维后,我们就无法解释特征和标签之间的关系了。当然,在不需要探究特征与标签之间关系的线性数据上,降维算法PCA SVD 也是可以使用的。
更好的方法是embedded嵌入法, 由于 L1 正则化会使得部分特征对应 的参数为 0 ,因此 L1 正则化可以用来做特征选择,结合嵌入法的模块 SelectFromModel ,我们可以很容易就筛选出 让模型十分高效的特征。注意,此时我们的目的是,尽量保留原数据上的信息,让模型在降维后的数据上的拟合效 果保持优秀,因此我们不考虑训练集测试集的问题,把所有的数据都放入模型进行降维。

机器学习sklearn-逻辑回归_第4张图片

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()

LR_ = LR(solver="liblinear",C=0.8)
score=cross_val_score(LR_,data.data,data.target,cv=10).mean()
X_embedded = SelectFromModel(LR_,norm_order=1).fit_transform(data.data,data.target) #使用L1范数进行筛选
score_=cross_val_score(LR_,X_embedded,data.target,cv=10).mean()
print(score)
print(score_)
print(X_embedded)

梯度下降

逻辑回归的数学目的是求解能够让模型最优化,拟合程度最好的参数 的值,即求解能够让损失函数最小化的值。对于二元逻辑回归来说,有多种方法可以用来求解参数 ,最常见的有梯度下降法(Gradient Descent) ,坐标下降法(Coordinate Descent) ,牛顿法 (Newton-Raphson method) 等,其中又以梯度下降法最为著名。每种方法都涉及复杂的数学原理,但这些计算在执行的任务其实是类似的。
一个多元函数的梯度,是对其自变量求偏导的结果,不是对其参数求偏导的结果。 但是在逻辑回归的数学过程中,损失函数的自变量刚好是逻辑回归的预测函数y(x) 的参数,所以才造成了这种让人误解的, 对多元函数的参数求偏导” 的写法。务必记住,正确的做法是: 在多元函数 ( 损失函数 ) 上对自变量 ( 逻辑回归的预测函数 y(x) 的参数 ) 求偏导 ,求解梯度的方式,和逻辑回归本身的预测函数 y(x) 没有一丝联系。
梯度是一个向量,因此它有大小也有方向。它的大小,就是偏导数组成的向量的大小,又叫
做向量的模。它的方向,几何上来说,就是损失函数的值增加最快的方向,就是小球每次滚动的方向的反方向。只要沿着梯度向量的反方向移动坐标,损失函数的取值就会减少得最快,也就最容易找到损失函数的最小值。
如果步长太大,损失函数下降得就非常快,需要的迭代次数就很少,但梯度下降过程可能跳过损失函数的最低点,无法获取最优值。而步长太小,虽然函数会逐渐逼近我们需要的最低点,但迭代的 速度却很缓慢,迭代次数就需要很多。
在sklearn当中,我们设置参数 max_iter 最大迭代次数来代替步长,帮助我们控制模型的迭代速度并适时地让模型停下。max_iter 越大,代表步长越小,模型迭代时间越长,反之,则代表步长设置很大,模型迭代时间很短。
绘制max_iter学习曲线。
机器学习sklearn-逻辑回归_第5张图片
from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer #导入乳腺癌数据集
from sklearn.model_selection import train_test_split
from sklearn.metrics import  accuracy_score
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


data=load_breast_cancer()
X=data.data
Y=data.target

l1=[]
l1test=[]

Xtrain,Xtest,Ytrain,Ytest=train_test_split(X,Y,test_size=0.3)

for i in np.arange(1,201,20):
    lrl2=LR(penalty='l2',solver='liblinear',C=0.9,max_iter=i)
    lrl2=lrl2.fit(Xtrain,Ytrain)
    l1.append(accuracy_score(lrl2.predict(Xtrain),Ytrain))
    l1test.append(accuracy_score(lrl2.predict(Xtest),Ytest))

graph = [l1,l1test]
color = ["black","green"]
label = ["L1","L1test"]

plt.figure(figsize=(20,8),dpi=80)

for i in range(len(graph)):
    plt.plot(np.arange(1,201,20),graph[i],c=color[i],label=label[i])

plt.legend(loc=0)
plt.xticks(np.arange(1,201,20))
plt.xlabel('max-iter')
plt.ylabel('accurancy')
plt.show()

 中途会遇到警告

这是在提醒我们:参数没有收敛,请增大 max_iter 中输入的数字。但我们不一定要听sklearn 的。 max_iter 很大,意味着步长小,模型运行得会更加缓慢。虽然我们在梯度下降中追求的是损失函数的最小值,但这也可能意味着我们的模型会过拟合(在训练集上表现得太好,在测试集上却不
一定),因此,如果在 max_iter 报红条的情况下,模型的训练和预测效果都已经不错了,那我们就不需要再增大max_iter中的数目了,毕竟一切都以模型的预测效果为基准 —— 只要最终的预测效果好,运行又快,那就一切都好,无所谓是否报红色警告了。

你可能感兴趣的:(sklearn,机器学习,逻辑回归)