逻辑回归阈值_数据分析|逻辑回归是怎样炼成的?(建议收藏)

9aca38f732f6e30afeb29f90a1a29e85.png

OX00 前言

逻辑回归在金融领域,以其出色的可解释性应用最广泛。Kaggle竞赛的统计中,LR算法以63.5%的出产率,荣获各领域中“出场率最高的算法”这一殊荣。

除此之外,逻辑回归(LR)建模过程还体现了数据建模中很重要的思想:对问题划分层次,并利用非线性变换和线性模型的组合,将未知的复杂问题分解为已知的简单问题;从数学推导、理解难度上看,LR也比较容易,没有svm那么繁杂。

#划重点#同步一个重要的事情,小编我近期开通了微信公号, 微信搜索求知鸟,即可关注。
公号里有一篇自我介绍,欢迎来撩。

OX01 认识逻辑回归

线性回归可以解决分类问题嘛?

不可以。

因为,我们实际使用线性回归模型时,做了众多假设,比如:

  • 自变量之间不能存在完全共线性;
  • 总体方程误差项服从均值为0的正态分布;(大数定理)
  • 误差项的方差不受自变量影响且为固定值;(同方差性)
  • 自变量与因变量之间呈线性相关。

逻辑回归其实不是回归算法,是一个分类算法,是一个用于二分分类的算法。其原理是将样本的特征样本发生的概率联系起来,即,预测的是样本发生的概率是多少。由于概率是一个数,因此被叫做“逻辑回归”。

那么回归与分类区别在哪?

分类模型和回归模型本质一样,分类模型可将回归模型的输出离散化,回归模型也可将分类模型的输出连续化。

Linear Regression: 输出一个标量 wx+b,这个值是连续值,所以可以用来处理 回归问题 Logistic Regression:把上面的 wx+b 通过 sigmoid 函数映射到(0,1)上,并划分一个阈值,大于阈值的分为一类,小于等于分为另一类,可以用来处理 二分类问题;
更多内容参考: https://www. zhihu.com/question/2132 9754/answer/151216012

通常意义上,我们将模型输出连续的称为回归模型,将模型输出离散的称为分类模型。

OX02 逻辑回归的数学原理

用条件概率分布的形式表示 P(Y|X),这里随机变量 X 取值为 n 维实数向量,例如x=(x(1),x(2),...,x(n)),Y 取值为 0 或 1;假设有一个二分类问题,输出为y∈{0,1}y∈{0,1},二线性回归模型z=wTx+b是个实数值,我们希望有一个理想的阶跃函数来帮我什么实现z值到0/1值的转化,于是找到了Sigmoid函数来代替:

99dd4a92c3dfdec984d7301fc42cea6a.png

1373813bf7b8bb72523cd6f73d3cfbff.png
数据科学家联盟

有了 Sigmoid 函数之后,由于其值取值范围在[0,1]。就可以将其视为类 1 的后验概率估计 p(y=1|X)。说白了,就是如果有了一个测试点 x,那么就可以用Sigmoid函数算出来的结果当作该点 x 属于类别 1 的概率大小。

于是,非常自然地,我们把 Sigmoid 函数计算得到的值大于等于0.5的归为类别1,小于0.5的归为类别0;(同样的逻辑也出现于感知机模型中,

;若
<=0,则判为误分类点,若
>0,则判为正分类点,“0”就是阈值)。

至于如何求Z中的w值,我们需要定义误差损失函数,模型线性回归最小误差平方和,logistic回归的回归就是模型线性回归中的最小误差平方和。

逻辑回归的损失函数?

简单来说,逻辑回归假设数据服从伯努利分布,通过极大似然函数的方法,运用梯度下降来求解参数,来达到将数据二分类的目的。

逻辑回归的损失函数:输出值与真实值之间差别的惩罚。

假设二分类问题,

02b0779b98f8bf2ab0e85e967b1c9a55.png

模型y的输出等于标签为1(0)的概率P:

a7385a31bf50487f0c183a1d991b9e07.png
MathType编写

2379d245261020e86a50b061d6317a36.png

可以将上面两个式子写成更一般的式子:

b40d5d33e0fad60bd31318e425a68291.png

接着,开始用最大似然求w:

求解步骤:

  1. 写出关于w的似然函数
  2. 取对数
  3. 对w求偏导
  4. 令偏导数为0,求出w

