用 Python 从零开始创建神经网络(七):梯度下降(Gradient Descent)/导数(Derivatives)

梯度下降(Gradient Descent)/导数(Derivatives)

  • 引言
  • 1. 参数对输出的影响
  • 2. 斜率(The Slope)
  • 3. 数值导数(The Numerical Derivative)
  • 4. 解析导数(The Analytical Derivative)
  • 5. 总结
    • 规则:

引言

随机更改并搜索最佳权重和偏差并未取得成功,主要原因是权重和偏差的可能组合是无限的,我们需要比单纯的运气更智能的方法才能取得任何成功。每个权重和偏差对损失的影响程度也不同——这种影响取决于参数本身以及当前样本,这些样本是第一层的输入。然后这些输入值被权重相乘,所以输入数据影响神经元的输出,并影响权重对损失的影响。相同的原理适用于下一层的偏差和参数,它们以前一层的输出作为输入。这意味着对输出值的影响取决于参数以及样本——这就是为什么我们要分别计算每个样本的损失值。最后,权重或偏差如何影响总体损失的函数并不一定是线性的。为了知道如何调整权重和偏差,我们首先需要了解它们对损失的影响。

需要注意的一个概念是,我们提到权重和偏差及其对损失函数的影响。然而,损失函数中并不包含权重或偏差。这个函数的输入是模型的输出,而神经元的权重和偏差影响这个输出。因此,即使我们是从模型的输出计算损失,而不是权重/偏差,这些权重和偏差直接影响了损失。

在接下来的章节中,我们将通过解释偏导数、梯度、梯度下降和反向传播来详细描述这一过程。基本上,我们将计算每一个单独的权重和偏差如何改变损失值(它对此有多大影响),给定一个样本(因为每个样本产生一个单独的输出,因此也产生一个单独的损失值),以及如何改变这个权重或偏差以减少损失值。记住——我们的目标是减少损失,我们将通过使用梯度下降来实现这一点。另一方面,梯度是偏导数计算的结果,我们将使用链式法则通过反向传播来更新所有的权重和偏差。如果这听起来还没有多大意义,不用担心;我们将在这一章和接下来的章节中解释所有这些术语以及如何执行这些操作。

要理解偏导数,我们需要从导数开始,它们是偏导数的一种特殊情况——从只取单个参数的函数中计算得出。


1. 参数对输出的影响

让我们从一个简单的函数开始,探索“影响”的含义。

一个非常简单的函数 y = 2 x y = 2x y=2x,其中 x x x为输入:

def f(x):return 2*x

现在让我们围绕这个函数编写一些代码来可视化数据 —— 我们将导入NumPyMatplotlib,创建一个从0到4的5个输入值的数组,计算每个输入值的函数输出,并将结果以连续点之间的线条形式绘制出来。这些点的坐标是输入 x x x和函数输出 y y y

import matplotlib.pyplot as plt
import numpy as npdef f(x):return 2*xx = np.array(range(5))
y = f(x)print(x)
print(y)plt.plot(x, y)
plt.show()
>>>
[0 1 2 3 4]
[0 2 4 6 8]

在这里插入图片描述


2. 斜率(The Slope)

这看起来像是 f ( x ) = 2 x f(x) = 2x f(x)=2x函数的输出,这是一条直线。你如何定义 x x x y y y的影响呢?有些人会说,“ y y y x x x的两倍”。另一种描述这种线性函数影响的方式来自代数学:斜率。你可能还记得学校里学过的一个短语“纵横比”(即“rise over run”)。一条直线的斜率是:

在这里插入图片描述
斜率是 y y y的变化量除以 x x x的变化量,或者用数学语言来说 —— Δ y \Delta y Δy除以 Δ x \Delta x Δx。那么 f ( x ) = 2 x f(x) = 2x f(x)=2x的斜率是多少呢?

要计算斜率,首先我们需要在函数图形上取任意两点,并对它们进行减法运算以计算变化量。减去这些点意味着分别减去它们的 x x x y y y维度。 y y y的变化量除以 x x x的变化量得到的结果就是斜率:

