【基于 PyTorch 的 Python 深度学习】5 机器学习基础(2)

news2024/10/4 14:23:58

前言

文章性质:学习笔记 📖

学习资料:吴茂贵《 Python 深度学习基于 PyTorch ( 第 2 版 ) 》【ISBN】978-7-111-71880-2

主要内容:根据学习资料撰写的学习笔记,该篇主要介绍了如何选择合适的激活函数、损失函数和优化器。

一、选择合适的激活函数

激活函数 在神经网络中的作用有很多,主要作用是给神经网络提供 非线性建模能力 。如果没有激活函数,那么再多层的神经网络也只能处理线性可分问题。作为神经网络的激活函数,通常需要满足如下 3 个条件:

  1.  非线性:为提高模型的学习能力,如果是线性,那么再多层都相当于只有两层效果。
  2.  可微性:有时可以弱化,在一些点存在偏导即可。
  3.  单调性:保证模型简单。

常用的激活函数有 sigmoid 、tanh 、ReLU 、softmax 等。它们的图形、表达式、导数等信息如表 5-2 所示。

在搭建神经网络时,如何选择激活函数?如果搭建的神经网络层数不多,选择 sigmoid 、tanh 、ReLU 、softmax 都可以;如果搭建的网络层次比较多,选择不当就可能导致梯度消失问题。此时一般不宜选择 sigmoid 、tanh 激活函数,因为其导数都小于 1 ,尤其是 sigmoid 的导数在 [ 0, 1/4 ] 之间,多层叠加后,根据微积分链式法则,随着层数增多,导数或偏导将会指数级变小。所以层数较多时,激活函数需要考虑其导数不宜小于 1 也不能大于 1 ,大于 1 将导致梯度爆炸,导数为 1 最好,激活函数 ReLU 正好满足这个条件。也就是说,搭建比较深的神经网络时,一般使用 ReLU 激活函数,当然一般神经网络也可使用。除此之外,由于激活函数 softmax 的 \sum_{i}\sigma _{i}(z)=1 ,softmax 常用于多分类神经网络输出层。激活函数在 PyTorch 中的使用示例:

m = nn.Sigmoid()
input = torch.randn(2)
output = m(input)

激活函数的输入维度与输出维度是一样的,其输入维度一般包括批量数 N ,即输入数据的维度一般是 4 维,如 ( N, C, W, H )

二、选择合适的损失函数

损失函数(Loss Function)在机器学习中非常重要,因为 训练模型的过程实际就是优化损失函数的过程 。损失函数对每个参数的偏导数就是梯度下降中提到的梯度,防止过拟合时添加的正则化项也是加在损失函数后面。损失函数用于衡量模型的好坏,损失函数值越小说明模型和参数越符合训练样本。任何能够衡量模型预测值与真实值之间的差异的函数都可以叫做损失函数。

在机器学习中常用的损失函数有两种,即 交叉熵 Cross Entropy 均方误差 Mean Squared Error ,分别对应机器学习中的 分类问题回归问题 。对分类问题的损失函数一般采用交叉熵,交叉熵反映了两个概率分布的距离(不是欧氏距离)。分类问题进一步又可分为多目标分类,如一次判断 100 张图是否包含 10 种动物,或单目标分类。回归问题预测的不是类别,而是一个任意实数。在神经网络中一般只有一个输出节点,该输出值就是预测值。其反映的预测值与实际值之间的距离可以用欧氏距离来表示,所以对这类问题我们通常使用均方差作为损失函数,均方差的定义如下:

