政安晨:梯度与导数~示例演绎《机器学习·神经网络》的高阶理解
这篇文章确实需要一定的数学基础,第一次接触的小伙伴可以先看一下我示例演绎这个主题的前两篇文章:
示例演绎机器学习中(深度学习)神经网络的数学基础——快速理解核心概念(一):
政安晨:示例演绎机器学习中(深度学习)神经网络的数学基础——快速理解核心概念(一){两篇文章讲清楚}
https://blog.csdn.net/snowdenkeke/article/details/136089968示例演绎机器学习中(深度学习)神经网络的数学基础——快速理解核心概念(二):
政安晨:示例演绎机器学习中(深度学习)神经网络的数学基础——快速理解核心概念(二){两篇文章讲清楚}
https://blog.csdn.net/snowdenkeke/article/details/136090846

简述概念
在机器学习中,神经网络是一种常用的模型,用于解决各种问题,如图像识别、自然语言处理等。神经网络通过一系列的神经元(也称为节点)组成的层次结构来模拟人脑的神经系统。
神经网络的训练过程可以看作是一个优化问题,目标是找到最优的参数来最小化损失函数。为了实现这个目标,梯度和导数是非常重要的概念。
梯度是损失函数对于参数的导数。在神经网络中,我们使用梯度来更新参数,以使损失函数最小化。通过计算损失函数对于每个参数的梯度,我们可以确定应该如何调整参数的值,以逐渐减少损失。
导数是函数在某一点的斜率或变化率。在神经网络中,我们将损失函数视为参数的函数,并计算其在参数点处的导数。这告诉我们在该点上损失函数是如何随参数的变化而变化的。
通过梯度和导数,我们可以了解损失函数如何随参数的变化而变化,并根据这些信息来调整参数的值,以改善模型的性能。梯度下降是一种常用的优化算法,它使用梯度的信息来逐步调整参数的值,以最小化损失函数。
总结起来,神经网络中的梯度和导数是用于优化模型的重要概念。它们提供了关于损失函数随参数变化的信息,帮助我们调整参数的值以改善模型性能。
基于梯度的优化
如同咱们前面文章提到的,对于咱们前面提到的深度学习中的模型而言,每个神经网络层都对输入数据进行如下变换:
output = relu(dot(input, W) + b)
这里,W和b是张量,均为该层的属性。它们被称为该层的权重(weight)或可训练参数(trainable parameter),分别对应属性kernel和bias。这些权重包含模型从训练数据中学到的信息。
咱们先大概了解一下:
在机器学习中,神经网络的kernel(或称为kernel function)指的是一种用于计算两个数据样本之间相似度的函数。这个函数会将输入的数据样本映射到一个高维特征空间,并在该特征空间中计算两个样本之间的相似度或距离。通过定义适当的kernel函数,可以处理非线性问题,并且可以提高神经网络的表达能力和预测性能。常见的kernel函数有线性核函数、多项式核函数、高斯核函数等。这些kernel函数可以根据具体的问题和数据特征选择和定义。在神经网络中,kernel函数通常用于支持向量机(SVM)和卷积神经网络(CNN)等模型中,用于计算样本之间的相似度。
同时,神经网络的bias(偏差)指的是模型在学习过程中对目标函数的预测的偏离程度。神经网络的bias项是模型的一个可学习参数,用于调整模型的输出值。它通常被添加到神经网络的每一层的神经元上,以调整模型的预测结果与真实值之间的偏差。bias可以理解为模型的预测的基准线,它的值决定了模型对于不同类型数据的初始偏好。通过调整bias的值,可以使模型更加适应不同类型的数据分布。
一开始,这些权重矩阵取较小的随机值,这一步叫作随机初始化(random initialization)。
当然,W和b都是随机的,relu(dot(input, W) + b)不会得到任何有用的表示。虽然得到的表示没有意义,但这是一个起点。下一步则是根据反馈信号逐步调节这些权重。这个逐步调节的过程叫作训练(training),也就是机器学习中的“学习”过程。
上述过程发生在一个训练循环(training loop)内,其具体流程如下:(在一个循环中重复下列步骤,直到损失值变得足够小)
1) 抽取训练样本x和对应目标y_true组成的一个数据批量。
2) 在x上运行模型(这一步叫作前向传播(forward pass)),得到预测值y_pred。
3) 计算模型在这批数据上的损失值,用于衡量y_pred和y_true之间的差距。
4) 更新模型的所有权重,以略微减小模型在这批数据上的损失值。
最终得到的模型在训练数据上的损失值非常小,即预测值y_pred与预期目标y_true之间的差距非常小,模型已“学会”将输入映射到正确的目标,虽然看起来很复杂,但如果您将其简化为基本步骤,那么会发现它变得非常简单。
第1步看起来很简单,只是输入/输出(I/O)的代码。
第2步和第3步仅仅是应用了一些张量运算,所以你完全可以利用咱们在前两篇文章里演绎的知识来实现这两步。
难点在于第4步:更新模型的权重。对于模型的某个权重系数,你怎么知道这个系数应该增大还是减小,以及变化多少呢?
一种简单的解决方案是:
保持模型的其他权重不变,只考虑某一个标量系数,让其尝试不同的取值。
假设这个系数的初始值为0.3。
对一批数据做完前向传播后,模型在这批数据上的损失值是0.5。
如果将这个系数改为0.35并重新运行前向传播,那么损失值增大为0.6。
但如果将这个系数减小到0.25,那么损失值减小为0.4。
在这个例子中,将系数减小0.05似乎有助于让损失值最小化。
对于模型的所有系数都要重复这一过程。
但上述这种方法非常低效,因为系数有很多(通常有上千个,有时甚至多达上百万个),对每个系数都要计算两次前向传播,计算代价很大。其实,有一种更好的方法:梯度下降法(gradient descent)。
梯度下降是驱动现代神经网络的优化方法,其要点如下:
我们的模型用到的所有函数(比如dot或+),都以一种平滑、连续的方式对输入进行变换。
举个例子,对于z = x + y,y的微小变化只会导致z的微小变化,如果你知道y的变化方向,就可以推断出z的变化方向。
用数学语言来讲,这些函数是可微(differentiable)的,将这样的函数组合在一起,得到的函数仍然是可微的,尤其是,将模型系数映射到模型在数据批量上损失值的函数,也是可微的:模型系数的微小变化,将导致损失值发生可预测的微小变化。
我们可以用一个叫作梯度(gradient)的数学运算符来描述:模型系数向不同方向移动时,损失值如何变化,计算出梯度,就可以利用它来更新系数,使损失值减小(在一次更新中全部完成,而不是一次更新一个系数)。
咱们接下来,更进一步来解释这个概念:
导数
假设有一个光滑的连续函数f(x) = y,将一个数字x映射到另一个数字y。我们以下图所示的函数为例:

