政安晨:梯度与导数~示例演绎《机器学习·神经网络》的高阶理解

这篇文章确实需要一定的数学基础,第一次接触的小伙伴可以先看一下我示例演绎这个主题的前两篇文章:

示例演绎机器学习中(深度学习)神经网络的数学基础——快速理解核心概念(一)

政安晨:示例演绎机器学习中(深度学习)神经网络的数学基础——快速理解核心概念(一){两篇文章讲清楚}icon-default.png?t=N7T8https://blog.csdn.net/snowdenkeke/article/details/136089968示例演绎机器学习中(深度学习)神经网络的数学基础——快速理解核心概念(二)

政安晨:示例演绎机器学习中(深度学习)神经网络的数学基础——快速理解核心概念(二){两篇文章讲清楚}icon-default.png?t=N7T8https://blog.csdn.net/snowdenkeke/article/details/136090846

简述概念

在机器学习中,神经网络是一种常用的模型,用于解决各种问题,如图像识别、自然语言处理等。神经网络通过一系列的神经元(也称为节点)组成的层次结构来模拟人脑的神经系统。

神经网络的训练过程可以看作是一个优化问题,目标是找到最优的参数来最小化损失函数。为了实现这个目标,梯度和导数是非常重要的概念。

梯度是损失函数对于参数的导数。在神经网络中,我们使用梯度来更新参数,以使损失函数最小化。通过计算损失函数对于每个参数的梯度,我们可以确定应该如何调整参数的值,以逐渐减少损失。

导数是函数在某一点的斜率或变化率。在神经网络中,我们将损失函数视为参数的函数,并计算其在参数点处的导数。这告诉我们在该点上损失函数是如何随参数的变化而变化的。

通过梯度和导数,我们可以了解损失函数如何随参数的变化而变化,并根据这些信息来调整参数的值,以改善模型的性能。梯度下降是一种常用的优化算法,它使用梯度的信息逐步调整参数的值,以最小化损失函数

总结起来,神经网络中的梯度和导数是用于优化模型的重要概念。它们提供了关于损失函数随参数变化的信息,帮助我们调整参数的值以改善模型性能。

基于梯度的优化

如同咱们前面文章提到的,对于咱们前面提到的深度学习中的模型而言,每个神经网络层都对输入数据进行如下变换:

output = relu(dot(input, W) + b)

这里,W和b是张量,均为该层的属性。它们被称为该层的权重(weight)可训练参数(trainable parameter),分别对应属性kernelbias。这些权重包含模型从训练数据中学到的信息。

咱们先大概了解一下

在机器学习中,神经网络的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_predy_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_valueW0处的梯度,也叫作“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])

小结论

模型由许多层链接在一起组成,并将输入数据映射为预测值。随后,损失函数将这些预测值与目标值进行比较,得到一个损失值,用于衡量模型预测值与预期结果之间的匹配程度。优化器将利用这个损失值来更新模型权重。

这是那个比较清晰的神经网络、层、损失函数与优化器之间的关系


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

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

相关文章

蓝桥杯嵌入式学习记录——按键的使用