MSE=\frac{\sum_{i=1}^{n}(y_i-y'_i)^{2}}{n}

PyTorch 中已经集成了多种损失函数,这里介绍两个经典的损失函数,其他损失函数基本上是在它们的基础上的变种或延伸。

1、torch.nn.MSELoss

具体格式:torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')

计算公式:

L(x,y)=[l_{1},l_{2},...,l_{N}]^{T},l_{n}=(x_{n}-y_{n})^{2} 

其中,N 是批量大小。如果参数 reduction 为非 None(默认值为‘mean’),则:

L(x,y)=\left\{\begin{matrix} mean(L), \: \, if \: \, reducation=\,'mean'\\ sum(L), \: \, if \: \, reducation=\,'sum' \end{matrix}\right.

公式说明:x 和 y 是任意形状的张量,每个张量都有 n 个元素,若 reduction 取 none 则 L(x, y) 将不是标量;若取 sum 则 L(x, y) 只是差平方的和,但不会除以 n 。

参数说明:size_average,reduce 在 PyTorch 官方的后续版本中将移除,主要看参数 reduction,可以取 'none', 'mean', 'sum',其默认值为 'mean' 。如果 size_average,reduce 都取了值,则将覆盖 reduction 的值。

import torch
import torch.nn as nn
import torch.nn.functional as F
 
torch.manual_seed(10)
 
loss = nn.MSELoss(reduction='mean')
input = torch.randn(1, 2, requires_grad=True)
print(input)
target = torch.randn(1, 2)
print(target)
output = loss(input, target)
print(output)
output.backward()

2、torch.nn.CrossEntropyLoss

交叉熵损失(Cross-Entropy Loss)又称为对数似然损失、对数损失,二分类时还可称为逻辑回归损失。在 PyTroch 里,它不是严格意义上的交叉熵损失函数,而是先将输入 input 经过 softmax 激活函数,将向量 “ 归一化 ” 为概率形式,然后再与实际值 target 计算严格意义上的交叉熵损失。在多分类任务中,经常采用 softmax 激活函数 + 交叉熵损失函数,因为交叉熵描述了两个概率分布的差异,然而神经网络输出的是向量,并不是概率分布的形式。所以需要 softmax 激活函数将一个向量进行 “ 归一化 ” 成概率分布的形式,再采用交叉熵损失函数计算损失值。

具体格式:torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')

计算公式:

loss(x,class)=-log(\frac{exp(x[class])}{\sum_{j}exp(x[j])})=-x[class]+log(\sum_{j}exp(x[j]))

如果带上权重参数 weight ,则:

loss(x,class)=weight[class](-x[class]+log(\sum_{j}exp(x[j])))

其中,weight 表示每个类别的损失设置权值,常用于类别不均衡问题。weight 必须是 float 类型的张量,其长度要与类别 C 一致,即每一个类别都要设置 weight 。代码示例:

import torch
import torch.nn as nn
 
torch.manual_seed(10)
 
loss = nn.CrossEntropyLoss()
# 假设类别数为 5
input = torch.randn(3, 5, requires_grad=True)
# 每个样本对应的类别索引,其值范围为 [0,4]
target = torch.empty(3, dtype=torch.long).random_(5)
output = loss(input, target)
output.backward()

三、选择合适的优化器

优化器 在机器学习、深度学习中往往起着举足轻重的作用,同一个模型,因选择的优化器不同,性能有可能相差很大,甚至导致模型无法训练。因此了解各种优化器的基本原理非常必要。本节重点介绍各种优化器或算法的主要原理,及其各自的优点或不足。

1、传统梯度优化算法

传统梯度优化算法 为最常见、最简单的一种参数更新策略。其基本思想是:先设定一个学习率 𝜆 ,参数沿梯度的反方向移动。假设基于损失函数 𝐿 (𝑓(𝑥, 𝜃), 𝑦) ,其中 𝜃 表示需要更新的参数,梯度为 g ,则其更新策略的伪代码如下所示:

这种梯度优化算法简洁,当学习率取值恰当时,可以收敛到全面最优点(凸函数)或局部最优点(非凸函数)。其不足也很明显:对超参数学习率比较敏感,过小导致收敛速度过慢,过大又越过极值点,如图 5-12 的 c 所示。在比较平坦的区域,因梯度接近 0 ,易导致提前终止训练,如图 5-12 的 a 所示。要选中一个恰当的学习速率往往要花费不少时间。

学习率不仅敏感,有时还会因其在迭代过程中保持不变,很容易造成算法被卡在鞍点的位置,如图 5-13 所示。

除此之外,在较平坦的区域,因梯度接近于 0 ,优化算法往往因误判还未到达极值点就提前结束迭代,如图 5-14 所示。

传统梯度优化算法的这些不足,在深度学习中会更加明显。为此,人们自然想到要克服这些不足。从前文更新策略的伪代码可知,影响优化的主要因素有:训练数据集的大小、梯度方向、学习率。很多优化方法从这些方面入手:

  • 从数据集优化方面入手,采用批量随机梯度下降方法;
  • 从梯度方向优化方面入手,采用动量更新策略;
  • 从学习率入手,涉及自适应问题;
  • 还有从两方面同时入手等方法。

接下来我们将具体介绍这些方法。

2、批量随机梯度下降法

梯度下降法是非常经典的算法,训练时如果使用全训练集,虽然可获得较稳定的值,但比较耗费资源,尤其当训练数据比较大时;另一个极端时,每次训练时用一个样本(又称为随机梯度下降法),这种训练方法振幅较大,也比较耗时,如图 5-15 所示。

这种方法虽然资源消耗较少,但非常消耗时间,因此无法充分发挥深度学习程序库中高度优化的矩阵运算的优势。为了更有效地训练模型,我们采用一种折中方法,即 批量随机梯度下降法 。这种梯度下降方法有两个特点:批量随机性

如何实现批量随机梯度下降呢? 其伪代码如下:

其中 x^{(i)} 和小批量数据集的所有元素都是从训练集中随机抽出的,这样梯度的预期将保持不变。相对于随机梯度下降,批量随机梯度下降降低了收敛波动性,即降低了参数更新的方差,使得更新更加稳定,有利于提升其收敛效果,如图 5-16 所示。

3、动量算法

梯度下降法在遇到平坦或高曲率区域时,学习过程有时很慢。利用 动量算法 能比较好地解决这个问题。

我们以求解函数 f(x_{1},x_{2})=0.05x_{1}^{2}+2x_{2}^{2}  极值为例,使用梯度下降法和动量算法分别进行迭代求解。

由图 5-17 可知,不使用动量算法的梯度下降法的学习速度比较慢,振幅比较大。由图 5-18 可知,使用动量算法的振幅较小,而且较快到达极值点。动量算法是如何做到这点的呢?动量(Momentum)是模拟物理里动量的概念,具有物理上惯性的含义。一个物体在运动时具有惯性,把这个思想运用到梯度下降法中,可以增加算法的收敛速度和稳定性,具体实现如图 5-19 所示。

由图 5-19 所示,动量算法每下降一步都是由前面下降方向的一个累积和当前点的梯度方向组合而成。

含动量的随机梯度下降法的算法伪代码如下:

动量算法的 PyTorch 代码实现如下:

def sgd_momentum(parameters, vs, lr, gamma):
    for param, v in zip(parameters, vs):
        v[:] = gamma * v + lr * param.grad
        param.data -= v
        param.grad.data.zero_()

其中 parameters 是模型参数,假设模型为 model ,则 parameters 为 model. parameters() 。

具体使用动量算法时,动量项的计算公式如下:

\nu _{k}\leftarrow \alpha \nu _{k-1}+(-\lambda \hat{g}(\theta _{k}))

如果按时间展开,则第 k 次迭代使用了从 1 到 k 次迭代的所有负梯度值,且负梯度按动量系数 α 指数级衰减,相当于使用了移动指数加权平均。假设每个时刻的梯度 \hat{g} 相似,则得到:

\nu_{k} \approx \frac{\lambda \, \hat{g}}{1-\alpha }

由此可知,当在比较平缓处,但 α = 0.5 , 0.9 时,梯度值将分别是梯度下降法的 2 倍、10 倍。使用动量算法,不但可以加快迭代速度,还可以跨过局部最优找到全局最优,如图 5-20 所示。

4、Nesterov 动量算法

既然每一步都要将两个梯度方向(历史梯度、当前梯度)做一个合并再下降,那为什么不先按照历史梯度往前走那么一小步,按照前面一小步位置的 “ 超前梯度 ” 来做梯度合并呢?可以先往前走一步,在靠前一点的位置(图 5-21 中的 C 点)看到梯度,然后按照那个位置来修正这一步的梯度方向,如图 5-21 所示。 

这就得到动量算法的一种改进算法,即 NAG(Nesterov Accelerated Gradient)算法,也称 Nesterov 动量算法。这种预更新方法能防止大幅振荡,不会错过最小值,并对参数更新更加敏感。如图 5-22 所示。

NAG 动量算法的伪代码如下: 

NAG 动量算法的 PyTorch 代码实现如下:

def sgd_nag(parameters, vs, lr, gamma):
    for param, v in zip(parameters, vs):
        v[:]*= gamma
        v[:]-= lr * param.grad
        param.data += gamma * gamma * v
        param.data -= (1 + gamma) * lr * param.grad
        param.grad.data.zero_()

NAG 动量算法和经典动量算法的差别就在 B 点和 C 点梯度的不同。动量算法更关注梯度下降方法的优化,如果能从方向和学习率同时优化,效果或许更理想。事实也确实如此,而且这些优化在深度学习中显得尤为重要。

接下来我们介绍几种自适应优化算法,这些算法可以同时从梯度方向及学习率进行优化,效果非常好。

5、AdaGrad 算法

传统梯度下降算法对学习率这个超参数非常敏感,难以驾驭;对参数空间的某些方向也没有很好的方法。这些不足在深度学习中,因高维空间、多层神经网络等因素,常会出现平坦、鞍点、悬崖等问题,因此,传统梯度下降法在深度学习中显得力不从心。还好现在已有很多解决这些问题的有效方法。上节介绍的动量算法在一定程度上缓解了参数空间某些方向的问题,但是需要新增一个参数,而且对学习率的控制还不是很理想。为了更好地驾驭这个超参数,人们想出来多种自适应优化算法,使用自适应优化算法,学习率不再是一个固定不变值,它会根据不同情况自动调整学习率以适用实际情况。这些算法使深度学习向前迈出一大步!下面我们将介绍几种自适应优化算法。先来看 AdaGrad 算法。
AdaGrad 算法 通过参数来调整合适的学习率 𝜆 ,能独立地自动调整模型参数的学习率,对稀疏参数进行大幅更新,对频繁参数进行小幅更新,如图 5-23 所示。因此,Adagrad 方法非常适合处理稀疏数据。AdaGrad 算法在某些深度学习模型上效果不错。但还有些不足,可能因其累积梯度平方导致学习率过早或过量地减少所致。

AdaGrad 算法的伪代码如下: 

由上面算法的伪代码可知:

1. 随着迭代时间越长,累积梯度参数 𝑟 越大,学习率 𝜆 / ( 𝛿+√𝑟) 会越小,在接近目标值时,不会因为学习速率过大而越过极值点。

2. 不同参数之间学习速率不同,因此,与前面的固定学习率相比,不容易在鞍点卡住。

3. 如果梯度累加参数 𝑟 比较小,则学习率会比较大,所以参数迭代的步长就会比较大。反之亦然。

AdaGrad 算法的 PyTorch 代码实现如下:

def sgd_adagrad(parameters, s, lr):
    eps = 1e-10
    for param, s in zip(parameters, s):
        s[:] = s + (param.grad) ** 2
        div = lr / torch.sqrt(s + eps) * param.grad
        param.data = param.data - div
        param.grad.data.zero_()

6、RMSProp 算法

RMSProp 算法 修改自 AdaGrad 算法,其在非凸背景下的效果更好,在凸函数中振幅可能较大,如图 5-24 所示。对梯度平方和累计越来越大的问题,RMSProp 算法用指数加权的移动平均代替梯度平方和。为了使用移动平均,RMSProp 算法引入了一个新的超参数 ρ ,用来控制移动平均的长度范围。

RMSProp 算法的伪代码如下: 

RMSProp 算法的 PyTorch 代码实现如下:

def rmsprop(parameters, s, lr, alpha):
    eps = 1e-10
    for param, sqr in zip(parameters, s):
        sqr[:] = alpha * sqr + (1 - alpha) * param.grad ** 2
        div = lr / torch.sqrt(sqr + eps) * param.grad
        param.data = param.data - div
        param.grad.data.zero_()

7、Adam 算法

Adam(Adaptive Moment Estimation,自适应矩估计)算法 本质上是带有动量项的 RMSprop 算法,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam 的优点主要在于经过偏置校正后,每一次迭代学习率都有 1 个确定范围,使得参数比较平稳,如图 5-25 所示。

Adam 算法的伪代码如下: 

Adam 算法的 PyTorch 代码实现如下:

def adam(parameters, vs, s, lr, t, beta1=0.9, beta2=0.999):
    eps = 1e-8
    for param, v, sqr in zip(parameters, vs, s):
        v[:] = beta1 * v + (1 - beta1) * param.grad
        sqr[:] = beta2 * sqr + (1 - beta2) * param.grad ** 2
        v_hat = v / (1 - beta1 ** t)
        s_hat = sqr / (1 - beta2 ** t)
        param.data = param.data - lr * v_hat / (torch.sqrt(s_hat) + eps)
        param.grad.data.zero_()

8、Yogi 算法

Adam 算法综合了动量算法及自适应算法的优点,是深度学习常用的算法,但也存在一些问题:即使在凸环境下,当 𝑟 的第二阶矩估计值爆炸时,它可能无法收敛。为此可通过改进 𝑟 和优化参数初始化等方法来解决。 其中通过改进 𝑟 是一种有效方法:

Yogi 算法的 PyTorch 代码实现如下:

def yogi(parameters, vs, s, lr, t, beta1=0.9, beta2=0.999):
    eps = 1e-8
    for param, v, sqr in zip(parameters, vs, s):
        v[:] = beta1 * v + (1 - beta1) * param.grad
        #sqr[:] = beta2 * sqr + (1 - beta2) * param.grad ** 2
        sqr[:] = sqr + (1 - beta2) * torch.sign(torch.square(param.grad) - sqr) * torch.square(param.grad)
        v_hat = v / (1 - beta1 ** t)
        s_hat = sqr / (1 - beta2 ** t)
        param.data = param.data - lr * v_hat / (torch.sqrt(s_hat) + eps)
        param.grad.data.zero_()

9、使用优化算法实例

前面介绍了深度学习的正则化方法,它是深度学习的核心;优化算法也是深度学习的核心。优化算法很多,如随机梯度下降法、自适应优化算法等,那么具体使用时该如何选择呢?RMSprop 、Nesterov 、Adadelta 和 Adam 被认为是自适应优化算法,因为它们会自动更新学习率。而使用 SGD 时,必须手动选择学习率和动量参数,因此通常会随着时间的推移而降低学习率。有时可以考虑综合使用这些优化算法,如先用 Adam 算法,再用 SGD 优化方法。实际上,由于在训练的早期阶段,SGD 对参数调整和初始化非常敏感,我们可以通过先使用 Adam 优化算法进行训练(这将大大节省训练时间,且不必担心初始化和参数调整),待用 Adam 训练获得较好的参数后,再切换到 SGD + 动量优化,以达到最佳性能。采用这种方法有时能达到很好效果,如图 5-26 所示,迭代次数超过 150 后,SGD 的效果好于 Adam 的效果。

实例:基于 MNIST 数据集,使用自定义的优化算法实现图像的分类任务。为便于比较,使用梯度下降法及动量算法两种优化算法。

参考代码:feiguyunai/Python-DL-PyTorch2/pytorch-05/pytorch-05-04.ipynb at main · Wumg3000/feiguyunai · GitHub

1)算法定义。

# 梯度下降法
def sgd(parameters, lr):
    for param in parameters:
        param.data -= lr * param.grad
        param.grad.data.zero_()
# 动量梯度下降法
def sgd_momentum(parameters, vs, lr, gamma):
    for param, v in zip(parameters, vs):
        v[:] = gamma * v + lr * param.grad
        param.data -= v
        param.grad.data.zero_()

  2)定义模型。

net = nn.Sequential(
    nn.Linear(784, 200),
    nn.ReLU(),
    nn.Linear(200, 10),
)

3)定义损失函数。