由于函数是连续的,因此x的微小变化只会导致y的微小变化——这就是函数连续性(continuity)的直观解释。假设x增加了一个很小的因子epsilon_x,这导致y发生了很小的变化epsilon_y,如下图所示:

此外,由于函数是光滑的(意思是,函数曲线没有任何突变的角度),因此在某个点p附近:
如果epsilon_x足够小,就可以将f近似地看作斜率为a的线性函数:
这样epsilon_y就等于a * epsilon_x。
f(x + epsilon_x) = y + a * epsilon_x
显然,只有在x足够接近p时,这个线性近似才有效。
斜率a被称为f在p点的导数(derivative)。
·如果a为负,那么说明x在p点附近的微增将导致f(x)减小(如下图所示);
·如果a为正,那么x的微增将导致f(x)增大。
·此外,a的绝对值(导数大小)表示这种增大或减小的速度。

对于每个可微函数f(x)(可微的意思是“可以被求导”,比如光滑的连续函数可以被求导),都存在一个导数函数f'(x),将x的值映射为f在该点局部线性近似的斜率。
例如,cos(x)的导数是-sin(x),f(x) = a * x的导数是f'(x) =a。
优化的目的就是找到使f(x)最小化的x值,就此而言,函数求导是一个非常强大的工具。如果你想将x改变一个很小的因子epsilon_x,目的是将f(x)最小化,并且你知道f的导数,那么问题已经解决了:导数描述的就是,改变x后f(x)会如何变化。如果你想减小f(x)的值,那么只需将x沿着导数的反方向移动一小步。
张量运算的导数:梯度
上文提到的函数f是将一个标量值x映射为另一个标量值y,你可以将函数绘制为二维平面上的一条曲线。
现在想象有一个函数,将标量元组(x, y)映射为一个标量值z,那么这是一个向量运算。你可以将它绘制为三维空间(以x、y、z为坐标轴)中的二维表面(surface)。同样,你还可以想象以矩阵为输入的函数、以3阶张量为输入的函数,等等。
导数这一概念可以应用于任意函数,只要函数所对应的表面是连续且光滑的。张量运算(或张量函数)的导数叫作梯度(gradient)。梯度就是将导数这一概念推广到以张量为输入的函数。还记不记得,对于一个标量函数来说,导数是如何表示函数曲线的局部斜率(local slope)的?同样,张量函数的梯度表示该函数所对应多维表面的曲率(curvature)。它表示的是,当输入参数发生变化时,函数输出如何变化。
咱们再举例。
假设我们有:
一个输入向量x(数据集中的一个样本);
一个矩阵W(模型权重);
一个目标值y_true(模型应该学到的与x相关的结果);
一个损失函数loss(用于衡量模型当前预测值与y_true之间的差距)。
你可以用W来计算预测值y_pred,然后计算损失值,即预测值y_pred与目标值y_true之间的差距。
# 利用模型权重W对x进行预测
y_pred = dot(W, x)# 估算预测值的偏差有多大
loss_value = loss(y_pred, y_true)
现在我们想利用梯度来更新W,以使loss_value变小。
如何做到这一点呢?
如果输入数据x和y_true保持不变,那么可以将前面的运算看作一个将模型权重W的值映射到损失值的函数。
# f描述的是:当W变化时,损失值所形成的曲线(或高维表面)
loss_value = f(W)
假设W的当前值为W0,f在W0点的导数是一个张量grad(loss_value, W0),其形状与W相同,每个元素grad(loss_value, W0)[i, j]表示当W0[i, j]发生变化时loss_value变化的方向和大小。
张量grad(loss_value, W0)是函数f(W) = loss_value在W0处的梯度,也叫作“loss_value相对于W在W0附近的梯度”。
偏导数
张量运算grad(f(W), W)以矩阵W为输入,它可以表示为标量函数grad_ij(f(W), w_ij)的组合,每个标量函数返回的是,loss_value =f(W)相对于W[i, j]的导数(假设W的其他所有元素都不变)。grad_ij叫作f相对于W[i, j]的偏导数(partial derivative)。
grad(loss_value, W0)具体代表什么呢?
我们在前面看到,单变量函数f(x)的导数可以看作函数f曲线的斜率。同样,grad(loss_value, W0)可以看作表示loss_value = f(W)在W0附近最陡上升方向的张量,也表示这一上升方向的斜率。每个偏导数表示f在某个方向上的斜率。
对于一个函数f(x),你可以通过将x沿着导数的反方向移动一小步来减小f(x)的值。同样,对于一个张量函数f(W),你也可以通过将W沿着梯度的反方向移动来减小loss_value = f(W)。
比如W1 = W0 - step * grad(f(W0), W0),其中step是一个很小的比例因子。也就是说,沿着f最陡上升的反方向移动,直观上看可以移动到曲线上更低的位置。注意,比例因子step是必需的,因为grad(loss_value, W0)只是W0附近曲率的近似值,所以不能离W0太远。
随机梯度下降
给定一个可微函数,理论上可以用解析法找到它的最小值:函数的最小值就是导数为0的点,因此只需找到所有导数为0的点,然后比较函数在其中哪个点的取值最小。
将这一方法应用于神经网络,就是用解析法求出损失函数最小值对应的所有权重值。可以通过对方程grad(f(W), W) = 0求解W来实现这一方法。这是一个包含N个变量的多项式方程,其中N是模型的系数个数。当N = 2或N = 3时,可以对这样的方程进行求解,但对于实际的神经网络是无法求解的,因为参数的个数不会少于几千个,而且经常有上千万个。
不过你可以使用刚才开头总结的算法:基于当前在随机数据批量上的损失值,一点一点地对参数进行调节。
我们要处理的是一个可微函数,所以可以计算出它的梯度,从而有效地实现第4步,沿着梯度的反方向更新权重,每次损失值都会减小一点:
(刚才咱们提到的步骤)
(1)抽取训练样本x和对应目标y_true组成的一个数据批量。
(2)在x上运行模型,得到预测值y_pred。这一步叫作前向传播。
(3)计算模型在这批数据上的损失值,用于衡量y_pred和y_true之间的差距。
(4)计算损失相对于模型参数的梯度。这一步叫作反向传播(backward pass)。
(5)将参数沿着梯度的反方向移动一小步,比如W -= learning_rate *gradient,从而使这批数据上的损失值减小一些。学习率(learning_rate)是一个调节梯度下降“速度”的标量因子。
我们刚刚介绍的方法叫作小批量随机梯度下降(mini-batch stochastic gradient descent,简称小批量SGD)。
接下里,咱们用下图给出了一维的示例,模型只有一个参数,并且只有一个训练样本:

