第二节 数学知识补充

一、线性代数

  • 向量的 L 2 L_2 L2范数(Euclidean范数/Frobenius范数)&矩阵的元素形式范数
    • 向量的 L 2 L_2 L2范数: ∣ ∣ x ∣ ∣ 2 = ( ∣ x 1 ∣ 2 + ⋯ + ∣ x m ∣ 2 ) 1 2 ||x||_2=(|x_1|^2+\cdots+|x_m|^2)^{\frac12} ∣∣x2=(x12++xm2)21
    • 矩阵的元素形式范数:将 m × n m\times n m×n矩阵按照列堆栈的形式排列成 m n × 1 mn \times 1 mn×1的向量,然后采用向量范数的定义,即可得到矩阵的范数: ∣ ∣ x ∣ ∣ p = ( ∑ i = 1 m ∑ j = 1 n ∣ a i j ∣ p ) 1 p ||x||_p=\left(\sum_{i=1}^m\sum_{j=1}^n|a_{ij}|^p\right)^{\frac1p} ∣∣xp=(i=1mj=1naijp)p1
      • 其中Frobenius范数(p=2)为: ∣ ∣ A ∣ ∣ F = ( ∑ i = 1 m ∑ j = 1 n ∣ a i j ∣ 2 ) 1 2 ||A||_F=\left(\sum_{i=1}^m\sum_{j=1}^n|a_{ij}|^2\right)^{\frac12} ∣∣AF=(i=1mj=1naij2)21,也可以写成迹函数的形式: ∣ ∣ A ∣ ∣ F = < A , A > 1 2 = t r ( A H A ) ||A||_F=<A,A>^{\frac12}=\sqrt{tr(A^HA)} ∣∣AF=<A,A>21=tr(AHA) 。也可称为Euclidean范数、Schur范数、Hilbert-Schmidt范数或者L2范数。
  • 两个矩阵按元素的乘法称为“哈达玛积”(Hadamard product)数学符号为 ⊙ \odot 。在Pytorch中,两个形状相同的张量按元素相乘表示为:A*B
  • 两个向量的点积表示为:torch.dot(x, y),结果为tensor类型
  • 矩阵向量积 A x Ax Ax表示为:torch.mv(A, x),mv=matrix vector multiplication
  • 矩阵和矩阵的乘积表示为:torch.mm(A, B)
  • 向量的 L 1 L_1 L1范数(元素的绝对值之和)表示为:torch.abs(x).sum()
  • 向量的 L 2 L_2 L2范数表示为:torch.norm(x),结果为tensor类型。注意❗需要将tensor的元素类型转换为float类型,x=x.float()
  • 矩阵的 F F F范数(弗罗贝尼乌斯范数)表示为:torch.norm(A)

