机器学习笔记(六)Logistic回归

目录

一、什么是Logistics回归

二、sigmoid函数

三、梯度上升法

四、代码实现

数据导入

 决策边界

 梯度上升

 五、总结


一、什么是Logistics回归

logistic回归是一种广义线性回归(generalized linear model),因此与多重线性回归分析有很多相同之处。它们的模型形式基本上相同,都具有 w‘x+b,其中w和b是待求参数,其区别在于他们的因变量不同,多重线性回归直接将w‘x+b作为因变量,即y =w‘x+b,而logistic回归则通过函数L将w‘x+b对应一个隐状态p,p =L(w‘x+b),然后根据p 与1-p的大小决定因变量的值。如果L是logistic函数,就是logistic回归,如果L是多项式函数就是多项式回归。

logistic回归的因变量可以是二分类的,也可以是多分类的,但是二分类的更为常用,也更加容易解释,多类可以使用softmax方法进行处理。实际中最为常用的就是二分类的logistic回归。

二、sigmoid函数

机器学习笔记(六)Logistic回归_第1张图片

使用逻辑回归进行分类,就是要找到绿色这样的分界线,使其能够尽可能地对样本进行正确分类,也就是能够尽可能地将两种样本分隔开来。因此我们可以构造这样一个函数,来对样本集进行分隔:

其中 i=1,2,...m,表示第 i个样本, n 表示特征数,当 z(x^{(i)})>0 时,对应着样本点位于分界线上方,可将其分为"1"类;当  z(x^{(i)})<0 时 ,样本点位于分界线下方,将其分为“0”类。

 

逻辑回归作为分类算法,它的输出是0/1。那么如何将输出值转换成0/1呢?

这就需要一个新的函数——sigmoid 函数

sigmoid 函数:

机器学习笔记(六)Logistic回归_第2张图片

函数图像为:

img

三、梯度上升法

梯度上升法基于的思想是:要找到某函数的 最大值,最好的方法是沿着该函数的梯度方向探寻。如果梯度记为∇,则函数f(x,y)的梯度由 下式表示:

这个梯度意味着要沿x的方向移动 ,沿y的方向移动 。其中,函数f(x,y) 必须要在待计算的点上有定义并且可微。如下图:

        如图,梯度上升算法到达每个点后都会重新估计移动的方向。从P0开始,计算完该点的梯度,函数就根据梯度移动到下一点P1。在P1点,梯度再次被重新计算,并沿新的梯度方向移动到P2。如此循环迭代,直到满足停止条件。迭代的过程中,梯度算子总是保证我们能选取到最佳的移动方向。

        梯度上升算法沿梯度方向移动了一步。可以看到,梯度算子总是指向函数值增长最快的方向。这里所说的是移动方向,而未提到移动量的大小。该量值称为步长,记做α。用向 量来表示的话,梯度上升算法的迭代公式如下:

        该公式将一直被迭代执行,直至达到某个停止条件为止,比如迭代次数达到某个指定值或算 法达到某个可以允许的误差范围。

四、代码实现

数据导入

# 加载数据集
def loadDataSet():
    dataMat = []                                                      # 数据列表
    labelMat = []                                                     # 标签列表
    fr = open('testSet.txt')                                          # 打开文件
    for line in fr.readlines():                                       # 遍历每行,读取数据
        lineArr = line.strip().split()                                # 去除回车符
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])   # 把此行的数据添加到数据列表里面
        labelMat.append(int(lineArr[2]))                              # 添加标签进列表
    return dataMat, labelMat