f17fe2839e665acc8730defb0f8158ff.png

给定初始值

指定步长
,就可以不断更新w,直到最大迭代次数,或梯度=0.

逻辑回归损失函数是凸函数,只有一个全局最优点,所以可以采用梯度下降

随机梯度下降与梯度下降最大区别就是梯度下降容易陷入局部最优。

随机梯度下降法更新w:

3fb00a60d158d8d7e710730edc802671.png

OX04 逻辑回归代码实现与调用

逻辑回归的实现:

  • 定义sigmoid方法,使用sigmoid方法生成逻辑回归模型
  • 定义损失函数,并使用梯度下降法得到参数
  • 将参数代入到逻辑回归模型中,得到概率
  • 将概率转化为分类
import numpy as np
# 因为逻辑回归是分类问题,因此需要对评价指标进行更改
from sklearn.metrics import accuracy_score
'''
sklearn.metrics.accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)
normalize:默认值为True,返回正确分类的比例;如果为False,返回正确分类的样本数
'''


class LogisticRegression:

    def __init__(self):
        """初始化Logistic Regression模型"""
        self.coef_ = None
        self.intercept_ = None
        self._theta = None

    """
    定义sigmoid方法
    参数:线性模型t
    输出:sigmoid表达式
    """
    def _sigmoid(self, t):
        return 1. / (1. + np.exp(-t))
    
    """
    fit方法,内部使用梯度下降法训练Logistic Regression模型
    参数:训练数据集X_train, y_train, 学习率, 迭代次数
    输出:训练好的模型
    """
    def fit(self, X_train, y_train, eta=0.01, n_iters=1e4):
        
        assert X_train.shape[0] == y_train.shape[0], 
            "the size of X_train must be equal to the size of y_train"

        """
        定义逻辑回归的损失函数
        参数:参数theta、构造好的矩阵X_b、标签y
        输出:损失函数表达式
        """
        def J(theta, X_b, y):
            # 定义逻辑回归的模型:y_hat
            y_hat = self._sigmoid(X_b.dot(theta))
            try:
                # 返回损失函数的表达式
                return - np.sum(y*np.log(y_hat) + (1-y)*np.log(1-y_hat)) / len(y)
            except:
                return float('inf')
        """
        损失函数的导数计算
        参数:参数theta、构造好的矩阵X_b、标签y
        输出:计算的表达式
        """
        def dJ(theta, X_b, y):
            return X_b.T.dot(self._sigmoid(X_b.dot(theta)) - y) / len(y)

        """
        梯度下降的过程
        """
        def gradient_descent(X_b, y, initial_theta, eta, n_iters=1e4, epsilon=1e-8):
            theta = initial_theta
            cur_iter = 0
            while cur_iter < n_iters:
                gradient = dJ(theta, X_b, y)
                last_theta = theta
                theta = theta - eta * gradient
                if (abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
                    break
                cur_iter += 1
            return theta

        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        initial_theta = np.zeros(X_b.shape[1])
        # 梯度下降的结果求出参数heta
        self._theta = gradient_descent(X_b, y_train, initial_theta, eta, n_iters)
        # 第一个参数为截距
        self.intercept_ = self._theta[0]
        # 其他参数为各特征的系数
        self.coef_ = self._theta[1:]
        return self

    """
    逻辑回归是根据概率进行分类的,因此先预测概率
    参数:输入空间X_predict
    输出:结果概率向量
    """
    def predict_proba(self, X_predict):
        """给定待预测数据集X_predict,返回表示X_predict的结果概率向量"""
        assert self.intercept_ is not None and self.coef_ is not None, 
            "must fit before predict!"
        assert X_predict.shape[1] == len(self.coef_), 
            "the feature number of X_predict must be equal to X_train"

        X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])
        # 将梯度下降得到的参数theta带入逻辑回归的表达式中
        return self._sigmoid(X_b.dot(self._theta))

    """
    使用X_predict的结果概率向量,将其转换为分类
    参数:输入空间X_predict
    输出:分类结果
    """
    def predict(self, X_predict):
        """给定待预测数据集X_predict,返回表示X_predict的结果向量"""
        assert self.intercept_ is not None and self.coef_ is not None, 
            "must fit before predict!"
        assert X_predict.shape[1] == len(self.coef_), 
            "the feature number of X_predict must be equal to X_train"
        # 得到概率
        proba = self.predict_proba(X_predict)
        # 判断概率是否大于0.5,然后将布尔表达式得到的向量,强转为int类型,即为0-1向量
        return np.array(proba >= 0.5, dtype='int')

    def score(self, X_test, y_test):
        """根据测试数据集 X_test 和 y_test 确定当前模型的准确度"""

        y_predict = self.predict(X_test)
        return accuracy_score(y_test, y_predict)

    def __main__(self):
        return "LogisticRegression()"