loss_sgd = nn.CrossEntropyLoss()

loss_sgd_mom = nn.CrossEntropyLoss()

4)加载数据。这里使用批量大小为 128 的训练数据集。

# 定义预处理函数
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.5], [0.5])])

# 下载数据,并对数据进行预处理
train_dataset = mnist.MNIST('./data', train=True, transform=transform, download=False)
test_dataset = mnist.MNIST('./data', train=False, transform=transform)

# 得到数据生成器
train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=128, shuffle=False)

5)训练模型。

# 初始化梯度平方项
s = []
for param in net.parameters():
    s.append(torch.zeros_like(param.data))

# 开始训练
losses0 = []
# losses1 = []
idx = 0

start = time.time()
for e in range(5):
    train_loss = 0
    for img, label in train_loader:
        # 展平 img
        img=img.view(img.size(0), -1)
        # 正向传播
        out = net(img)
        loss = loss_sgd(out, label)
        # loss = loss_sgd_mom(out, label)
        # 反向传播
        net.zero_grad()
        loss.backward()
        sgd(net.parameters(), 1e-2)
        # sgd_momentum(net.parameters(), vs, 1e-2, 0.9)
        # 记录误差
        train_loss += loss.item()
        if idx % 30 == 0:
            losses0.append(loss.item())
            # losses1.append(loss.item())
        idx += 1
    print('epoch: {}, Train Loss: {:.6f}'.format(e, train_loss / len(train_loader)))
