【机器学习】基于Softmax松弛技术的离散数据采样

1.引言

1.1.离散数据采样的意义

离散数据采样在深度学习中起着至关重要的作用,它直接影响到模型的性能、泛化能力、训练效率、鲁棒性和解释性。

首先,采样方法能够有效地平衡数据集中不同类别的样本数量,使得模型在训练时能够更均衡地学习各个类别的特征,从而避免因数据不平衡导致的偏差。

其次,合理的采样策略可以确保模型在训练过程中能够接触到足够多的样本,避免过拟合和欠拟合问题,提高模型的泛化能力。

此外,通过随机选择部分样本来减少训练数据的规模,可以提高训练效率,使得深度学习模型在处理大规模数据集时更加高效。同时,离散数据采样还能增加数据集的多样性,使得模型在训练过程中能够接触到更多不同类型的样本,从而提高模型的鲁棒性,使其能够更好地适应各种实际应用场景。

最后,通过控制训练数据的分布来影响模型的决策过程,离散数据采样可以为深度学习模型提供一定的解释性,使得模型的决策过程更加可理解和可信任。

在实际应用中,选择合适的离散数据采样策略对于提高深度学习模型的性能和可解释性至关重要。

1.2.主要内容

本文探讨了如何从非结构化的向量数据中有效地采样出离散变量,并将这些变量转化为具有特定结构的实体,例如集合、序列或网络图等形式,进而将它们嵌入到可微分的模型框架中。

文章的核心在于应用连续的松弛技术来处理离散随机变量,尤其是二元和分类类型的变量。在第一部分中,我们详细介绍了利用Gumbel-Softmax技巧来实现从离散概率分布中进行采样。通过这种方法,我们成功地训练了一个变分自编码器模型,该模型具备了分类型的潜在变量。这种技巧为处理离散性和结构化数据提供了一种新颖的途径,并使得模型能够通过标准的反向传播算法进行训练和优化。

2.离散数据采样理论和实践

2.1.使用Gumbel-Argmax进行分类采样

Gumbel-Argmax,也称为Gumbel-Softmax trick,是一种在深度学习中处理离散变量的技巧,特别是在变分推断和生成模型中。这种方法允许我们从离散分布中进行可微分的采样,从而使得梯度下降算法可以应用于包含离散选择的模型。

2.1.1.基本原理

Gumbel-Argmax方法基于Gumbel分布,一种极端值分布,它可以被用来将离散的随机变量转换成连续的形式,从而便于梯度的传播。Gumbel-Argmax方法,也称为Gumbel-Softmax trick,在深度学习中是一种处理离散变量的技巧,尤其是在需要不同iable的随机采样时。这种方法利用Gumbel分布的特性,允许模型通过softmax函数进行梯度的反向传播。

Gumbel分布是一种极端值分布,常用于模拟独立随机变量的最大值或最小值。它的概率密度函数(PDF)和累积分布函数(CDF)具有以下形式:

  • PDF:
    f ( z ; μ , β ) = 1 β exp ⁡ ( − z − μ β ) exp ⁡ ( − exp ⁡ ( − z − μ β ) ) f(z; \mu, \beta) = \frac{1}{\beta} \exp\left(-\frac{z - \mu}{\beta}\right) \exp\left(-\exp\left(-\frac{z - \mu}{\beta}\right)\right) f(z;μ,β)=β1exp(βzμ)exp(exp(βzμ))
    其中 μ \mu μ是位置参数, b e t a beta beta是尺度参数。

  • CDF:
    F ( z ; μ , β ) = exp ⁡ ( − exp ⁡ ( − z − μ β ) ) F(z; \mu, \beta) = \exp\left(-\exp\left(-\frac{z - \mu}{\beta}\right)\right) F(z;μ,β)=exp(exp(βzμ))

在Gumbel-Argmax技巧中,通常将尺度参数 β \beta β设为1,以简化计算。

2.1.2.Gumbel-Argmax的工作原理

  1. Gumbel噪声的添加:对于每个离散选择的对数几率 ( x_k ),我们添加一个独立的Gumbel噪声 ( g_k ),得到 ( x_k + g_k )。

  2. Softmax归一化:将添加了噪声的对数几率通过softmax函数进行归一化,得到概率分布 ( \pi_k )。

  3. Argmax采样:在前向传播中,使用softmax得到的概率分布进行argmax操作,得到最可能的选择。在反向传播中,使用softmax的梯度进行传播。

2.1.3.梯度传播的实现

Gumbel-Argmax方法的关键优势在于它允许梯度通过离散采样过程进行传播。在反向传播时,尽管argmax操作本身不可微,但是可以通过Gumbel噪声的连续性来实现梯度的传播。这就是所谓的“直通估计器”(Straight-Through Estimator, STE)。

2.1.4.采样步骤

  1. Gumbel噪声采样:对于每个离散选择,我们首先从Gumbel分布中采样一个噪声项。Gumbel分布是一种以0为位置参数,1为尺度参数的分布。

  2. 对数几率调整:将Gumbel噪声加到原始的对数几率(logits)上,使得每个选择的值变为 logits + Gumbel噪声

  3. Softmax归一化:应用softmax函数对调整后的值进行归一化,得到一个概率分布。

  4. Argmax转换:在前向传播中,使用softmax得到的分布进行argmax操作,得到最可能的选择;在反向传播中,使用softmax的梯度进行传播。

2.1.5.采样数学模型

假设我们有一个具有 C C C个可能值的分类分布,每个值的权重为 w i ∈ ( 0 , ∞ ) w_i \in (0,\infty) wi(0,),我们的目标是从此分布中抽取一个样本,类别 c i c_i ci的概率由softmax分布决定,公式如下:

p i = exp ⁡ ( log ⁡ ( w i ) ) ∑ j exp ⁡ ( log ⁡ ( w j ) ) p_i = \frac{\exp(\log(w_i))}{\sum_{j} \exp(\log(w_j))} pi=jexp(log(wj))exp(log(wi))

Gumbel-Argmax采样方法的步骤是:

  1. 从均匀分布 U n i f o r m ( 0 , 1 ) Uniform(0,1) Uniform(0,1)中独立同分布地采样 U k U_k Uk,然后计算 r k = log ⁡ ( w i ) − log ⁡ ( − log ⁡ U k ) r_k = \log(w_i) - \log(-\log U_k) rk=log(wi)log(logUk)
  2. 选择使得 r k r_k rk最大的索引 i i i(即执行argmax操作),并返回一个1-hot编码的向量,其中第 i i i位为1,其余位置为0。
    添加到 r k r_k rk中的噪声项 − l o g ( − log ⁡ U k ) -log(-\log U_k) log(logUk)遵循Gumbel分布,这也是该方法名称的由来。Gumbel分布(位置参数为0,尺度参数为1)的累积分布函数定义为:

