【李宏毅机器学习】自编码器auto-encoder

note:

  • VAE的本质结构:重构的过程是希望没噪声的,而 KL loss 则希望有高斯噪声的,两者是对立的。所以,VAE 跟 GAN 一样,内部其实是包含了一个对抗的过程,只不过它们两者是混合起来,共同进化的。

一、auto-encoder

在这里插入图片描述
auto encoder是一个基本的生成模型,以encoder-decoder的架构进行先编码(如将图像压缩成更低维度向量),再解码(如将刚才的低维向量还原为图像),并且还原出的图像和原图像越接近越好,reconstruction error。常见的transformer模型就是这种auto-encoder模型(其实FCN的卷积和反卷积也是这样)。
在这里插入图片描述

  • 在训练时,加入噪声能使得学得的model泛化能力更强;

二、自编码器的应用

2.1 Feature Disentangle

如果人声音有两种信息(人信息+声音内容信息),可以将两个encoder后的向量中,分别提取人信息、声音内容信息,进行语音合成(变声器)。

2.2 Text as Representation(学会产生摘要)​

直接encoder-decoder学到的摘要可能狗P不通,大佬们利用GAN概念,加上discriminator(看过人写的句子长啥样)。
在这里插入图片描述

2.3 Anomaly Detection(欺诈检测)

常规的异常检测中,我们需要找到正样本(容易获取,正常的信用卡交易记录),但是负样本不容易获取或者构造,用auto-encoder就能解决这个问题:利用auto-encoder基于同类(比如说正样本)图片训练好的模型,在测试时:
(1)比如正样本(正常类)图片通过encoder编码和decoder解码,计算还原后的照片和原照片的差异,如果很小则认为是这类是在训练时看过的照片(正样本)。
(2)比如负样本(异常类)图片,因为这类照片在训练时没看过,经过encoder和decoder后很难还原回来,差异很大则认为是异常情况。

在这里插入图片描述

三、HW8:FCN auto-encoder

class fcn_autoencoder(nn.Module):
    def __init__(self):
        super(fcn_autoencoder, self).__init__()
        self.encoder = nn.Sequential(
            nn.Linear(64 * 64 * 3, 128),
            nn.ReLU(),
            nn.Linear(128, 64),
            nn.ReLU(), 
            nn.Linear(64, 12), 
            nn.ReLU(), 
            nn.Linear(12, 3)
        )
        
        self.decoder = nn.Sequential(
            nn.Linear(3, 12),
            nn.ReLU(), 
            nn.Linear(12, 64),
            nn.ReLU(),
            nn.Linear(64, 128),
            nn.ReLU(), 
            nn.Linear(128, 64 * 64 * 3), 
            nn.Tanh()
        )

    def forward(self, x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x

class conv_autoencoder(nn.Module):
    def __init__(self):
        super(conv_autoencoder, self).__init__()
        self.encoder = nn.Sequential(
            nn.Conv2d(3, 12, 4, stride=2, padding=1),         
            nn.ReLU(),
            nn.Conv2d(12, 24, 4, stride=2, padding=1),        
            nn.ReLU(),
			      nn.Conv2d(24, 48, 4, stride=2, padding=1),         
            nn.ReLU(),
        )
        self.decoder = nn.Sequential(
			      nn.ConvTranspose2d(48, 24, 4, stride=2, padding=1),
            nn.ReLU(),
			      nn.ConvTranspose2d(24, 12, 4, stride=2, padding=1), 
            nn.ReLU(),
            nn.ConvTranspose2d(12, 3, 4, stride=2, padding=1),
            nn.Tanh(),
        )

    def forward(self, x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x

class VAE(nn.Module):
    def __init__(self):
        super(VAE, self).__init__()
        self.encoder = nn.Sequential(
            nn.Conv2d(3, 12, 4, stride=2, padding=1),            
            nn.ReLU(),
            nn.Conv2d(12, 24, 4, stride=2, padding=1),    
            nn.ReLU(),
        )
        # encoder have two encoder_output
        self.enc_out_1 = nn.Sequential(
            nn.Conv2d(24, 48, 4, stride=2, padding=1),  
            nn.ReLU(),
        )
        self.enc_out_2 = nn.Sequential(
            nn.Conv2d(24, 48, 4, stride=2, padding=1),
            nn.ReLU(),
        )
        self.decoder = nn.Sequential(
			      nn.ConvTranspose2d(48, 24, 4, stride=2, padding=1), 
            nn.ReLU(),
			      nn.ConvTranspose2d(24, 12, 4, stride=2, padding=1), 
            nn.ReLU(),
            nn.ConvTranspose2d(12, 3, 4, stride=2, padding=1), 
            nn.Tanh(),
        )

    def encode(self, x):
        h1 = self.encoder(x)
        return self.enc_out_1(h1), self.enc_out_2(h1)

    def reparametrize(self, mu, logvar):
        std = logvar.mul(0.5).exp_()
        if torch.cuda.is_available():
            eps = torch.cuda.FloatTensor(std.size()).normal_()
        else:
            eps = torch.FloatTensor(std.size()).normal_()
        eps = Variable(eps)
        return eps.mul(std).add_(mu)

    # decoder part
    def decode(self, z):
        return self.decoder(z)

    def forward(self, x):
        mu, logvar = self.encode(x)
        z = self.reparametrize(mu, logvar)
        return self.decode(z), mu, logvar


def loss_vae(recon_x, x, mu, logvar, criterion):
    """
    recon_x: generating images
    x: origin images
    mu: latent mean
    logvar: latent log variance
    """
    mse = criterion(recon_x, x)
    KLD_element = mu.pow(2).add_(logvar.exp()).mul_(-1).add_(1).add_(logvar)
    KLD = torch.sum(KLD_element).mul_(-0.5)
    return mse + KLD

四、VAEs在推荐系统的应用

参考:推荐系统从零到负无穷(十)-自编码器AutoRec。VAE即变分自编码器。
在这里插入图片描述

Reference

[1] 李宏毅21版视频地址:https://www.bilibili.com/video/BV1JA411c7VT
[2] 李宏毅ML官方地址:http://speech.ee.ntu.edu.tw/~tlkagk/courses.html
[3] https://github.com/unclestrong/DeepLearning_LHY21_Notes
[4] 自编码器李宏毅
[5] 变分自编码器(VAEs)在推荐系统中的应用
[6] https://www.kaggle.com/competitions/ml2022spring-hw8/rules
[7] 变分自编码器VAE:原来是这么一回事 | 附开源代码
[8] 推荐系统从零到负无穷(十)-自编码器AutoRec

附:时间安排

任务内容时间note
task1P23 24自编码器10月10号2个视频一天!
task2P25 adversarial attack(上)10月11、12号
task3P26 adversarial attack(下)10月13、14号
task4P27 机器学习模型的可解释性(上)10月15、16号
task5P28 机器学习模型的可解释性(下)10月17、18、19号
task6P29 领域自适应性10月20、21、22号
task7总结10月23号
  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山顶夕景

小哥哥给我买个零食可好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值