end = time.time()
print('使用时间: {:.5f} s'.format(end - start))

如果使用动量算法,只要把 sgd(net.parameters(),1e-2) 改为 sgd_momentum(net.parameters(), vs, 1e-2, 0.9) 即可。

6)可视化两种优化算法的运行结果

x_axis = np.linspace(0, 5, len(losses0), endpoint=True)
plt.semilogy(x_axis, losses0, label='sgd')
plt.semilogy(x_axis, losses1, label='momentum')
plt.legend(loc='best')

根据运行结果图可知,动量算法的优势还是非常明显的。

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

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

相关文章

【系统架构师】-案例篇(三)NoSQL与分布式对象调用

1、NoSQL 一个基于Web 2.0的大型社交网络系统。就该系统的数据架构而言,李工决定采用公司熟悉的数据架构,使用通用的商用关系型数据库,系统内部数据采用中央集中方式存储。该系统投入使用后,初期用户数量少,系统运行平…

第二证券|北交所股票散户可以买吗?门槛多少?

北交所股票散户能够买,不过一般来说,北交所股票出资风险比较大,不适合资金实力不雄厚的散户。 北交所买卖权限注册条件:请求注册权限前20个买卖日的证券账户和资金账户内的财物日均不低于50万元,其间不包括经过融资融…

