机器学习 Logistic回归 原理Python实现

基本思想

回归:

假设有一些数据点,我们用一条直线对这些数据点进行拟合(该线成为最佳拟合直线),这个拟合过程就称为回归。

Logistic回归主要思想:

根据现有数据对分类边界线建立回归公式,以此进行分类,使用最优化算法寻找最佳拟合参数。

Logistic回归优缺点

优点:计算代价不高,易于理解和实现
缺点:容易欠拟合,分类精度可能不高
使用数据类型:数值型和标称型

Sigmoid函数

为了对数据进行预测分类,我们想要的函数应该是,能够接受所有的输入,然后预测出分类结果。我们可以使用一些函数对最终的结果进行处理,如Sigmoid函数:

σ(z)=11+ez

《机器学习 Logistic回归 原理Python实现》

当x=0 时,Sigmoid函数值为0.5,随着x值增大,对应的函数值逼近1,随着x值减小,对应的Sigmoid值逼近于0.

即将样本的每个特征值都乘以回归系数,然后把所有的结果值相加,将这个总和带入Sigmoid函数中,进而得到一个0~1之间的数值,如果数值大于0.5则归为1类,否则归为0类。

Logistic拟合曲线

z=w0x0+w1x1+...+wnXn

or


z=WtX

W为拟合参数, X为特征向量

梯度上升

梯度上升是一种优化算法。其基本思想是沿着函数梯度上升的方向去寻找函数最大值。(梯度下降法同理).梯度记为 ,则函数 f(x,y) 的梯度表示为:

f(x,y)=f(x,y)xf(x,y)y

梯度即为移动方向,乘以移动步长就可以更新回归系数:


w:=w+αwf(w)

python代码实现

def sigmoid(inX):
    return 1.0 / (1 + exp(-inX))

#梯度上升算法
def gradAscent(dataMatIn, classLabels):
    dataMatrix = mat(dataMatIn)  # convert to NumPy matrix
    labelMat = mat(classLabels).transpose()  # convert to NumPy matrix
    m, n = shape(dataMatrix)
    alpha = 0.001
    maxCycles = 500
    weights = ones((n, 1))
    for k in range(maxCycles):  # heavy on matrix operations
        h = sigmoid(dataMatrix * weights)  # matrix mult
        error = (labelMat - h)  # vector subtraction
        weights = weights + alpha * dataMatrix.transpose() * error  # matrix mult
    return weights
#改进后的随机梯度上升算法
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  # apha decreases with iteration, does not
            randIndex = int(random.uniform(0, len(dataIndex)))  # go to 0 because of the constant
            h = sigmoid(sum(dataMatrix[randIndex] * weights))
            error = classLabels[randIndex] - h
            weights = weights + alpha * error * dataMatrix[randIndex]
            del (dataIndex[randIndex])
    return weights
#分类与测试实例
def classifyVector(inX, weights):
    prob = sigmoid(sum(inX * weights))
    if prob > 0.5:
        return 1.0
    else:
        return 0.0


def colicTest():
    frTrain = open('horseColicTraining.txt');
    frTest = open('horseColicTest.txt')
    trainingSet = [];
    trainingLabels = []
    for line in frTrain.readlines():
        currLine = line.strip().split('\t')
        lineArr = []
        for i in range(21):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[21]))
    trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 1000)
    errorCount = 0;
    numTestVec = 0.0
    for line in frTest.readlines():
        numTestVec += 1.0
        currLine = line.strip().split('\t')
        lineArr = []
        for i in range(21):
            lineArr.append(float(currLine[i]))
        if int(classifyVector(array(lineArr), trainWeights)) != int(currLine[21]):
            errorCount += 1
    errorRate = (float(errorCount) / numTestVec)
    print "the error rate of this test is: %f" % errorRate
    return errorRate


def multiTest():
    numTests = 10;
    errorSum = 0.0
    for k in range(numTests):
        errorSum += colicTest()
    print "after %d iterations the average error rate is: %f" % (numTests, errorSum / float(numTests))

解释:由于原始梯度梯度上升算法,没更新一次回归系数都要遍历整个数据集,计算复杂度太高,所以对其进行了改进。改进之后的算法成为随机梯度上升算法,它一次仅用一个样本点来更新回归系数。即可以在新样本到来时对数据进行增量式更新,所以该算法是一个在线学习算法。
除此之外,随机梯度上升又进行了两点改进:
1,每次迭代都会调整 α 的值,以此来缓解数据波动和高频波动。
2,通过随机选取样本来更新回归系数,以此来减少周期性波动

点赞