【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】3.33 用NumPy进行梯度下降优化

在这里插入图片描述

3.33 用NumPy进行梯度下降优化

目录
  1. 梯度下降优化的基本概念
    1.1 梯度下降的定义
    1.2 梯度下降的种类
    1.3 梯度下降的优缺点
  2. 使用NumPy实现梯度下降优化的方法
    2.1 初始化权重和偏置
    2.2 前向传播
    2.3 计算损失
    2.4 反向传播
    2.5 更新权重和偏置
  3. 梯度下降优化的实际应用案例
    3.1 线性回归
    3.2 逻辑回归
    3.3 神经网络
  4. 代码实现:详细原理和源码注释
    4.1 线性回归的梯度下降
    4.2 逻辑回归的梯度下降
    4.3 神经网络的梯度下降
  5. 总结与参考资料
思维导图
Syntax error in textmermaid version 10.9.0

1. 梯度下降优化的基本概念

1.1 梯度下降的定义

梯度下降(Gradient Descent)是一种优化算法,用于最小化一个函数。在机器学习和深度学习中,梯度下降主要用来最小化损失函数,从而找到模型的最佳参数。梯度下降通过计算损失函数对参数的梯度,逐步调整参数,使损失函数的值逐渐减小。

1.2 梯度下降的种类

梯度下降主要有以下几种类型:

  • 批量梯度下降(Batch Gradient Descent):在每次迭代中使用所有训练样本计算梯度。
  • 小批量梯度下降(Mini-batch Gradient Descent):在每次迭代中使用一小部分训练样本计算梯度。
  • 随机梯度下降(Stochastic Gradient Descent, SGD):在每次迭代中只使用一个训练样本计算梯度。

每种类型的梯度下降都有其优缺点,具体选择哪种类型取决于数据集的大小和计算资源的限制。

1.3 梯度下降的优缺点
优点
  1. 简单直观:梯度下降算法的原理简单,易于理解和实现。
  2. 全局最优解:在凸函数的情况下,梯度下降能够找到全局最优解。
  3. 可扩展性:可以通过调整学习率和批量大小来适应不同的问题。
缺点
  1. 局部最优解:在非凸函数的情况下,梯度下降可能会陷入局部最优解。
  2. 计算复杂度:批量梯度下降需要计算所有样本的梯度,计算复杂度高。
  3. 学习率敏感:学习率的选择对算法的收敛速度和效果影响较大。

2. 使用NumPy实现梯度下降优化的方法

2.1 初始化权重和偏置

在使用梯度下降优化模型之前,需要对模型的权重和偏置进行初始化。初始化的方式对模型的训练效果有重要影响。常见的初始化方法包括随机初始化和零初始化。零初始化可能会导致梯度消失问题,因此通常使用随机初始化。

代码实现

import numpy as np

# 初始化权重和偏置
def initialize_parameters(input_size, hidden_size, output_size):
    W1 = np.random.randn(input_size, hidden_size)  # 输入层到隐藏层的权重
    b1 = np.zeros((1, hidden_size))  # 输入层到隐藏层的偏置
    W2 = np.random.randn(hidden_size, output_size)  # 隐藏层到输出层的权重
    b2 = np.zeros((1, output_size))  # 隐藏层到输出层的偏置
    return W1, b1, W2, b2

# 示例
input_size = 784  # 输入特征数
hidden_size = 128  # 隐藏层神经元数
output_size = 10  # 输出类别数
W1, b1, W2, b2 = initialize_parameters(input_size, hidden_size, output_size)
2.2 前向传播

前向传播是从输入层到输出层的信号传递过程。每一层的神经元接收来自前一层的输入,经过加权求和和激活函数处理,生成新的输出信号,传递给下一层。

代码实现

# 定义Sigmoid激活函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))  # Sigmoid激活函数