如你所见,直观上来看,learning_rate因子的取值很重要:
如果取值太小,那么沿着曲线下降需要很多次迭代,而且可能会陷入局部极小点。
如果取值过大,那么更新权重值之后可能会出现在曲线上完全随机的位置。
注意,小批量SGD算法的一个变体是每次迭代只抽取一个样本和目标,而不是抽取一批数据。这叫作真SGD(true SGD,有别于小批量SGD)。
还可以走向另一个极端:每次迭代都在所有数据上运行,这叫作批量梯度下降(batch gradient descent)。
这样做的话,每次更新权重都会更加准确,但计算成本也高得多。这两个极端之间有效的折中方法则是选择合理的小批量大小。
下图展示的是一维参数空间中的梯度下降,但在实践中需要在高维空间中使用梯度下降。
神经网络的每一个权重系数都是空间中的一个自由维度,神经网络则可能包含数万个甚至上百万个参数。为了对损失表面有更直观的认识,你还可以将沿着二维损失表面的梯度下降可视化,如下图所示:
(但你不可能将神经网络的真实训练过程可视化,因为无法用人类可以理解的方式来可视化1 000 000维空间。因此最好记住,在这些低维表示中建立的直觉,实践中不一定总是准确的。这一直是深度学习研究的问题来源。)

