AE部分
AE定义
class AE(nn.Module):
def __init__(self, n_enc_1, n_enc_2, n_enc_3, n_dec_1, n_dec_2, n_dec_3,
n_input, n_z):
super(AE, self).__init__()
self.enc_1 = Linear(n_input, n_enc_1)
self.enc_2 = Linear(n_enc_1, n_enc_2)
self.enc_3 = Linear(n_enc_2, n_enc_3)
self.z_layer = Linear(n_enc_3, n_z)
self.dec_1 = Linear(n_z, n_dec_1)
self.dec_2 = Linear(n_dec_1, n_dec_2)
self.dec_3 = Linear(n_dec_2, n_dec_3)
self.x_bar_layer = Linear(n_dec_3, n_input)
def forward(self, x):
enc_h1 = F.relu(self.enc_1(x))
enc_h2 = F.relu(self.enc_2(enc_h1))
enc_h3 = F.relu(self.enc_3(enc_h2))
z = self.z_layer(enc_h3)
dec_h1 = F.relu(self.dec_1(z))
dec_h2 = F.relu(self.dec_2(dec_h1))
dec_h3 = F.relu(self.dec_3(dec_h2))
x_bar = self.x_bar_layer(dec_h3)
return x_bar, z
编码器和解码器都由3层的线性层和ReLU激活函数组成。
ReLU
定义是f(x) = max(0, x)。因此,ReLU激活函数看起来和行为都像一个线性函数,但实际上是一个非线性函数。
ReLU激活函数的导数具有以下性质:
- 当x > 0时,f’(x) = x ,f’(x) = 1
- 当x <= 0时,f(x) = 0 ,f’(x) = 0
因此,在正区域,ReLU 的导数恒为1,这避免了梯度消失的问题。对深层神经网络来说,正区域占很大一部分,所以大部分情况下ReLU能保证梯度不衰减。
线性层+ReLU是最简单的特征提取模块,堆叠多层可以生成具有足够表达能力的深度网络。
Pretrain AE
主要流程:
- 定义dataloader,从dataset中批量读取数据,shuffle对样本顺序进行随机打乱。
- 定义Adam优化器,优化autoencoder模型的参数,学习率设置为1e-3。
- 循环训练epoch次:
- 每批次输入x,经过模型前向计算,获得重构的x_bar 计算重构x_bar和原x之间的MSE loss
- Adam优化器优化:先梯度清零,loss反向传播计算梯度,更新模型参数。
- 输出loss
- 利用模型隐层向量z进行KMeans聚类,监控聚类效果。
- 保存最终模型参数。
学习率选择1e-3的理由:AE作为无监督特征学习模型,目标是学习输入数据的内在结构表达,而非具体预测任务。因此不需要太大的学习率推动模型快速迭代。
def pretrain_ae(model, dataset, y):
train_loader = DataLoader(dataset, batch_size=256, shuffle=True)
print(model)
optimizer = Adam(model.parameters(), lr=