梯度下降的三种形式——BGD、SGD、MBGD

机器学习里面,梯度下降法可以说是随处可见,虽然它不是什么高大上的机器学习算法,但是它却是用来解决机器学习算法的良药。我们经常会用到梯度下降法来对机器学习算法进行训练。
BGD,SGD,MBGD。也就是批量梯度下降法BGD,随机梯度下降法SGD,小批量梯度下降法MBGD。

下面这篇文章对这三个概念讲解的很到位:
http://www.cnblogs.com/maybe2030/p/5089753.html#_label0

总结一下:
1、批量梯度下降每次更新使用了所有的训练数据,最小化损失函数,如果只有一个极小值,那么批量梯度下降是考虑了训练集所有的数据,是朝着最小值迭代运动的,但是缺点是如果样本值很大的话,更新速度会很慢。
2、随机梯度下降在每次更新的时候,只考虑一个样本点,这样会大大加快训练数据,也恰好是批量梯度下降的缺点,但是有可能由于训练数据的噪声点较多,那么每一次利用噪声点进行更新的过程中,就不一定是朝着极小值方向更新,但是由于更新多轮,整体方向还是朝着极小值方向更新,又提高了速度。
3、小批量梯度下降法是为了解决批量梯度下降的训练速度慢,以及随机梯度下降法的准确性综合而来,但是这里注意,不同问题的batch是不一样的,要通过实验结果来进行超参数的调整。

参考python代码:

# coding=utf-8

import numpy as np
import matplotlib.pyplot as plt

# 构造数据
def get_data(sample_num=1000):
    """
    拟合函数为
    y = 5*x1 + 7*x2
    :return:
    构造1000组数据集(x1,x2,y)
    """
    '''生成具有sample_num=1000个等间隔元素的范围是[0,9]的一个数列'''
    x1 = np.linspace(0, 9, sample_num)
    x2 = np.linspace(4, 13, sample_num)
    '''将x1,x2合并成2*sample_num的矩阵并转置,最终是sample_num*2的矩阵'''
    x = np.concatenate(([x1], [x2]), axis=0).T
    '''x.dot(y) 等价于 np.dot(x,y)  两个矩阵相乘'''
    y = np.dot(x, np.array([5, 7]).T)
    return x, y

# 梯度下降法
def SGD(samples, y, step_size=0.1, max_iter_count=2000):
    """
    :param samples: 样本
    :param y: 结果value
    :param step_size: 每一接迭代的步长
    :param max_iter_count: 最大的迭代次数
    :param batch_size: 随机选取的相对于总样本的大小
    :return:
    """
    # 确定样本数量以及变量的个数初始化theta值

    m, var = samples.shape  # m=1000是行,var=2是列
    theta = np.zeros(2)
    '''flatten,把y降到一维,默认是按横的方向降。y.flatten('F')按竖的方向降。
       此处就是将y进行转置
    '''
    y = y.flatten()
    # 进入循环内
    loss = 1
    iter_count = 0

    iter_list = []
    loss_list = []
    theta1 = []
    theta2 = []
    # 当损失精度大于0.01且迭代此时小于最大迭代次数时,进行
    while loss > 0.01 and iter_count < max_iter_count:
        loss = 0
        # 梯度计算
        theta1.append(theta[0])
        theta2.append(theta[1])

        # 样本维数下标
        rand1 = np.random.randint(0, m, 1)  # 生成大小在范围[0,m]内的一个随机数
        h = np.dot(theta, samples[rand1].T)  # samples[rand1]第rand1行
        # 关键点,只需要一个样本点来更新权值
        for i in range(len(theta)):
            theta[i] = theta[i] - step_size * (1/m) * (h - y[rand1]) * samples[rand1, i]

        """
        # batch_size = np.random.randint(0, m, 1)
        batch_size = range(1, m)
        batch_size = np.array(batch_size)
        (si,) = batch_size.shape
        dev = 0
        for i in range(len(theta)):
            for j in batch_size:
                h = np.dot(theta, samples[j].T)
                dev = dev + (1 / si) * (h - y[j]) * samples[j, i]
            theta[i] = theta[i] - step_size * dev

        """
        # 计算总体的损失精度,等于各个样本损失精度之和
        for i in range(m):
            h = np.dot(theta.T, samples[i])
            # 每组样本点损失的精度
            every_loss = (1 / (var * m)) * np.power((h - y[i]), 2)
            loss = loss + every_loss

        print("iter_count: ", iter_count, "the loss:", loss)

        iter_list.append(iter_count)
        loss_list.append(loss)

        iter_count += 1

    plt.plot(iter_list, loss_list)
    plt.xlabel("iter")
    plt.ylabel("loss")
    plt.show()
    return theta1, theta2, theta, loss_list

if __name__ == '__main__':
    samples, y = get_data()
    theta1, theta2, theta, loss_list = SGD(samples, y)
    print(theta)  # 会很接近[5, 7]

你可能感兴趣的:(机器学习(Machine,Learning),机器学习)