数据集:

#数据展示

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

iris = datasets.load_iris()
X = iris.data
y = iris.target
X = X[y<2,:2]
y = y[y<2]
plt.scatter(X[y==0,0], X[y==0,1], color="red")
plt.scatter(X[y==1,0], X[y==1,1], color="blue")
plt.show()

调用逻辑回归算法

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

X_train, X_test, y_train, y_test = train_test_split(X, y, seed=666)
log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)
# 查看训练数据集分类准确度
log_reg.score(X_test, y_test)
"""
输出:1.0
"""

# 查看逻辑回归得到的概率
log_reg.predict_proba(X_test)
"""
输出:
array([ 0.92972035,  0.98664939,  0.14852024,  0.17601199,  0.0369836 ,
        0.0186637 ,  0.04936918,  0.99669244,  0.97993941,  0.74524655,
        0.04473194,  0.00339285,  0.26131273,  0.0369836 ,  0.84192923,
        0.79892262,  0.82890209,  0.32358166,  0.06535323,  0.20735334])
"""

# 得到逻辑回归分类结果
log_reg.predict(X_test)
"""
输出:
array([1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0])
"""
sklearn中的评价方法: https:// blog.csdn.net/hlang8160 /article/details/78040311

OX05 决策边界

在逻辑回归算法中,可以求出各个参数的系数和截距,即参数组

(上文中的w)值。那这个参数有几何意义么?

在本篇文章中会引出分类文中非常重要的一个概念:决策边界。通过对决策边界的学习,可以更加好的可视化分类结果。进而更好的理解分类算法。

5.1 什么是决策边界

所谓决策边界就是能够把样本正确分类的一条边界,主要有线性决策边界(linear decision boundaries)和非线性决策边界(non-linear decision boundaries)。

注意:决策边界是假设函数的属性,由参数决定,而不是由数据集的特征决定。

下面主要举一些例子,形象化的来说明线性决策边界和非线性决策边界。先看一个线性决策边界的例子:

OX05 决策边界

c3b8920975b3b885c19dd7aa195b246e.png

如果遇到下图的情况,就不能用一个直线将其进行分类了,而是可以用一个圆将数据进行分类。下面来看一下非线性的决策边界的例子:

ca2ef67990f209ea88852d1e0c8c5a70.png

5.2 线性决策边界

在逻辑回归中,我们把 Sigmoid 函数计算得到的值大于等于0.5的归为类别1,小于0.5的归为类别0;

为啥是0.5?

对于公式:

a6ad3805009a31940e6af56ed516b7c5.png

当t>0,p>0.5;当t<0时,p<0.5.

也就是说,存在一个边界点

,大于这个边界点,标签为1,小于这个边界点,标签为0.
我们称呼
为决策边界。

决策边界

同时也是一条直线;假设x有两个特征x1,x2,那么有

也就是说,

e2c7a96808b89c57e0dd11e52eb9f934.png

线性决策边界可视化:

#数据展示
#线性决策边界可视化 数据展示
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

iris = datasets.load_iris()
X = iris.data
y = iris.target
X = X[y<2,:2]
y = y[y<2]
plt.scatter(X[y==0,0], X[y==0,1], color="red")
plt.scatter(X[y==1,0], X[y==1,1], color="blue")
plt.show()

03ba7ed74d4a60c2ccf44d3e89dace1f.png
#使用逻辑回归进行训练
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

X_train, X_test, y_train, y_test = train_test_split(X, y)
log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)
log_reg.coef_
"""
输出:
array([ 3.01796521, -5.04447145])
"""
log_reg.intercept_
"""
输出:
-0.6937719272911228
"""

现在按照公式,创建一个函数x2,一旦传来一个x1,就根据公式得到决策边界的直线:

