VAE

1.先来看AE(自动编码器)

本质是无监督学习,主要就是一个Encoder和Decoder

i.Encoder

将高维数据映射到低维空间,实际上起一个降维的作用,用 gθg_\theta 表示Encoder的网络, z=gθ(x)z=g_\theta(x) 表示高维数据x经过网络之后产生低维的z

ii.Decoder

从降维后的数据还原到原始数据,用 fλf_\lambda 表示Encoder的网络, xnew=fλ(x)x^{new}=f_\lambda(x)

此外,还需要一个loss函数,可以简单定义为xnewx^{new}与x的距离(L2范数):
L(θ,λ)=1ni=1n(xixnew(i))2L(\theta,\lambda)=\frac{1}{n}\sum_{i=1}^n(x^i-x^{new(i)})^2

由此可见,AE可以完成一些降维、压缩、特征提取等任务

iii.代码示例

AE model定义


# 定义 Autoencoder 模型 用nn.Module作为父类,方便用优化器追踪梯度
class Autoencoder(nn.Module):
    def __init__(self, input_size, hidden_size):
        super(Autoencoder, self).__init__()
        
        # 编码器
        self.encoder = nn.Sequential(
            nn.Linear(input_size, hidden_size),
            nn.ReLU()  # 激活函数
        )
        #nn.linear是网络中的全连接层,第一个参数代表的是输入的二维张量的第二个size,相当于上一层神经元个数,第二个参数则是下一层神经元个数
        #将每一个input_size维数的高维向量转化维hidden_size的低维向量
        
        # 解码器
        self.decoder = nn.Sequential(
            nn.Linear(hidden_size, input_size),
            nn.Sigmoid()  # 将输出范围限定在 [0, 1]
        )
        #这里要恢复到原始维数,所以参数是倒过来的
    
    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded

加载数据,定义优化器、损失函数

X = np.random.rand(1000, 64)  # 1000 个样本,每个样本有 64 维光谱特征
X = torch.tensor(X, dtype=torch.float32)

# 创建数据加载器
dataset = TensorDataset(X, X)  # 输入数据与输出数据相同
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

# 定义模型、优化器和损失函数
input_size = 64
hidden_size = 32  # 压缩到 32 维
autoencoder = Autoencoder(input_size=input_size, hidden_size=hidden_size)
optimizer = optim.Adam(autoencoder.parameters(), lr=0.001)
#我们定义的model用了nn.Module的基类,通过.parameters就可以访问所有要训练的参数
#包括encoder和decoder二者的参数,因为二者是要一起训练的
criterion = nn.MSELoss()  # 损失函数为均方误差

train

# 训练 Autoencoder 模型
num_epochs = 50
for epoch in range(num_epochs):
    for data, target in dataloader:
        optimizer.zero_grad() #清空梯度
        output = autoencoder(data) #前向传播
        loss = criterion(output, target)
        #target即为原始数据
        loss.backward()
        #反向传播
        optimizer.step()
        #step 梯度下降
    
    if epoch % 10 == 0:
        print(f'Epoch {epoch}, Loss: {loss.item()}')

test

# 使用训练好的模型进行降维和重构
encoded_data = autoencoder.encoder(X).detach().numpy()
decoded_data = autoencoder.decoder(torch.tensor(encoded_data)).detach().numpy()

2.VAE(变分自动编码器)

准备知识

(1)潜在变量

(2)极大似然估计

(3)KL散度

VAE主要思想

VAE的损失函数推导

采样:重参数技巧

代码实例


VAE
https://fightforql.github.io/2025/03/27/VAE/
Author
lsy
Posted on
March 27, 2025
Licensed under