机器学习-自编码器AE实战(二)

本篇是自编码器实战,和之前相同的是数据集加载过程,但需要注意不使用标签信息。此处的自定义类,训练过程等都是换汤不换药,但图片重建是我们之前没接触到的,大家可以认真看一下。对于神经网络的学习关键要明白输入是什么,输出是什么,包括数值形状等。


目录

1.数据集加载:

2.自定义AE类:

3.具体训练:

4.图片重建:


1.数据集加载:

h_dim = 20
batchsz = 512
lr = 1e-3

(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.

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)

本次数据集选用的是Fashion Mnist,和Mnist相比略显复杂,也是黑白图片。

注意,自编码器不需要标签信息,仅规格化数据信息,构建训练集和测试集时也不需要标签信息。

几个预设参数:

h_dim;经过编码降到的维度数

batchsz 和lr 大家应该比较熟悉了,代表分批大小和学习率


2.自定义AE类:

class AE(keras.Model):

    def __init__(self):
        super(AE, self).__init__()

        # 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)
        ])

定义编码器encoder和解码器decoder。

编码器encoder子网络实现:输入为长度为784的向量,经过三个全连接层,最终得到长度为h_dim的向量,激活函数都选择用relu。

解码器decoder子网络实现:输入为长度为h_dim的向量,经过三个全连接层,最终得到长度为784的向量,代表了28*28图片打平后的向量,激活函数都选择用relu。

    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)

设定一些参数:

设定网络对象为AE()。规定输入规格。规定使用Adam优化器,并指定学习率。


3.具体训练:

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, float(rec_loss))

循环100轮,将图片打平,构建梯度下降记录器。

将x输入到网络中,得到重构后的x:x_rec_logits,在x和x_rec_logits之间求损失函数。

from_logits=True实际上是隐式调用Softmax激活函数对其进行优化

最终求出来损失函数的平均值,对所有待优化变量进行梯度更新


4.图片重建:

损失函数在此应用中只能在一定程度上评价学习效果的好坏,我们最终希望获得还原度较高的重构图片。因此从测试集中随机采样测试图片,经过自编码器计算得到重建后的图片, 然后将真实图片与重建图片保存为图片阵列,并可视化,方便比对。


        x = next(iter(test_db))
        logits = model(tf.reshape(x, [-1, 784]))
        #print(logits)
        x_hat = tf.sigmoid(logits)
        #print(x_hat)
        # [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)
        save_images(x_concat, 'D:\桌面\文档\结果\结果果trec_epoch_%d.png'%epoch)

我们看一下此部分代码:大家应该还记得我们每次都有初始化数据这一步骤,即将训练集和测试集中的数据规格化到-1~1,因此我们是根据一个-1~1的数据进行神经网络的训练的,最终经过神经网络的训练结果也是一个-1~1的向量。想要可视化表示,我们就需要像素值这一概念,我们此次使用的是Fashion Mnist数据集,是黑白图片,因此像素值是0~255的一个数值。因此我们需要将神经网络的输出结果进行优化,先利用sigmoid激活函数优化到0~1的数值,经过形状转化,图片合并等一系列操作之后,将其*255,最终得到0~255的像素值,使图片可视化出来。


代码来自于《TensorFlow深度学习》-龙龙老师

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值