机器学习_logistic(梯度上升)

一、概念

逻辑回归(Logistic Regression),简单来说就是 —— 线性回归+sigmoid函数。旨在解决分类问题而非回归 [千万别被名字误导了!!]

1、回归问题

如下图,回归其实就是用我们高中统计学到的最小二乘法(这里我就不放最小二乘法的公式了感兴趣的可以自行查阅,就是求直线的公式其实),对数据点进行拟合的过程。如图所示,蓝色点是我们的样本数据点,通过最小二乘法得到红线,使数据点大致分布在红线,红线就是我们要拟合得到的回归曲线。

但有个问题是,线性回归的输出是某个函数值,但是函数值的大小是不确定的对我们区分样本类别有一定的阻碍。简单举个例子 ,比方我们算出来的值有几十,但也能达到好几万,数据范围很大,没有办法判断多大才是预测为正样本。因此,下面就通过sigmoid函数处理【深度学习中广泛应用的激活函数】,可以简单理解为将数据值做一定的约束处理在特定的范围内,好处多多请看下节。

2、sigmoid

原理:利用sigmoid函数特性,将线性回归输出的任意实数映射到 [0,1] 的范围,设置阈值及进行分类。[ 比方说阈值为0.5 ,那么大于0.5则为正类,小于则为负类 ]

(1)sigmoid函数:

\mathrm{g(z)}=\frac{1}{1+e^{-z}}

(2)损失函数

在机器学习里成为代价函数,深度学习则为交叉熵。

cost(h_\theta(x),y)=\sum_{i=1}^m-y_ilog(h_\theta(x))-(1-y_i)log(1-h_\theta(x))

 在y = 1 和 y = 0情况下损失为

可以看到,

在y = 1下,损失要越小则\mathrm{h}_\theta\left(\mathrm{x}\right)越大,即\mathrm{h}_\theta\left(\mathrm{x}\right) —>1

在y = 0下,损失要越小则\mathrm{h}_\theta\left(\mathrm{x}\right)越小,即\mathrm{h}_\theta\left(\mathrm{x}\right) —>0


整个过程可以从下面这张表简单描述:

 

 

二、实例

这里附上数据集的下载地址(当然这里的数据集就是简单无意义的一些样本点):

1、加载数据集

import numpy as np 
import matplotlib.pyplot as plt

def loadDataSet():
    data = []                                                        #创建数据列表
    label = []                                                        #创建标签列表
    fr = open('testSet.txt')                                            #打开文件   
    for line in fr.readlines():                                            #逐行读取
        lineArr = line.strip().split()                                    #去回车,放入列表
        data.append([1.0, float(lineArr[0]), float(lineArr[1])])        #添加数据
        label.append(int(lineArr[2]))                                #添加标签
    fr.close()                                                            #关闭文件
    return data, label                                            #返回

def plotDataSet():
    data, label = loadDataSet()                                    #加载数据集
    print(data,label)
    dataArr = np.array(data)                                            #转换成numpy的array数组
    n = np.shape(data)[0]                                            #数据个数
    xcord1 = []; ycord1 = []                                            #正样本
    xcord2 = []; ycord2 = []                                            #负样本
    for i in range(n):                                                    #根据数据集标签进行分类
        if int(label[i]) == 1:
            xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])    #1为正样本
        else:
            xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])    #0为负样本
    fig = plt.figure()
    ax = fig.add_subplot(111)                                            #添加subplot
    ax.scatter(xcord1, ycord1, s = 20, c = 'red', marker = 's',alpha=.5)#绘制正样本
    ax.scatter(xcord2, ycord2, s = 20, c = 'green',alpha=.5)            #绘制负样本
    plt.title('DataSet')                                                #绘制title
    plt.xlabel('x'); plt.ylabel('y')                                    #绘制label
    plt.show()                                                            #显示

if __name__ == '__main__':
    plotDataSet()

【可视化】print效果 + 散点图 

2、sigmoid函数和梯度上升

#实现sigmoid函数
def sigmoid(in_x):
    return 1.0/(1 + np.exp(-in_x))

#实现梯度上升
def gradAscent(data,label):
    data = np.mat(data)
    label = np.mat(label)
    r,l = np.shape(data)
    alpha = 0.001   #步长/学习率
    epoch = 500     #迭代次数
    weights = np.ones((l,1))     #
    for k in range(epoch):
        pre_lable = sigmoid(data*weights)   #预测值
        error = (label - pre_lable)     #预测值和真实值误差
        weights = weights + alpha * data.transpose() * error    #梯度上升——权重更新
    return weights

#输出看看效果
if __name__ == '__main__':
    data,label = loadDataSet()
    weights = gradAscent(data,label)
    print(weights)

【可视化】

3、画出回归后的拟合曲线

但是,在上述例子中,样本数量为100,需要进行3*100次计算。类似的,如果在较大数据集下的计算复杂度会高很多,导致模型收敛较慢,因此我们考虑对算法进行改进,只需要每轮迭代一次运算即可——随机梯度下降。 

 4、随机梯度下降

# 随机梯度上升
def sgraDscent(data,label):
    data = np.array(data)
    r,l = np.shape(data)
    epoch = 500
    weights = np.ones(l)
    for k in range(epoch):
        dataIndex = list(range(r))
        for i in range(r):
            alpha = 4/(1.0+k+i)+0.01    #学习率不断减小
            randIndex = int(np.random.uniform(0,len(dataIndex)))
            y_pred = sigmoid(sum(data[randIndex]*weights))  #随机选一个
            error = label[randIndex] - y_pred
            weights = weights + alpha * error * data[randIndex]
            del(dataIndex[randIndex])
    return weights

if __name__ == '__main__':
    data,label = loadDataSet()
    # weights = gradAscent(data,label)
    # print(weights)
    # plotFit(weights)
    weights2 = sgraDscent(data,label)
    print(weights2)
    plotFit(weights2)

【可视化】 

不过从可视化结果也可以看到,在这个例子下,梯度下降比随机梯度下降分类准确率高一些,这也引出了另一个需要注意的:当数据量少时使用梯度下降,数据量大时用随机梯度下降

随机梯度下降的算法可以明显地加快模型的收敛,如下图

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值