【资源分享】完胜谷歌翻译的Deepl翻译

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验,帮助大家尽早适应研究生生活,尽快了解科研的本质。祝一切顺利!—…

【算法】动态规划之背包DP与树形DP

前言: 本系列是学习了董晓老师所讲的知识点做的笔记 董晓算法的个人空间-董晓算法个人主页-哔哩哔哩视频 (bilibili.com) 动态规划系列 【算法】动态规划之线性DP问题-CSDN博客 【算法】动态规划之背包DP问题(2024.5.11)-CSDN博客 背包…

银河麒麟服务器操作系统ssh服务无法启动报exit-code

尝试重装ssh服务后依然无法解决,查看日志journalctl -xe,发现可能是ssh配置文件权限问题导致的。 journalctl -xe AWARNING: UNPROTECTED PRIVATE KEY FILE! AA Permissions 0755 for /etc/ssh/ssh_host_rsa_key are too open. A It is required that …

EPAI手绘建模APP工程图工具栏

(2) 工程图工具栏 ① 模板 1) 打开模板选择页面。 图 306 工程图模板列表 2) 模板选择页面列出了可以使用的工程图模板类型,每个模板规定了工程的大小、方向、规格、标准、常用字段等。也包括一些空白模板,此时可以通过添加表格等注释自定义工程图样式…