在这里插入图片描述
接着写代码,我们将所有 x x x值保存在一个单维度的NumPy数组 x x x中,所有结果保存在另一个单维度数组 y y y中。为了执行相同的操作,我们将取 x [ 0 ] x[0] x[0] y [ 0 ] y[0] y[0]作为第一个点,然后取 x [ 1 ] x[1] x[1] y [ 1 ] y[1] y[1]作为第二个点。现在我们可以计算它们之间的斜率:

import matplotlib.pyplot as plt
import numpy as npdef f(x):return 2*xx = np.array(range(5))
y = f(x)plt.plot(x, y)
plt.show()print((y[1]-y[0]) / (x[1]-x[0]))
>>>
2.0

这条直线的斜率是 2 2 2并不令人意外。我们可以说 x x x y y y的影响度量是 2 2 2。我们可以以相同的方式计算任何线性函数的斜率,包括那些不那么明显的线性函数。

那么对于一个非线性函数如 f ( x ) = 2 x 2 f(x) = 2x^2 f(x)=2x2呢?

def f(x):return 2*x**2

此函数创建一个不形成直线的图形:
在这里插入图片描述

我们可以测量这条曲线的斜率吗?根据我们选择使用的 2 点,我们将测量不同的斜率:

y = f(x) # Calculate function outputs for new functionprint(x)
print(y)
>>>
[0 1 2 3 4]
[ 0 2 8 18 32]

现在讨论第一点:

print((y[1]-y[0]) / (x[1]-x[0]))
>>>
2

另一个:

print((y[3]-y[2]) / (x[3]-x[2]))
>>>
10

在这里插入图片描述

代码的可视化: https://nnfs.io/bro

我们如何衡量 x x x y y y在这个非线性函数中的影响呢?微积分提出,我们可以通过测量 x x x点(对于函数的一个特定输入值)的切线斜率来衡量,这给出了瞬时斜率(该点的斜率),即导数。切线是通过在曲线上的两个“无限接近”的点之间画一条线来创建的,但这条曲线必须在导数点处是可微分的。这意味着它必须是连续且平滑的(我们无法计算在我们可以描述为“尖角”的东西上的斜率,因为它包含无数个斜率)。然后,因为这是一条曲线,所以没有单一的斜率。斜率取决于我们在哪里测量它。举一个直接的例子,我们可以通过使用 x x x点和另一个也在 x x x点但加上一个非常小的增量,例如0.0001的点来近似这个函数在 x x x处的导数。这个数字是一个常见的选择,因为它不会引入太大的误差(在估计导数时)或导致整个表达式在数值上不稳定(由于浮点数分辨率, Δ x \Delta x Δx可能会四舍五入到0)。这让我们能够像以前一样计算斜率,但是在两个非常接近的点上进行,从而得到 x x x处斜率的良好近似:

import matplotlib.pyplot as plt
import numpy as npdef f(x):return 2*x**2p2_delta = 0.0001x1 = 1
x2 = x1 + p2_delta # add deltay1 = f(x1) # result at the derivation point
y2 = f(x2) # result at the other, close pointapproximate_derivative = (y2-y1)/(x2-x1)print(approximate_derivative)
>>>
4.0001999999987845

我们很快就会了解到,当 x = 1 x=1 x=1时, 2 x 2 2x^2 2x2的导数应该恰好是4。我们看到的差异(约为4.0002)来自于计算切线的方法。我们选择了一个足够小的 δ \delta δ,以尽可能准确地近似导数,但又足够大以防止四舍五入误差。

更详细地说,一个无限小的 δ \delta δ值将近似一个准确的导数;然而, δ \delta δ值需要在数值上稳定,意味着,我们的 δ \delta δ不能超过Python浮点精度的限制(不能太小,否则可能会被四舍五入为0,而我们知道,除以0是“非法”的)。因此,我们的解决方案受限于估计导数和保持数值稳定之间,因此引入了这个小但可见的误差。


3. 数值导数(The Numerical Derivative)

这种计算导数的方法称为数值微分——使用两个无限接近的点计算切线的斜率,或者像代码解决方案中那样——计算由两个“足够接近”的点构成的切线的斜率。我们可以通过以下内容来可视化为什么我们要在两个接近的点上执行这个操作:

在这里插入图片描述
在这里插入图片描述

代码的可视化: https://nnfs.io/cat

我们可以看到,这两个点越接近,切线就显得越正确。