def x2(x1):
    return (-log_reg.coef_[0] * x1 - log_reg.intercept_) / log_reg.coef_[1]

# 生成一条直线,x为4~8范围内的1000点 y为x2函数的调用,
x1_plot = np.linspace(4, 8, 1000)

x2_plot = x2(x1_plot)
plt.scatter(X[y==0,0], X[y==0,1], color="red")
plt.scatter(X[y==1,0], X[y==1,1], color="blue")
plt.plot(x1_plot, x2_plot)
plt.show()

ea8f87df609e79b0993e5980b5d30cfc.png

这条直线就是决策边界,新来的点在直线上方分类为0,直线下方分类为1

但是可以看出,线性决策边界只是一根直线,很简单,因此加入多项式项,使得分类算法的决策边界不再规律。

5.3 非线性决策边界

如果我们遇到下图的情况,我们就不能用一个直线将其进行分类了,而是可以用一个圆将数据进行分类。

0e63731904b324f6dc7e4a56fb855e9b.png

那么如何使用逻辑回归算法得到非直线的决策边界呢?

我们回忆一下中学的数据知识——圆的表达式:

b4ad742b2b1ad46d7b57cf4a2da9d3c3.png
# 非线性决策边界


import numpy as np
import matplotlib.pyplot as plt

np.random.seed(666)
X = np.random.normal(0, 1, size=(200, 2))
y = np.array((X[:,0]**2+X[:,1]**2)<1.5, dtype='int')
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

a79c22cffd816cd2d855f81acb2a7767.png

首先我们使用没添加多项式项的逻辑回归函数,对上面的样本进行划分。得到的分类结果应该是很差的。

#使用没有添加多项式特征,对样本进行划分
from sklearn.linear_model import LogisticRegression
log_reg = LogisticRegression()
log_reg.fit(X, y)
log_reg.score(X, y)

# 绘制决策边界的方法
def plot_decision_boundary(model, axis):
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1, 1),
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]
    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)
    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9']) 
    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)

plot_decision_boundary(log_reg, axis=[-4, 4, -4, 4])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

f3436d183b630ed8e31dace2db1fd806.png

然后使用逻辑回归的方式添加多项式特征,对上面的样本进行划分:

为逻辑回归算法添加多项式项。设置pipeline。列表中每个元素是管道中的一步,每一步是一个元组,元组第一个元素是字符串表示做什么,第二个元素是类的对象。管道的第一步是添加多项式项,第二部是归一化,第三部进行逻辑回归过程,返回实例对象。
# 逻辑回归使用多项式特征后
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

# 为逻辑回归添加多项式项的管道
def PolynomialLogisticRegression(degree):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scaler', StandardScaler()),
        ('log_reg', LogisticRegression())
    ])

# 使用管道得到对象
poly_log_reg = PolynomialLogisticRegression(degree=2)
poly_log_reg.fit(X, y)

"""
输出:
Pipeline(steps=[('poly', PolynomialFeatures(degree=2, include_bias=True, interaction_only=False)), ('std_scaler', StandardScaler(copy=True, with_mean=True, with_std=True)), ('log_reg', LogisticRegression())])
"""

poly_log_reg.score(X, y)
"""
输出:
0.94999999999999996
"""
plot_decision_boundary(poly_log_reg, axis=[-4, 4, -4, 4])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

8cc531b808812a1ea3d40e302c83371b.png

下面我们更改degree参数(多项式拓展的阶数),将其变大(那肯定会过拟合):

poly_log_reg2 = PolynomialLogisticRegression(degree=20)
poly_log_reg2.fit(X, y)
plot_decision_boundary(poly_log_reg2, axis=[-4, 4, -4, 4])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

a95119acbf1e5b56dd469c85a8a7c151.png

总结:

决策边界是分类中非常重要的一个概念。线性决策边界就是一条直线,而在真实数据,很少是一根直线就能分类的,通常都要加上多项式项,也就是非线性的决策边界。这样才能解决更复杂的问题。

但是多项式项的阶数越大,越容易过拟合。那么就要进行模型的正则化。

OX06 sklearn中的逻辑回归与正则化

6.1 sklearn中的逻辑回归

在逻辑回归中添加多项式项,从而得到不规则的决策边界,进而对非线性的数据进行很好的分类。但是众所周知,添加多项式项之后,模型会变得很复杂,非常容易出现过拟合。因此就需要使用正则化,且sklearn中的逻辑回归,都是使用的正则化。

