机器学习04-logistic梯度下降算法

logistic回归算法

我们将使用Logistic回归分类器来寻找最优值这是一个最优化算法问题。我们在k邻近算法中通过计算给定点到样本集合中所有点的距离,来判断该店所属于的类别,其实我们可以换一种解法,我们可以通过做一条直线将属于label1 和 label2 的两大类的点集进行区分,这样在给点点(x,y)可以通过判断(x,y)再直线的上方和下方来判断(x,y)的类别,那儿我们如何找到最适合的直线呢? 这里可能有一系列斜率值w直线,我们通过最优算法来确认最优质的w。

梯度下降算法

拟合曲线

对于给定的训练集我们可以使用曲线去做拟合,如下图:

我们可以为每个特征值赋一个权值w,这样我们就能得到我们的拟合曲线 hθ(x) = θ0 + θ1x1 + … θnxn = θx,回归算法的目的就是求出W的最佳权值。

损失函数

评估我们得到的θ是否合适,我们就需要使用损失算法去计算得到的W带入训练集得到的目标值和正确值之间的差异,这里我们采用平方差来定义损失函数。

要找到损失函数的最小值,我们可以采用梯度下降算法去获取,每次按照梯度减少的方向去调整我们的θ,最终能够找到符合损失范围的一个θ值。
这里我们就需要J(θ)对θ求偏导,最终得到偏导函数:

偏导函数乘于一个步长序数得到每次回归θ的减少值,下面是最终θ的回归公式:

在进行梯度下降寻找最小值时由于θ的初始值问题有可能最终得到的最小值时区域最小值而非全局最小值。如果我们最终要预测的值试一个0或1,这种时候我们已经可以使用单位阶跃函数Sigmoid f(z) = 1/(1+e-z) 其中-z是幂数,将hθ(x)带入其中当时f(z)>0.5时属于分类1,当f(z)<0.5时属于分类0。

使用梯度算法寻找最佳拟合直线

我们使用在knn里面的训练数据为它们寻找拟合曲线,训练数据分布:

首先按照往常使用下面脚本加载数据:

#-*- coding=utf-8 -*-
from numpy import *
from math import *

#加载数据的接口
def loadDataSet():
    dataMat = [];labelMat = []
    fr = open('testSet.txt')
    for line in fr.readlines():
        lineArr = line.strip().split("\t")
        #这里的1.0实际定义为 θ0的默认值
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
        labelMat.append(int(lineArr[2]))

    return dataMat, labelMat

#定义我们的Sigmoid函数
def sigmiod(z):
    return 1.0/(1 + exp(-z))

算法实现:

    #训练算法
    def dataTrain(dataMatIn, classLables):
        #因为要使用矩阵方法,都先转换为矩阵
        dataMatIn = mat(dataMatIn)
        classLables = mat(classLables)
        m,n = shape(dataMatIn)
        #m表示测试数据量,n表示特征数
        #我们为每个特征数指定一个默认的权值
        weights = ones([n,1])
        #设置每次移动的步长,这个步长是可以自己进行调整的
        alpha = 0.001
        #设置回归次数,其实有两种方法来终止回归,一种是指定回归次数,一种是指定误差值范围
        maxCycles = 500
       for k in range(maxCycles):
            #获取预测结果 这里使用的是矩阵乘法 MxN * Nx1 = Mx1
            h = sigmiod(dataMatIn*weights)
            #获取误差值,相当于上面的求导公式里面的 hθ(x) - y
            #当然这里的结果是一个矩阵向量 Mx1矩阵
            error = (h - classLabels)
            #一次回归θ 按照公式 θ = θ - alpha * error * dataMatIn
            weights = weights - alpha * dataMatIn.transpose() * error

        return weights 

    #分类方法   
    def classify(intX, weights):
        value = sigmiod(inX * weights)
        if value > 0.5:
            return 1
        return 0

#weight result:
    matrix([[ 4.12414349],
        [ 0.48007329],
        [-0.6168482 ]])     

最终得到的拟合直线:

随机梯度下降

上面的梯度算法我们的训练集总共有100个数据,回归次数500次,每次回归我们都会涉及到对所有训练集进行计算,计算复杂度太高。因此引出了我们的随机梯度下降算法,该算法一次仅适用一个样本点来更新回归系数,这个算法能够实现在线学习算法,当新样本到达时我们就可以对分类器做增量更新。
算法实现:

def randomDataTrain(dataMatIn, classLabels):
    m,n = shape(dataMatIn)
    classLabels = mat(classLabels)
    weights = ones(n)
    alpha = 0.1
    for i in range(m):
        #这里是array数组相乘
        h = sigmoid(sum(dataMatIn[i]*weights.transpose()))
        error = h - classLabels[i]      #一次回归
        weights = weights - alpha * mat(dataMatIn[i]) * error   return weights

    weights result:
matrix([[ 2.38604812,  0.95218922, -0.72978254]])

拟合曲线绿色的之前表示随机梯度下降得到的值:

这里可以看出得到的权值并不是最优权值,原因是因为我们的训练集合样本太少。但这并不能说明随机算法比上面的循环算法差,判断一个算法的优劣应该是看它是否收敛,参数是否达到稳定值。

补充

上面的随机梯度下降算法存在一个挺严重的问题是,由于每次使用其中的一条数据进行训练,会出现由于训练集合里面存在异常的数据项,从而导致我们的特征权值出现比较严重的波动,最终影响算法的收敛,针对这个问题我们可以进行改进。

def stocGradAscent1(dataMatrix, classLabels, numIter=150):
    m,n = shape(dataMatrix)
    weights = ones(n)   #initialize to all ones
    for j in range(numIter):
        dataIndex = range(m)
        for i in range(m):
                 #随着循环次数的增加使得我们的每次移动的步长值减少
            alpha = 4/(1.0+j+i)+0.0001  
            #go to 0 because of the constant
            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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值