目录 一、按键原理简介 二、cubeMX的配置 三、按键的短按代码 四、按键的长按代码 一、按键原理简介 在STM32中,按键连接通常使用GPIO(通用输入/输出)端口来实现。当按键未被按下时,GPIO端口处于高电平状态(即1&am…

springboot188基于spring boot的校园商铺管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计,课程设计参考与学习用途。仅供学习参考, 不得用于商业或者非法用途,否则,一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

高德地图上绘制热力图的方法

百度地图和高德地图的JavaScript API都提供了热力图的绘制方法,都是将热力图作为新的图层,叠加到地图上。但是百度地图的经纬度体系与我们的经纬度存在偏差,高德的与我们相符,应当使用高德地图JavaScript API。 因为是JavaScript…

COM初体验——新建文档并写入内容。

我想在程序里和Word交互。老师跟我说不要学COM,因为它已经过时了。但是我不想再把代码移植到C#上面,然后用VSTO——已经用了std::unordered_set!因为我使用了Copilot,结合我的思考,写了下面的代码: #impor…

【Langchain Agent研究】SalesGPT项目介绍(四)

【Langchain Agent研究】SalesGPT项目介绍(三)-CSDN博客 github地址:GitHub - jerry1900/SalesGPT: Context-aware AI Sales Agent to automate sales outreach. 上节课,我们主要介绍了SalesGPT的类属性和它最重要的类方法f…

【教学类-47-01】20240206UIBOT+IDM下载儿童古诗+修改文件名

背景需求: 去年12月,我去了其他幼儿园参观,这是一个传统文化德育教育特色的学校,在“古典集市”展示活动中,小班中班大班孩子共同现场念诵《元日》《静夜思》包含了演唱版本和儿歌念诵版本。 我马上也要当班主任了&a…

微信小程序开发学习笔记《17》uni-app框架-tabBar

微信小程序开发学习笔记《17》uni-app框架-tabBar 博主正在学习微信小程序开发,希望记录自己学习过程同时与广大网友共同学习讨论。建议仔细阅读uni-app对应官方文档 一、创建tabBar分支 运行如下的命令,基于master分支在本地创建tabBar子分支&#x…

Netty Review - 服务端channel注册流程源码解析

文章目录 PreNetty主从Reactor线程模型服务端channel注册流程源码解读入口 serverBootstrap.bind(port)执行队列中的任务 : AbstractUnsafe#register0注册 doRegister() 源码流程图 Pre Netty Review - ServerBootstrap源码解析 Netty Review - NioServerSocketCh…

TCP高频知识点

本篇文章主要讲述一下在面试过程中TCP的高频知识点 1.TCP三次握手流程图: 客户端发送一个SYN(同步)报文段给服务器,选择一个初始序列号,并设置SYN标志位为1。服务器接收到客户端的SYN报文段后,回复一个ACK&#xff08…

OJ刷题:杨氏矩阵【建议收藏】

看见这个题目&#xff0c;很多人的第一反应是遍历整个数组查找数字&#xff0c;但是这种方法不仅效率低&#xff0c;而且远远不能满足题目要求。下面介绍一种高效的查找方法&#xff1a; 代码实现&#xff1a; #include <stdio.h>int Yang_Find_Num(int arr[][3], int …

steam游戏搬砖项目靠谱吗?有没有风险?

作为一款fps射击游戏&#xff0c;csgo在近几年可谓是火出圈&#xff0c;作为一款全球竞技游戏&#xff0c;深受玩家喜爱追捧&#xff0c;玩家追求的就是公平公正&#xff0c;各凭本事&#xff0c;像其他游戏可能还会有皮肤等装备属性加成&#xff0c;在csgo里面是不存在的。 纯…

K8sGPT 的使用

K8sGPT 介绍 k8sgpt 是一个扫描 Kubernetes 集群、诊断和分类问题的工具。它将 SRE 经验编入其分析器中&#xff0c;并帮助提取最相关的信息&#xff0c;通过人工智能来丰富它。它还可以与 OpenAI、Azure、Cohere、Amazon Bedrock 和本地模型结合使用。 K8sGPT Github 地址 …

Vue插槽

Vue插槽 一、插槽-默认插槽1.作用2.需求3.问题4.插槽的基本语法5.代码示例6.总结 二、插槽-后备内容&#xff08;默认值&#xff09;1.问题2.插槽的后备内容3.语法4.效果5.代码示例 三、插槽-具名插槽1.需求2.具名插槽语法3.v-slot的简写4.代码示例5.总结 四、作用域插槽1.插槽…

安卓价值1-如何在电脑上运行ADB

ADB&#xff08;Android Debug Bridge&#xff09;是Android平台的调试工具&#xff0c;它是一个命令行工具&#xff0c;用于与连接到计算机的Android设备进行通信和控制。ADB提供了一系列命令&#xff0c;允许开发人员执行各种操作&#xff0c;包括但不限于&#xff1a; 1. 安…

在python中JSON数据格式的使用

什么是JSON&#xff1f; JSON是一种数据格式&#xff0c;由美国程序设计师DouglasCrockford创建的&#xff0c;JSON全名是JavaScript Object Notation,由JSON英文全文字义我们可以推敲JSON的缘由&#xff0c;最初是为JavaScript开发的。这种数据格式由于简单好用被大量应用在We…

DS Wannabe之5-AM Project: DS 30day int prep day15

Q1. What is Autoencoder? 自编码器是什么&#xff1f; 自编码器是一种特殊类型的神经网络&#xff0c;它通过无监督学习尝试复现其输入数据。它通常包含两部分&#xff1a;编码器和解码器。编码器压缩输入数据成为一个低维度的中间表示&#xff0c;解码器则从这个中间表示重…

数据库被人破解,删除数据,勒索

事情是这样的&#xff0c;我买了一台服务器自己部署项目玩儿玩儿&#xff0c;我的数据库运行在3306端口&#xff0c;密码没改&#xff0c;就是默认的123456&#xff0c;诡异的事情发生了&#xff0c;用了一段时间之后&#xff0c;数据库突然连接不上了&#xff0c;我一通操作猛…

Python爬虫——解析库安装(1)

目录 1.lxml安装2.Beautiful Soup安装3.pyquery 的安装 我创建了一个社区&#xff0c;欢迎大家一起学习交流。社区名称&#xff1a;Spider学习交流 注&#xff1a;该系列教程已经默认用户安装了Pycharm和Anaconda&#xff0c;未安装的可以参考我之前的博客有将如何安装。同时默…

【开源】SpringBoot框架开发企业项目合同信息系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 合同审批模块2.3 合同签订模块2.4 合同预警模块2.5 数据可视化模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 合同审批表3.2.2 合同签订表3.2.3 合同预警表 四、系统展示五、核心代码5.1 查询合同…

Linux多线程[二]

引入知识 进程在线程内部执行是OS的系统调度单位。 内核中针对地址空间&#xff0c;有一种特殊的结构&#xff0c;VM_area_struct。这个用来控制虚拟内存中每个malloc等申请的空间&#xff0c;来区别每个malloc的是对应的堆区哪一段。OS可以做到资源的精细度划分。 对于磁盘…