# 数据点可视化
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(666)
# 构建服从标准差为0,方差为1的分布,200个样本,有两个特征
X = np.random.normal(0, 1, size=(200, 2))
# 构建输入空间X与标签y的关系:是一个抛物线,通过布尔向量转为int类型
y = np.array((X[:,0]**2+X[:,1])<1.5, dtype='int')
# 随机在样本中挑20个点,强制分类为1(相当于噪音)
for _ in range(20):
    y[np.random.randint(200)] = 1
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

c175e82c9ce2c07e13ea165fe6ebe39d.png
# 训练模型
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)

log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)
#输出
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='warn',
          n_jobs=None, penalty='l2', random_state=None, solver='warn',
          tol=0.0001, verbose=0, warm_start=False)

C:正则化系数,且超参数C默认1。

Penalty:惩罚项目,L1,L2,默认L2.当模型参数满足高斯分布时,用L2;当模型参数参数满足拉普拉斯分布,使用L1;当选择L1时,损失函数只能选择liblinear(坐标轴下降法,l1正则化的损失函数不是连续可导的-产生稀疏解);选择L2正则项,那么可以选择lbfgs(拟牛顿法也就是二阶导数海森矩阵来优化损失函数),newton-cg(牛顿法家族),sag(随机平均梯度下降法,一阶求导),saga,libliner

Solver:逻辑回归损失函数。Libliner,lbfgs,newton-cg,sag,saga.默认libliner(L1或L2),适用于数据量小的数据集,当数据集大,使用sag,或saga法(使用一部分样本计算梯度)

class_weight:类型权重参数,一般默认值选择类型权重一致!而balanced,根据训练样本量自动计算权重,当类型样本多,权重低;当类型样本量越少,权重高!(当样本实衡选择balanced)

Max_iter:最大迭代次数,默认为10

N_jobs:拟合,预测时,选择cpu的核数,默认是1.

sample_weight:样本权重参数,当样本实衡时,调节class_weight与在使用fit函数时,选择sample_weight来自己调节每个样本权重!

Thresholds:设置阈值范围!(当样本失衡,可以调增阈值来使得对较小的类别更加敏感!)

5114c81de132ae9ea03ef963accde7fa.png
参考: https:// blog.csdn.net/lc5742605 70/article/details/82116197
log_reg.score(X_train, y_train)
"""
输出:
0.79333333333333333
"""
log_reg.score(X_test, y_test)
"""
输出:
0.85999999999999999
"""

我们发现准确不高,这很正常!因为设置的就是非线性的数据,而现在用的还是没加多项式的逻辑回归。

下面可以可视化一下决策边界:

def plot_decision_boundary(model, axis):   
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1, 1),
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]
    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)
    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)

plot_decision_boundary(log_reg, axis=[-4, 4, -4, 4])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

42a1a5f0464a779d3f98e5bd86ad028c.png

尝试使用多项式项进行逻辑回归。使用pipeline方式组合三个步骤,得到一个使用多项式项的逻辑回归的方法:

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

def PolynomialLogisticRegression(degree):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scaler', StandardScaler()),
        ('log_reg', LogisticRegression())
    ])

poly_log_reg = PolynomialLogisticRegression(degree=2)
poly_log_reg.fit(X_train, y_train)
#输出
Pipeline(memory=None,
     steps=[('poly', PolynomialFeatures(degree=2, include_bias=True, interaction_only=False)), ('std_scaler', StandardScaler(copy=True, with_mean=True, with_std=True)), ('log_reg', LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='warn',
          n_jobs=None, penalty='l2', random_state=None, solver='warn',
          tol=0.0001, verbose=0, warm_start=False))])

训练结果:

# 训练结果

poly_log_reg.score(X_train, y_train)
"""
输出:0.91333333333333333
"""
poly_log_reg.score(X_test, y_test)
"""
输出:
0.93999999999999995
"""
plot_decision_boundary(poly_log_reg, axis=[-4, 4, -4, 4])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

bc3e49298cc83a2d785f36ff0077ea76.png

下面设置一个比较大的阶数

#给多项式添加一个高阶