二、矩阵运算(矩阵求导)

  • 当y是标量,x是列向量时, ∂ y ∂ x \frac{\partial y}{\partial \boldsymbol{x}} xy是行向量, ∂ y ∂ x = [ ∂ y ∂ x 1 , ∂ y ∂ x 2 , . . . , ∂ y ∂ x n ] \frac{\partial y}{\partial \boldsymbol{x}}=\left[ \frac{\partial y}{\partial x_1},\frac{\partial y}{\partial x_2},...,\frac{\partial y}{\partial x_n} \right] xy=[x1y,x2y,...,xny]梯度和等高线正交,指向该点处。值变换最大的方向。
  • 当y是列向量,x是标量时, ∂ y ∂ x \frac{\partial \boldsymbol{y}}{\partial x} xy是列向量, ∂ y ∂ x = [ ∂ y 1 ∂ x ∂ y 2 ∂ x ⋮ ∂ y m ∂ x ] \frac{\partial\mathbf{y}}{\partial x}=\begin{bmatrix}\frac{\partial y_1}{\partial x}\\\frac{\partial y_2}{\partial x}\\\vdots\\\frac{\partial y_m}{\partial x}\end{bmatrix} xy= xy1xy2xym
  • 当y是列向量,x是列向量时, ∂ y ∂ x \frac{\partial \boldsymbol{y}}{\partial \boldsymbol{x}} xy是矩阵, ∂ y ∂ x = [ ∂ y 1 ∂ x ∂ y 2 ∂ x ⋮ ∂ y m ∂ x ] = [ ∂ y 1 ∂ x 1 , ∂ y 1 ∂ x 2 , … , ∂ y 1 ∂ x n ∂ y 2 ∂ x 1 , ∂ y 2 ∂ x 2 , … , ∂ y 2 ∂ x n ⋮ ∂ y m ∂ x 1 , ∂ y m ∂ x 2 , … , ∂ y m ∂ x n ] \frac{\partial\mathbf{y}}{\partial\mathbf{x}}=\begin{bmatrix}\frac{\partial\mathbf{y}_1}{\partial\mathbf{x}}\\\frac{\partial\mathbf{y}_2}{\partial\mathbf{x}}\\\vdots\\\frac{\partial\mathbf{y}_m}{\partial\mathbf{x}}\end{bmatrix}=\begin{bmatrix}\frac{\partial\mathbf{y}_1}{\partial x_1},\frac{\partial\mathbf{y}_1}{\partial x_2},\ldots,\frac{\partial\mathbf{y}_1}{\partial x_n}\\\frac{\partial\mathbf{y}_2}{\partial x_1},\frac{\partial\mathbf{y}_2}{\partial x_2},\ldots,\frac{\partial\mathbf{y}_2}{\partial x_n}\\\vdots\\\frac{\partial\mathbf{y}_m}{\partial x_1},\frac{\partial\mathbf{y}_m}{\partial x_2},\ldots,\frac{\partial\mathbf{y}_m}{\partial x_n}\end{bmatrix} xy= xy1xy2xym = x1y1,x2y1,,xny1x1y2,x2y2,,xny2x1ym,x2ym,,xnym
    • ∂ ( A x ) ∂ x = A \frac{\partial \left( A\boldsymbol{x} \right)}{\partial \boldsymbol{x}}=A x(Ax)=A
    • ∂ ( x T A ) ∂ x = A T \frac{\partial \left( \boldsymbol{x}^TA \right)}{\partial \boldsymbol{x}}=A^T x(xTA)=AT ∂ < x , w > ∂ w = x T \frac{\partial \left< \boldsymbol{x,w} \right>}{\partial \boldsymbol{w}}=\boldsymbol{x}^T wx,w=xT,注意分子求内积运算,x和w都是列向量,求内积时表示为 x T w \boldsymbol{x}^T \boldsymbol{w} xTw
      在这里插入图片描述

三、自动求导

标量的链式法则同样可以扩展到向量,注意形状。

链式求导简单举例:
在这里插入图片描述

Ⅰ自动求导

(1)相关概念

自动求导指计算一个函数在指定值上的导数。有别于符号求导和数值求导。

  1. 符号求导(Symbolic Differentiation): 符号求导是基于数学规则(如链式法则、幂规则、导数的乘积规则等)进行的求导过程,它能产生导数的精确解析表达式。例如,使用符号计算软件如 MATLAB 的 Symbolic Math Toolbox 或 Mathematica,用户可以输入一个数学函数并得到它的精确导数公式。这种方法的优点是可以提供清晰的数学表达式,有助于深入理解函数行为和优化算法的设计,但它对函数形式有一定要求,不适合处理复杂的非结构化或动态变化的函数。

  2. 数值求导(Numerical Differentiation): 数值求导是一种近似求导的方法,它不寻找导数的封闭形式表达式,而是通过对函数在相邻点的值进行差分来估计导数。例如,使用有限差分方法(如前向差分、后向差分或中心差分)来计算某一点处的导数值。这种方法适用性广泛,能够处理任意可计算的函数,但求得的是导数的近似值,且误差与步长的选择有关,过大的步长可能导致较大的误差,过小的步长则可能受到浮点计算精度的影响。

    给任何f(x),不需要知道形式,可以通过数值去拟合导数: ∂ f ( x ) ∂ x = lim ⁡ h → 0 f ( x + h ) − f ( x ) h \frac{\partial f(x)}{\partial x}=\lim_{h\to0}\frac{f(x+h)-f(x)}{h} xf(x)=limh0hf(x+h)f(x)

  3. 自动求导(Automatic Differentiation,AD): 自动求导是一种结合了符号和数值求导特点的技术,它基于链式法则和逆向传播的思想,追踪并累加每个计算步骤的微小导数贡献。在现代机器学习和深度学习框架(如 TensorFlow、PyTorch、Theano 等)中广泛应用。自动求导分为前向模式(Forward Mode)和反向模式(Reverse Mode,又称 Backpropagation),其中反向模式尤为适合大型神经网络中梯度的高效计算。自动求导既能给出精确的导数值,又能处理复杂的、非结构化的函数甚至是包含循环和条件语句的程序,而且相比于纯符号求导,它更适合于动态生成的计算图或大规模优化问题。