苹果15适合用哪些充电宝充电?苹果15可以用充电宝推荐

在如今移动设备如此普遍的时代,充电宝已成为我们日常生活中不可或缺的一部分。对于拥有苹果15的用户来说,选择一款适合的充电宝尤为重要。因为接口以及苹果手机配置上的一个升级,市面上很多普通充电宝已经不能兼容苹果15充电了。苹果15作为一…

5.10.8 Transformer in Transformer

Transformer iN Transformer (TNT)。具体来说,我们将局部补丁(例如,1616)视为“视觉句子”,并将它们进一步划分为更小的补丁(例如,44)作为“视觉单词”。每个单词的注意力将与给定视…

ChatGLM 本地部署指南(问题解决)

硬件要求(模型推理): INT4 : RTX3090*1,显存24GB,内存32GB,系统盘200GB 如果你没有 GPU 硬件的话,也可以在 CPU 上进行推理,但是推理速度会更慢。 模型微调硬件要求更高。…

高效测评系统方案助力沃尔玛、亚马逊卖家提升产品销量

无论在哪个电商平台,测评确实是最有效的推广方式。测之前一定要选好产品,因为对于大部分卖家而言,不可能你店铺里所有的都是爆款,所以选择的是需要有潜力成为爆款的产品。测评是指通过搭建安全的环境模拟真实的买家购物行为&#…

