C++ 微积分 - 求导 - 自动微分(Automatic Differentiation)
C++ 微积分 - 求导 - 自动微分(Automatic Differentiation)
flyfish
自动微分(Automatic Differentiation,简称 AD)是一种用于精确计算函数导数的技术。它结合了符号微分的准确性和数值微分的效率。自动微分的核心思想是利用计算图对函数进行分解,通过链式法则高效地计算导数,而无需进行符号运算或近似计算。自动微分能自动计算复杂函数的精确梯度。
C++ 微积分 - 求导 - 解析法(符号计算、符号微分)
C++ 微积分 - 求导 - 数值法
自动微分的基本概念
1 计算图:
自动微分将计算过程表示为一个有向无环图(DAG),其中节点表示变量或中间计算结果,边表示计算操作。通过这个图,可以追踪每个变量对输出的影响。
2 链式法则:
自动微分利用链式法则逐步计算导数。链式法则表示复合函数的导数为各个部分导数的乘积。
在计算图中,每个节点对输出的贡献可以通过链式法则从后往前累积计算。
3 前向模式和反向模式:
前向模式(Forward Mode):逐个变量进行传播计算,适用于输入变量较少的情况。
反向模式(Reverse Mode):从输出开始逐步传播导数,适用于输出变量较少的情况(如机器学习中的损失函数)。
自动微分提供精确的导数值,而不是近似值。与符号微分相比,自动微分在计算复杂函数时更高效。用户无需手动推导导数,可以直接获得函数的导数。
符号微分:处理复杂函数的导数推导可能非常复杂,容易导致表达式膨胀。
数值微分:容易受到舍入误差的影响,特别是在计算机浮点运算中。
自动微分的强大之处在于它可以自动地应用一系列简单的微积分规则来计算复杂函数的导数。通过重载运算符,Dual 结构体能够使用这些基本规则构建导数,而无需手动推导。
常见求导法则及其实现
1. 加法法则
对于两个函数 f ( x ) f(x) f(x) 和 g ( x ) g(x) g(x),有:
( f ( x ) + g ( x ) ) ′ = f ′ ( x ) + g ′ ( x ) (f(x) + g(x))' = f'(x) + g'(x) (f(x)+g(x))′=f′(x)+g′(x)实现: 在 Dual 结构体中,两个 Dual 对象相加时,值和导数分别相加。
Dual operator+(const Dual& other) const {return Dual(value + other.value, derivative + other.derivative);
}
2. 乘法法则
对于两个函数 f ( x ) f(x) f(x) 和 g ( x ) g(x) g(x),有:
( f ( x ) ⋅ g ( x ) ) ′ = f ′ ( x ) ⋅ g ( x ) + f ( x ) ⋅ g ′ ( x ) (f(x) \cdot g(x))' = f'(x) \cdot g(x) + f(x) \cdot g'(x) (f(x)⋅g(x))′=f′(x)⋅g(x)+f(x)⋅g′(x)实现: 在 Dual 结构体中,两个 Dual 对象相乘时,使用乘积法则计算导数。
Dual operator*(const Dual& other) const {return Dual(value * other.value, value * other.derivative + derivative * other.value);
}
3. 商法则
对于两个函数 f ( x ) f(x) f(x) 和 g ( x ) g(x) g(x),有:
( f ( x ) g ( x ) ) ′ = f ′ ( x ) ⋅ g ( x ) − f ( x ) ⋅ g ′ ( x ) ( g ( x ) ) 2 \left(\frac{f(x)}{g(x)}\right)' = \frac{f'(x) \cdot g(x) - f(x) \cdot g'(x)}{(g(x))^2} (g(x)f(x))′=(g(x))2f′(x)⋅g(x)−f(x)⋅g′(x)实现: 在 Dual 结构体中,两个 Dual 对象相除时,使用商法则计算导数。
Dual operator/(const Dual& other) const {return Dual(value / other.value, (derivative * other.value - value * other.derivative) / (other.value * other.value));
}
4. 链式法则
对于复合函数 f ( g ( x ) ) f(g(x)) f(g(x)),有:
( f ( g ( x ) ) ) ′ = f ′ ( g ( x ) ) ⋅ g ′ ( x ) (f(g(x)))' = f'(g(x)) \cdot g'(x) (f(g(x)))′=f′(g(x))⋅g′(x)
自动微分天然支持链式法则,因为每个操作都跟踪其导数,计算过程中自动应用链式法则。
使用基本规则计算复合函数的导数
展示如何使用这些基本规则计算复合函数 h ( x ) = ( x 2 + 1 ) ⋅ sin ( x ) h(x) = (x^2 + 1) \cdot \sin(x) h(x)=(x2+1)⋅sin(x) 的导数。
#include <iostream>
#include <cmath>const double M_PI = 3.1415;
// 双数结构体,用于实现前向模式自动微分
struct Dual {double value; // 函数值double derivative; // 导数值// 构造函数,初始化双数Dual(double v, double d) : value(v), derivative(d) {}// 重载加法运算符Dual operator+(const Dual& other) const {return Dual(value + other.value, derivative + other.derivative);}// 重载乘法运算符Dual operator*(const Dual& other) const {return Dual(value * other.value,value * other.derivative + derivative * other.value);}// 重载正弦函数friend Dual sin(const Dual& x) {return Dual(std::sin(x.value), std::cos(x.value) * x.derivative);}
};int main() {// 初始化 x 为一个双数,值为 π/4,导数为 1Dual x(M_PI / 4, 1.0);// 计算 h(x) = (x^2 + 1) * sin(x)Dual x_squared = x * x; // x^2Dual one(1.0, 0.0); // 常数 1Dual h = (x_squared + one) * sin(x);// 输出结果std::cout << "h(x) 的值为: " << h.value << std::endl;std::cout << "h(x) 的导数为: " << h.derivative << std::endl;return 0;
}
自动微分法:使用前向模式自动微分来处理更复杂的函数,包括加法、乘法、除法、指数和对数函数。
-
结构体
Dual: -
value表示函数的值。
derivative表示导数的值。
支持常见的运算符重载(加、减、乘、除、取反)以便进行代数操作。 -
数学函数支持:
实现了exp和log函数,分别表示指数和对数函数的自动微分。 -
复杂函数计算:
compute_function函数实现了一个复杂的函数 f ( x ) = x 2 + 2 x + e x f(x) = x^2 + 2x + e^x f(x)=x2+2x+ex,并使用自动微分来计算其值和导数。
#include <iostream>
#include <cmath>// Dual number structure for automatic differentiation
struct Dual {double value; // Function valuedouble derivative; // Derivative valueDual(double v, double d) : value(v), derivative(d) {}// Overload additionDual operator+(const Dual& other) const {return Dual(value + other.value, derivative + other.derivative);}// Overload subtractionDual operator-(const Dual& other) const {return Dual(value - other.value, derivative - other.derivative);}// Overload multiplicationDual operator*(const Dual& other) const {return Dual(value * other.value, value * other.derivative + derivative * other.value);}// Overload divisionDual operator/(const Dual& other) const {return Dual(value / other.value, (derivative * other.value - value * other.derivative) / (other.value * other.value));}// Overload unary minusDual operator-() const {return Dual(-value, -derivative);}
};// Exponential function
Dual exp(const Dual& x) {double exp_value = std::exp(x.value);return Dual(exp_value, exp_value * x.derivative);
}// Logarithm function
Dual log(const Dual& x) {return Dual(std::log(x.value), x.derivative / x.value);
}// Function to compute f(x) = x^2 + 2x + exp(x)
Dual compute_function(const Dual& x) {return x * x + Dual(2.0, 0.0) * x + exp(x);
}int main() {// Initialize x = 1.0 with derivative 1.0 (i.e., d(x)/dx = 1)Dual x(1.0, 1.0);// Compute the function and its derivativeDual result = compute_function(x);std::cout << "Function value at x = " << x.value << " is " << result.value << std::endl;std::cout << "Derivative at x = " << x.value << " is " << result.derivative << std::endl;return 0;
}
相关文章:
C++ 微积分 - 求导 - 自动微分(Automatic Differentiation)
C 微积分 - 求导 - 自动微分(Automatic Differentiation) flyfish 自动微分(Automatic Differentiation,简称 AD)是一种用于精确计算函数导数的技术。它结合了符号微分的准确性和数值微分的效率。自动微分的核心思想…...
面试题-每日5道
26.在 Queue 中 poll()和 remove()有什么区别? 相同点:都是删除第一个元素并返回。 不同点:如果没有元素poll()会返回null,而remove()会抛出NoSuchElementException异常 27.哪些集合类是线程安全的? Vector,Stock,Hashtable都是线程安全的&a…...
STM32卡死、跑飞如何调试确定问题
目录 前言 一、程序跑飞原因 二、调试工具 2.1Registers工具 2.2 Memory工具 2.3 Disassembly工具 2.4 Call Stack工具 三、找到程序跑飞位置 方式一、 方式二、 前言 我们初学STM32的时候代码难免会出现疏忽,导致程序跑飞,不再正常运行&#…...
代理模式和Spring MVC
Spring是一个分层的轻量级的开源Java框架。核心是IOC(Inverse of Control 控制反转)和AOP(Aspect Oriented Programming 面向切面编程) AOP 面向切面 AOP (Aspect Orient Programming),直译过来就是 面向切面编程,AOP 是一种编程思想&#x…...
深入理解Vue slot的原理
文章目录 前言为什么需要插槽作用域插槽插槽的原理总结 前言 插槽是Vue中一个重要的特性,它有很多种用法:默认插槽、具名插槽、作用域插槽。尤其作用域插槽,还有一堆特性,比如解构prop,解构prop的时候还可以进行属性名…...
git fetch作用与用法
目录 git fetch作用 git fetch用法 git fetch作用 git fetch 命令在 Git 版本控制系统中扮演着重要的角色。其主要作用是从远程仓库获取最新版本的项目文件,但不会自动合并或修改你当前的工作。这意味着,使用 git fetch 后,你需要手动合并…...
pycharm如何查看git历史版本变更信息
通过名字查看不同版本 查看版本不同地方...
【2.2 python中的变量】
2.2 python中的变量 在Python中,变量是存储数据值的容器。Python是一种动态类型语言,这意味着你不需要在声明变量时指定变量的类型;Python会根据你赋给变量的值自动确定其类型。下面我将详细介绍Python中的变量,包括保留字&#…...
Python软体中找出一组字符串的最长公共前缀:算法与实现
Python软体中找出一组字符串的最长公共前缀:算法与实现 在处理字符串数据时,寻找多个字符串之间的共同特征是一个常见的需求。特别是在文件名、URL、或其他文本数据中,找到最长公共前缀(Longest Common Prefix, LCP)可以帮助我们进行更高效的搜索和分类。本文将详细介绍如…...
git lfs使用(huggingface下载大模型文件)-教程记录
写的比较清楚的教程,用于之后有需求时查找用: https://blog.csdn.net/flyingluohaipeng/article/details/130788293...
1. 什么是操作系统
文章目录 1.1 从功能上来看操作系统1.2 硬件资源 1.1 从功能上来看操作系统 对用户来说,操作系统是一个控制软件,可以用来管理应用程序,它可以限制不同的程序来占用的资源。对内部的软件来说,操作系统是一个管理外设和分配资源的…...
数据科学 - 数据预处理 (数据清洗,结构化数据)
1. 前言 数据清洗与结构化数据在数据分析和机器学习项目中扮演着至关重要的角色。随着大数据时代的到来,数据的质量、准确性和可用性成为决定项目成功与否的关键因素。 数据清洗提高数据质量,保证数据集的一致性;促进数据分析与挖掘…...
基于SpringBoot+Vue的校车调度管理系统(带1w+文档)
基于SpringBootVue的校车调度管理系统(带1w文档) 基于SpringBootVue的校车调度管理系统(带1w文档) 如今,因为无线网相关技术的快速,尤其是在网上进行资源的上传下载、搜索查询等技术,以及信息处理和语言开发技术的进步,同时编程语…...
基于改进拥挤距离的多模态多目标优化差分进化(MMODE-ICD)求解无人机三维路径规划(MATLAB代码)
一、无人机多目标优化模型 无人机三维路径规划是无人机在执行任务过程中的非常关键的环节,无人机三维路径规划的主要目的是在满足任务需求和自主飞行约束的基础上,计算出发点和目标点之间的最佳航路。 1.1路径成本 无人机三维路径规划的首要目标是寻找…...
opencascade AIS_Trihedron源码学习 绘制三轴坐标系
opencascade AIS_Trihedron 前言 //! 创建一个可选择的三轴坐标系 //! 该三轴坐标系包括一个原点,三个轴线和三个标签。 //! 标签的默认文本为 “X”, “Y”, “Z”。 //! 可以更改原点和任意轴线的颜色,箭头和标签的颜色也可以改变。 //! 可视化呈现可…...
【C++】C++应用案例-通讯录管理系统
目录 一、整体介绍 1.1、需求和目标 1.2、整体功能描述 二、页面及功能描述 2.1 主菜单 2.2 添加联系人菜单 2.3 显示联系人菜单 2.4 修改联系人菜单 2.5 退出功能 三、流程设计 3.1 主流程 3.2 添加操作流程 3.3 显示联系人操作流程 3.4 修改联系人操作流程 四…...
使用Python自动批量提取增值税发票信息并导出为Excel文件
要批量提取增值税发票的关键信息并将其导出为 Excel 文件,可以使用 Python 脚本结合 pdfplumber(用于解析 PDF 内容)、pandas(用于处理数据并导出 Excel)等库来实现。以下是实现这一目标的详细步骤。 1. 环境设置 首…...
vitis (eclipse) 的Indexer不能搜索、不能跳转到函数和变量定义和声明不能打开调用层次的解决方法
在使用vitis(2021.1) 过程中,有一个非常方便实用的功能,就是在函数或变量等源代码上通过右键菜单或快捷键F3、F4、CtrlAltH,也可以按住Ctrl键然后鼠标停留在函数名或变量名上,点击出现的链接,可以跳转到函数或变量的定…...
最佳HR软件指南:11款高效管理工具
文章介绍了11款人力资源管理工具:Moka、友人才、北森HRSaaS、同鑫eHR、i人事、红海eHR、BambooHR、Skuad、Hibob、OrangeHRM、Verint。 在选择人力资源管理软件时,选错不仅浪费时间和金钱,还会影响团队的工作效率和员工满意度。本文总结了11款…...
家长为孩子出国留学择校的四个步骤
如何为孩子选择最好的学校?无论您是选择公立或私立学校还是在家上学,无论您是否支付学费,都必须仔细规划。在为孩子选择学校的过程中,以下部分有供您考虑的问题。 写下对你来说最重要的五件事 在考虑选择学校时,您可…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