此外,SGD还有多种变体,比如带动量的SGD、Adagrad、RMSprop等。
它们的不同之处在于,计算下一次权重更新时还要考虑上一次权重更新,而不是仅考虑当前的梯度值,这些变体被称为优化方法(optimization method)或优化器(optimizer)。动量的概念尤其值得关注,它被用于许多变体,动量解决了SGD的两个问题:收敛速度和局部极小值。
下图给出了损失作为模型参数的函数的曲线:

在某个参数值附近,有一个局部极小点(local minimum):在这个点附近,向左和向右移动都会导致损失值增大。
如果使用学习率较小的SGD对参数进行优化,那么优化过程可能会陷入局部极小点,而无法找到全局极小点。
使用动量方法可以避免这样的问题,这一方法的灵感来源于物理学:一个有用的思维模型是将优化过程想象成小球从损失函数曲线上滚下来,如果小球的动量足够大,那么它不会卡在峡谷里,最终会到达全局极小点。动量方法的实现过程是,每一步移动小球,不仅要考虑当前的斜率值(当前的加速度),还要考虑当前的速度(由之前的加速度产生)。
这在实践中的含义是:更新参数w不仅要考虑当前梯度值,还要考虑上一次参数更新,其简单实现如下:
past_velocity = 0.# 不变的动量因子
momentum = 0.1# 优化循环
while loss > 0.01:w, loss, gradient = get_current_parameters()velocity = past_velocity * momentum - learning_rate * gradientw = w + momentum * velocity - learning_rate * gradientpast_velocity = velocityupdate_parameter(w)
链式求导:反向传播算法
在前面的算法中,我们假设函数是可微的,所以很容易计算其梯度。
但这种假设是合理的吗?
我们在实践中如何计算复杂表达式的梯度?
对于咱们开头说到的双层模型,我们如何计算出损失相对于权重的梯度?这时就需要用到反向传播算法(backpropagation algorithm)。
链式法则
反向传播是这样一种方法:利用简单运算(如加法、relu或张量积)的导数,可以轻松计算出这些基本运算的任意复杂组合的梯度。重要的是,神经网络由许多链接在一起的张量运算组成,每个张量运算的导数都是已知的,且都很简单。
例如:
咱们上文给的代码,定义的模型可以表示为,一个由变量W1、b1、W2和b2(分别属于第1个和第2个Dense层)参数化的函数,其中用到的基本运算是dot、relu、softmax和+,以及损失函数loss,这些运算都是很容易求导的。
loss_value = loss(y_true, softmax(dot(relu(dot(inputs, W1) + b1), W2) + b2))
根据微积分的知识,这种函数链可以利用下面这个恒等式进行求导,它叫作链式法则(chain rule)。
考虑两个函数f和g,以及它们的复合函数fg:fg(x) == f(g(x))。
def fg(x):x1 = g(x)y = f(x1)return y
链式法则规定:grad(y, x) == grad(y, x1) * grad(x1, x)。因此,只要知道f和g的导数,就可以求出fg的导数,如果添加更多的中间函数,看起来就像是一条链,因此得名链式法则。
def fghj(x):x1 = j(x)x2 = h(x1)x3 = g(x2)y = f(x3)return ygrad(y, x) == (grad(y, x3) * grad(x3, x2) * grad(x2, x1) * grad(x1, x))
将链式法则应用于神经网络梯度值的计算,就得到了一种叫作反向传播的算法。
咱们来具体看一下它的工作原理:
用计算图进行自动微分
思考反向传播的一种有用方法是利用计算图(compu- tation graph)。计算图是TensorFlow和深度学习革命的核心数据结构。它是一种由运算(比如我们用到的张量运算)构成的有向无环图。
计算图是计算机科学中一个非常成功的抽象概念。
有了计算图,我们可以将计算看作数据:将可计算的表达式编码为机器可读的数据结构,然后用于另一个程序的输入或输出。
例如,你可以想象这样一个程序:接收一个计算图作为输入,并返回一个新的计算图,新计算图可实现相同计算的大规模分布式版本。这意味着你可以对任意计算实现分布式,而无须自己编写分布式逻辑。或者想象这样一个程序:接收一个计算图作为输入,然后自动计算它所对应表达式的导数。如果将计算表示为一个明确的图数据结构,而不是.py文件中的几行ASCII字符,那么做这些事情就容易多了。
如今,人们利用能够自动微分的现代框架来实现神经网络,比如TensorFlow。自动微分是利用刚才咱们所述的计算图来实现的。自动微分可以计算任意可微张量运算组合的梯度,只需要写出前向传播,而无须做任何额外工作。
ensorFlow的梯度带GradientTape是一个API,让你可以充分利用TensorFlow强大的自动微分能力。它是一个Python作用域(scope),能够以计算图[有时也被称为“条带”(tape)]的形式“记录”在其中运行的张量运算。计算图可用来获取任意输出相对于任意变量或变量集的梯度,这些变量或变量集都是tf.Variable类的实例,tf.Variable是一类用于保存可变状态的张量,比如神经网络的权重就是tf.Variable的实例。
import tensorflow as tf# 将标量Variable的值初始化为0
x = tf.Variable(0.) #创建一个GradientTape作用域
with tf.GradientTape() as tape:# 在作用域内,对变量做一些张量运算y = 2 * x + 3# 利用梯度带获取输出y相对于变量x的梯度
grad_of_y_wrt_x = tape.gradient(y, x)
GradientTape也可用于张量运算:
# 将Variable初始化为形状为(2, 2)的零张量
x = tf.Variable(tf.zeros((2, 2)))with tf.GradientTape() as tape:y = 2 * x + 3# grad_of_y_wrt_x是一个形状为(2, 2)的张量(形状与x相同),表示y = 2 * a + 3在x = [[0, 0], [0, 0]]附近的曲率
grad_of_y_wrt_x = tape.gradient(y, x)
它还适用于变量列表:
W = tf.Variable(tf.random.uniform((2, 2)))
b = tf.Variable(tf.zeros((2,)))
x = tf.random.uniform((2, 2))
with tf.GradientTape() as tape:# 在TensorFlow中,matmul是指点积y = tf.matmul(x, W) + b# grad_of_y_wrt_W_and_b是由两个张量组成的列表,这两个张量的形状分别与W和b相同
grad_of_y_wrt_W_and_b = tape.gradient(y, [W, b])
小结论
模型由许多层链接在一起组成,并将输入数据映射为预测值。随后,损失函数将这些预测值与目标值进行比较,得到一个损失值,用于衡量模型预测值与预期结果之间的匹配程度。优化器将利用这个损失值来更新模型权重。