F ( z ) = exp ⁡ ( − exp ⁡ ( − z ) ) F(z) = \exp(-\exp(-z)) F(z)=exp(exp(z))

备注:有关这种方法确实能从softmax分布中采样的证明,如下:

在神经网络、广义线性模型、主题模型以及许多其他概率模型中,人们常常希望用一个无约束的向量来参数化一个离散分布,即一个不受单纯形限制、可以是负数等的向量。解决这个问题的一个非常常见的方法是使用“softmax”变换:
π k = exp ⁡ { x k } ∑ k ′ = 1 K exp ⁡ { x k ′ } \pi_k = \frac{\exp\{x_k\}}{\sum_{k'=1}^K\exp\{x_{k'}\}} πk=k=1Kexp{xk}exp{xk}其中 x k x_k xk R \mathbb{R} R 中是无约束的,但是 π k \pi_k πk 位于单纯形上,即 π k ≥ 0 \pi_k \geq 0 πk0 ∑ k π k = 1 \sum_{k}\pi_k=1 kπk=1 x k x_k xk 参数化了一个离散分布(不是唯一的),我们可以通过执行softmax变换然后进行通常的抽样来生成数据。有趣的是,实际上存在一种替代方法来获得这样的离散样本,而不需要构建离散分布。

这种方法是softmax-离散过程的等价物:向每个 x k x_k xk 添加Gumbel噪声,然后取argmax。也就是说,向每个 x k x_k xk 添加独立的噪声,然后进行最大值操作。这并没有改变算法的渐近复杂度,但是为一些有趣的实现可能性打开了大门。这是如何工作的呢?具有单位尺度和位置参数 μ \mu μ 的Gumbel分布具有以下概率密度函数(PDF):
f ( z ; μ ) = exp ⁡ { − ( z − μ ) − exp ⁡ { − ( z − μ ) } } . f(z\,;\,\mu) = \exp\{-(z-\mu) - \exp\{-(z-\mu)\}\}. f(z;μ)=exp{(zμ)exp{(zμ)}}.Gumbel的累积分布函数(CDF)是
F ( z ; μ ) = exp ⁡ { − exp ⁡ { − ( z − μ ) } } . F(z\,;\,\mu) = \exp\{-\exp\{-(z-\mu)\}\}. F(z;μ)=exp{exp{(zμ)}}.现在,假设我们的第 k k k 个Gumbel,位置参数为 x k x_k xk,结果为 z k z_k zk。所有其他的 z k ′ ≠ k z_{k'\neq k} zk=k 小于这个值的概率是
Pr ⁡ ( z k is largest ∣ z k , { x k ′ } k ′ = 1 K ) = ∏ k ′ ≠ k exp ⁡ { − exp ⁡ { − ( z k − x k ′ ) } } . \Pr(z_k \text{ is largest}\,|\, z_k, \{x_{k'}\}^K_{k'=1}) = \prod_{k'\neq k}\exp\{-\exp\{-(z_k-x_{k'})\}\}. Pr(zk is largestzk,{xk}k=1K)=k=kexp{exp{(zkxk)}}.我们知道 z k z_k zk 的边缘分布,我们需要积分它来找到整体概率:
Pr ⁡ ( k is largest ∣ { x k ′ } ) = ∫ exp ⁡ { − ( z k − x k ) − exp ⁡ { − ( z k − x k ) } } × ∏ k ′ ≠ k exp ⁡ { − exp ⁡ { − ( z k − x k ′ ) } } d z k . \Pr(\text{$k$ is largest}\,|\,\{x_{k'}\}) = \\ \int \exp\{-(z_k-x_k)-\exp\{-(z_k-x_k)\}\}\times\\ \prod_{k'\neq k}\exp\{-\exp\{-(z_k-x_{k'})\}\} \,\mathrm{d}z_k. Pr(k is largest{xk})=exp{(zkxk)exp{(zkxk)}}×k=kexp{exp{(zkxk)}}dzk.通过一些代数运算,我们得到:
Pr ⁡ ( k is largest ∣ { x k ′ } ) = exp ⁡ { x k } ∑ k ′ = 1 K exp ⁡ { x k ′ } . \Pr(\text{$k$ is largest}\,|\,\{x_{k'}\}) = \frac{\exp\{x_k\}}{\sum_{k'=1}^K\exp\{x_{k'}\}}. Pr(k is largest{xk})=k=1Kexp{xk}exp{xk}.我们可以看到,这正是softmax概率.

简而言之,使用Gumbel重新参数化技巧对分类变量进行采样的步骤如下:

  1. 给定权重 w i w_i wi,计算 r i = w i + g i r_i = w_i + g_i ri=wi+gi,其中 g i g_i gi是从Gumbel分布中独立同分布采样得到的。
  2. 执行Argmax操作:返回最大的 r i r_i ri对应的索引,作为1-hot向量。

3.Softmax松弛技术

在深度学习中,当我们需要从一个分布中选取一个类别时,通常会使用softmax函数来得到每个类别的概率分布,然后使用argmax来选取概率最大的类别。然而,由于argmax操作在大多数深度学习框架中是不可导的,这就使得在训练过程中无法使用基于梯度的优化算法。

为了解决这个问题,我们采用softmax函数来近似argmax,因为它本身是连续且可导的。但是,原始的softmax输出是一个概率分布,而argmax输出的是一个离散值(即类别的索引)。为了控制softmax输出与1-hot向量的接近程度,我们引入了温度参数 τ \tau τ(希腊字母tau)。

引入温度参数 τ \tau τ后的softmax函数可以写作:

p i = exp ⁡ ( r i / τ ) ∑ j exp ⁡ ( r j / τ ) p_i = \frac{\exp(r_i / \tau)}{\sum_j \exp(r_j / \tau)} pi=jexp(rj/τ)exp(ri/τ)

其中, p i p_i pi是第 i i i个类别的概率, r i r_i ri是该类别的原始得分(在深度学习模型中通常是模型的输出层的线性变换结果), τ \tau τ是温度参数。

当温度参数 τ \tau τ较小时,softmax的输出会更加接近一个1-hot向量,即最大概率的类别概率接近1,而其他类别的概率接近0。这使得softmax的输出更接近于argmax的结果。

相反,当温度参数 τ \tau τ较大时,softmax的输出会更加平滑,即所有类别的概率都会相对均匀,没有哪一个类别的概率特别突出。这有助于在训练初期鼓励模型探索不同的类别,避免过早地陷入局部最优解。

因此,通过调整温度参数 τ \tau τ,我们可以控制softmax输出与1-hot向量的距离,从而实现对argmax操作的可导近似。在训练过程中, τ \tau τ可以是一个固定的值,也可以是一个可学习的参数,根据具体的任务和数据集进行调整。

温度参数对分布和样本的影响可以通过下图(图引用自论文:CATEGORICAL REPARAMETERIZATION WITH GUMBEL-SOFTMAX)观察到。
在这里插入图片描述

在训练过程中,可以通过调整 τ \tau τ来控制模型的“柔软度”。开始时,可以使用较大的 τ \tau τ值来帮助模型在类别之间进行探索,随着训练的进行,逐渐减小 τ \tau τ值以鼓励模型做出更确定的预测。

然而,如果你提到的是Gumbel-Softmax采样,这是一种用于离散潜变量(如分类变量)的可导近似方法。Gumbel-Softmax允许你通过softmax函数从离散分布中采样,同时保持整个过程的可导性。这种方法通过添加Gumbel噪声到原始logits(未归一化的概率)上,然后使用softmax进行归一化,并通过一个温度参数来控制分布的离散程度。

Gumbel-Softmax采样的基本步骤如下:

  1. 对于每个logits x i x_i xi,从其对应的Gumbel分布中抽取一个样本 g i g_i gi
  2. 计算 r i = x i + g i r_i = x_i + g_i ri=xi+gi
  3. 应用带有温度参数 τ \tau τ的softmax函数,得到 softmax τ ( r ) \text{softmax}_\tau(r) softmaxτ(r)
  4. 最后,通常使用softmax输出的概率作为权重,从类别中进行采样(在训练时通常使用softmax输出本身作为近似,而在测试时可能使用argmax或采样)。

注意,在训练过程中,Gumbel-Softmax通常用于反向传播梯度,因为它是可导的。然而,在评估或测试模型时,你可能想要一个离散的输出,这时可以使用argmax或基于softmax输出的采样方法。

4.分类变分自编码器(Categorical VAE)

我们编写了一个Gumbel-Softmax技巧应用的案例,呈现了一个变分自编码器(VAE),它专门设计用于处理MNIST数据集,并拥有一个由分类变量构成的潜在空间。这个潜在空间由多个分类变量组成,每个变量都能够取有限个可能的类别。

具体来说,在这个例子中,我们的潜在空间由30个独立的分类变量组成,每个变量都限定在10个可能的类别中。鉴于VAE模型的工作原理,我们需要为这些潜在变量定义一个先验分布,这里我们选择了一个均匀的分类分布作为先验,意味着在潜在空间中每个类别的出现概率是相同的。

通过这种方式,我们能够利用Gumbel-Softmax分布来实现对潜在变量的可微分采样,从而允许模型通过标准的反向传播算法进行训练。这种采样方法不仅提供了一种灵活的方式来处理离散数据,而且还保持了模型在概率建模上的理论完整性。

4.1.设置

我们从所需的导入和超参数定义开始。

import numpy as np  # 导入NumPy库,用于数学运算import torch  # 导入PyTorch库,用于构建和训练神经网络
import torch.nn.functional as F  # 导入PyTorch的功能性模块,包含一些神经网络中常用的函数
from torch import nn, optim  # 从PyTorch中导入神经网络模块(nn)和优化器模块(optim)
from torch.nn import functional as F  # 导入PyTorch神经网络的功能性方法,F是函数库的别名
from torchvision import datasets, transforms  # 从torchvision库中导入数据集和转换模块,用于加载和预处理数据
from torchvision.utils import save_image  # 从torchvision.utils中导入保存图像的函数
from torch.distributions.one_hot_categorical import OneHotCategorical  # 从PyTorch的分布库中导入OneHotCategorical分布import matplotlib  # 导入matplotlib库,用于绘图
import matplotlib.pyplot as plt  # 导入matplotlib的pyplot模块,用于创建图表
%matplotlib inline  # 使得matplotlib的图表可以在Jupyter笔记本中直接显示cuda=True  # 设置是否使用CUDA(GPU加速),如果设置为True且GPU可用,代码将使用GPU进行加速
batch_size = 100  # 设置每个批次的样本数量为100
epochs = 10  # 设置训练的轮数(epoch)为10
latent_dim = 30  # 设置潜在空间的维度为30
categorical_dim = 10  # 设置分类潜在变量的类别数量为10
temp = 1.0  # 设置Gumbel-Softmax采样中的温度参数为1.0,控制采样的随机性

4.2.Gumbel采样

我们现在转向实现Gumbel-Softmax采样的过程,这是一种在深度学习中处理离散变量的策略,允许模型利用梯度下降算法进行训练。以下是三个关键函数的定义,它们共同构成了Gumbel-Softmax采样方法:

  1. sample_gumbel 函数
    这个函数用于生成Gumbel分布的样本。它首先从均匀分布 U ( 0 , 1 ) U(0,1) U(0,1) 中抽取随机数,然后通过计算 − log ⁡ ( − log ⁡ ( U ( 0 , 1 ) ) ) -\log(-\log(U(0,1))) log(log(U(0,1))) 来得到Gumbel分布的样本。这些样本是按照尺度为0、位置参数为1的Gumbel分布生成的。

  2. gumbel_softmax_sample 函数
    该函数负责将Gumbel噪声添加到未经归一化的对数概率(即logits)上,然后通过设置一个温度参数来控制softmax函数的平滑程度,最终应用softmax函数来获取概率分布。

  3. gumbel_softmax 函数
    这个函数结合了上述的采样和softmax操作,并增加了评估模式下的行为。在评估模式下,它直接从由logits定义的分类分布中采样,而不会进行Gumbel-Softmax松弛。这允许我们在模型评估时获得确定性的样本。

这些函数的实现为深度学习模型中离散变量的处理提供了一种有效的方法,使模型能够通过连续的放松来优化通常不可微的离散采样步骤。通过这种方式,我们可以训练通常难以优化的模型,并且能够处理更广泛的数据类型和结构。

def sample_gumbel(shape, eps=1e-20):# 函数用于生成Gumbel分布的样本U = torch.rand(shape)  # 生成与shape相同形状的[0,1)之间的均匀分布随机数if cuda:U = U.cuda()  # 如果cuda为True,将数据转移到GPU上return -torch.log(-torch.log(U + eps) + eps)  # 通过变换得到Gumbel分布的样本,eps用于避免对数为负无穷def gumbel_softmax_sample(logits, temperature):# 函数用于在给定的对数几率(logits)和温度参数下,通过Gumbel-Softmax技巧采样y = logits + sample_gumbel(logits.size())  # 将Gumbel分布的样本加到logits上return F.softmax(y / temperature, dim=-1)  # 应用softmax函数,并除以温度参数,得到概率分布def gumbel_softmax(logits, temperature, evaluate=False):# 函数用于在评估模式下进行Gumbel-Softmax采样或者进行训练if evaluate:# 如果是在评估模式下,直接从分类分布中采样d = OneHotCategorical(logits=logits.view(-1, latent_dim, categorical_dim))  # 创建OneHotCategorical分布return d.sample().view(-1, latent_dim * categorical_dim)  # 采样并重塑形状# 如果不是评估模式,使用Gumbel-Softmax技巧进行采样y = gumbel_softmax_sample(logits, temperature)  # 调用上面定义的采样函数return y.view(-1, latent_dim * categorical_dim)  # 重塑采样结果的形状

这些函数中使用了一些PyTorch的函数和类,例如torch.rand生成均匀分布的随机数,F.softmax应用softmax函数,以及OneHotCategorical分布用于从分类变量中采样。cuda变量用于判断是否使用GPU加速运算。logits是分类概率的对数,temperature参数控制了采样的随机性,evaluate参数用于判断当前是在训练模式还是评估模式。在评估模式下,直接采样并返回离散的样本;在训练模式下,使用Gumbel-Softmax技巧进行梯度估计和优化。

4.3.VAE模型

我们现在转向构建一个变分自编码器(VAE)模型,该模型采用了Gumbel-Softmax技巧来处理潜在空间中的离散变量:

  1. 模型定义
    我们创建了一个名为 VAE_gumbel 的类,它基于PyTorch的 nn.Module 构建。这个类实现了一个VAE模型,其中潜在变量通过Gumbel-Softmax分布进行采样,从而允许梯度下降算法的应用。

  2. 初始化 (__init__ 方法)
    在类的构造函数中,我们初始化了模型所需的网络层,包括线性层、ReLU激活函数和Sigmoid激活函数。这些层构成了模型的编码器和解码器部分。

  3. 编码过程 (encode 方法)
    encode 方法负责将输入数据 x 转换成潜在变量的对数几率。这一过程涉及多个线性层和非线性激活函数,最终输出潜在变量的未归一化对数概率。

  4. 解码过程 (decode 方法)
    decode 方法接收潜在变量作为输入,并通过一个由线性层和激活函数组成的网络结构来重建输入数据。最终,该方法输出重构数据的概率分布。

  5. 前向传播 (forward 方法)
    forward 方法实现了模型的前向传播。它首先通过编码器获取潜在变量的对数几率,然后根据提供的 temp 温度参数和 evaluate 标志,使用Gumbel-Softmax技巧或确定性采样来生成潜在变量。最后,解码器将潜在变量转换为重构数据。

  6. 温度参数和评估标志

    • temp 参数控制Gumbel-Softmax采样的随机性。较低的温度值使得采样更接近确定性选择,而较高的温度值则增加随机性。
    • evaluate 标志用于确定是否在评估模式下运行模型。在评估模式下,模型使用确定性采样来直接从潜在变量的分布中获取样本,以便进行模型的评估和测试。

通过这种方式,VAE_gumbel 类提供了一种灵活的方法来训练和评估VAE模型,同时处理潜在空间中的离散性质。这种模型特别适用于那些需要学习离散潜在表示的任务,例如处理分类数据或进行结构化数据建模。

class VAE_gumbel(nn.Module):def __init__(self, temp):super(VAE_gumbel, self).__init__()  # 调用基类的初始化方法# 定义模型的层self.fc1 = nn.Linear(784, 512)  # 定义一个线性层,输入维度784,输出维度512self.fc2 = nn.Linear(512, 256)  # 定义一个线性层,输入维度512,输出维度256self.fc3 = nn.Linear(256, latent_dim * categorical_dim)  # 定义一个线性层,输出维度为潜在维度乘以分类维度self.fc4 = nn.Linear(latent_dim * categorical_dim, 256)  # 定义一个线性层,输入维度为潜在维度乘以分类维度self.fc5 = nn.Linear(256, 512)  # 定义一个线性层,输入维度256,输出维度512self.fc6 = nn.Linear(512, 784)  # 定义一个线性层,输出维度784# 定义激活函数self.relu = nn.ReLU()  # ReLU激活函数self.sigmoid = nn.Sigmoid()  # Sigmoid激活函数def encode(self, x):# 定义编码器h1 = self.relu(self.fc1(x))  # 通过线性层和ReLU激活函数h2 = self.relu(self.fc2(h1))  # 通过第二个线性层和ReLU激活函数return self.relu(self.fc3(h2))  # 通过第三个线性层和ReLU激活函数得到潜在变量的对数几率def decode(self, z):# 定义解码器h4 = self.relu(self.fc4(z))  # 通过线性层和ReLU激活函数h5 = self.relu(self.fc5(h4))  # 通过第二个线性层和ReLU激活函数return self.sigmoid(self.fc6(h5))  # 通过第三个线性层和Sigmoid激活函数得到重构图像的概率def forward(self, x, temp, evaluate=False):# 定义前向传播过程q = self.encode(x.view(-1, 784))  # 对输入x进行编码,得到潜在变量的对数几率q_y = q.view(q.size(0), latent_dim, categorical_dim)  # 重塑编码后的形状z = gumbel_softmax(q_y, temp, evaluate)  # 使用Gumbel-Softmax技巧进行采样return self.decode(z), F.softmax(q_y, dim=-1).reshape(*q.size())  # 解码并返回重构图像和潜在变量的概率分布

4.2.计算KL散度

在变分自编码器(VAE)的训练过程中,除了重建输入数据,模型还需要确保潜在变量的分布与先验分布保持一致。这通常通过最小化潜在分布与均匀先验分布之间的Kullback-Leibler (KL) 散度来实现。

  1. KL散度的计算
    VAE模型中的KL散度衡量了潜在变量的概率分布 $ q(x) $ 与均匀先验分布 $ p(x) = \frac{1}{C} $ 之间的差异。对于离散的潜在变量,KL散度可以表示为:
    KLD ( q ∣ ∣ p ) = ∑ i = 1 C q ( x i ) log ⁡ ( C ⋅ q ( x i ) 1 ) \text{KLD}(q||p) = \sum_{i=1}^{C} q(x_i) \log \left(\frac{C \cdot q(x_i)}{1}\right) KLD(q∣∣p)=i=1Cq(xi)log(1Cq(xi))
    其中, C C C 是潜在变量可能取值的总数, q ( x i ) q(x_i) q(xi) 是潜在变量取第 i i i 个值的概率。

  2. 重构损失
    除了KL散度,VAE的损失函数还包括重构损失,它通常采用二元交叉熵(Binary Cross-Entropy, BCE)来衡量模型重构的图像 recon _ x \text{recon}\_x recon_x 与原始输入图像 x x x 之间的差异。

  3. VAE损失的组成
    VAE的总损失是重构损失和KL散度的结合,可以表示为:
    VAE Loss = BCE ( recon x , x ) + KLD ( q ∣ ∣ p ) \text{VAE Loss} = \text{BCE}(\text{recon}_x, x) + \text{KLD}(q||p) VAE Loss=BCE(reconx,x)+KLD(q∣∣p)
    这种损失函数的设计旨在使模型在保持数据重构精度的同时,也让潜在变量的分布接近于先验分布。

  4. 损失函数的作用
    通过最小化这个损失函数,VAE模型学习到如何将输入数据有效地编码到潜在空间,并且在这个空间中探索数据的分布。KL散度正则化确保了潜在变量的分布不会偏离均匀分布太远,这有助于模型学习到更加泛化的特征表示。

  5. 实现考虑
    在实际实现中,为了数值稳定性和计算效率,我们通常会对KL散度进行一些调整,例如通过减去一个常数项或使用log-trick来避免数值下溢。

通过这种方式,VAE模型不仅能够学习到数据的重构,还能够学习到数据的潜在结构,使其能够在生成任务或特征学习中发挥重要作用。

def loss_function(recon_x, x, qy):# 定义VAE的损失函数,包括重构损失和KL散度BCE = F.binary_cross_entropy(  # 计算重构损失recon_x,                  # 模型重构的图像x.view(-1, 784),           # 原始图像,调整为匹配重构图像的形状size_average=False         # 不使用大小平均,直接使用所有样本的总损失) / x.shape[0]               # 将损失平均到每个样本log_ratio = torch.log(qy * categorical_dim + 1e-20)  # 计算潜在变量分布的对数比率,1e-20用于数值稳定性KLD = torch.sum(               # 计算KL散度,即潜在变量分布与先验分布之间的差异qy * log_ratio,            # 每个潜在维度上的KL散度贡献dim=-1                     # 沿着最后一个维度(潜在变量的类别维度)求和).mean()                      # 计算所有样本的平均KL散度return BCE + KLD               # 返回总损失,即重构损失和KL散度的和

4.3.建立并训练模型

为了构建一个变分自编码器(VAE)并进行训练,我们需要定义模型结构、损失函数、优化器,以及数据加载器。

4.3.1.训练准备

在本阶段,我们的主要任务是设置变分自编码器(VAE)模型的训练环境,并准备相应的数据加载器。

  1. 模型初始化
    我们首先实例化VAE模型,这是执行数据学习和重构的核心组件。

  2. 数据加载器的准备
    利用PyTorch的DataLoader工具,我们能够高效地加载训练和测试数据。DataLoader的优势在于它支持批量数据处理、多线程加载,以及自动的数据随机化,这些都是训练过程中的重要特性。

  3. GPU加速
    通过检查CUDA的可用性,我们有条件地将模型和数据迁移到GPU,这样做可以显著提升计算速度,尤其是在处理大规模数据集或复杂模型时。

  4. 优化器配置
    我们选择了Adam优化器,这是深度学习中一个非常流行的选择,因为它自适应地调整学习率,通常能够更快地收敛。通过optim.Adam,我们初始化了优化器,并设置了一个初始学习率0.001。

  5. 损失目标的计算
    在训练过程中,我们不仅计算放松目标,也评估未放松目标。虽然未放松目标不直接用于训练,但它提供了一个基准,帮助我们理解当前模型的状态,并指导我们如何调整模型参数,特别是温度参数,以平衡训练性能和目标的接近度。

  6. 训练与评估的平衡
    通过评估放松目标与实际目标之间的差异,我们可以调整模型的温度参数,确保在训练过程中,模型既能有效学习数据的分布,又能保持潜在空间的离散性。

通过这些步骤,我们建立了一个完整的训练框架,它不仅包括模型的构建和数据的准备,还包括了训练过程中的监控和调整机制,确保模型能够在学习数据的同时,保持良好的泛化能力和生成能力。

model = VAE_gumbel(temp)  # 创建VAE模型实例,temp是温度参数
if cuda:model.cuda()  # 如果cuda为True,将模型转移到GPU上
optimizer = optim.Adam(model.parameters(), lr=1e-3)  # 创建Adam优化器,用于模型参数的优化,学习率为0.001# 设置数据加载器的参数,如果使用GPU,则使用多线程和锁定内存
kwargs = {'num_workers': 1, 'pin_memory': True} if cuda else {}# 创建训练数据加载器,使用MNIST数据集
train_loader = torch.utils.data.DataLoader(datasets.MNIST('./data/MNIST', train=True, download=True,  # MNIST训练数据集路径和下载选项transform=transforms.ToTensor()),  # 将图像转换为Tensorbatch_size=batch_size,  # 每个批次的样本数量shuffle=True,  # 在每个epoch开始时打乱数据**kwargs  # 根据是否使用GPU设置多线程和锁定内存的参数
)# 创建测试数据加载器,使用MNIST数据集
test_loader = torch.utils.data.DataLoader(datasets.MNIST('./data/MNIST', train=False,  # MNIST测试数据集路径transform=transforms.ToTensor()),batch_size=batch_size,  # 每个批次的样本数量shuffle=True,  # 在每个epoch开始时打乱数据**kwargs  # 根据是否使用GPU设置多线程和锁定内存的参数
)

4.3.2.训练模型

在训练阶段,我们通过编写两个关键函数traintest来对变分自编码器(VAE)模型进行训练和评估。

  1. 训练过程 (train 函数)

    • 每个epoch期间,模型遍历整个训练数据集。
    • 损失函数计算当前批次的重构误差和潜在变量分布的KL散度。
    • 执行反向传播来计算损失相对于模型参数的梯度。
    • 更新模型参数以最小化损失。
  2. 评估过程 (test 函数)

    • 在评估模式下运行模型,此时模型不会进行梯度更新。
    • 计算并输出模型在测试集上的性能,通常是通过测试损失来衡量。
  3. GPU加速

    • 使用cuda变量检查GPU是否可用,以决定是否将模型和数据迁移到GPU上,从而加速训练。
  4. 梯度管理

    • 在每次迭代前,optimizer.zero_grad()确保梯度被清零,避免累积。
    • loss.backward()根据当前损失计算参数梯度。
    • optimizer.step()根据计算出的梯度更新模型参数。
  5. 评估模式

    • evaluate=True参数指示模型在评估模式下运行,此时Gumbel-Softmax采样是确定性的,直接从潜在变量的分布中采样。
  6. 温度参数的影响

    • 训练时,可以尝试不同的温度值来观察其对放松目标与真实目标之间关系的影响,以及如何求解最接近的值。

通过这些步骤,我们能够系统地训练VAE模型,并通过调整温度参数来平衡模型的训练性能和目标接近度。这种方法不仅有助于提高模型的重构能力,还能够确保模型在潜在空间中学习到有意义的分布。

def train(epoch):# 定义训练循环model.train()  # 设置模型为训练模式train_loss = 0  # 初始化训练损失为0train_loss_unrelaxed = 0  # 初始化未放松训练目标的损失为0for batch_idx, (data, _) in enumerate(train_loader):  # 遍历训练数据加载器if cuda:data = data.cuda()  # 如果使用GPU,将数据转移到GPU上optimizer.zero_grad()  # 清除之前的梯度recon_batch, qy = model(data, temp)  # 通过模型得到重构图像和潜在变量的分布loss = loss_function(recon_batch, data, qy)  # 计算损失loss.backward()  # 反向传播,计算梯度train_loss += loss.item() * len(data)  # 累加损失optimizer.step()  # 更新模型参数# 评估未放松训练目标(不用于训练,仅用于比较)recon_batch_eval, qy_eval = model(data, temp, evaluate=True)loss_eval = loss_function(recon_batch_eval, data, qy_eval)train_loss_unrelaxed += loss_eval.item() * len(data)print('Epoch: {} Average loss relaxed: {:.4f} Unrelaxed: {:.4f}'.format(epoch, train_loss / len(train_loader.dataset),  # 打印平均放松损失train_loss_unrelaxed / len(train_loader.dataset)))  # 打印平均未放松损失def test(epoch):# 定义评估循环model.eval()  # 设置模型为评估模式test_loss = 0  # 初始化测试损失为0for i, (data, _) in enumerate(test_loader):  # 遍历测试数据加载器if cuda:data = data.cuda()  # 如果使用GPU,将数据转移到GPU上recon_batch, qy = model(data, temp, evaluate=True)  # 通过模型得到重构图像和潜在变量的分布(评估模式)test_loss += loss_function(recon_batch, data, qy).item() * len(data)  # 累加损失test_loss /= len(test_loader.dataset)  # 计算平均测试损失print('Eval loss: {:.4f}'.format(test_loss))  # 打印平均测试损失

4.3.3.评估模型

本节定义了一个名为 run 的函数,它负责驱动VAE模型的训练和评估周期。

  1. 训练周期 (epoch)epoch 是指模型完整地在训练集上学习一次的周期。
  2. 训练轮数指定:使用 range(1, epochs + 1) 来确定训练过程需要进行的总周期数。
  3. 执行训练 (train(epoch)):在每个周期内,调用 train 函数来执行训练任务。此函数通过反向传播算法更新模型参数,目的是减少训练损失。
  4. 执行评估 (test(epoch)): 每个周期训练结束后,调用 test 函数对模型进行评估。此函数计算模型在测试集上的损失表现,并输出结果,但不会对模型参数进行更新。
    通过连续的训练和评估循环,我们可以监测模型性能的变化。理想情况下,我们期望训练损失逐渐降低,测试损失也应保持稳定或降低,这显示了模型正在有效地学习数据特征,同时避免了对训练集的过拟合。
def run():# 定义run函数来运行整个训练和评估过程for epoch in range(1, epochs + 1):  # 从第1个epoch到epochs变量指定的epoch数train(epoch)  # 调用train函数进行训练test(epoch)   # 调用test函数对模型在测试集上进行评估run()  # 调用run函数开始训练和评估过程

4.3.4.生成样本

现在,我们将从训练完成的解码器中生成图像样本。这一过程涉及从先验分布中采样均匀分类变量,并将这些变量输入解码器。我们定义了两个函数:generate_samples用于从VAE模型生成样本,而show_gray_image_grid则用于展示这些生成的图像。
generate_samples函数

  • model.eval():设置模型为评估模式,确保在生成样本时不应用如Dropout或Batch Normalization等只在训练时使用的层。
  • 创建一个形状为 [64, latent_dim, categorical_dim] 的张量,填充为1,然后每个元素乘以 1/categorical_dim,得到均匀的概率分布。这里的64代表生成样本的数量。
  • 使用 OneHotCategorical 分布根据概率 probs 采样,并通过 .cuda() 将概率张量转移到GPU(如果使用CUDA)。
  • model.decode(cat_samples):将one-hot编码的潜在变量通过解码器转换回图像数据。
  • output.view(-1,28,28).detach().cpu().numpy():将解码器的输出调整为28x28像素的图像尺寸,从PyTorch张量分离出来,并转换为NumPy数组,以便于展示和处理。

show_gray_image_grid函数

  • plt.subplots(x, y, figsize=size):根据提供的行数 x、列数 y 和图像大小 size 创建一个图像网格。
  • axs.flatten():将二维轴数组展平为一维,以便于迭代。
  • ax.imshow(np.squeeze(img), cmap='gray'):在每个轴上展示图像,使用灰度色彩映射,np.squeeze(img) 用于去除不必要的单维度。
  • ax.set_axis_off():关闭坐标轴显示,以便更清晰地展示图像。
  • 如果提供了 path 参数,plt.savefig(path) 会将图像保存到文件;否则,plt.show() 会直接展示图像。

最后,通过调用 show_gray_image_grid(samples, 8,8),我们以8行8列的格式展示生成的样本图像。这允许我们直观地评估模型生成图像的质量和多样性。

def generate_samples():# 生成样本的函数model.eval()  # 设置模型为评估模式probs = torch.ones([64, latent_dim, categorical_dim])*(1/categorical_dim)  # 创建一个均匀概率向量cat_samples = OneHotCategorical(probs=probs.cuda()).sample().view(-1, latent_dim*categorical_dim)  # 从均匀分布采样得到分类样本output = model.decode(cat_samples)  # 使用模型的解码器部分生成图像return output.view(-1,28,28).detach().cpu().numpy()  # 将输出转换为numpy数组并返回samples = generate_samples()  # 调用函数生成样本def show_gray_image_grid(imgs, x=2, y=5, size=(8,8), path=None, save=False):# 展示灰度图像网格的函数fig, axs = plt.subplots(x, y, figsize=size)  # 创建图像展示的网格axs = axs.flatten()  # 将轴对象扁平化为一维数组for img, ax in zip(imgs, axs):  # 遍历每个图像和对应的轴对象ax.imshow(np.squeeze(img), cmap='gray')  # 在轴上展示图像,使用灰度色彩映射ax.set_axis_off()  # 不展示坐标轴if save:  # 如果指定了保存路径plt.savefig(path)  # 保存图像到文件else:plt.show()  # 直接展示图像show_gray_image_grid(samples, 8,8)  # 展示生成的样本图像,8行8列的网格布局

4.4.Gumbel直通(Gumbel Straight-Through)

在深度学习中,我们经常遇到需要训练包含离散变量的模型的情况。然而,这些离散变量的放松值可能不适合作为模型输入,或者我们可能需要在优化过程中使用分类/离散输入。为了解决这个问题,我们可以使用一种称为直通估计器(Straight-Through Estimator, STE)的启发式方法。

4.4.1.直通估计器(STE)的概念:

  1. 预激活与采样
    给定预激活值 y y y,我们首先通过非可微的采样操作(例如,从分类或伯努利分布中采样)来计算样本 z z z

  2. 下游函数计算
    使用得到的硬样本 z z z来计算下游函数 f f f

  3. 直通梯度
    在反向传播过程中,我们采用直通梯度,忽略非可微的采样步骤,直接将相对于 z z z的梯度 ∂ z f \partial_z f zf作为相对于 y y y的梯度 ∂ y f \partial_y f yf传递回去。

    ∂ y f : = ∂ z f \partial_y f := \partial_z f yf:=zf

4.4.2.Gumbel-Softmax与直通估计器的结合:

  1. Gumbel-Softmax松弛
    我们使用Gumbel-Softmax技巧来生成放松的离散样本,这些样本在训练过程中是连续的,但在前向传递中可以被视为硬离散值。

  2. 硬采样与直通梯度结合
    给定硬向量 y hard y_{\text{hard}} yhard和软向量 y y y,我们使用以下技巧来结合直通梯度:

    y = ( y hard − y ) .detach() + y y = (y_{\text{hard}} - y) \text{.detach()} + y y=(yhardy).detach()+y

    这样,在前向传递中使用 y hard y_{\text{hard}} yhard,在反向传递中则使用 y y y的梯度。

  3. gumbel_softmax 函数的变体
    我们定义了一个名为 gumbel_softmax 的函数,它是Gumbel-Softmax技巧的一个变体,允许在评估模式下进行硬采样,或者在训练模式下使用直通梯度进行优化。

通过这种方法,我们可以有效地训练包含离散变量的模型,即使这些变量在模型的某些部分需要以确定性的方式进行处理。直通估计器提供了一种在反向传播中处理非可微操作的有效手段,使得模型能够学习到离散变量的分布,同时保持梯度的流动。这种技巧在处理强化学习策略、序列生成模型以及其他需要离散决策的领域中非常有用。

def gumbel_softmax(logits, temperature, evaluate=False, hard=False):# logits: 分类概率的对数几率# temperature: 控制采样随机性的温度参数# evaluate: 是否处于评估模式,如果是,则直接采样# hard: 是否执行直通梯度估计,如果是,则返回硬采样(one-hot编码)if evaluate:# 如果处于评估模式,直接从潜在变量的分布中采样d = OneHotCategorical(logits=logits.view(-1, latent_dim, categorical_dim))return d.sample().view(-1, latent_dim * categorical_dim)y = gumbel_softmax_sample(logits, temperature)  # 应用Gumbel-Softmax采样if hard:# 如果需要硬采样,执行直通梯度估计# 取得每个样本最大值的索引,并将其转换为one-hot向量shape = logits.size()_, k = y.max(-1)  # 取得最大值的索引y_hard = torch.zeros_like(logits)  # 创建一个和logits形状相同的零张量y_hard = y_hard.zero_().scatter_(-1, k.view(shape[:-1] + (1,)), 1.0)  # 在最大值索引位置插入1# 直通梯度技巧:在前向传播中使用硬采样值,在反向传播中使用放松梯度y = (y_hard - y).detach() + y  # 将y的梯度固定,只传递y_hard的梯度return y.view(-1, latent_dim * categorical_dim)  # 返回重塑为(N, latent_dim * categorical_dim)形状的张量

在这个函数中:

  • logits 是指每个潜在类别的对数几率。
  • temperature 是控制Gumbel-Softmax分布随机性的超参数。
  • evaluate 标志指示是否处于评估模式,在评估模式下,模型会直接从潜在变量的分布中采样,而不是使用Gumbel-Softmax技巧。
  • hard 标志指示是否执行直通梯度估计,在这种情况下,函数会返回一个硬采样的one-hot向量,但在反向传播时使用Gumbel-Softmax采样的梯度。

直通梯度技巧允许我们在前向传播中使用硬采样的离散值,而在反向传播中使用放松的连续梯度,这有助于训练包含离散选择的模型。当然,你也可以使用上述函数在模型定义中使用Gumbel-Straight-Through来训练上述VAE模型,并将hard设置为True

5.总结和展望

5.1.总结

Gumbel-Softmax提供了一种强大的方法,用于在深度学习模型中引入离散性和结构化变量。通过使用这种技巧,我们可以训练通常难以优化的模型,并且能够处理更广泛的数据类型和结构。随着深度学习领域的不断发展,Gumbel-Softmax和其他相关技术将继续在开发新的模型和算法中发挥关键作用。

5.2.未来方向

未来的研究可能会探索如何将Gumbel-Softmax与其他类型的梯度估计技术结合使用,以进一步提高模型的性能和稳定性。此外,研究者可能会探索如何将这些技术应用于强化学习、序列建模和其他需要离散决策的领域。

最后,随着对Gumbel-Softmax和其他相关技术的深入理解,我们可能会发现新的应用场景,这些场景以前由于计算和优化的限制而无法实现。这将为开发更智能、更灵活的AI系统开辟新的可能性。

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

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

相关文章

实用软件下载:会声会影2023最新安装包及详细安装教程

可以说它不仅符合家庭或个人所需的影片剪辑功能,甚至能够挑战专业级的影片剪辑软件,适合一般大众使用,操作简单易懂,界面简洁明快。从总体上来看影片制作向导模式,只要三个步骤就可快速做出DV影片,入门初学…

乌班图Ubuntu 24.04 SSH Server 修改默认端口重启无效

试用最新的乌班图版本,常规修改ssh端口,修改完毕后重启sshd提示没有找到service,然后尝试去掉d重启ssh后查看状态,端口仍然是默认的22,各种尝试都试了不行,重启服务器后倒是端口修改成功了,心想…

推出一系列GaN功率放大器: QPA2211、QPA2211D、QPA2212、QPA2212D、QPA2212T,支持卫星通信和5G基础设施。

推出用于支持支持卫星通信和5G基础设施的GaN功率放大器: QPA2211 QPA2211D QPA2212 QPA2212D QPA2212T QPA2211 10W GaN功率放大器是一款Ka波段功率放大器,采用0.15m碳化硅基氮化镓工艺 (QGaN15) 制造而成。该放大器的工作频率范围为27.5GHz至31GHz&…

【JUC并发编程】

Java并发常见面试题总结(上) 线程 什么是线程和进程? 何为进程? 进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。 在 Java 中&am…

基于SpringBoot+Vue教材订购系统设计和实现(源码+LW+调试文档+讲解等)

💗博主介绍:✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,…

文件上传漏洞-下篇

一、白名单绕过 目录路径检测绕过 00截断 简介: 0x00是字符串的结束标识符,攻击者可以利用手动添加字符串标识符的方式来将后面的内容进行截断,而后面的内容又可以帮助我们绕过检测。 饶过条件 利用操作:Pass-12 要求&#xff…

高考志愿填报,二个准备三个重点四个原则

对于高考生而言,高考完毕并不是可以轻松地开始,接下来需要研究怎么报考的问题。如何在理想和现实中取得平衡?如何根据就业和专业的前景做合适的安排,对于还处于青少年阶段的高考生们来说不是容易的事情,要掌握哪些技巧…

CANoe CAPL如何模拟发送CAN错误帧?

目录 canOutputErrorFrame介绍代码output(errorframe)代码总结canOutputErrorFrame 介绍 代码 canOutputErrorFrame(errorFrame, 12, 0); //output Error Frame with 12 dominant bits on CAN1 canOutputErrorFrame(CAN2.errorFrame, 6,

快手可灵大模型开放视频续写功能,可生成最长约3分钟视频

6月21日,可灵再度进化,正式推出图生视频功能,支持用任意静态图像生成5s视频,并且可搭配不同的文本内容,实现丰富的视觉叙事 。 同时,可灵还发布了业内领先的视频续写功能,可为已生成的视频&…

Chromium 开发指南2024 Mac篇-开始编译Chromium(五)

1.引言 在之前的指南中,我们已经详细介绍了在 macOS 上编译和开发 Chromium 的准备工作。您学会了如何安装和配置 Xcode,如何下载和配置 depot_tools,以及如何获取 Chromium 的源代码。通过这些步骤,您的开发环境已经搭建完毕&am…

如何级联移位寄存器(74HC595)

在这个项目中,我们将使用 74HC595 移位寄存器将 2 个移位寄存器级联在一起。这样级联移位寄存器现在可以控制 16 个输出。 当然您可以级联任意数量的移位寄存器。如果您要级联第三个移位寄存器,它可以控制 24 个输出。如果您级联第四个移位寄存器&#x…

任务3.8.4 利用RDD实现分组排行榜

文章目录 1. 任务说明2. 解决思路3. 准备成绩文件4. 采用交互式实现5. 采用Spark项目实战概述:使用Spark RDD实现分组排行榜任务背景任务目标技术选型实现步骤1. 准备数据2. 数据上传至HDFS3. 启动Spark Shell4. 读取数据生成RDD5. 数据处理6. 计算TopN7. 输出结果8…

学习es6

1、let变量 2、const常量 3、解构赋值 4、模板字符串 5、简化对象写法 6、参数默认值 7、rest参数 8、扩展运算符 9、扩展对象方法 10、扩展数组方法 11、Set 12,Promise 13、Module模块

Leetcode - 周赛402

目录 一,3185. 构成整天的下标对数目 II 二,3186. 施咒的最大总伤害 三,3187. 数组中的峰值 一,3185. 构成整天的下标对数目 II 这里的T1,T2是一个题,这里直接一起讲了, 当我们已知 x%24 的值…

MobileNetV3轻量化YOLOv8

1 轻量化模型 一般而言,模型轻量化有三个途径: 知识蒸馏:大模型引导小模型训练,让其逼近大模型效果 轻量化模块替换:利用一些轻量化模块进行替换,减少模型参数 剪枝:通过优化算法引导模型裁剪无用的参数 MobileNetV3论文如下,自行搜索 2 修改步骤 在nn/modules的文…

qt+halcon实战

注意建QT工程项目用的是MSVC,如果选成MinGW,则会报错 INCLUDEPATH $$PWD/include INCLUDEPATH $$PWD/include/halconcppLIBS $$PWD/lib/x64-win64/halconcpp.lib LIBS $$PWD/lib/x64-win64/halcon.lib#include "halconcpp/HalconCpp.h" #include &quo…

Kubernetes Ingress 简介

前言 Ingress 是 Kubernetes 中的一种资源对象,用于管理从集群外部到内部服务的 HTTP 和 HTTPS 路由。它提供了灵活的路由功能、SSL/TLS 终止、负载均衡和虚拟主机支持。Ingress 需要一个 Ingress 控制器来实际处理路由,并且可以通过配置不同的控制器来…

RedHat9 | Web服务配置与管理(Apache)

一、实验环境 1、Apache服务介绍 Apache服务,也称为Apache HTTP Server,是一个功能强大且广泛使用的Web服务器软件。 起源和背景 Apache起源于NCSA httpd服务器,经过多次修改和发展,逐渐成为世界上最流行的Web服务器软件之一。…

蔚来汽车AI算法工程师,如何理解注意力?

大家好啊,我是董董灿。 今天分享一个上海蔚来汽车的AI算法岗位面试经验总结帖,面试岗位为算法工程师。 这次面试提到的问题,除了与实习相关内容和反问之外,面试官总共问了8个问题,主要集中在深度学习基础概念的理解上…

共93本!全网最全Frontiers旗下期刊2022、2023版影响因子和分区对比完整版目录!

本周投稿推荐 SSCI • 1区,4.0-5.0(无需返修,提交可录) EI • 各领域沾边均可(2天录用) CNKI • 7天录用-检索(急录友好) SCI&EI • 4区生物医学类,0.1-0.5&…