继续进行数值微分,让我们可视化切线并观察它们如何随着计算位置的不同而变化。首先,我们将使用Numpyarange()函数使这个函数的图形更加细致,从而允许我们以更小的步骤绘图。np.arange()函数接收起始点、终点和步长参数,允许我们每次取0.001这样的小步长:

import matplotlib.pyplot as plt
import numpy as npdef f(x):return 2*x**2# np.arange(start, stop, step) to give us smoother line
x = np.arange(0, 5, 0.001)
y = f(x)plt.plot(x, y)
plt.show()

在这里插入图片描述

为了绘制这些切线,我们将推导出某一点处切线的函数,并在该点的图形上绘制切线。直线的函数是 y = m x + b y = mx + b y=mx+b。其中 m m m是我们已经计算出的斜率或近似导数, x x x是输入,这使得 b b b,即 y y y截距,需要我们来计算。斜率保持不变,但目前,您可以通过 y y y截距“上移”或“下移”线。我们已经知道 x x x m m m,但 b b b仍然未知。假设为了图形的目的令 m = 1 m=1 m=1,看看这实际意味着什么:

在这里插入图片描述

代码的可视化: https://nnfs.io/but

要计算 b b b,公式是 b = y − m x b = y - mx b=ymx

在这里插入图片描述

到目前为止,我们已经使用了两个点——我们想要计算导数的点和与其“足够接近”的点来计算导数的近似值。现在,根据上述 b b b的方程,导数的近似值,以及同一个“足够接近”的点(具体来说是它的 x x x y y y坐标),我们可以将它们代入方程中,得到该导数点处切线的 y y y截距。使用代码:

import matplotlib.pyplot as plt
import numpy as npdef f(x):return 2*x**2# np.arange(start, stop, step) to give us smoother line
x = np.arange(0, 5, 0.001)
y = f(x)plt.plot(x, y)# The point and the "close enough" point
p2_delta = 0.0001
x1 = 2
x2 = x1+p2_deltay1 = f(x1)
y2 = f(x2)print((x1, y1), (x2, y2))# Derivative approximation and y-intercept for the tangent line
approximate_derivative = (y2-y1)/(x2-x1)
b = y2 - approximate_derivative*x2# We put the tangent line calculation into a function so we can call
# it multiple times for different values of x
# approximate_derivative and b are constant for given function
# thus calculated once above this function
def tangent_line(x):return approximate_derivative*x + b# plotting the tangent line
# +/- 0.9 to draw the tangent line on our graph
# then we calculate the y for given x using the tangent line function
# Matplotlib will draw a line for us through these points
to_plot = [x1-0.9, x1, x1+0.9]
plt.plot(to_plot, [tangent_line(i) for i in to_plot])print('Approximate derivative for f(x)', f'where x = {x1} is {approximate_derivative}')plt.show()
>>>
(2, 8) (2.0001, 8.000800020000002)
Approximate derivative for f(x) where x = 2 is 8.000199999998785

在这里插入图片描述

橙色的线是函数 f ( x ) = 2 x 2 f(x) = 2x^2 f(x)=2x2 x = 2 x=2 x=2处的近似切线。我们为什么要关心这个?你很快会发现,我们只关心这条切线的斜率,但是可视化和理解切线都非常重要。我们关心切线的斜率,因为它告诉我们 x x x在特定点对这个函数的影响,被称为瞬时变化率。我们将使用这个概念来确定一个特定的权重或偏置对给定样本的总损失函数的影响。现在,对于不同的 x x x值,我们可以观察到对函数的不同影响。我们可以继续之前的代码,查看不同输入( x x x)的切线 - 我们将代码的一部分放在一个循环中,遍历示例 x x x值,并绘制多条切线:

