逻辑回归 Logistic Regression

  • 一. 小测试
  • 二 . 决策边界
  • 三 . 逻辑回归中的多项式特征


一. 小测试

上次博客的结尾,我们根据前面的分析给出了逻辑回归算法中最主要得到代码,那么下面我们用上期博客留下来的代码测试一下这个算法的可行性,还是以鸢尾花数据集为例:

既然是测试嘛,数据就不要那么庞大了,简单一点就好!

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] #在X的每一行中,我们只需要选取对于y = 0或者y =1的行
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()

得到的图像为:

逻辑回归代码 skelarn 逻辑回归代码_数据

from model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,seed=666)

from LogisticRegression import LogisticRegression
log_reg = LogisticRegression()
log_reg.fit(X_train,y_train)
log_reg.score(X_test,y_test) #测试一下分类结果怎样?

上面这些代码都是机器学习里面的老套路了,就不赘述了!

log_reg.predict_proba(X_test) #看一下返回的概率怎么样!

逻辑回归代码 skelarn 逻辑回归代码_数据_02


而 y_test 中真实的值又是怎样的呢?Look:

逻辑回归代码 skelarn 逻辑回归代码_逻辑回归代码 skelarn_03


将log_reg.predict_proba(X_test) 的结果经过predict函数之后,得到:

逻辑回归代码 skelarn 逻辑回归代码_多项式_04


显然,预测的都是正确的!看来我们的函数并没有特别大的漏洞!

二 . 决策边界

再回到上篇博客的数学推导部分,梳理一下整个过程:
逻辑回归代码 skelarn 逻辑回归代码_数据_05
我们采用数据集的大量训练得到了 逻辑回归代码 skelarn 逻辑回归代码_多项式_06向量,如果这个样本有 逻辑回归代码 skelarn 逻辑回归代码_python_07 个维度的话,那么 逻辑回归代码 skelarn 逻辑回归代码_多项式_06 就有逻辑回归代码 skelarn 逻辑回归代码_数据_09 个元素(增加一个逻辑回归代码 skelarn 逻辑回归代码_机器学习_10),将其与新传入的样本数据分别进行点乘 ,再将其结果传给 逻辑回归代码 skelarn 逻辑回归代码_多项式_11 函数,得到我们需要的 概率逻辑回归代码 skelarn 逻辑回归代码_python_12 ,如果这个 逻辑回归代码 skelarn 逻辑回归代码_python_12

换句话说,根据 逻辑回归代码 skelarn 逻辑回归代码_多项式_11 函数本身的属性,如果 逻辑回归代码 skelarn 逻辑回归代码_逻辑回归代码 skelarn_15,则返回1;反之,返回 0;
所以,到底取 逻辑回归代码 skelarn 逻辑回归代码_逻辑回归代码 skelarn_16逻辑回归代码 skelarn 逻辑回归代码_数据_17 的关键在于 逻辑回归代码 skelarn 逻辑回归代码_python_18 的取值是否为 逻辑回归代码 skelarn 逻辑回归代码_逻辑回归代码 skelarn_16

逻辑回归代码 skelarn 逻辑回归代码_python_20就是决策边界!

假设我们导入的样本数据中 逻辑回归代码 skelarn 逻辑回归代码_多项式_21 只有两个特征,易得:逻辑回归代码 skelarn 逻辑回归代码_逻辑回归代码 skelarn_22

在二维坐标系中,横轴代表逻辑回归代码 skelarn 逻辑回归代码_多项式_23,纵轴代表 逻辑回归代码 skelarn 逻辑回归代码_多项式_24,故可以 逻辑回归代码 skelarn 逻辑回归代码_多项式_24逻辑回归代码 skelarn 逻辑回归代码_机器学习_26

逻辑回归代码 skelarn 逻辑回归代码_python_27

代码实现一下:

def x2(x1):
    return (-log_reg.coef_[0]*x1 - log_reg.intercept_)/log_reg.coef_[1]
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()

如下图所示:

逻辑回归代码 skelarn 逻辑回归代码_机器学习_28