# 绘制数据集
def showData():
    dataMat, labelMat = loadDataSet()                      # 加载数据集,标签
    dataArr = array(dataMat)                               # 转换成umPy的数组
    n = shape(dataArr)[0]                                  # 获取数据总数
    xcord1 = []; ycord1 = []                               # 存放正样本
    xcord2 = []; ycord2 = []                               # 存放负样本
    for i in range(n):                                     # 依据数据集的标签来对数据进行分类
        if int(labelMat[i]) == 1:                          # 数据的标签为1,表示为正样本
            xcord1.append(dataArr[i, 1]); ycord1.append(dataArr[i, 2])
        else:                                              # 否则,若数据的标签不为1,表示为负样本
            xcord2.append(dataArr[i, 1]); ycord2.append(dataArr[i, 2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=15, c='blue')             # 绘制正样本
    ax.scatter(xcord2, ycord2, s=15, c='red', marker='s')  # 绘制负样本
    plt.title('DateSet')                                   # 标题
    plt.xlabel('X1'); plt.ylabel('X2')                     # x,y轴的标签
    plt.show()

决策边界

# sigmoid函数
def sigmoid(inX):
    return 1.0 / (1 + exp(-inX))
# 梯度上升算法
def gradAscent(dataMatIn, classLabels):                            # dataMatIn数据集、classLabels数据标签
    dataMatrix = mat(dataMatIn)                                    # 转换为NumPy矩阵
    labelMat = mat(classLabels).transpose()                        # 转换为NumPy矩阵,并且矩阵转置
    m, n = shape(dataMatrix)                                       # 获取数据集矩阵的大小,m为行数,n为列数
    alpha = 0.001                                                  # 目标移动的步长
    maxCycles = 500                                                # 迭代次数
    weights = ones((n, 1))                                         # 权重初始化为1
    for k in range(maxCycles):                                     # 重复矩阵运算
        h = sigmoid(dataMatrix * weights)                          # 矩阵相乘,计算sigmoid函数
        error = (labelMat - h)                                     # 计算误差
        weights = weights + alpha * dataMatrix.transpose() * error # 矩阵相乘,更新权重
    return weights
# 获得回归系数
dataMat, labelMat = loadDataSet()
weigths = gradAscent(dataMat, labelMat)
print("w0: %f, w1: %f, W2: %f" % (weigths[0], weigths[1], weigths[2]))
# 绘制数据集和Logistic回归最佳拟合直线
def plotBestFit(weights):
    dataMat, labelMat = loadDataSet()                      # 加载数据集,标签
    dataArr = array(dataMat)                               # 转换成umPy的数组
    n = shape(dataArr)[0]                                  # 获取数据总数
    xcord1 = []; ycord1 = []                               # 存放正样本
    xcord2 = []; ycord2 = []                               # 存放负样本
    for i in range(n):                                     # 依据数据集的标签来对数据进行分类
        if int(labelMat[i]) == 1:                          # 数据的标签为1,表示为正样本
            xcord1.append(dataArr[i, 1]); ycord1.append(dataArr[i, 2])
        else:                                              # 否则,若数据的标签不为1,表示为负样本
            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')  # 绘制正样本
    ax.scatter(xcord2, ycord2, s=30, c='green')            # 绘制负样本
    x = arange(-3.0, 3.0, 0.1)                             # x区间
    y = (-weights[0] - weights[1] * x) / weights[2]        # 最佳拟合直线
    ax.plot(x, y)
    plt.title('BestFit')                                   # 标题
    plt.xlabel('X1'); plt.ylabel('X2')                     # x,y轴的标签
    plt.show()
# 运行画出图
dataMat, labelMat = loadDataSet()
weigths = gradAscent(dataMat, labelMat)
plotBestFit(weigths.getA())
print("w0: %f, w1: %f, W2: %f" % (weigths[0], weigths[1], weigths[2]))

机器学习笔记(六)Logistic回归_第3张图片

梯度上升

#随机梯度上升算法
def stocGradAscent0(dataMatrix,classLabels):
    m,n = np.shape(dataMatrix)
    alpha = 0.1
    weights = np.ones(n)
    for i in range(m):
        h = sigmoid(sum(dataMatrix[i]*weights))
        error = classLabels[i] - h
        weights = weights + alpha * error * dataMatrix[i]
    return weights

dataArr,labelMat = loadDataSet()

weights = stocGradAscent0(array(dataArr),labelMat)
plotBestFit(weights)

机器学习笔记(六)Logistic回归_第4张图片

 随机梯度上升算法在上述数据集上的执行结果,最佳拟合直线并非最佳分类线,可以看出拟合曲线出现了很大的偏差。所以我们对随机梯度上升算法进行改进:

#改进的随机梯度上升算法
def stocGradAscent1(dataMatrix,classLabels,numIter=150):
    m,n = np.shape(dataMatrix)
    weights = np.ones(n)
    for j in range(numIter):
        dataIndex = list(range(m))
        for i in range(m):
            alpha = 4/(1.0+j+i)+0.01
            randIndex = int(random.uniform(0,len(dataIndex)))
            h = sigmoid(sum(dataMatrix[randIndex]*weights))
            error = classLabels[randIndex] - h
            weights = weights + alpha * error * dataMatrix[randIndex]
            del(dataIndex[randIndex])
    return weights

dataArr,labelMat = loadDataSet()
weights = stocGradAscent1(array(dataArr),labelMat)
plotBestFit(weights)

机器学习笔记(六)Logistic回归_第5张图片

你可能感兴趣的:(回归,逻辑回归)