import matplotlib.pyplot as plt
import numpy as npdef f(x):return 2*x**2
# np.arange(start, stop, step) to give us a smoother curve
x = np.array(np.arange(0,5,0.001))
y = f(x)plt.plot(x, y)colors = ['k','g','r','b','c']def approximate_tangent_line(x, approximate_derivative):return (approximate_derivative*x) + bfor i in range(5):p2_delta = 0.0001x1 = ix2 = x1+p2_deltay1 = f(x1)y2 = f(x2)print((x1, y1), (x2, y2))approximate_derivative = (y2-y1)/(x2-x1)b = y2-(approximate_derivative*x2)to_plot = [x1-0.9, x1, x1+0.9]plt.scatter(x1, y1, c=colors[i])plt.plot([point for point in to_plot], [approximate_tangent_line(point, approximate_derivative) for point in to_plot], c=colors[i])print('Approximate derivative for f(x)', f'where x = {x1} is {approximate_derivative}')plt.show()
>>>
(0, 0) (0.0001, 2e-08)
Approximate derivative for f(x) where x = 0 is 0.00019999999999999998
(1, 2) (1.0001, 2.00040002)
Approximate derivative for f(x) where x = 1 is 4.0001999999987845
(2, 8) (2.0001, 8.000800020000002)
Approximate derivative for f(x) where x = 2 is 8.000199999998785
(3, 18) (3.0001, 18.001200020000002)
Approximate derivative for f(x) where x = 3 is 12.000199999998785
(4, 32) (4.0001, 32.00160002)
Approximate derivative for f(x) where x = 4 is 16.000200000016548

在这里插入图片描述

对于这个简单的函数 f ( x ) = 2 x 2 f(x) = 2x^2 f(x)=2x2,我们通过近似导数(即切线的斜率)并没有支付高昂的代价,并且得到了足够接近我们需求的值。

问题在于,我们神经网络中实际使用的函数并不简单。损失函数包含了所有的层、权重和偏置——这是一个在多个维度上运作的绝对庞大的函数!使用数值微分计算导数需要对单个参数更新进行多次前向传递(我们将在第10章讨论参数更新)。我们需要执行前向传递作为参考,然后通过增量值更新单个参数,并再次通过我们的模型执行前向传递以查看损失值的变化。接下来,我们需要计算导数并恢复我们为这次计算所做的参数更改。我们必须对每个权重和偏置以及每个样本重复这一过程,这将非常耗时。我们还可以将这种方法视为强行计算导数的方法。再次强调,正如我们快速涵盖了许多术语,导数是作为单个参数输入的函数的切线的斜率。我们将利用这种能力计算损失函数在每个权重和偏置点的斜率——这将引导我们进入多变量函数,这是一个涉及多个参数的函数,是下一章的主题——偏导数。


4. 解析导数(The Analytical Derivative)

现在我们对什么是导数有了更好的理解,如何计算数值导数(也称为通用导数),以及为什么这种方法不适合我们,我们可以继续探讨解析导数,这是我们将在代码中实现的实际导数解法。

在数学中,解决问题通常有两种方法:数值方法和解析方法。数值解决方法涉及计算一个数字来找到解决方案,就像上面的近似导数方法一样。数值解也是一种近似。另一方面,解析方法提供了精确且在计算方面更快的解决方案。然而,正如我们将很快学到的,识别给定函数的导数的解析解在复杂性上会有所不同,而数值方法的复杂度从不增加——它总是调用两次方法,用两个输入来计算某一点的近似导数。一些解析解非常明显,有些可以通过简单的规则计算,而一些复杂的函数可以分解成更简单的部分,并使用所谓的链式法则进行计算。我们可以利用已经证明的某些函数的导数解,而其他一些函数——像我们的损失函数——可以通过上述方法的组合来解决。

要使用解析方法计算函数的导数,我们可以将它们分解为简单的基本函数,找到这些函数的导数,然后应用链式法则(我们很快会解释这一点)来得到完整的导数。为了开始建立直觉,让我们从简单的函数及其各自的导数开始。简单常数函数的导数:

在这里插入图片描述

在这里插入图片描述

代码的可视化: https://nnfs.io/cow

当计算函数的导数时,回想一下导数可以被解释为斜率。在这个例子中,这个函数的结果是一条水平线,因为任何 x x x的输出值都是1:

通过观察,很明显导数等于0,因为从一个 x x x值到任何其他 x x x值都没有变化(即,没有斜率)。

