机器学习入门(十)——逻辑回归(中)

1.0 决策边界

1.1 什么是决策边界

        以logistic回归为例,当求得参数\theta 之后,那么对于每一个个例x_b,都可以通过代入下式的sigmoid函数对其结果进行预测,函数结果为定义的事件\hat{y} =1概率值\hat{p} ,当\hat{p} >0.5,则认为事件可以发生记为1,否则事件不发生,记为0。

\sigma (x)  = \frac{1}{1+e^{-t} } , t=\theta ^T·x_b

        事件的发生结果以概率值\hat{p} =0.5作为分界判断,而此时的t即为决策边界(decision boundary ),即t=\theta ^T·x_b=0。那么当t=\theta ^T·x_b>0时,1<1+e^{-t}<2,则\hat{p} = \frac{1}{1+e^{-t} }>0.5;反之t=\theta ^T·x_b<0时,1+e^{-t}>2,则\hat{p} <0.5。

        而\theta ^T·x_b=0实际为一条直线。假设特征X只有两个变量\left\{ x_{1},x_{2} \right\} 时,那么决策边界可改写为\theta_{0} + \theta_{1}x_{1}+\theta_{2}x_{2}=0,于是有x_{2}=\frac{ -\theta_{0}-\theta_{1}x_{1}}{\theta_{2}},这样就可以在二维坐标空间中进行绘制。

1.2 决策边界可视化

        以sklearn中的鸢尾花数据集为例,观察logistics回归的决策划分。

1.2.1 准备数据


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]      # 取标签为0,1的数据,取特征的前两个,

y = y[y<2]      # 取标签0,1

plt.scatter(X[y==0,0], X[y==0,1], color="red")      # 绘制标签为0的数据点

plt.scatter(X[y==1,0], X[y==1,1], color="blue")      # 绘制标签为1的数据点

plt.show()

1.2.2 逻辑回归

        然后使用逻辑回归进行分类:


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)

log_reg.coef_      # 输出array([ 3.01749692, -5.03046934])

log_reg.intercept_      # 输出-0.6827383698993108


1.2.3 绘制决策边界

        按照x_{2}=\frac{ -\theta_{0}-\theta_{1}x_{1}}{\theta_{2}}绘制决策边界


def decision_boundary(x1):      # 定义决策边界函数

        x2 = (-log_reg.intercept_ - log_reg.coef_[0] * x1) / log_reg.coef_[1]

        return x2

x1 = np.linspace(4,8,500)      # 生成决策边界的横轴数据

x2 = decision_boundary(x1)        # 生成决策边界的纵轴数据

plt.plot(x1, x2)      # 绘制决策边界

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.legend(('dcsn_bdry', 'Label 0', 'Label 1'))

plt.show()


         上图中的浅蓝色直线就是该分类模型中决策边界,直线上方分类为0,直线下方分类为1。

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

        决策边界实际就是能够把样本正确分类的一条界线,主要有线性决策边界(linear decision boundaries)和非线性决策边界(non-linear decision boundaries)。对于上图中的浅蓝色的直线可以比较完美地将数据分成两类,但是直线的分类方式通常过于简单,实际中遇到更多为复杂的非线性情况。

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

        下面举例一个非线性决策边界的情况:


np.random.seed(666)

X = np.random.normal(0,1,(200,2))      # 生成200在0,1之间的点

y = np.array((X[:,0]**2+X[:,1]**2)<1.5, dtype='int')      # 半径在1.5以内的标签为1,其他为0

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.legend(('Label 0', 'Label 1'))

plt.show()


        根据上图的数据集进行逻辑回归。从上图可以判断,逻辑回归的决策边界接近于一个圆形,因此决策边界的函数应该和圆的函数非常接近,是二次项构成的。因此构建二次多项式logistics回归:


from sklearn.preprocessing import PolynomialFeatures

from sklearn.pipeline import Pipeline

from sklearn.preprocessing import StandardScaler


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)


def PolynomialLogisticRegression(degree):      # 定义多项式logistics回归

      return Pipeline([

                ("poly", PolynomialFeatures(degree)),

                ("std_scaler", StandardScaler()),

                ("log_reg", LogisticRegression())         

      ])


poly_log_reg = PolynomialLogisticRegression(degree=2)      # 建立二次多项式logistics回归实例

poly_log_reg.fit(X,y)

poly_log_reg.score(X, y)      # 输出0.97

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


        上图通过二次多项式得到了较好的决策边界。但实际情况很难通过图形直接判断决策边界函数适合的多项式次数。此时可以设置较大的次数,再通过正则化提高分类结果的准确性。

3.0 逻辑回归和正则化

        依然使用上一章的数据作为示例。

3.1 准备数据

        在上一章数据进行修改,增加部分噪音数据:


np.random.seed(666) 

 X = np.random.normal(0, 1, size=(200, 2)) 

 y = np.array((X[:,0]**2+X[:,1])<1.5, dtype='int') 

for _ in range(20):        # 随机将20个点的标签设为1,作为噪音 

    y[np.random.randint(200)]=1 

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


3.2 逻辑回归(线性)

        首先建立线性的逻辑回归模型:       


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

log_reg3 = LogisticRegression()      # logistic回归的实例化

log_reg3.fit(X_train, y_train)

log_reg.score(X_train, y_train)      # 输出0.7933333333333333

log_reg.score(X_test, y_test)      # 输出0.86


logistic回归的实例化的输出

        上图logistic回归实例化的输出内容中,有几个参数需要注意下。首先“c=1.0”,这里c为超参数,但逻辑回归的正则化中,超参数是加在函数项而非惩罚项,即CJ(\theta ) +L_2,这里与一般正则化的形式不太一样,需要注意。其次“penalty='l2'”,意思是惩罚项采用的L2正则化。

3.3 可视化决策边界

        在回归模型的基础上可视化决策边界:


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


3.4 逻辑回归(多项式)并可视化决策边界

        对上述数据建立多项式逻辑回归模型:


poly_log_reg2 = PolynomialLogisticRegression(degree=2)

poly_log_reg2.fit(X_train, y_train)

poly_log_reg2.score(X_train, y_train)      # 输出0.9133333333333333

poly_log_reg2.score(X_test, y_test)      # 输出0.94

plot_decision_boundary(poly_log_reg2, axis=[-4, 4, -4, 4])

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


       上图可以明显看出多项式回归下的决策边界分界效果明显要比线性分界要好,这一点从score值也可以看出来。

3.5 逻辑回归(高次多项式)和正则化

       建立高次多项式的逻辑回归,如20次,决策边界可视化如下。这强烈不规则的边界必然带来的过拟合。下面就在这个过拟合的基础上加入正则化。

3.5.1 L1正则化

        构建高次(20)多项式的逻辑回归,增加L1正则化。从决策边界可视化结果看出,虽然分类准确率没有非常高,但是没有过拟合,且分类决策边界非常接近原本的真实数据了。


def PolynomialLogisticRegression2(degree, C, penalty):      # 定义含惩罚项参数的多项式逻辑回归模型

        return Pipeline([

                ("poly", PolynomialFeatures(degree=degree)),

                ("std_scaler", StandardScaler()),

                ("log_reg", LogisticRegression(C=C, penalty=penalty))

        ])


    poly_log_reg4 = PolynomialLogisticRegression2(degree=20, C=0.1, penalty='l1')      # 超参数0.1,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], color='red')

    plt.scatter(X[y==1,0], X[y==1,1], color='blue')

    plt.show()


最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容