基于Logistic回归和Sigmoid函数的分类(一)

2019-08-14 17:00:13 浏览数 (1)

  • 线性回归

假设现有一些二维数据点,我们用一条线(直线或者曲线)对这些点进行拟合,这个拟合的过程就称作回归。如果用直线拟合,就是线性回归。

在多维空间下线性回归的公式为:

z = w0*x0 w1*x1 w2*x2 ··· wn*xn。其中w0~wn为回归系数,

x0~ xn为各坐标值。

用矩阵的写法则为:

  • Logistic 函数

Logistic函数是一类函数的集合,其定义为:

其中,x0为x值的中点,L为函数曲线的最大值,k为函数曲线的曲率

  • Sigmoid 函数

Sigmoid函数是一个在生物学中常见的S型函数,也称为S型生长曲线。它可以将实数域映射到(0,1),并且单调递增。其函数由下列公式定义:

其导数为:

可以看出,Sigmoid 函数是Logistic函数的一个特例。

Sigmoid函数常用做神经网络的激活函数。它也可以用于Logistic回归分类。我们在每一个特征上乘以一个回归系数然后求和:

再将结果代入Sigmoid函数中,h =S(z), 进而得到一个范围在0~1之间的数值。假如我们的分类问题的结果只有两个类别,则可以将大于等于0.5的归入1类,小于0.5即被归入0类(即z >0 归入1类,z<0 归入0类)。

确定了分类器的函数形式之后,现在的问题变成了:最优的回归系数(矩阵W)是多少?

  • 梯度下降算法求最优回归系数

本例的数据集保存在文本文件中:

首先导入数据集,注意,代码里额外添加了一个常数特征x0=1,和w0乘得到截距w0。

代码语言:javascript复制
from numpy import *
def loadDataSet():
    dataMat = []; labelMat = []
    fr = open('testSet.txt')
    for line in fr.readlines():
        lineArr = line.strip().split()
        ##添加一个常数特征x0=1,和w0乘得到截距,z = w0   w1*x1 w2*x2
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])#
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat

定义Sigmoid函数:

代码语言:javascript复制
def sigmoid(inX):
    return 1.0/(1 exp(-inX))

再用梯度下降算法求权重系数:

代码语言:javascript复制
def gradDescend(dataMatIn, classLabels):
    dataMatrix = mat(dataMatIn) #mx3  #转换成100x3矩阵(3个特征,含常数特征)
    labelMat = mat(classLabels).transpose() #转换成mx1矩阵 
    m,n = shape(dataMatrix) #m=100, n=
    alpha = 0.001 #步长
    maxCycles = 500 #最大迭代步数
    weights = ones((n,1))#初始化权重可以全部设置为1
    for k in range(maxCycles):              #heavy on matrix operations
        h = sigmoid(dataMatrix*weights)     #matrix mult, h shape is m x1
        error = h - labelMat             #误差,shape mx1
        #梯度下降算法的变种
        weights -=  alpha * dataMatrix.transpose() *error#matrix mult (  3xm x mx1 -> 3x1)
    #print("error = ", error)
    return weights # 3x1

求得权重weights(w0,w1, w2 =weights)之后,根据判别临界条件: w0*x0 w1* x1 w2*x2 = 0 ,

即 w0 w1*X w2*Y =0 可得到分类所用直线的方程为:

Y = -(w0 w1*X)/ w2

最后用matplotlab 把数据点和分类的边界线画出来。

可以看到,错判的点数很少。当然,这和数据集的数据点分布有关。只有当数据集基本线性可分时,用本例的线性回归分类算法才能得到较好的效果。

代码语言:javascript复制
def plotBestFit(weights):
    import matplotlib.pyplot as plt
    dataMat,labelMat=loadDataSet()
    dataArr = array(dataMat)
    n = shape(dataArr)[0] 
    xcord1 = []; ycord1 = []
    xcord2 = []; ycord2 = []
    for i in range(n):
        if int(labelMat[i])== 1:
            xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])
        else:# label =0
            xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s', label ="class 1")
    ax.scatter(xcord2, ycord2, s=30, c='green',label ="class 0")

    #画出分类所用的线
    x = arange(-4.0, 4.0, 0.1)
    w0, w1, w2 = weights
    y = (0 - w0 - w1*x) / w2
    #x= x.reshape(1,-1)
    ax.plot(x, y,label ="判别线")
    plt.xlabel('X1'); plt.ylabel('X2');
    ax.legend()
    plt.title("梯度下降算法  Logistic回归 示例")
    plt.show()
    
    
dataArr, labelMat = loadDataSet()
weights = gradDescend(dataArr, labelMat)
print(weights)
plotBestFit(weights)

0 人点赞