到目前为止,我们通过取一个单一参数 x x x来计算函数的导数,在每个例子中我们都是这样做的。这在计算偏导数时会有所改变,因为偏导数涉及到具有多个参数的函数,并且我们将一次只对其中一个参数计算导数。目前,对于导数,它总是相对于单一参数。为了表示导数,我们可以使用撇号记法,例如对于函数 f ( x ) f(x) f(x),我们加上一个撇号 ( ′ ) (') () f ′ ( x ) f'(x) f(x)。对于我们的例子, f ( x ) = 1 f(x) = 1 f(x)=1,其导数 f ′ ( x ) = 0 f'(x) = 0 f(x)=0。我们还可以使用的另一种记法称为莱布尼茨记法——依赖于撇号记法和用莱布尼茨记法书写导数的多种方式如下:


这些记法的含义相同 —— 函数的导数(相对于 x x x)。在接下来的例子中,我们将使用这两种记法,因为有时使用一种记法或另一种记法更方便。我们也可以在同一个等式中同时使用这两种记法。

5. 总结

规则:

函数的常数倍的导数等于该函数导数的常数倍:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

我们在这里使用 x x x的值而不是整个函数 f ( x ) f(x) f(x),因为整个函数的导数的计算方式有些不同。我们将在下一章中解释这个概念,并结合链式法则进行讲解。

既然我们已经了解了什么是导数以及如何解析地计算它们,稍后我们将在代码中实现,我们可以更进一步,在下一章中讨论偏导数。

本章的章节代码、更多资源和勘误表:https://nnfs.io/ch7

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/60620.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

防爆手机市场“百花齐放”,该怎么选?

在危险作业场景,如石化煤矿,通讯设备采购关系到提高生产效率‌,保障安全生产‌,‌符合法规要求‌。在应急救援通信场景,通讯设备采购,与保障救援行动的效率和准确性息息相关。而通信设备的性能参数是评估其…

似然函数解析

从贝叶斯定理引出似然函数 最大似然估计用来估计均值方差的 文心对似然函数的解释,注意 抛出正反的概率,就是固定均值方差的条件概率密度了

记录配置ubuntu18.04下运行ORBSLAM3的ros接口的过程及执行单目imu模式遇到的问题(详细说明防止忘记)

今天的工作需要自己录制的数据集来验证昨天的标定结果 用ORBSLAM3单目imu模式运行,mentor给的是一个rosbag格式的数据包,配置过程出了几个问题记录一下,沿配置流程写。 一.orbslam3编译安装 1.首先是安装各种依赖 这里不再赘述&#xff0…

实验5:网络设备发现、管理和维护

实验5:网络设备发现、管理和维护 实验目的及要求: 通过实验,掌握Cisco 路由器和交换机的IOS配置管理。自动从NTP服务器获取时间信息。能够利用TFTP服务器实现路由器和交换机配置文件的备份和恢复。同时验证CDP协议和LLDP协议的网络参数。完…

前端(2)——快速入门CSS

参考: 罗大富 CSS 参考手册 | 菜鸟教程 CSS 参考手册 1. CSS CSS全名是层叠样式表,中文名层叠样式表。用于定义网页样式和布局的样式表语言。 通过 CSS,你可以指定页面中各个元素的颜色、字体、大小、间距、边框、背景等样式,…

yolo标签自动标注(使用python和yolo方法)

yolo代码自动标注 1.引言1.初阶“自动标注”,给每个图像都生成一个固定的标注文件,进而在labglimg中对矩形框进行微调,减少标注的工作量2.高阶自动标注,利用我们训练好的(但是没有特别精准的)yolo文件先对每…

jmeter常用配置元件介绍总结之线程组

系列文章目录 安装jmeter jmeter常用配置元件介绍总结之线程组 1.线程组(用户)1.1线程组1.1.setUp线程组和tearDown线程组1.2.Open Model Thread Group(开放模型线程组)1.3.bzm - Arrivals Thread Group(到达线程组)1.4.jpgc - Ultimate Thread Group(终极线程组)1.5.jpgc - St…

spring gateway 动态路由

##yml配置 spring:application:name: public-gateway # cloud: # gateway: # routes: # - id: mybatis-plus-test # 路由的唯一标识 # uri: http://192.168.3.188:9898 # 目标服务的地址 # predicates: # - Path/test/** # 匹配…

NVT新能德科技入职测评SHL题库更新:数字推理+演绎推理高分答案、真题解析

新能德的入职Verify测评主要考察应聘者的逻辑推理能力、数学能力、数据分析能力以及处理信息的能力。根据搜索结果,测评通常包含以下几个部分: 1. **语言理解**:这部分包括阅读理解、逻辑填空和语句排序。要求应聘者在17分钟内完成30题&#…

学法减分交管12123模拟练习小程序源码前端和后端和搭建教程

交管推出个学法减分,每个驾驶员可以把被扣的6分,以看视频答题的形式学习回来,然后答题这个一共二十道题每道题60秒,有好多人不会,用咱们的小程序就可以模拟练习强化练习,还有拍照识别题目找到正确答案&…

element-plus <el-date-picker>日期选择器踩坑!!!!

我怎么一上午踩两个坑&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff08;大声bb&#xff09; 原来的vue2老项目是这样写的 <el-form-item label"时间" prop"time"><el-date-pickerv-model"addForm.time"typ…

JS的学习与使用

JS的学习与使用 一 什么是Javascript&#xff1f; Javascript是一门跨平台&#xff0c;面向对象的脚本语言&#xff0c;是用来控制网页行为的&#xff0c;它能使网页可以交互 java与Javascript是完全不同的语言&#xff0c;不论是概念还是设计&#xff0c;但是基础语法类似 E…

ubuntu20.04 解决Pytorch默认安装CPU版本的问题

ubuntu20.04 解决Pytorch默认安装CPU版本的问题 在使用Anaconda安装支持CUDA的PyTorch版本时&#xff0c;遇到只能安装CPU版本的PyTorch是一个常见问题。这通常由于Anaconda环境配置、镜像源设置不当或版本匹配问题导致。以下是详尽的解决方案和步骤&#xff0c;以确保能够正确…

【操作系统】守护进程

一、守护进程的概念 守护进程是一个在后台运行并且不受任何终端控制的进程 二、自己实现守护进程 1.预备知识 &#xff08;1&#xff09;/dev/null /dev/null是一个特殊的设备文件&#xff0c;往这个文件里写不进去任何数据&#xff0c;也读不出来任何数据 因此&#xff0…

【数据结构与算法】第12课—数据结构之归并排序

文章目录 1. 归并排序2. 计数排序3. 排序算法复杂度及稳定性分析在这里插入图片描述 1. 归并排序 分治法&#xff08;Divide and Conquer&#xff09;是一种重要的算法设计策略&#xff0c;其核心思想是将一个复杂的大问题分解为若干个小规模的子问题&#xff0c;递归地解决这些…

【安全通信】告别信息泄露:搭建你的开源视频聊天系统briefing

文章目录 前言1.关于briefing2.本地部署briefing3.使用briefing4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定briefing公网地址 前言 在这个信息爆炸的时代&#xff0c;视频聊天几乎成了我们日常沟通的标配。但你是否曾在视频会议中感到不安&#xff0c;担心自己的私…

pip install tkinter报错

pip install tkinter&#xff1a;ERROR: Could not find a version that satisfies the requirement tkinter 这是因为&#xff0c;安装python的时候没有安装tkinter选项&#xff0c;解决这个问题有下面两种方法 一、重新安装python 但是这个步骤有点麻烦 二、在python-3.1…

Python的面向对象day7

1、什么是面向对象 面向对象称为OO&#xff0c;他通过将数据和功能封装在一个被称为‘对象’的实体中&#xff0c;来组织和管理代码。面向对象变成&#xff08;OOP&#xff09;具有四个特性&#xff0c;封装、继承、多态、抽象 优点&#xff1a;模块化、安全性高、代码重用性…

自动化工具 Gulp

自动化工具 gulp 摘要 概念&#xff1a;gulp用于自动化开发流程。 理解&#xff1a;我们只需要编写任务&#xff0c;然后gulp帮我们执行 核心概念&#xff1a; 任务&#xff1a;通过定义不同的任务来组织你的构建流程。 管道&#xff1a;通过管道方式将文件从一个插件传递…

探索 Seata 分布式事务

Seata(Simple Extensible Autonomous Transaction Architecture)是阿里巴巴开源的一款分布式事务解决方案,旨在帮助开发者解决微服务架构下的分布式事务问题。它提供了高效且易于使用的分布式事务管理能力,支持多种事务模式,确保数据的一致性和完整性。 以下是 Seata 的一…