AH1515-12v转3V20A电源芯片

AH1515-12v转3V20A电源芯片:一款强大的电源解决方案 在当今的电子设备领域,电源管理的重要性不言而喻。一款优秀的电源芯片能够为各种设备提供稳定、高效的电能转换。今天,我们将为大家介绍一款极具特色的电源芯片——AH1515。这款芯片将为您…

FMEA存在的五个主要不足及改进措施——FMEA软件

免费试用FMEA软件-免费版-SunFMEA 在制造业和产品设计领域,失效模式与影响分析(Failure Modes and Effects Analysis,简称FMEA)被广泛运用,用于预防潜在的设计或制造缺陷。然而,尽管FMEA在风险管理方面发挥…

【51】Camunda8-Zeebe核心引擎-Zeebe Gateway

概述 Zeebe网关是Zeebe集群的一个组件,它可以被视为Zeebe集群的联系点,它允许Zeebe客户端与Zeebe集群内的Zeebe代理进行通信。有关Zeebe broker的更多信息,请访问我们的附加文档。 总而言之,Zeebe broker是Zeebe集群的主要部分,它完成所有繁重的工作,如处理、复制、导出…

加州大学欧文分校英语高级语法专项课程01:Verb Tenses and Passives 学习笔记

Verb Tenses and Passives Course Certificate Course Intro 本文是学习 Verb Tenses and Passives 这门课的学习笔记。 文章目录 Verb Tenses and PassivesWeek 01: Simple, Progressive, and Perfect Verb Tenses ReviewLearning Objectives Present Perfect Tense Review L…

Spring Cloud Alibaba Sentinel 集成与限流实战(6)

项目的源码地址 Spring Cloud Alibaba 工程搭建(1) Spring Cloud Alibaba 工程搭建连接数据库(2) Spring Cloud Alibaba 集成 nacos 以及整合 Ribbon 与 Feign 实现负载调用(3) Spring Cloud Alibaba Ribbo…

MySQL————创建存储过程函数

存储过程使用大纲 有参数传递 delimiter $$ 声明一个名称为get_student_introduce create procedure add_student_infor( in p_userName VARCHAR(20),in p_phone VARCHAR(11),in p_sex char(2),in p_introduce VARCHAR(255)) 开始操作 BEGIN 撰写真正在操作DMLDQL都行 INSE…

Transformer模型详解04-Encoder 结构

文章目录 简介基础知识归一化作用常用归一化 残差连接 Add & NormFeed Forward代码实现 简介 Transformer 模型中的 Encoder 层主要负责将输入序列进行编码,将输入序列中的每个词或标记转换为其对应的向量表示,并且捕获输入序列中的语义和关系。 具…

(超详细讲解)实现将idea的java程序打包成exe (新版,可以在没有java的电脑下运行,即可以发给好朋友一起玩)

目录 实现打包到exe大概步骤 工具准备 1.将java程序文件打包成jar文件 2.准备好jre文件 3.使用exe4j软件打包好 4.最终打包 实现打包到exe大概步骤 1.打包需要满足的条件:将java文件转成jar文件的工具exe4j、 以及需要满足jdk1.8以上(因安装exe4…

Android面试题之Kotlin和Java之间互操作

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点 互操作性和可空性 要注意Java中所有类型都是可空的String!表示平台数据类型 public class JavaTest {public String generateName() {return …

2024中国(重庆)无人机展览会8月在重庆举办

2024中国(重庆)无人机展览会8月在重庆举办 邀请函 主办单位: 中国航空学会 重庆市南岸区人民政府 招商执行单位: 重庆港华展览有限公司 报名:【交易会I 59交易会2351交易会9466】 展会背景: 为更好的培养航空航天产业和无人…