ML02

ML02

梯度下降

Gradient Descent

  • Have some function J(w,b) , What min J(w,b)
  • 多次梯度下降的步骤,可以看作是“从山顶最快达到山脚”的路线选择,其中路线选择的依据是“最速下降”的方向
  • 如果改变“下山”的位置,“山顶”的选择不同,最终到达“山脚”的位置,不一定相同。因为有“局部最小值”的出现,算作是梯度下降的特性之一。

实习梯度下降

  • 以下是梯度更新的方式:

​ 注意,完成w参数的更新后,不能用作后续b参数更新的代入值,需要分别完成计算后,再进行更新。“同步更新”

  • 这里的 α 称作 学习率 。决定梯度下降的步长
  • α 后的导数部分可被视为J(w)函数(是一个u形函数)在w点的斜率(这里假设b=0),可以先这样简单理解。

学习率

  • 如果学习率太小,会导致梯度下降过慢
  • 如果学习率太大,会导致梯度下降过程中,超过最小点,且可能会发散(无法收敛)
  • 如果梯度下降过程中,w的值位于局部最小值,那么梯度下降算法不会进行任何操作。
  • 当越来越接近最小值的时候,即使 α 的值不变,其下降的速度也会变慢,因为函数的斜率也就是导数部分在变小。

线性回归的梯度下降

  • 梯度下降:

  • 线性回归函数的代价函数是一个凸函数,也就是弓形函数(注意这里的开口向上)

  • 批量梯度下降:每次梯度下降都在查看所有的训练样本,而不是训练数据的一个子集

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    !sudo apt-get update
    !sudo apt-get install -y fonts-wqy-zenhei
    !sudo fc-cache -fv # 更新系统字体缓存

    import matplotlib.pyplot as plt
    import matplotlib.font_manager as fm
    import numpy as np
    import os
    # import shutil # 导入 shutil 模块用于删除目录,但不再需要,因为移除了get_cachedir

    # 定义文泉驿正黑字体的常见路径
    wqy_zenhei_font_path = '/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc'

    # 检查字体文件是否存在
    if os.path.exists(wqy_zenhei_font_path):
    # 1. 删除 matplotlib 的内部字体缓存,强制其重新加载 (此方法导致AttributeError,已移除)
    # cache_dir = fm.get_cachedir()
    # if os.path.exists(cache_dir):
    # shutil.rmtree(cache_dir)
    # print(f"Deleted matplotlib font cache directory: {cache_dir}")

    # 2. 将字体直接添加到 matplotlib 的字体管理器中
    fm.fontManager.addfont(wqy_zenhei_font_path)

    # 3. 获取 matplotlib 识别的字体家族名称
    prop = fm.FontProperties(fname=wqy_zenhei_font_path)
    font_name_from_file = prop.get_name() # 通常会是 'WenQuanYi Zen Hei'

    # 4. 设置 matplotlib 以使用新的字体
    # 添加一个或多个备用字体以防主要字体加载失败
    plt.rcParams['font.sans-serif'] = [font_name_from_file, 'DejaVu Sans', 'Arial Unicode MS']
    plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
    print(f"Set font to '{font_name_from_file}' using font file: {wqy_zenhei_font_path}")
    print(f"Matplotlib's resolved font path for '{font_name_from_file}': {fm.findfont(font_name_from_file)}")

    else:
    print(f"Error: Font file not found at {wqy_zenhei_font_path}. Chinese characters might not display correctly.")
    # 如果字体文件未找到,则回退到 Colab 默认字体
    plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'Arial Unicode MS']
    plt.rcParams['axes.unicode_minus'] = False

    # 1. 定义目标函数 (例如: f(x) = (x - 3)^2 + 2)
    def objective_function(x):
    return (x - 3)**2 + 2

    # 2. 定义目标函数的导数
    def derivative_function(x):
    return 2 * (x - 3)

    # 3. 梯度下降算法实现
    def gradient_descent(
    initial_x, learning_rate, num_iterations
    ):
    x_history = [initial_x]
    for _ in range(num_iterations):
    gradient = derivative_function(x_history[-1])
    new_x = x_history[-1] - learning_rate * gradient
    x_history.append(new_x)
    return np.array(x_history)

    # 参数设置
    initial_x = 10.0 # 初始值设置得离最小值3远一些
    learning_rate = 0.1
    num_iterations = 50

    # 运行梯度下降
    x_values = gradient_descent(initial_x, learning_rate, num_iterations)
    y_values = objective_function(x_values)

    # 4. 可视化结果
    x_plot = np.linspace(-5, 15, 400) # 调整x范围以更好地展示新函数
    y_plot = objective_function(x_plot)

    plt.figure(figsize=(10, 6))
    plt.plot(x_plot, y_plot, label='目标函数 $f(x) = (x - 3)^2 + 2$')
    plt.scatter(
    x_values,
    y_values,
    color='red',
    label='梯度下降路径',
    zorder=5
    )
    plt.plot(
    x_values,
    y_values,
    color='red',
    linestyle='--',
    linewidth=1,
    alpha=0.6
    )
    plt.xlabel('x 值')
    plt.ylabel('f(x) 值')
    plt.title('梯度下降演示 (目标函数: $(x - 3)^2 + 2$)')
    plt.legend()
    plt.grid(True)
    plt.show()

    print(f"初始 x 值: {initial_x}")
    print(f"学习率: {learning_rate}")
    print(f"迭代次数: {num_iterations}")
    print(f"最终 x 值: {x_values[-1]:.4f}")
    print(f"最终 f(x) 值: {y_values[-1]:.4f}")



  • 输出结果:

    1
    2
    3
    4
    5
    初始 x 值: 10.0
    学习率: 0.1
    迭代次数: 50
    最终 x 值: 3.0001
    最终 f(x) 值: 2.0000