白手起家学习数据科学 ——梯度下降法之“优化步长和随机梯度下降篇”(六)

2023-11-09

选择正确的步长(Choosing the Right Step Size)

虽然针对梯度移动的基本原理是清楚的,但是移动多少是不清楚的。的确,选择一个合适的步长是一门艺术。流行的选择包括:

  • 使用固定的步长
  • 随时间逐步缩小步长
  • 在每次迭代,选择最小化目标函数的步长

最后一个听起来是最优的,但是,实际上它是最耗时的。通过尝试几种步长来选择最小化目标函数的步长,近似于最后一种方法:

step_sizes = [100, 10, 1, 0.1, 0.01, 0.001, 0.0001, 0.00001]

可能某个步长对于目标函数会引起无效的输入。我们需要创建一个”safe apply”函数,这个函数对于无效的输入返回无限(infinity):

def safe(f):
    """return a new function that's the same as f,
    except that it outputs infinity whenever f produces an error"""
    def safe_f(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except:
            return float('inf') # this means "infinity" in Python
    return safe_f

优化步长+梯度下降法(Putting It ALL Together)

一般情况下,我们有想要最小化的目标函数 target_fn,我们也有它的梯度函数gradient_fn。例如,target_fn可能表示一个模型(带参函数)的误差函数,我们想要找到最小化误差函数的参数。

我们选择一个开始值为参数theta_0,然后我们执行梯度下降法:

def minimize_batch(target_fn, gradient_fn, theta_0, tolerance=0.000001):
    """use gradient descent to find theta that minimizes target function"""

    step_sizes = [100, 10, 1, 0.1, 0.01, 0.001, 0.0001, 0.00001]

    theta = theta_0 # set theta to initial value
    target_fn = safe(target_fn) # safe version of target_fn

    while True:
        gradient = gradient_fn(theta)
        next_thetas = [step(theta, gradient, -step_size)
                        for step_size in step_sizes]
        # choose the one that minimizes the error function
        next_theta = min(next_thetas, key=target_fn)
        next_value = target_fn(next_theta)

        # stop if we're "converging"
        if abs(value - next_value) < tolerance:
            return theta
        else:
            theta, value = next_theta, next_value

我们叫它最小化批量(minimize_batch),因为对于每个梯度步骤,它作用于全部的数据集上(target_fn返回的是全部数据集的误差)。后面我们会介绍另外一种方法:在同一时间里只作用于一个数据点。

有时候,代替的我们想要最大化一个函数,我们能通过最小化的负数来实现:

def negate(f):
    """return a function that for any input x returns -f(x)"""
    return lambda *args, **kwargs: -f(*args, **kwargs)

def negate_all(f):
    """the same when f returns a list of numbers"""
    return lambda *args, **kwargs: [-y for y in f(*args, **kwargs)]

    def maximize_batch(target_fn, gradient_fn, theta_0, tolerance=0.000001):
        return minimize_batch(negate(target_fn),
                                negate_all(gradient_fn),
                                theta_0,
                                tolerance)

随机梯度下降

正如我前面所提,我们常常使用梯度下降法选择一个模型的参数来最小化误差函数,使用前面的批量方法,需要我们做预测,计算全部数据集的梯度,这个会让每个步骤非常耗时。

现在使用的误差函数都是相加的,那个意思是在整个数据集上的误差函数其实是每个数据点上预测的误差简单的相加。

这种情况,我们能使用一种叫做随机梯度下降法来计算每个数据点的梯度,循环整个数据直到到达一个停止点。

在这个循环中,我们想要在一个随机顺序中迭代整个数据:

def in_random_order(data):
    """generator that returns the elements of data in random order"""
    indexes = [i for i, _ in enumerate(data)] # create a list of indexes
    random.shuffle(indexes) # shuffle them
    for i in indexes: # return the data in that order
        yield data[i]

我们想要每个数据点移动一小步,这种方法仅有的一种可能是永远的在最小值附近循环,所以不论何时我们停止改进,我们都会减少步长直到最后放弃:

def minimize_stochastic(target_fn, gradient_fn, x, y, theta_0, alpha_0=0.01):

    data = zip(x, y)
    theta = theta_0 # initial guess
    alpha = alpha_0 # initial step size
    min_theta, min_value = None, float("inf") # the minimum so far
    iterations_with_no_improvement = 0

    # if we ever go 100 iterations with no improvement, stop
    while iterations_with_no_improvement < 100:
        value = sum( target_fn(x_i, y_i, theta) for x_i, y_i in data )

        if value < min_value:
            # if we've found a new minimum, remember it
            # and go back to the original step size
            min_theta, min_value = theta, value
            iterations_with_no_improvement = 0
            alpha = alpha_0
        else:
            # otherwise we're not improving, so try shrinking the step size
            iterations_with_no_improvement += 1
            alpha *= 0.9

        # and take a gradient step for each of the data points
        for x_i, y_i in in_random_order(data):
            gradient_i = gradient_fn(x_i, y_i, theta)
            theta = vector_subtract(theta, scalar_multiply(alpha, gradient_i))

    return min_theta

随机版本要比批量版本快很多,当然,我们也想要一个最大化的版本:

def maximize_stochastic(target_fn, gradient_fn, x, y, theta_0, alpha_0=0.01):
    return minimize_stochastic(negate(target_fn),
                                negate_all(gradient_fn),
                                x, y, theta_0, alpha_0)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

白手起家学习数据科学 ——梯度下降法之“优化步长和随机梯度下降篇”(六) 的相关文章

随机推荐

  • 数据结构有哪些

    概念 数据结构 数据用什么样的方式组合在一起 数据结构是计算机存储数据的方式 指相互之间存在一种或多种特定关系的数据元素集合 常见数据结构 数据存储的常用结构有 栈 队列 数组 链表和红黑树 栈 stack 又称堆栈 它是运算受限的线性表
  • springboot基于Java的衣服穿搭推荐系统-计算机毕业设计

    收藏关注不迷路 文章目录 一 项目介绍 二 开发环境 三 功能介绍 四 核心代码 五 效果图 六 文章目录 一 项目介绍 随着人们物质生活水平的提高 对于精神需求也日趋增长 在日常生活中会更加注意外在形象 尤其是在穿衣搭配方面 无论是日常生
  • C++智能指针详解

    1 概述 我们知道除了静态内存和栈内存外 每个程序还有一个内存池 这部分内存被称为自由空间或者堆 程序用堆来存储动态分配的对象即那些在程序运行时分配的对象 当动态对象不再使用时 我们的代码必须显式的销毁它们 在C 中 动态内存的管理是用一对
  • Linux下的两个特殊的文件(可用来清理日志)——/dev/null与/dev/zero

    1 dev null简介 在类Unix系统中 dev null被称为空设备 是一个特殊的设备文件 写入 dev null 会丢弃一切写入其中的数据 但报告写入操作成功 读取 dev null 则会立即得到一个EOF 在Unix行话中 dev
  • OpenMP、MPI、CUDA总结

    文章目录 一 OpenMP 1 1 多执行绪的概念 1 2 多执行绪的程式 1 3 OpenMP 的基本使用 1 4 OpenMP使用详解 二 MPI Message Passing Interface 三 CUDA 3 1 CUDA发展历
  • 华为OD2023(A卷)基础题23【最短木板长度】

    题目描述 小明有n块木板 第i 1 i n 块木板的长度为ai 小明买了一块长度为m的木料 这块木料可以切割成任意块 拼接到已有的木板上 用来加长木板 小明想让最短的木板尽量长 请问小明加长木板后 最短木板的长度最大可以为多少 输入描述 输
  • Git超实用总结,再也不怕记忆力不好了

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由腾讯工蜂发表于云 社区专栏 Git 是什么 Git 是一个分布式的代码管理容器 本地和远端都保有一份相同的代码 Git 仓库主要是由是三部分组成 本地代码 缓存区 提交历史 这
  • js if判断多个条件_python量化基础

    编辑 Cowboy 校对 李明 来源 牛角财经 目的 python量化基础 条件分支与循环 IF条件分支判断语句的用法 python教程 从入门到高级 免费 特点 案例基于金融市场数据展开 让python量化初学者快速上手 一 基础部分 人
  • springboot/cloud版本升级常见问题和文档

    版本对照链接 https spring io projects spring cloud overview 升级mybatis的starter版本后 集成mybatis spring尽量用高版本 要不然容易出现datesource无法找到或
  • MATLAB R2021b(07)

    详细原文介绍 神经网络入门详解 nftool MathWoks 神经网络入门随记 以及 matlab中神经网络工具箱的使用 关于神经网络的非常基础概念 个人笔记 不具权威性 仅供参考 欢迎指正错误 提供意见 交流讨论等 1 思路简介 我们有
  • 【PCIe】3: PCIe BDF(Bus,Device,Function)

    目录 1 概述 2 BUS 总线号 3 Device 设备号 4 Function 功能号 1 概述 PCIe总线中的每一个功能都有一个唯一的标识符与之对应 这个标识符就是BDF Bus Device Function
  • Knife4j 基础(OpenAPI2)

    1 Knife4j OpenApi2 入门示例 Knife4j是一个集Swagger2 和 OpenAPI3 为一体的增强解决方案 本文按照官方文档 在 SpringBoot2 7 项目中 集成 Knife4j 的 OpenApi2 版本
  • vscode中编译时当前工作目录的设置

    options cwd usr bin 在tasks json中options选项中 使用cwd项进行编译过程当前工作目录的设置 上面的代码把编译时的当前工作目录强制设置到 usr bin 如果使用该选项不设置 则工作目录为当前打开工程的文
  • go ethereum private net 在miner.start()后返回null及停止挖矿的问题

    查了好久在go ethereum社区查到一个情况相同的提问 why does miner start return null does not start in private testchain 提问者也是在miner start 后进入
  • 1、asyncio aiohttp aiofile 异步爬取图片

    1 asyncio aiohttp aiofile 异步爬取图片 前后折腾了好多天 不废话 先直接上代码 再分析 1 import aiohttp 2 import asyncio 3 import aiofiles 4 5 header
  • Surround the Trees

    http acm zju edu cn onlinejudge showProblem do problemId 453 There are a lot of trees in an area A peasant wants to buy
  • Linux下的grub2引导修复

    目录 引导故障分析处理 1 修复grub2引导故障 2 修复grub2 误删掉 boot grub2 3 修复grub2 引导破坏故障 4 修复 boot 下所有文件被删除故障 引导故障分析处理 1 修复grub2引导故障 故障原因 gru
  • 第五章-数字水印-2-原理及实现

    数字水印原理 根据之前图像获取位平面的操作可知 最低位位平面对整体图像的影响最小 因此数字水印的原理为在图像的最低有效位上嵌入隐藏信息 即在图像的最低位替换为数字水印位平面 完成数字的嵌入操作 对已嵌入数字水印的图片提取最低位位平面 即可得
  • 计算机数值分析课学后感,计算方法课程总结 心得体会

    计算方法课程总结 心得体会 一 课程简介 本课程是信息与计算科学 数学与应用数学本科专业必修的一门专业基础课 我们需在掌握数学分析 高等代数和常微分方程的基础知识之上 学习本课程 在实际中 数学与科学技术一向有着密切关系并相互影响 科学技术
  • 白手起家学习数据科学 ——梯度下降法之“优化步长和随机梯度下降篇”(六)

    选择正确的步长 Choosing the Right Step Size 虽然针对梯度移动的基本原理是清楚的 但是移动多少是不清楚的 的确 选择一个合适的步长是一门艺术 流行的选择包括 使用固定的步长 随时间逐步缩小步长 在每次迭代 选择最