这是那个比较清晰的神经网络、层、损失函数与优化器之间的关系。
相关文章:
政安晨:梯度与导数~示例演绎《机器学习·神经网络》的高阶理解
这篇文章确实需要一定的数学基础,第一次接触的小伙伴可以先看一下我示例演绎这个主题的前两篇文章: 示例演绎机器学习中(深度学习)神经网络的数学基础——快速理解核心概念(一): 政安晨&#…...
CTFSHOW命令执行web入门29-54
description: >- 这里就记录一下ctfshow的刷题记录是web入门的命令执行专题里面的题目,他是有分类,并且覆盖也很广泛,所以就通过刷这个来,不过里面有一些脚本的题目发现我自己根本不会笑死。 如果还不怎么知道写题的话,可以去看我的gitbook,当然csdn我也转载了我自己的…...
探索ChatGPT4:新一代人工智能语言模型的突破
ChatGPT4,作为最新一代的语言处理模型,代表了人工智能在自然语言理解和生成方面的最新突破。本文将深入介绍ChatGPT4的新特性,探讨其在各个领域的潜在应用。 ChatGPT4概述 在继承了前一代模型的强大基础之上,ChatGPT4引入了多项…...
PVST详解
PVST(Per-VLAN Spanning Tree)是Cisco公司的一种扩展的Spanning Tree协议,允许在每个VLAN中独立运行一个Spanning Tree实例,从而提高网络的可靠性和性能。 PVST协议在每个交换机中维护多个Spanning Tree实例,每个实例…...
c++ 子进程交互 逻辑
目录 一、主进程逻辑 1、创建子进程时候,写入自己的HWND 2、响应子进程消息...
C#实现矩阵乘法
目录 一、使用的方法 1.矩阵 2.矩阵的乘法原理 二、实例 1.源码 2.生成效果 一、使用的方法 矩阵相当于一个数组,主要用来存储一系列数,例如,mn矩阵是排列在m行和n列中的一系列数,mn矩阵可与一个np矩阵相乘,结果…...
Objective-C 中的SEL
在 Objective-C 中,SEL(Selector)是一种用来表示方法的类型。 它实际上是一个指向方法的指针,用于在运行时动态调用方法。 下面是一个使用 SEL 的代码示例: #import <Foundation/Foundation.h>interface MyCl…...
使用 Docker 镜像预热提升容器启动效率详解
概要 在容器化部署中,Docker 镜像的加载速度直接影响到服务的启动时间和扩展效率。本文将深入探讨 Docker 镜像预热的概念、必要性以及实现方法。通过详细的操作示例和实践建议,读者将了解如何有效地实现镜像预热,以加快容器启动速度,提高服务的响应能力。 Docker 镜像预热…...
锁(二)队列同步器AQS
一、队列同步器AQS 1、定义 用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。是实现锁的关键。 2、实现 同步器的设计是基于模板方法模式的,也就是说&#…...
【知识整理】招人理念、组织结构、招聘
1、个人思考 几个方面: 新人:选、育、用、留 老人:如何甄别? 团队怎么演进? 有没有什么注意事项 怎么做招聘? 2、 他人考虑 重点: 1、从零开始,讲一个搭建团队的流程 2、标…...
监控概述、安装zabbix、配置zabbixagent、添加被控端主机、常用监控指标、自定义监控项
目录 监控概述 监控命令 zabbix 安装zabbix 6.0 配置zabbix监控web1服务器 在web1上安装agent 在web页面中添加对web1的监控 常用监控指标 自定义监控项 实现监控web1用户数量的监控项 在被控端创建key 创建模板 应用模板到主机 查看结果 监控概述 对服务的管理&am…...
恒创科技:香港 BGP 服务器网络连通性如何测试?
随着互联网的快速发展,网络连通性测试变得越来越重要。网络连通性测试的目的是确定网络设备之间的连接是否正常,以及数据包是否能够在网络中顺利传输。本文将介绍一种简单易行的香港 BGP 服务器网络连通性的测试方法,利用tracer测试工具。这里…...
《动手学深度学习(PyTorch版)》笔记7.6
注:书中对代码的讲解并不详细,本文对很多细节做了详细注释。另外,书上的源代码是在Jupyter Notebook上运行的,较为分散,本文将代码集中起来,并加以完善,全部用vscode在python 3.9.18下测试通过&…...
Quicker读取浏览器的书签(包括firefox火狐)
从edge换了火狐,但是quicker不能读取本地的bookmarks文件了,就研究了一下。 方法1:读取本地Bookmarks文件(仅谷歌内核浏览器) 谷歌内核的浏览器本地会有Bookmarks文件,放了所有的书签数据,直接…...
【数学建模】【2024年】【第40届】【MCM/ICM】【B题 搜寻潜水器】【解题思路】
一、题目 (一)赛题原文 2024 MCM Problem A: Resource Availability and Sex Ratios Maritime Cruises Mini-Submarines (MCMS), a company based in Greece, builds submersibles capable of carrying humans to the deepest parts of the ocean. A …...
深入探索Redis:如何有效遍历海量数据集
深入探索Redis:如何有效遍历海量数据集 Redis作为一个高性能的键值存储数据库,广泛应用于各种场景,包括缓存、消息队列、排行榜等。随着数据量的增长,如何高效地遍历Redis中的海量数据成为了一个值得探讨的问题。在本篇博客中&am…...
贪心算法之田忌赛马,多种语言实现
目录 题目描述: 输入: 样例输入: 样例输出: c代码实现: c++代码实现: python代码实现: Java代码实现: 题目描述: 这是中国历史上一个著名的故事。 “那是大约2300年前的事了。田骥将军是齐国的高级官员。他喜欢和国王和其他人一起赛马。 “田和王都有三匹不同等级…...
C++ static 修饰全局变量时的作用探究
C static 修饰全局变量时的作用探究 作为一个c开发者,我们面试时经常被问到 static 变量的作用,其中有一个问题是,static 修饰全局变量时起什么作用。 通常我们会回答,“static 修饰全局变量时代表限制这个变量为此源文件可见&a…...
Git的基础操作指令
目录 1 前言 2 指令 2.1 git init 2.2 touch xxx 2.3 git status 2.4 git add xxx 2.5 git commit -m xxxx 2.5 git log及git log --prettyoneline --all --graph --abbrev-commit 2.6 rm xxx 2.7 git reset --hard xxx(含小技巧) 2.8 git reflog 2.9 mv xxx yyy 1…...
前端开发:(四)JavaScript入门
JavaScript是一种强大的脚本语言,用于在网页中实现交互性和动态性。它的发展历史可以追溯到1995年,由Netscape公司的Brendan Eich设计开发而成。JavaScript的重要性在于它能够让网页实现丰富的功能和用户体验,成为Web开发的核心技术之一。 1…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