(2)计算图

等价于用链式法则的计算过程。计算图(Computation Graph)是一种用于表示数学运算和变量之间依赖关系的数据结构,将计算表示成了一个无环图,特别在机器学习和深度学习领域应用广泛。它通过节点(nodes)和边(edges)构建,其中节点代表数学运算或者变量值边则代表这些运算或变量之间的数据流动路径,以及它们相互间的依赖关系

  1. 在计算图中:

    • 节点(Operations / Functions):每个节点执行特定的数学运算,比如加法、乘法、激活函数(如sigmoid、ReLU)、矩阵运算,或者是更复杂的层操作如卷积层或全连接层等。节点没有具体的数值,直到给定所有输入值时才会进行计算。
    • 边(Edges / Tensors):边连接着不同的节点,代表了数据从一个运算传递到另一个运算的过程。边携带的是参与运算的数据,通常表现为多维数组(即张量)。在机器学习中,这些张量通常是权重、偏置、输入特征或是中间层的输出。
    • 变量(Variables):计算图中的变量是具有持久状态的节点,它们存储了模型参数或需要在整个训练过程中更新的中间结果。
    • 反向传播(Backpropagation):当计算图用于训练神经网络时,反向传播利用自动求导技术来高效地计算整个图中所有参数的梯度,这使得我们可以更新网络权重以最小化损失函数。
  2. 计算图的构造有两种主要方式:显式构造(Explicit Construction)和隐式构造(Implicit Construction)。

    (1)显式构造(Explicit Construction)Tensorflow/Theano/MXNet

    在显式构造的计算图中,程序员明确地定义了计算图的结构,也就是预先确定了哪些操作(operations)将被执行以及它们之间的依赖关系。程序员通常需要手动构建图的节点和边,所有的计算都被组织成一个固定结构的图,只有在图构建完成后才能执行计算。

    例如,在TensorFlow 1.x版本中,用户需要通过 tf.Session()tf.Graph() 明确地创建计算图,并通过 tf.Variable()tf.Operation() 等API来显式地添加节点。执行时,数据通过计算图从输入流向输出,而梯度计算(如反向传播)则沿着相反的方向进行。

    (2)隐式构造(Implicit Construction)PyTorch/MXNet

    在隐式构造(或动态构造)的计算图中,计算图是在运行时动态构建的,这意味着每次执行操作时都会实时创建和更新计算图。程序员无需预先声明完整的计算图结构,而是通过直接操作张量(tensor)来进行计算,框架会在背后自动构建和管理计算图。

    例如,在PyTorch中,计算图是在运行时逐行代码构建的,当调用一个操作(如加法、矩阵乘法等)时,相应的计算节点和边会立即加入到计算图中。这种动态特性使得代码更加直观易读,便于调试和实验。

    总结起来,显式构造和隐式构造的主要区别在于构建和执行计算图的时机和方式:

    • 显式构造要求提前定义完整的计算图结构,执行时按图进行计算;
    • 隐式构造则允许在运行时动态构建和更新计算图,代码执行与计算图构建同步进行,灵活性更高。

参考文章:

机器学习入门(10)— 浅显易懂的计算图、链式法则讲解_请画出该函数的计算图,请用方形节点表示-CSDN博客

(先这样简单地了解一下是什么,后续可能实际构造会用到……)

(3)两种求导模式

在这里插入图片描述

  • 正向累积:执行图,存储中间结果
  • 反向累积:从相反方向执行图,可以去除不需要的枝
  • 复杂度
    • n为操作子个数
    • 计算复杂度:正反向代价类似,都为 O ( n ) O(n) O(n)
    • 内存复杂度:
      • 反向累积: O ( n ) O(n) O(n),因为需要存储正向所有中间结果(深度神经网络求梯度耗GPU资源)
      • 正向累积: O ( 1 ) O(1) O(1),不需要存储中间结果

Ⅱ自动求导的实现

深度学习框架通过自动计算导数,即自动微分(automatic differentiation)来加快求导。 实际中,根据设计好的模型,系统会构建一个计算图(computational graph), 来跟踪计算是哪些数据通过哪些操作组合起来产生输出。 自动微分使系统能够随后反向传播梯度。 这里,反向传播(backpropagate)意味着跟踪整个计算图,填充关于每个参数的偏导数。

  • 自动计算导数的思想:首先将梯度附加到想要对其计算偏导数的变量上,然后记录目标值的计算,执行它的反向传播函数,并访问得到的梯度。

假设相对函数 y = 2 x T x y=2\boldsymbol{x}^T\boldsymbol{x} y=2xTx关于列向量 x \boldsymbol{x} x求导,运算结果应该为 4 x 4\boldsymbol{x} 4x【数学情况下应该是 4 x T 4\boldsymbol{x}^T 4xT,但是由于1维的tensor没有行列之分,所以也等于 4 x 4\boldsymbol{x} 4x】:

import torch
x = torch.arange(4.0)  # 创建变量x并对其分配初始值
x.requires_grad_(True)  # 等价于 x = torch.arange(4.0, requires_grad = True)
y = 2 * torch.dot(x, x) # 结果为tensor(28., grad_fn=<MulBackward0>)
y.backward()  # 启动反向传播过程
print(x.grad)   # tensor([ 0.,  4.,  8., 12.])
  1. torch.arange() 函数本身生成的是一维张量(tensor),而不是严格意义上的行向量或列向量。这个一维张量可以看作是一个数列,不具备明确的行或列属性。可以通过 reshape()方法将其转换为行向量或列向量【二维张量】,或者使用torch.transpose(x1, 0, 1)进行转置。

    在这里插入图片描述

  2. x.requires_grad_(True)用于启用张量 x 上的梯度计算的功能。当一个张量的 requires_grad 属性被设置为 True 时,意味着在其上的任何操作都会被跟踪并记录到计算图中,以便在反向传播过程中计算梯度。

  3. grad_fn=<MulBackward0> 表明这个张量是由其他张量经过运算(在这个例子中是乘法操作,由 MulBackward0 指代)产生的,并且参与了反向传播过程,因此它有梯度信息。这意味着如果对该张量求梯度,框架能够追溯到之前的运算步骤以计算梯度。如果前面没有设置启用梯度计算的功能,则不会显示该属性。

    叶子节点通常为None,只有结果节点的grad_fn才有效,用于指示梯度函数是哪种类型。

  4. 在PyTorch中,y.backward() 是用于启动反向传播过程的函数调用,以计算张量 y 相关的所有梯度。当我们处理神经网络或者其他需要梯度计算的任务时,常常会在前向传播阶段结束并计算出损失函数值后,调用此函数。y.backward() == torch.autograd.backward(y)

  5. 多次执行y.backward()会报如下错误:

    在这里插入图片描述

    在PyTorch中,每次调用.backward()方法执行反向传播时,默认情况下会释放中间计算结果以节省内存。当你再次调用.backward()时,先前的计算图已经清理掉了,无法再次进行反向传播。因此,如果你需要在同一个计算图上多次执行反向传播,你需要在.backward()调用时添加参数retain_graph=True,这样PyTorch就会保留计算图,直到显式清除它为止。

    但是频繁地保留计算图可能会占用大量的内存资源,尤其是在复杂的模型中。通常,你应在完成多次反向传播之后手动清空不需要的梯度,以避免内存泄漏:x.grad.zero_(),得到一个全零张量。

    如果不调用清除梯度值的函数,当我们调用 y.backward(retain_graph=True) 并且多次执行时,x.grad 会不断变化的原因在于每次执行反向传播时,新的梯度会累积到现有的梯度之上。由于设置了 retain_graph=True,即使在多次调用 .backward() 后,也不会清除原有的计算图,使得可以不断地在原有基础上累加梯度。

    例如,假设第一次执行反向传播时,计算出 xy 的梯度为 dx1,第二次反向传播时,又计算出梯度为 dx2,那么两次之后 x.grad 将会是 dx1 + dx2

  6. backward()的作用一直都是求出某个张量对于某些标量节点的梯度。注意非标量变量反向传播的计算,注意backward()中的参数:

    Pytorch autograd,backward详解

分离计算

有时,我们希望将某些计算移动到记录的计算图之外。 例如,假设y是作为x的函数计算的,而z则是作为yx的函数计算的。 当我们想计算z关于x的梯度,但由于某种原因,希望将y视为一个常数, 并且只考虑到xy被计算后发挥的作用。

这里可以使用u=y.detach()分离y来返回一个新变量u,该变量与y具有相同的值, 但丢弃计算图中如何计算y的任何信息。 换句话说,梯度不会向后流经ux。 因此,下面的反向传播函数计算z=u*x关于x的偏导数,同时将u作为常数处理, 而不是z=x*x*x关于x的偏导数。

x.grad.zero_()
y = x * x
u = y.detach() #用于从计算图中分离一个张量,这意味着对 .detach() 后得到的新张量所做的任何操作都不会影响原始计算图中的梯度计算。
# u 是 y 的副本,但它与原来的计算图断开了联系,即 u 的梯度不会回传到 x
z = u * xz.sum().backward()
x.grad == u  # tensor([True, True, True, True])

计算二阶导的参考方法:

在 PyTorch 中,虽然自动求导机制主要用于一阶导数的计算,但通过组合现有的一阶导数和 PyTorch 提供的功能,可以间接计算二阶导数,即 Hessian 矩阵或其他二阶导数相关的信息。

对于一个可微分函数 f(x),如果你有一个张量 x 并且 x.requires_grad=True,你可以先通过 .backward() 计算一阶导数(梯度)。然后,如果你想计算二阶导数(例如 Hessian 矩阵),通常需要执行以下步骤:

  1. 计算一阶导数

    x = torch.randn(size=(n,), requires_grad=True)
    y = f(x)# 假设 f 是基于 x 的某些操作组成的函数
    y.backward()# 计算 y 关于 x 的梯度,存储在 x.grad 中
    
  2. 保存一阶导数: 在计算二阶导数之前,你需要保存第一次求导得到的一阶导数,因为接下来的第二次求导会覆盖这些值。

    first_derivative = x.grad.clone().detach()
    
  3. 计算二阶导数: 对于每个元素的 Hessian 矩阵,可以通过对一阶导数再次求导来获得。但在实际操作中,由于内存限制和计算效率问题,直接计算整个 Hessian 矩阵通常是不可行的,尤其是对于大规模神经网络。因此,常常采用逐元素或者稀疏的方式估算 Hessian-vector 乘积,或者采用近似方法(如有限差分法)。

    # 创建一个与 x 形状相同的张量作为“方向向量”
    v = torch.randn_like(x, requires_grad=False)# 将一阶导数当作中间变量,并计算关于它的梯度
    # 这里是对一阶导数求导,相当于得到 Hessian-vector 乘积
    x.grad.zero_()
    torch.autograd.grad(outputs=first_derivative, inputs=x, grad_outputs=v, retain_graph=True, create_graph=True)[0].view_as(v)
    

    上述代码中的 retain_graph=True 参数确保在计算完成后原始计算图不会被释放,以便进行多次反向传播。而 create_graph=True 则意味着在进行这次反向传播时也记录新的计算图,使得能够对新得到的梯度再求导。

如果确实需要计算完整的 Hessian 矩阵,可能需要借助第三方库,或者编写循环结构来分别计算每一项。不过请注意,这样的操作在计算资源和时间开销上往往非常昂贵,特别是在高维度情况下。对于大型模型,研究者更倾向于使用更有效率的二阶优化方法或二阶信息的近似。

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

👌使f(x)=sin(x),绘制f(x)和df(x)/dx的图像:

import torch
import matplotlib.pyplot as plt# 创建可微分的张量
x = torch.arange(0., 10., 0.1, requires_grad=True)
y = torch.sin(x)# 计算 y 的总和,并反向传播得到 dy/dx
y_sum = y.sum()
y_sum.backward()# 将 PyTorch 张量转换为 NumPy 数组以便 Matplotlib 绘图
x_np = x.detach().numpy()
y_np = y.detach().numpy()
# 不能将具有 requires_grad=True 属性的 PyTorch 张量直接转换为 NumPy 数组。
# 在需要进行反向传播的计算过程中,这样的张量不能直接转换成 NumPy 数组,因为它们包含了梯度信息。
# 解决这个问题的方法是在转换之前使用 .detach() 方法断开张量与计算图的连接,使其不再跟踪梯度。
dy_dx_np = x.grad.numpy()# 分别绘制正弦函数和它的导数
plt.plot(x_np, y_np, label='y')
plt.plot(x_np, dy_dx_np, label='dy/dx')# 添加图例和显示图形
plt.legend()
plt.show()

在这里插入图片描述

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

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

相关文章

电脑桌面便签哪个好,好用的电脑桌面便签推荐

在如今信息爆炸的时代&#xff0c;人们的工作和生活节奏越来越快&#xff0c;记事和备忘变得尤为重要。而电脑桌面便签作为一种方便快捷的记录工具&#xff0c;备受广大用户青睐。那么&#xff0c;电脑桌面便签哪个好&#xff0c;哪个更加出色呢&#xff1f; 作为一名人事专员…

CryoEM - 使用 cryoSPARC 基于单颗粒图像从头重构蛋白质三维结构

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/136384544 基于冷冻电镜单颗粒图像重构蛋白质三维结构,利用冷冻电镜技术测定生物大分子结构的方法。原理是从冷冻电镜获得大量同一种蛋白质分子的二维投影图…

【数据结构】实现队列

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解队列&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一. 队列的概念及结构二. 队列的实现队列的结构体初始化销毁队尾插入队头删除显示第一个节点的值…

【Java程序员面试专栏 算法思维】六 高频面试算法题:动态规划

一轮的算法训练完成后,对相关的题目有了一个初步理解了,接下来进行专题训练,以下这些题目就是汇总的高频题目,本篇主要聊聊回溯算法,主要就是排列组合问题,所以放到一篇Blog中集中练习 题目关键字解题思路时间空间零钱兑换动态规划+双重循环dp[i]表示兑换金额为i元的最少…

iOS消息转发流程

当向Objc对象发送消息时&#xff0c;如果找到对象对应的方法&#xff0c;就会进入消息转发流程&#xff0c;给开发者提供一些最后的机会处理消息无法发送问题&#xff0c;以免出现程序崩溃。 1. 回调对象的resolveInstanceMethod方法&#xff0c;在这个方法中&#xff0c;允许开…

阿里云定价_ECS产品价格_云服务器收费标准 - 阿里云官方活动

2024年最新阿里云服务器租用费用优惠价格表&#xff0c;轻量2核2G3M带宽轻量服务器一年61元&#xff0c;折合5元1个月&#xff0c;新老用户同享99元一年服务器&#xff0c;2核4G5M服务器ECS优惠价199元一年&#xff0c;2核4G4M轻量服务器165元一年&#xff0c;2核4G服务器30元3…

基于 LLaMA 和 LangChain 实践本地 AI 知识库

有时候,我难免不由地感慨,真实的人类世界,本就是一个巨大的娱乐圈,即使是在英雄辈出的 IT 行业。数日前,Google 正式对外发布了 Gemini 1.5 Pro,一个建立在 Transformer 和 MoE 架构上的多模态模型。可惜,这个被 Google 寄予厚望的产品并未激起多少水花,因为就在同一天…

S2---FPGA-A7板级原理图硬件实战

视频链接 FPGA-A7板级系统硬件实战01_哔哩哔哩_bilibili FPGA-A7板级原理图硬件实战 基于XC7A100TFGG484的FPGA硬件设计流程图 A7核心板&#xff0c;是基于XILINX公司的ARTIX-7系列100T的XC7A100T,2FGG484I这款芯片开发的高性能核心板&#xff0c;具有高速&#xff0c;高带宽&a…

Android 签名机制

V1是内部文件单个签 但是增加apk文件目录下面随意增加文件并不会有影响,它只关心meta-info文件 mf汇总清单的各个文件sha256 V2 整个APK文件,按文件进行hash 那么便不能随便在这里面增加文件了,增加了签名分块&#xff08;不然签名信息存哪里&#xff09;这里涉及一个文件概念 …

如何修炼成“神医”——《OceanBase诊断系列》之一

本系列是基于OcenaBase 开发工程师在工作中的一些诊断经验&#xff0c;也欢迎大家分享相关经验。 1. 关于神医的故事 扁鹊&#xff0c;中国古代第一个被正史记载的医生&#xff0c;他的成才之路非常传奇。年轻时&#xff0c;扁鹊是一家客栈的主管。有一位名叫长桑君的客人来到…

性能优化篇(二) 静态合批步骤与所有注意事项\游戏运行时使用代码启动静态合批

静态合批步骤: 1.开启Project Settings —>Player–>Other Setting里勾选Static Batching选项(一般情况下unity都是默认勾选状态) 2.勾选需要合批的静态物体上的Batching Static项,勾选后此物体下的所有子物体都默认参与静态合批(勾选后物体不能进行移动/旋转/缩放操作,…

02-设计概述

上一篇&#xff1a;01-导言 本章重点讨论 JNI 中的主要设计问题。本节中的大多数设计问题都与本地方法有关。调用 API 的设计将在第 5 章&#xff1a;调用 API 中介绍。 2.1 JNI 接口函数和指针 本地代码通过调用 JNI 函数来访问 Java 虚拟机功能。JNI 函数可通过接口指针使用…

LeetCode383. 赎金信(C++)

LeetCode383. 赎金信 题目链接代码 题目链接 https://leetcode.cn/problems/ransom-note/description/ 代码 class Solution { public:bool canConstruct(string ransomNote, string magazine) {int record[26] {0};if(ransomNote.size() > magazine.size()) return fa…

多层感知器(神经网络)与激活函数

单个神经元&#xff08;二分类&#xff09; 多个神经元&#xff08;多分类&#xff09; 多层感知器 多层感知器&#xff0c;他是一种深度学习模型&#xff0c;通过多层神经元的连接和激活来解决非线性问题。 激活函数 激活函数的种类包括relu&#xff0c;sigmoid和tanh等 …

批量检测微信小程序是否封禁接口源码

<?php // 要检测的 appid 列表 $appids array(appid1, appid2, appid3); // 使用实际的 appid // 循环调用接口检测小程序状态 foreach ($appids as $appid) { $url https://yan.changxunwangluo.cn/xcx/check_mini_program.php?appid . urlencode($appid); $…

敏捷开发模型:一种灵活、协作和持续的软件开发方法

敏捷开发模型&#xff1a;一种灵活、协作和持续的软件开发方法 引言 在软件开发领域&#xff0c;随着市场需求的不断变化和技术的迅速发展&#xff0c;传统的瀑布模型逐渐暴露出其局限性。为了应对这些挑战&#xff0c;敏捷开发模型应运而生。敏捷开发模型强调灵活、协作和持…

【ArcPy】简化ArcGISPro默认Python环境体量

参考文献 安装 ArcPy—ArcGIS Pro | 文档

[数据集][目标检测]鸡蛋破蛋数据集VOC+YOLO格式792张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;792 标注数量(xml文件个数)&#xff1a;792 标注数量(txt文件个数)&#xff1a;792 标注类别…

同源不同页面之间的通信,SharedWorker使用

同源不同页面之间的通信&#xff0c;SharedWorker使用 描述实现结果 描述 同源不同页面之间的通信&#xff0c;使用SharedWorker&#xff0c;或者使用全局方法通信&#xff0c;这里使用SharedWorker来实现 mdn地址&#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/A…

Odoo迈入开源第一低代码开发平台的重要里程碑

Odoo17的正式发布已经过去好几个月了&#xff0c;通过一段时间的运用&#xff0c;最大的感触就是&#xff0c;Odoo会成为企业管理软件低代码开发平台的重要一员&#xff0c;而V17则会成为这个过程中具有里程碑意义的版本。 时隔四个月&#xff0c;让我们回头来看看Odoo17带来的…