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

本文深入探讨了逻辑回归中的决策边界概念,解释了其几何意义,并通过鸢尾花数据集的可视化展示了线性和非线性决策边界的形成。通过添加多项式特征,实现了对非线性数据的分类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0x00 前言

在逻辑回归算法中,可以求出各个参数的系数和截距,即参数组 值。那这个参数有几何意义么?

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

0x01 决策边界

1.1 什么是决策边界

回顾逻辑回归分类的原理:通过训练的方式求出一个n+1维向量 ,每当新来一个样本 时,与参数 进行点乘,结果带入sigmoid函数,得到的值为该样本发生我们定义的 事件发生的概率值。如果概率大于0.5,分类为1;否则分类为0。

对于公式:

当t>0时, ,因此  ; 当t>0时, ,因此  ;

也就是,其中有一个边界点  ,大于这个边界点,分类为1,小于这个边界点。我们称之为决策边界(decision boundary)

决策边界:  同时也代表一个直线:假设 有两个特征 ,那么有 

这是一个直线,可以将数据集分成两类。可以改写成我们熟悉的形式:

1.2 决策边界的可视化

在鸢尾花数据集中,画出决策边界。首先可视化数据集

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 playML.model_selection import train_test_split
from playML.LogisticRegression 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.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()

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

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

1.3 线性&非线性决策边界

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

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

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

对于线性这条直线可以比较完美地将数据分成两类。但是直线的分类方式,太简单了。

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

0x02 逻辑回归的非线性决策边界

2.1 线性回归转换成多项式回归

对于线性这条蓝色的直线可以比较完美地将数据分成两类。但是直线的分类方式,太简单了。

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

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

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

为了让逻辑回归学习到这样的决策边界,我们需要引入多项式项。如果将上式中的 整体看作第一个特征 ,将 整体看作第二个特征 ,那么则可以转换成线性回归的问题:其中 前的系数为1, 前系数也为1,且 是系数

这样就从 来说还是线性边界,针对于 来说变成了非线性的圆形决策边界。这就从线性回归转换成多项式回归,同理为逻辑回归添加多项式项,就可以对非线性的方式进行比较好的分类,决策边界就是曲线的形状。

2.2 代码

使用多项式的思路,如何对非线性决策边界的数据进行很好的分类

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

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

from myAlgorithm.LogisticRegression 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()

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

为逻辑回归算法添加多项式项。设置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()

下面我们更改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()

最终的结果,决策边界的外侧比较奇怪,这就是典型的过拟合。

0xFF 总结

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

但是多项式项的阶数越大,越容易过拟合。那么就要进行模型的正则化。下一章就在逻辑回归中使用正则化,且看看sklearn中是如何使用逻辑回归的。

热门文章

直戳泪点!数据从业者权威嘲讽指南!

AI研发工程师成长指南

数据分析师做成了提数工程师,该如何破局?

算法工程师应该具备哪些工程能力

数据团队思考:如何优雅地启动一个数据项目!

数据团队思考:数据驱动业务,比技术更重要的是思维的转变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值