您的位置:首页 > 其它

如何优雅的ML(四) Logistic 回归

2014-07-15 21:52 225 查看
利用Logistic回归进行分类的主要思想是,根据现有数据对分类边界建立回归公式,以此进行分类。

这里的回归表示要找到最佳拟合参数集。训练分类器就是要寻找最佳拟合参数。

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


Sigmoid函数:能够接受所有的输入然后预测出类别,在两个类的情况下,输出0或1。

计算公式f(x)=1/(1+e^-x)。

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

要实现Logistic回归分类器,在每个特征上乘以一个回归系数,然后把结果相加代入Sigmoid函数即可。

任何大于0.5的数据分为1类,小于0.5分为0类。

如何确定最佳回归系数:

若将Sigmoid函数的输入记为向量z,则z=w0x0+w1x1+...+wnxn,它表示系数向量与特征向量对应元素相乘后再相加的值。

寻找最佳系数要用到最优化理论。

梯度上升算法:

要找到某函数最大值,最好沿着该函数的梯度方向探寻。

如果梯度记为▽,则函数f(x,y)的梯度表示为:▽f(x,y)={∂f(x,y)/∂x, ∂f(x,y)/∂y},意味着沿x方向移动∂f(x,y)/∂x,沿y方向移动∂f(x,y)/∂y。

其中函数f(x,y)必须要在待计算的点上有定义且可微。

梯度算子总是指向函数值增长最快的方向。移动量称为步长,记做α。

用向量来表示梯度上升算法的迭代公式:w:=w+α▽_w{f(w)}

该公式将一直被迭代执行,直到迭代次数达到某个值或达到算法允许的误差范围。

梯度上升算法在每次更新回归系数时都要重新遍历整个数据集,复杂度太高。

一次仅用一个样本点来更新回归系数,称为随机梯度上升算法。

它可以在新样本到来时对分类器进行增量式更新,因此是一个在线学习算法。

# coding=gbk

from numpy import *

def loadDataSet(filename):
    """
    从文件中读取数据
    Returns:
        dataMat: 数据集
        labelMat: 标签集
    """
    dataMat = [] # 数据集
    labelMat = [] # 标签集
    fr = open(filename)
    for line in fr.readlines():
        lineArr = line.strip().split() # 分割数据
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) # 输入前两个值属于数据集,为方便计算第一列置为 1
        labelMat.append(int(lineArr[2])) # 第三个值属于标签集
    return dataMat, labelMat # 返回数据集与标签集

def sigmoid(inX):
    """
    Sigmoid 函数
    """
    return 1.0 / (1 + exp(-inX))

def gradAscent(dataMatIn, classLabels):
    """
    梯度上升算法
    Args:
        dataMatIn: 数据集,二维矩阵,每列代表不同的特征,每行代表训练样本
        classLabels: 标签集,类别标签,是一个一维向量
    Returns:
        weights: 回归系数
    """
    dataMatrix = mat(dataMatIn) # 数据样本矩阵
    labelMat = mat(classLabels).transpose() # 标签矩阵的转置
    m, n = shape(dataMatrix) # 读取矩阵的大小 m * n,m 是行数,n是列数
    alpha = 0.001 # 向目标移动的步长
    maxCycles = 500 # 迭代次数
    weights = ones((n, 1)) # 创建 n*1 的数组
    for k in range(maxCycles):
        h = sigmoid(dataMatrix * weights) # 矩阵相乘,得到一个 m * 1 的矩阵
        error = (labelMat - h)
        weights = weights + alpha * dataMatrix.transpose() * error # 梯度上升算法的迭代公式
    return weights

def stocGradAscent0(dataMatIn, classLabels):
    """
    随机梯度上升算法 beta
    """
    dataMatrix = array(dataMatIn)
    m, n = shape(dataMatrix)
    alpha = 0.01
    weights = ones(n)
    for i in range(m):
        h = sigmoid(sum(dataMatrix[i] * weights))
        error = classLabels[i] - h
        weights = weights + alpha * error * dataMatrix[i]
    return weigths

def stocGradAscent1(dataMatIn, classLabels, numIter = 150):
    """
    随机梯度上升算法
    """
    dataMatrix = array(dataMatIn)
    m, n = shape(dataMatrix)
    weights = ones(n)
    for j in range(numIter):
        dataIndex = 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

def plotBestFit(dataMatIn, classLabels, wei):
    """
    画出数据集和Logistic回归最佳拟合直线的函数
    """
    import matplotlib.pyplot as plt
    #weights = wei.getA()
    weights = wei
    dataMat, labelMat = dataMatIn, classLabels
    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:
            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)
    y = (-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x,y)
    plt.xlabel('X1'); plt.ylabel('X2')
    plt.show()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: