梯度下降法及变式(代码实现)

梯度下降

BGD

def batchGradientDescent(x, y, theta, alpha, m, maxInteration):
    '''批梯度下降算法简单实现
    x: 输入
    y: 输出
    theta: w 和 b 组成的向量
    alpha: 学习率
    m: 批数据数量
    maxInteration:最大迭代次数
    '''
    x_train = x.transpose() # 转置
    for i in range(0, maxInteration):
        # 预测值
        hypothesis = np.dot(x, theta)
        # 预测误差
        error = hypothesis - y
        # 下降梯度
        gradient = np.dot(x_train, error) / m
        # 更新theta
        theta = theta - alpha * gradient
    return theta

SGD(Stochastic gradient descent)

def stochasticGradientDescent(x, y, theta, alpha, maxInteration):
    '''批梯度下降算法简单实现
    x: 输入
    y: 输出
    theta: w 和 b 组成的向量
    alpha: 学习率
    m: 批数据数量
    maxInteration:最大迭代次数
    '''
    data = []
    for i in range(4):
        data.append(i)
    for i in range(0, maxInteration):
        hypothesis = np.dot(x, theta)
        # 预测误差
        error = hypothesis - y
        # 选取一个随机数
        index = random.sample(data, 1)  # 从列表data中随机选取一个数据
        index1 = index[0]
        # 下降梯度
        gradient = error[index1] * x[index1]
        # 求导之后得到theta
        theta = theta - alpha * gradient
    return theta

MBGD

def miniBatchGradientDescent(x, y, theta, alpha, m, batch_size, epochs):
    '''
    x: 输入
    y: 输出
    theta: w 和 b 组成的向量
    alpha: 学习率
    m: 数据集的数据量
    batch_size:一个批次的数据量
    epochs:数据集最大迭代次数
    '''
    for epoch in range(epochs):
        # 生成索引列表
        indexs_list = np.arange(m)
        # 按批次迭代
        for batch in range(m // batch_size):
            # 生成批次数据索引
            index_list = indexs_list[batch*batch_size : batch*batch_size+batch_size]
            # 获取批次数据
            x_batch = x[index_list]
            y_batch = y[index_list]
            # 预测值
            hypothesis = np.dot(x_batch, theta)
            # 预测误差
            error = hypothesis - y_batch
            # 下降梯度
            gradient = np.dot(x_batch.T, error) / m
            # 更新theta
            theta = theta - alpha * gradient
    return theta

MSGD

def mini_batch_stochastic_gradient_descent(x, y, theta, alpha, m, batch_size, epochs):
    '''
    x: 输入
    y: 输出
    theta: w 和 b 组成的向量
    alpha: 学习率
    m: 数据集的数据量
    batch_size:一个批次的数据量
    epochs:数据集最大迭代次数
    '''
    for epoch in range(epochs):
        # 生成索引列表
        data_index = np.arange(m)
        # 打乱样本顺序
        np.random.shuffle(data_index)
        # 按批次迭代
        for batch in range(m // batch_size):
            # 生成批次数据索引
            batch_index = data_index[batch*batch_size : batch*batch_size+batch_size]
            # 获取批次数据
            x_batch = x[batch_index]
            y_batch = y[batch_index]
            # 预测值
            hypothesis = np.dot(x_batch, theta)
            # 预测误差
            error = hypothesis - y_batch
            # 下降梯度
            gradient = np.dot(x_batch.T, error) / m
            # 更新theta
            theta = theta - alpha * gradient
    return theta

Momentum

def momentum(x_start, step, g, discount = 0.7): 
    '''
    x_start: 是优化的起始点,即优化算法的初始参数
    step: 是学习率,用于控制参数更新的步长
    g: 是一个函数,用于计算参数 x 处的梯度
    discount: 是动量的衰减因子,默认值为 0.7
    '''
    x = np.array(x_start, dtype='float64')
    # 创建一个与参数 x 具有相同形状的零数组,用于存储上一步的		梯度信息
    pre_grad = np.zeros_like(x)
    for i in range(50):
        grad = g(x)
        pre_grad = pre_grad * discount + grad * step
        x -= pre_grad
        
        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if abs(sum(grad)) < 1e-6:
            break;
    return x

Nesterov

def nesterov(x_start, step, g, discount = 0.7):
   '''
   x_start: 是优化的起始点,即优化算法的初始参数
   step: 是学习率,用于控制参数更新的步长
   g: 是一个函数,用于计算参数 x 处的梯度
   discount: 是 Nesterov 加速梯度下降中的动量衰减因子,默认值	为 0.7
   ''' 
    x = np.array(x_start, dtype='float64')
    pre_grad = np.zeros_like(x)
    for i in range(50):
        # 预测未来的参数位置,利用当前参数 x 和动量信息来计	算。
        x_future = x - step * discount * pre_grad
        # 计算预测位置处的梯度
        grad = g(x_future)
        # 更新动量信息,结合上一步的动量信息和当前的梯度信息。
        pre_grad = pre_grad * 0.7 + grad 
        x -= pre_grad * step
        
        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if abs(sum(grad)) < 1e-6:
            break;
    return x
nesterov([150,75], 0.012, g)

RMSprop

Adam

posted @ 2024-04-05 21:03  0214jx  阅读(72)  评论(0)    收藏  举报