Tensorflow学习笔记----Auto-Encoders自动编码器原理及代码实现

有监督无监督

我们在之前所学习的模型大多都是有监督学习,而Auto-Encoders是无监督的,我们先来理解有监督、无监督的概念。

  • 有监督学习(Supervised Learning):对具有概念标记(分类)的训练样本进行学习,以尽可能对样本集外的数据进行标记(分类)预测,相当于有明确的分类目标。有监督学习可分为回归和分类
    通俗的来说:有监督学习就是训练样本的标记信息是已知的,我们完成一个分类任务时,我们是知道要分为哪些类的,只是对数据进行提取属性再直接分类就好。
    我们之前所学算法的都是进行的有监督学习。而现实中的问题也有很多的没有明确的分类目标的。

  • 无监督学习(Unsupervised Learning):对没有概念标记(分类)的训练样本进行学习,以发现训练样本集中的结构性知识,所有的标记(分类)都是未知的。无监督学习的典型就是聚类
    通俗的来说:无监督学习就是训练样本的标记信息是未知的,目标是通过对无标记训练样本的学习来揭示数据的内在性质和规律。再通俗来讲就是,当我们想要完成一个分类任务时,我们完全不知道应该分为几类,具体的类别也是未知的。

Auto-Encoders概念

Auto-Encoders就是无监督的,它的目标是重建自己,它是一个特殊的全连接层,输入和输出的维度是一样的,这样能保证自己能够重建。中间有一个neck(脖子),这样既可以升维也可以降维,这里降到两维的好处是,二维的图片是可视化的,不仅已经降维,而且在空间中还保证了语义的相关性(通过无监督的聚类可以发现)。
在这里插入图片描述
在之前我们都是使用PCA降维,PCA在高维数据中寻找方差最大的方向,只选择方差最大的轴。然而,PCA具有线性特性,这对特征维数的提取有很大的限制。Auto-Encoders比PCA降维的效果要好。

Auto-Encoders变种:

Denoising AutoEncoders(去噪AutoEncoders)

如果只在像素级别的重建,便不能发现一些更加深层次的特征,网络可能会记住一些特征,为了防止这种情况出现,我们可以在原输入图片后加入随机噪声累加到原图片上:
在这里插入图片描述

Dropout AutoEncoders

在训练的时候随机对某些连接进行断开(通过将该连接的w设置为0),相当于将下一层的得到的信息添加干扰,那么将会迫使网络尽可能的提升还存在的连接的表征能力,降低对多个神经元的依赖程度:
在这里插入图片描述

Adversarial AutoEncoders(对抗 AutoEncoders)

在原始的AutoEncoders中,没有呈现出原有数据的分布,有可能生成的数据是一样的,Adversarial AutoEncoders额外的添加了一个Discriminator(鉴别器),我们希望生成的Z符合真实的Z‘的分布,将真实的和生成的都送到鉴别器计算差距,如果属于希望的分布就输出为1,否则输出为0:
在这里插入图片描述

Auto-Encoders代码实现

import  os
import  tensorflow as tf
import  numpy as np
from    tensorflow import keras
from    tensorflow.keras import Sequential, layers
from    PIL import Image
from    matplotlib import pyplot as plt



tf.random.set_seed(22)
np.random.seed(22)
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
assert tf.__version__.startswith('2.')


def save_images(imgs, name): #把多张图片存到一张图片里去
    new_im = Image.new('L', (280, 280))

    index = 0
    for i in range(0, 280, 28):
        for j in range(0, 280, 28):
            im = imgs[index]
            im = Image.fromarray(im, mode='L')
            new_im.paste(im, (i, j))
            index += 1

    new_im.save(name)


h_dim = 20 #目标维度,将图片的维度最终压缩到这里
batchsz = 512
lr = 1e-3 #learning rate

#加载数据集
(x_train, y_train), (x_test, y_test) = keras.datasets.fashion_mnist.load_data()
x_train, x_test = x_train.astype(np.float32) / 255., x_test.astype(np.float32) / 255.
# we do not need label
train_db = tf.data.Dataset.from_tensor_slices(x_train)
train_db = train_db.shuffle(batchsz * 5).batch(batchsz)
test_db = tf.data.Dataset.from_tensor_slices(x_test)
test_db = test_db.batch(batchsz)

print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)



class AE(keras.Model): #建立Auto-Encoders模型

    def __init__(self):
        super(AE, self).__init__()
        #创建容器,包括两个容器:Encoders,Decoders
        # Encoders ,降维
        self.encoder = Sequential([ #三层神经网络
            layers.Dense(256, activation=tf.nn.relu),
            layers.Dense(128, activation=tf.nn.relu),
            layers.Dense(h_dim)
        ])

        # Decoders ,升维
        self.decoder = Sequential([
            layers.Dense(128, activation=tf.nn.relu),
            layers.Dense(256, activation=tf.nn.relu),
            layers.Dense(784)
        ])

    #前向传播过程
    def call(self, inputs, training=None):
        # [b, 784] => [b, 10]
        h = self.encoder(inputs)
        # [b, 10] => [b, 784]
        x_hat = self.decoder(h) #重建

        return x_hat



model = AE() #创建模型
model.build(input_shape=(None, 784))
model.summary()

optimizer = tf.optimizers.Adam(lr=lr) #优化器
#训练
for epoch in range(100):

    for step, x in enumerate(train_db):

        #[b, 28, 28] => [b, 784]
        x = tf.reshape(x, [-1, 784])

        with tf.GradientTape() as tape:
            x_rec_logits = model(x)

            rec_loss = tf.losses.binary_crossentropy(x, x_rec_logits, from_logits=True)
            rec_loss = tf.reduce_mean(rec_loss) #得到损失函数

        grads = tape.gradient(rec_loss, model.trainable_variables) #求到梯度
        optimizer.apply_gradients(zip(grads, model.trainable_variables))


        if step % 100 ==0:
            print(epoch, step, ' loss:',float(rec_loss))


        # evaluation
        x = next(iter(test_db))
        logits = model(tf.reshape(x, [-1, 784]))
        x_hat = tf.sigmoid(logits) #(0~1)
        # [b, 784] => [b, 28, 28]
        x_hat = tf.reshape(x_hat, [-1, 28, 28])

        # [b, 28, 28] => [2b, 28, 28]
        x_concat = tf.concat([x, x_hat], axis=0)
        x_concat = x_hat
        x_concat = x_concat.numpy() * 255.
        x_concat = x_concat.astype(np.uint8) #转化为numpy的图片保存格式
        save_images(x_concat, 'ae_images/rec_epoch_%d.png'%epoch)

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值