poly_log_reg2 = PolynomialLogisticRegression(degree=20)
poly_log_reg2.fit(X_train, y_train)
poly_log_reg2.score(X_train, y_train)
"""
输出:0.93999999999999995
"""
poly_log_reg2.score(X_test, y_test)
"""
输出:0.93999999999999995
"""
plot_decision_boundary(poly_log_reg2, axis=[-4, 4, -4, 4])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

f8501f0efd9452eaca2010523cf663ef.png

其实单看结果,还看不出来太多,因为我们的模型设置的很简单。但是看决策边界的话,就知道,这个奇奇怪怪的曲线,一瞅就是过拟合了。

6.2 正则化

前面提到,逻辑回归默认采用l2正则,这里我们调整参数C,来看看正则化效果:

# 逻辑回归默认采用l2正则,这里调控参数C模拟正则
def PolynomialLogisticRegression(degree, C):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scaler', StandardScaler()),
        ('log_reg', LogisticRegression(C=C))
    ])

poly_log_reg3 = PolynomialLogisticRegression(degree=20, C=0.1)
poly_log_reg3.fit(X_train, y_train)
#输出
Pipeline(memory=None,
     steps=[('poly', PolynomialFeatures(degree=20, include_bias=True, interaction_only=False)), ('std_scaler', StandardScaler(copy=True, with_mean=True, with_std=True)), ('log_reg', LogisticRegression(C=0.1, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='warn',
          n_jobs=None, penalty='l2', random_state=None, solver='warn',
          tol=0.0001, verbose=0, warm_start=False))])

使用参数进行模型正则化,在构建管道时,用参数C去覆盖。同时在生成多项式逻辑回归实例参数时,同样设置阶数为20,然后设置一个比较小的损失函数的权重参数,相当于让模型正则化的项起到更大的作用,让分类准确度损失函数起到小一点的作用。

在训练数据集及测试数据集上的表现如下:

poly_log_reg3.score(X_train, y_train)
"""
输出:0.85333333333333339
"""
poly_log_reg3.score(X_test, y_test)
"""
输出:0.92000000000000004
"""
plot_decision_boundary(poly_log_reg3, axis=[-4, 4, -4, 4])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

a9ea6190021245ca50e5ae1703055c84.png

与没正则的情况下相比较,貌似是好了一点。

换用l1正则,再测试下:

#换用l1正则,继续测试

def PolynomialLogisticRegression(degree, C, penalty):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scaler', StandardScaler()),
        ('log_reg', LogisticRegression(C=C, penalty=penalty))
    ])

poly_log_reg4 = PolynomialLogisticRegression(degree=20, C=0.1, penalty='l1')
poly_log_reg4.fit(X_train, y_train)
poly_log_reg4.score(X_train, y_train)
"""
输出:0.8266666666666667
"""
poly_log_reg4.score(X_test, y_test)
"""
输出:0.9
"""
plot_decision_boundary(poly_log_reg4, axis=[-4, 4, -4, 4])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

8f072b4d3db480e1aad28de59274edfc.png

虽然分类准确率比较低,但是没有过拟合,分类决策边界非常接近原本的真实数据了。

总结:

在这一篇文章中,就介绍了sklearn中如何使用逻辑回归,并对不同的正则化项得到的效果进行了展示。在实际使用中,阶数degree,参数C以及正则化项,都是超参数,使用网格搜索的方式得到最佳的组合。

推荐阅读(获权):

出场率No.1的逻辑回归算法,是怎样“炼成”的?

逻辑回归的本质及其损失函数的推导、求解 (两种不同角度的解答,很精彩)

逻辑回归代码实现与调用

逻辑回归的决策边界及多项式

sklearn中的逻辑回归中及正则化


看到这里,这么长的干货还不点赞收藏嘛,嘻嘻。

目前知乎数据分析专栏,已经将近1500小伙伴关注了,点击下方链接关注专栏:

数据分析​zhuanlan.zhihu.com
e2d208952010b889468e32b098693f1d.png

-------------------------正文结束--------------------------

#划重点#同步一个重要的事情,小编我近期开通了微信公号,

微信搜索求知鸟,即可关注。

公号里有一篇自我介绍,欢迎来撩。

开通公号的原因:

  • 文章越来越多,很多号主开始转载我的文章,为了交流方便就开通了公号。
  • 通过公号,可以很方便的获得代码,csv文件。
  • 通过公号,可以更快的找到我。(现在加v,可以交流秋招经历哦)。
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值