机器学习系列(二十七)——决策边界与Logistic回归使用多项式特征

决策边界

由逻辑回归的原理知,对于我们求得的概率:

当时,,此时,即样本被分类为类别1,否则样本将被分类为类别0。而逻辑回归是基于线性回归的,这个影响分类结果的超平面就被称之为决策边界。如果仅有两个特征,则这个决策边界就是一条直线。以上篇文章中使用的分离出来的鸢尾花数据为例,我们来绘制一下相应的决策边界,绘制之前要知道求得的和截距值:

x.png

下面绘制决策边界:

'''绘制决策边界'''
def x2(x1):
    return (-log_reg.coef_[0] * x1 - log_reg.interception_)/log_reg.coef_[1]
x1_plot = np.linspace(4,8,1000)

x2_plot = x2(x1_plot)

plt.plot(x1_plot,x2_plot)
plt.scatter(X[y==0,0],X[y==0,1],color='r')
plt.scatter(X[y==1,0],X[y==1,1],color='b')
plt.show()
决策边界图示

这样一来对于一个新来的样本,如果,即样本落到直线下方,我们将它分类为1,相反则分类为0。如果落在决策边界上,则分类为任一类都是可以的。
由此也可以看出,目前为止,逻辑回归的本质还是基于线性回归的,不过我们也可以像多项式回归一样,加入多项式项,这样就可以得到不规则的决策边界。首先来封装一个决策边界绘制函数:

'''绘图查看决策边界'''
def plot_decision_boundary(model,axis):
    '''axis是x轴y轴对应的范围'''
    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, 7.5, 1.5, 4.5])
plt.scatter(X[y==0,0],X[y==0,1],color='r')
plt.scatter(X[y==1,0],X[y==1,1],color='b')
plt.show()
决策边界

我们也可以绘制其它分类算法的决策边界,比如knn,在同样的样本数据下绘制knn算法的决策边界:

'''knn决策边界是没有表达式的'''
from sklearn.neighbors import KNeighborsClassifier
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train,y_train)
knn_clf.score(X_test,y_test)
plot_decision_boundary(knn_clf,axis=[4, 7.5, 1.5, 4.5])
plt.scatter(X[y==0,0],X[y==0,1],color='r')
plt.scatter(X[y==1,0],X[y==1,1],color='b')
plt.show()
knn决策边界

可以看到knn决策边界是不规则的。由于knn算法支持多分类,鸢尾花数据集共三个类别,下面绘制有三个类别的决策边界,不过为了可视化方便,特征仍然是取前两个:

'''knn天然支持多分类,三分类决策边界'''
X2 = iris.data[:,:2]
y2 = iris.target
knn_clf_all = KNeighborsClassifier()
knn_clf_all.fit(X2,y2)
plot_decision_boundary(knn_clf_all,axis=[4, 8, 1.5, 4.5])
plt.scatter(X2[y2==0,0],X2[y2==0,1],color='r')
plt.scatter(X2[y2==1,0],X2[y2==1,1],color='g')
plt.scatter(X2[y2==2,0],X2[y2==2,1],color='b')
plt.show()
三分类决策边界

这个的决策边界更是不规则,由模型的复杂度理论知道,knn算法中k越小,模型复杂度就越高,也越容易出现过拟合,这样的决策边界往往是过拟合的。将k增大到50,再绘制一次决策边界:

'''指定k=50重新绘制'''
knn_clf2 = KNeighborsClassifier(50)
knn_clf2.fit(X2,y2)
plot_decision_boundary(knn_clf2,axis=[4, 8, 1.5, 4.5])
plt.scatter(X2[y2==0,0],X2[y2==0,1],color='r')
plt.scatter(X2[y2==1,0],X2[y2==1,1],color='g')
plt.scatter(X2[y2==2,0],X2[y2==2,1],color='b')
plt.show()
k=50决策边界

此时决策边界就要光滑很多,因为k增大了,模型复杂度也相应降低,模型泛化能力更强。


逻辑回归中添加多项式特征

实际中并非所有决策边界都能用直线表示,如下面的二分类就是一个非线性决策边界:

非线性决策边界

我们能不能让逻辑回归学习到这样的决策边界呢?答案是肯定的,可以在逻辑回归中添加多项式特征项,由于多项式可以任意精度逼近任何曲线,加入多项式项的逻辑回归自然也能有任意形状的决策边界。下面在模拟数据集上测试一下加入多项式特征的逻辑回归。生成模拟数据集:

import numpy as np
import matplotlib.pyplot as plt
np.random.seed(666)
X = np.random.normal(0,1,size=(200,2))
'''特征平方和小于1.5归类为1'''
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 play_Ml.LogisticRegression import LogisticRegression
log_reg = LogisticRegression()
log_reg.fit(X,y)

分类准确率:


准确率

这个准确率是比较低的,相应的决策边界:

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()
逻辑回归决策边界

决策边界也和实际大不相符。
加入多项式特征后使用逻辑回归:

'''添加多项式'''
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
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)
poly_log_reg.score(X,y)

我们仍然是使用了Pipeline来将这些过程封装到了一起,使用的逻辑回归却是我们自己写的,不过由于逻辑是模拟sklearn中的逻辑回归,所以可以无缝衔接使用,此时准确率:


准确率

准确率已有95%,相应的决策边界:


决策边界

加入多项式特征项后和真实的边界已非常接近。
关于加入多项式特征的逻辑回归需要注意的是,多项式回归中如果次数过高会出现过拟合,因此逻辑回归使用的多项式次数很高时也会出现过拟合,所以在逻辑回归中一般都会对模型进行正则化,关于逻辑回归的正则化,将在下一篇介绍。

你可能感兴趣的:(机器学习系列(二十七)——决策边界与Logistic回归使用多项式特征)