《机器学习实战》第5章 Logistic回归 关于改进的随机梯度上升算法的两个问题

首先看看梯度上升算法:

def gradAscent(dataMatIn, classLabels):
    dataMatrix = np.mat(dataMatIn)
    labelMat = np.mat(classLabels).transpose()
    m, n = np.shape(dataMatrix)
    alpha = 0.001
    maxCycles = 500
    weights = np.ones((n, 1))
    for i in range(maxCycles):
        h = sigmoid(dataMatrix * weights)
        error = (labelMat - h)
        weights = weights + alpha * dataMatrix.transpose() * error
    return weights

再看看改进的随机梯度上升算法:


def stocGradAscent1(dataMatrix, classLabels, numInter=150):
    m, n = np.shape(dataMatrix)
    weights = np.ones(n)
    for j in range(numInter):
        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

《机器学习实战》书中原话:

梯度上升算法在每次更新回归系数是都需要遍历整个数据集,该方法在处理100个左右的数据集尚可,但如果有数十亿样本和成千上万的特征,那么该方法的计算复杂度就太高了。一种改进方法是一次仅用一个样本点来更新回归系数,该方法称为随机梯度上升算法。

然后在网上看到如下问题:

问题一: 改进的随机梯度上升算法的内层循环次数是100,该算法还是把数据集中的每个样本都遍历了一遍,那么这和之前的梯度上升算法有什么区别?

我们注意到:
梯度上升算法遍历一次数据集时只对回归系数进行了一次修改,而改进的随机梯度上升算法对数据集遍历一次时,因为每选择一个样本点,就对回归系数进行了一次修改,遍历完整个数据集其实对回归系数修改了100次!

问题二:

randIndex通过randIndex=int(random.uniform(0, len(dataIndex)))得到 [0,100)之间的一个整数,假设randIndex=10,那么del(dataIndex[randIndex])之后len(dataIndex)就变为99了。第二次循环时randIndex在区间[0,99)中随机取一个整数,万一刚好又取到randIndex=10,则又要用该样本点来修改回归系数。试想一种极端的情况:randIn一直取到10,难道要一直用这一个样本点来修改参数吗,其他样本点没起到一点作用,这显然不合理啊!

Too Naive!还是Python语法学的不够牢固啊!
我们先来看看下面这段代码,熟悉熟悉del函数的功能

motorcycles=['honda','yamaha','toyota','suzuki']
del(motorcycles[1])
print(motorcycles)

输出 [‘honda’, ‘toyota’, ‘suzuki’]
del()函数直接删除列表中对应下标的元素
再看看下面这个代码,你就一目了然了,根本不是问题二所说的那么回事!

import random
a = list(range(10))
for i in range(10):
    print('------------------------')
    print(a)
    randIndex = int(random.uniform(0, len(a)))
    print(randIndex)
    del(a[randIndex])
    print(a)

输出的结果如下:

------------------------
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
9
[0, 1, 2, 3, 4, 5, 6, 7, 8]
------------------------
[0, 1, 2, 3, 4, 5, 6, 7, 8]
7
[0, 1, 2, 3, 4, 5, 6, 8]
------------------------
[0, 1, 2, 3, 4, 5, 6, 8]
3
[0, 1, 2, 4, 5, 6, 8]
------------------------
[0, 1, 2, 4, 5, 6, 8]
3
[0, 1, 2, 5, 6, 8]
------------------------
[0, 1, 2, 5, 6, 8]
3
[0, 1, 2, 6, 8]
------------------------
[0, 1, 2, 6, 8]
1
[0, 2, 6, 8]
------------------------
[0, 2, 6, 8]
3
[0, 2, 6]
------------------------
[0, 2, 6]
0
[2, 6]
------------------------
[2, 6]
0
[6]
------------------------
[6]
0
[]

看到没,删除相应下标的元素,该元素就从列表中移除了。观察输出结果的第10行到第20行,虽然randIndex都是3,但对应的列表元素已经换了!分别是3,4,5。所以即使randIndex取到相同的值,但绝不是相同的样本了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值