机器学习-Logistic回归

1、一般流程


1)收集数据:采用任意方法收集数据
2)数据准备:由于需要进行距离计算,因此要求数据类型为数据型
3)分析数据:采用任意方法对数据进行分析
4)训练算法:大部分时间将用于训练,训练的目的是为了找到最佳分类回归系数
5)测试算法:一旦训练完成了,分类将会很快
6)使用算法:首先,需要输入一些数据,将其转换为对应的结构化数值;接着,基于训练好的回归系数就可以对这些数值进行简单的回归计算,判定他们属于哪个类别。

2、Logistic回归的优缺点


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

3、梯度上升找到最佳参数


梯度上升法伪代码:

每个回归系数初始化为1
重复N次:

计算整个数据集的梯度
使用学习率*梯度(错误X当前样本值)更新回归系数的向量

返回回归系数

准备数据和分类器

# 加载数据
def loadDataSet():
    dataMat, labelMat = [], []
    fr = open(fil)
    for line in fr.readlines():
        lineArr = line.strip().split()
        # 数据前两行分别为x1,x2。 1.0为初始截距项
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    return dataMat, labelMat


# 分类器
def sigmoid(inx):
    return 1.0 / (1 + exp(-inx))

梯度上升优化算法

def gradAscent(dataMatIn, classLabels):
    # 梯度上升优化算法计算回归系数
    dataMatrix = mat(dataMatIn)     # 转换成Numpy矩阵类型
    labelMat = mat(classLabels).transpose()
    m, n = shape(dataMatrix)

    alpha = 0.001   # 学习率
    maxCycle = 500  # 最大迭代次数
    weight = ones((n, 1))
    for k in range(maxCycle):
        h = sigmoid(dataMatrix * weight)
        error = (labelMat - h)
        weight += alpha * dataMatrix.transpose() * error
    return weight


#  测试
dataArr, labelMat = loadDataSet()
gradAscent(dataArr, labelMat)

分析数据:画出决策边界

def plotBestFit(weights):
    import matplotlib.pyplot as plt
    plt.style.use('ggplot')

    dataMat, labelMat = loadDataSet()
    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, c='red', marker='s')
    ax.scatter(xcord2, ycord2, c='green')
    x = arange(-3.0, 3.0, 0.1)   # -3 到 3 步长 0.1
    # 此处设定z = w0x0+w1x1+w2x2 = 0 即sigmoid函数为0.5,即分界处。从而算出 x1与x2的关系 如下
    y = (-weights[0] - weights[1] * x) / weights[2]
    ax.plot(x, y)
    plt.xlabel('x1')
    plt.ylabel('x2')
    plt.show()


# 测试
weights = gradAscent(dataArr, labelMat)
plotBestFit(weights)

随机梯度上升
随机梯度上升法伪代码:

每个回归系数初始化为1
对数据集每个样本:

计算该样本的梯度
使用学习率*梯度(错误X当前样本值)更新回归系数的向量

扫描二维码关注公众号,回复: 1442517 查看本文章

返回回归系数

def stocGradAscent0(dataMatrix, classLabels):
    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 += alpha * error * dataMatrix[i]
    return weights


# 测试
dataArr, labelMat = loadDataSet()
w =  stocGradAscent0(array(dataArr), labelMat)
plotBestFit(w)

随机梯度上升算法与梯度上升算法的区别:
第一,后者的变量h和误差error都是向量,而前者则全是数值
第二,前者没有矩阵的转换过程,所有的变量的数据类型全都是Numpy

改进的随机梯度上升

def stocGradAscent1(dataMatrix, classLabels, numberIter = 150):
    m, n = shape(dataMatrix)
    weights = ones(n)

    # 多次迭代
    for j in range(numberIter):
        dataIndex = list(range(m))
        # 一次梯度上升更新weights
        for i in range(m):
            alpha = 4/(1.0 + j + i ) + 0.01  #迭代次数越多学习率越接近0.01 为了快速上升
            randIndex = int(random.uniform(0, len(dataIndex)))  # 随机选取减少周期性波动

            h = sigmoid(sum(dataMatrix[randIndex] * weights))
            error = classLabels[randIndex] - h
            weights += alpha * error * dataMatrix[randIndex]
            del(dataIndex[randIndex])   # 防止重复抽样
    return weights

# 测试
w = stocGradAscent1(array(dataArr), labelMat, 500)
plotBestFit(w)

4、从疝气病预测病马的死亡率


一般思路

1)收集数据:给定数据集
2)准备数据:用Python解析文本文件并填充缺失值
3)分析数据:可视化并观察数据
4)训练算法:使用优化算法,找到最佳系数
5)测试算法:为了量化回归的效果,需要观察错误率。根据错误率决定是否退回到训练阶段,通过改变迭代次数和步长等参数得到更好的回归系数
6)使用算法:一个简单的命令行收集马的症状并输出预测结果

Logistic回归分类函数

数据做过预处理(用0填补缺失值)

def classifyVector(inX, weights):
    # 判断类型
    prob = sigmoid(sum(inX*weights))
    if prob > 0.5:
        return 1.0
    else:
        return 0.0


def colicTest():
    trfil = r'D:\horseColicTraining.txt'
    tefil = r'D:\horseColicTest.txt'
    frTrain = open(trfil, 'r')
    frTest = open(tefil, 'r')
    tr_set, tr_labels = [], []

    # 生成训练集特征数据及标签数据
    for line in frTrain.readlines():
        cline = line.strip().split('\t')
        lineArr = []
        for i in range(21):
            lineArr.append(float(cline[i]))
        tr_set.append(lineArr)
        tr_labels.append(float(cline[21]))

    # 梯度上升算的权重
    tr_weights = stocGradAscent1(array(tr_set), tr_labels, 500)

    errorCount=0; numTestVec = 0.0
    # 生成测试集特征数据
    for line in frTest.readlines():
        numTestVec += 1.0
        cline1 = line.strip().split('\t')
        lineArr1 = []
        for i in range(21):
            lineArr1.append(float(cline1[i]))

        # 计算错误率
        clf = classifyVector(array(lineArr1), tr_weights)
        lb = cline1[21]
        if int(clf) != int(lb):
            errorCount += 1

    errorRate = float(errorCount)/numTestVec
    print("The error rate of this average rate is: {}".format(errorRate))
    return errorRate

10次迭代后的平均错误率为32%左右,该结果不算差,因为有30%的数据缺失。调整梯度上升的迭代次数还可以提高准确率

在最优算法中,最常用的就是梯度上升算法,而梯度上升算法又可以简化为随机梯度上升算法

参考:《机器学习实战》
数据:链接:https://pan.baidu.com/s/1FvyfRQgqQR7zFyGBJ_WtTw 密码:ffzk

猜你喜欢

转载自blog.csdn.net/scc_hy/article/details/80379615