python机器学习算法实训 - (三) 逻辑回归和梯度下降法

一日双更,最为致命。

一.逻辑回归

1.1 监督与非监督,回归与分类

监督学习,即训练集样本是包含标签的即我们,如房价预测,自变量为面积,标签为房价;无监督学习则是样本没有标签,我们通过发掘内在的联系将其划分,典型如将一群二维空间的点分成几个簇。
监督学习一般又分分类和回归,分类是预测离散值,比如判断患癌症的可能,标签为0和1;而回归是预测连续值,如房价取值是理论上的整个实数空间。

1.2 什么是逻辑回归

逻辑回归比较调皮,写作回归,其实一般是作为一种分类算法。逻辑回归是解决的分类问题(Classification)中目前最流行使用最广泛的一种学习算法之一。
逻辑回归
通常选定一个threshold(如0.5),当hx的预测值大于threshold时预测值为0/1,小于时为1/0。

1.3 逻辑回归的代价函数

我们知道,训练模型的最终目标就是让模型的泛化能力强,即我们在看得到的资料Ein上要让代价函数最小。
代价函数
仔细观察,这样的cost function是满足我们的需求的:当y和hx都为1时,误差为0;而y=2时,随着hx从1变小到0,cost function的值从0增大到很大;y=0时,随着hx从0变大到1,cost function的值从0增大到很大。
因为y=0和1,聪明的你也许能想到这样的方式:
在这里插入图片描述
这就是我们要最小化的目标函数。

二.梯度下降

2.1 逻辑回归中的梯度

取自然对数以方便计算后,逻辑回归中Ein(即训练集误差,即cost function,基石课程中林老师喜欢这么写)的表达式可以写作:
Ein
对以w(参数)为自变量求导,最后算得梯度即一阶导为:
梯度
然而通常情况下,这个式子是没有闭式解的,所以很难通过令一阶导数为零求得最小值的w。此时只能用到迭代的方法求解。
迭代的每次更新

2.2 梯度下降法

从图中我们可以看到,随机的从某一点出发,在Ein的曲线上,通过向坡度相反的方向“走”一步,我们就可以离“谷底”,即我们希望的最小值,更近一点。
批量更新
整个下山过程由两个因素影响:一个是下山的单位方向v;另外一个是下山的步长η。η如果太小的话,那么下降的速度就会很慢;η如果太大的话,那么之前利用Taylor展开的方法就不准了,造成下降很不稳定,甚至会上升。因此,η应该选择合适的值,一种方法是在梯度较小的时候,选择小的η,梯度较大的时候,选择大的η,即η正比于||∇Ein(wt)||。这样保证了能够快速、稳定地得到最小值Ein(w)。
什么时候停止呢?可以是设立判断当Ein足够小足够接近谷底时,也可以同时设定最大迭代的次数。
迭代公式

2.3 随机梯度下降

上文介绍的梯度上升算法,在每次更新回归系数的时候都要遍历整个数据集(累加)。但是如果训练样本数量较多,每个样本的特征又足够多,那计算复杂度将成倍增加。
为了提高logistic regression中gradient descent算法的速度,可以使用另一种算法:随机梯度下降算法(Stochastic Gradient Descent)。
随机梯度下降算法每次迭代只找到一个点,计算该点的梯度,作为我们下一步更新w的依据。这样就保证了每次迭代的计算量大大减小,我们可以把整体的梯度看成这个随机过程的一个期望值。可以理解为用很小的稳定性牺牲换计算速度。
在这里插入图片描述
SGD的迭代的变化:
SGD

三. 代码实现

老规矩,自己写一遍,再用sklearn

#利用逻辑回归对西瓜分类
from numpy import *
import pandas as pd
import matplotlib.pyplot as plt

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

#梯度上升函数
def gradAscent(dataMat, labelMat):
    m,n = shape(dataMat)
    print(m, n)
    alpha = 0.1
    maxCycles = 500
    weights = array(ones((n, 1)))
    for k in range(maxCycles):
        z = dot(dataMat, weights)
        hx = sigmoid(z)
        error = labelMat - hx
        weights += alpha * dot(dataMat.transpose(), error)
    return weights

#随机梯度上升
def randomgradAscent(dataMat, label, numIter=50):
    m,n = shape(dataMat)
    weights = ones(n)
    for j in range(numIter):
        dataIndex = list(range(m))
        for i in range(m):
            #迭代次数越多,学习率越小
            alpha = 40/(1.0+j+i)+0.2
            rand_num = int(random.uniform(0, len(dataIndex)))
            rand_index = dataIndex[rand_num]
            z = dot(dataMat[rand_index], weights)
            hx = sigmoid(sum(z))
            error = label[rand_index] - hx
            weights += alpha * error[0,0] * (dataMat[rand_index].transpose())
            del(dataIndex[rand_num])
    return weights

#画图
def plotBestFit(weights):
    m = shape(dataMat)[0]
    xcord1 = []
    ycord1 = []
    xcord2 = []
    ycord2 = []
    for i in range(m):
        if labelMat[i] == 1:
            xcord1.append(dataMat[i, 1])
            ycord1.append(dataMat[i, 2])
        else:
            xcord2.append(dataMat[i, 1])
            ycord2.append(dataMat[i, 2])
    plt.figure(1)
    ax = plt.subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
    ax.scatter(xcord2, ycord2, c='green')
    x = arange(0.2, 0.8, 0.1)
    y = array((-weights[0] - weights[1] * x)/weights[2])
    print(shape(x))
    print(shape(y))
    plt.sca(ax)
    #plt.plot(x, y[0])   #gradAscent
    plt.plot(x, y)  #randmgradAscent
    plt.xlabel('density')
    plt.ylabel('ratio_sugar')
    #plt.title('gradAscent logistic regression')
    plt.title('random gradAscent logistic regression')
    plt.show()

#读入csv文件数据
df = pd.read_csv('/data/shixunfiles/03d07802327d2fae5cbde9b1466fe53e_1582714323718.csv')
m, n = shape(df)
#df的第一列为index,在实验原理中该列的值应当为1,所以采用“idx”索引df对其修改
df['idx'] = ones((m, 1))
dataMat = array(df[['idx', 'idensity', 'ratio_sugar']].values[:, :])
labelMat = mat(df['label'].values[:]).transpose()
#weights = gradAscent(dataMat, labelMat)
weights = randomgradAscent(dataMat, labelMat, numIter=10)
plotBestFit(weights)

结果:
两个特征的西瓜数据集
喜欢的话点个赞8 你的支持是我们更新的动力(是不是觉得很熟悉)^ ^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值