但往往事实并不是那么的简单和完美,正常情况下,样本的特征远远不止2种,所以决策边界也就不再是直线了:

对于不规则的决策边界,假设平面中有无数可以细分的点,运用之前的算法去预测每个点的具体分类结果,最后绘制出来的不同颜色的点大致构成了其决策边界,算法如下:

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, 7.5, 1.5, 4.5])
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()

逻辑回归代码 skelarn 逻辑回归代码_机器学习_29


再把记忆的时间轴拉回到刚开始学习 逻辑回归代码 skelarn 逻辑回归代码_逻辑回归代码 skelarn_30

from sklearn.neighbors import KNeighborsClassifier ##创建分类器
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train,y_train)

knn_clf.score(X_test,y_test) #准确率为100%

plot_decision_boundary(knn_clf,axis=[4, 7.5, 1.5, 4.5])
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()

最后得到的为决策边界为:

逻辑回归代码 skelarn 逻辑回归代码_python_31


显然,这里不再是一条直线了,当然,这个样本具有偶然性,当逻辑回归代码 skelarn 逻辑回归代码_逻辑回归代码 skelarn_30算法作用在三个类别上时,决策边界又会发生什么变化呢?

knn_clf_all = KNeighborsClassifier(n_neighbors=50) #这里的n_neighbors取50 提高准确率!
knn_clf_all.fit(iris.data[:,:2],iris.target)

plot_decision_boundary(knn_clf_all,axis=[4, 8, 1.5, 4.5])
plt.scatter(iris.data[iris.target==0,0],iris.data[iris.target==0,1])
plt.scatter(iris.data[iris.target==1,0],iris.data[iris.target==1,1])
plt.scatter(iris.data[iris.target==2,0],iris.data[iris.target==2,1])
plt.scatter(X[y==1,0],X[y==1,1],color='blue')
plt.show()

得到的可视化决策边界为:

逻辑回归代码 skelarn 逻辑回归代码_多项式_33


怎么样,是不是对这个算法的作用效果更加的清晰了!

三 . 逻辑回归中的多项式特征

现实应用带来得到数据复杂性并不会简单了用一个直线或者二次曲线作为决策边界就完事了,啥样的情况都有,那么带来的决策边界也是啥样的图形都可能会用上!

逻辑回归代码 skelarn 逻辑回归代码_数据_34


如果你能用直线把这两种颜色的样本点分开,请一定要在评论区留下你的联系方式,我得好好向您请教一下~~

类似于圆形可能更加的适合,逻辑回归代码 skelarn 逻辑回归代码_逻辑回归代码 skelarn_35,那么我们能否让逻辑回归算法学习到这样的一个决策边界呢?

思路依然是来自线性回归,在学习线性回归的时候,多项式回归是不是用来处理不规则曲线拟合的?

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

得到的散点图如下:

逻辑回归代码 skelarn 逻辑回归代码_python_36


显然,其决策边界很像是一个圆形或者是椭圆形,现在用原先的方法看看效果:

from LogisticRegression import LogisticRegression
log_reg =  LogisticRegression()
log_reg.fit(X,y)

来看一下准确率:

逻辑回归代码 skelarn 逻辑回归代码_数据_37


准确率只有 60% 左右,再来看看绘制的决策边界:

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

逻辑回归代码 skelarn 逻辑回归代码_多项式_38


显然,这决策边界画的 啥也不是!我们来引入 多现实特征拟合:

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()) #不是sklearn中的 ,自己实现的
    ])

实例化:

poly_log_reg = PolynomialLogisticRegression(degree=2)
poly_log_reg.fit(X,y)

结果为:

我们现在再来看一下准确率:

逻辑回归代码 skelarn 逻辑回归代码_多项式_39


再来看一下此时的准确率:

逻辑回归代码 skelarn 逻辑回归代码_多项式_40


逻辑回归代码 skelarn 逻辑回归代码_逻辑回归代码 skelarn_41 !,竟然达到了95%,那么决策边界图又是啥样的呢?

逻辑回归代码 skelarn 逻辑回归代码_python_42