# 定义前向传播
def forward_propagation(X, W1, b1, W2, b2):
    z1 = np.dot(X, W1) + b1  # 输入层到隐藏层的加权求和
    a1 = sigmoid(z1)  # 隐藏层的激活值
    z2 = np.dot(a1, W2) + b2  # 隐藏层到输出层的加权求和
    a2 = sigmoid(z2)  # 输出层的激活值
    return z1, a1, z2, a2

# 示例
X = np.random.rand(1, input_size)  # 生成一个随机输入样本
z1, a1, z2, a2 = forward_propagation(X, W1, b1, W2, b2)
print(f'隐藏层加权求和: {
     z1}')
print(f'隐藏层激活值: {
     a1}')
print(f'输出层加权求和: {
     z2}')
print(f'输出层激活值: {
     a2}')
2.3 计算损失

损失函数用于衡量模型的预测值与真实值之间的差距。常用的损失函数包括均方误差(MSE)和交叉熵损失(CE)。

代码实现

# 定义均方误差损失函数
def mean_squared_error(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)  # 均方误差

# 定义交叉熵损失函数
def cross_entropy_loss(y_true, y_pred):
    y_pred = np.clip(y_pred, 1e-15, 1 - 1e-15)  # 防止 log(0) 导致的数值不稳定
    return -np.mean(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))  # 交叉熵损失

# 示例
y_true = np.array([0, 1, 1, 0], dtype=np.float32)
y_pred = np.array([0.1, 0.9, 0.8, 0.2], dtype=np.float32)
mse_loss = mean_squared_error(y_true, y_pred)
ce_loss = cross_entropy_loss(y_true, y_pred)
print(f'均方误差损失: {
     mse_loss}')
print(f'交叉熵损失: {
     ce_loss}')
2.4 反向传播

反向传播是梯度下降算法的关键步骤,用于计算损失函数对权重和偏置的梯度,并将梯度逐层反向传递。通过反向传播,我们可以更新每一层的权重和偏置,使模型的预测值更加接近真实值。

代码实现

# 定义反向传播
def backward_propagation(X, y_true, z1, a1, z2, a2, learning_rate=0.1):
    m = X.shape[0]  # 样本数

    # 计算输出层的误差
    dz2 = a2 - y_true  # 输出层的误差
    dW2 = (1/m) * np.dot(a1.T, dz2)  # 输出层权重的梯度
    db2 = (1/m) * np.sum(dz2, axis=0, keepdims=True)  # 输出层偏置的梯度

    # 计算隐藏层的误差
    da1 = np.dot(dz2, W2.T)  # 隐藏层的误差
    dz1 = da1 * a1 * (1 - a1)  # 隐藏层的误差,使用Sigmoid激活函数的导数
    dW1 = (1/m) * np.dot(X.T, dz1)  # 隐藏层权重的梯度
    db1 = (1/m) * np.sum(dz1, axis=0, keepdims=True)  # 隐藏层偏置的梯度

    # 更新权重和偏置
    W1 -= learning_rate * dW1  # 更新输入层到隐藏层的权重
    b1 -= learning_rate * db1  # 更新输入层到隐藏层的偏置
    W2 -= learning_rate * dW2  # 更新隐藏层到输出层的权重
    b2 -= learning_rate * db2  # 更新隐藏层到输出层的偏置

    return W1, b1, W2, b2

# 示例
X = np.random.rand(4, input_size)  # 生成4个随机输入样本
y_true = np.array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]], dtype=np.float32)
z1, a1, z2, a2 = forward_propagation(X, W1, b1, W2, b2)
W1, b1, W2, b2 = backward_propagation(X, y_true, z1, a1, z2, a2, learning_rate=0.1)
2.5 更新权重和偏置

通过反向传播计算得到的梯度,我们可以更新模型的权重和偏置。更新的方式通常采用梯度下降法,通过调整学习率来控制权重和偏置的更新速度。

3. 梯度下降优化的实际应用案例

3.1 线性回归

线性回归是一种基本的回归算法,用于预测连续值的目标变量。我们可以通过最小化均方误差来训练模型。

代码实现

import matplotlib.pyplot as plt

# 生成线性回归数据
np
posted @   爱上编程技术  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示