TensorFlow在MNIST中的应用-无监督学习-自编码器(autoencoder)和encoder

2023-11-05

参考:

《TensorFlow技术解析与实战》

TensorFlow上实现AutoEncoder自编码器

########################################################################################

  前面讲到的都是有监督学习,他的重要特征是数据都是有标记的。无标记的数据应该用什么样的网络模型来学习呢?

这里用一个叫做-自编码网络-的网络模型。

  AutoEncoder大致是一个将数据的高维特征进行压缩降维编码,再经过相反的解码过程的一种学习方法。学习过程中通过解码得到的最终结果与原数据进行比较,通过修正权重偏置参数降低损失函数,不断提高对原数据的复原能力。学习完成后,前半段的编码过程得到结果即可代表原数据的低维“特征值”。通过学习得到的自编码器模型可以实现将高维数据压缩至所期望的维度,原理与PCA相似。

  自编码网络的作用是将输入样本压缩到隐藏层,,然后解压,在输出端重建样本。最终输出层神经元数量和输入层神经元数量相同。

 

########################################################################################

# -*- coding:utf-8 -*-
# ==============================================================================
# 20171115
# HelloZEX
# 自编码网络AutoEncoder
# ==============================================================================

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data

# 导入MNIST数据
mnist = input_data.read_data_sets("MNIST_Labels_Images", one_hot=False)

#设置训练超参数
learning_rate = 0.01    #学习速率
training_epochs = 10    #训练轮数
batch_size = 256        #训练批次大小
display_step = 1        #显示间隔
examples_to_show = 10   #表示从测试集中选择十张图片去验证自动编码器的结果
n_input = 784           #数据的特征值个数

# 输入数据,不需要标记
X = tf.placeholder("float", [None, n_input])

# 用字典的方式存储各隐藏层的参数   网络参数
n_hidden_1 = 256 # 第一编码层神经元个数256,也是特征值个数
n_hidden_2 = 128 # 第二编码层神经元个数128,也是特征值个数

# 权重和偏置的变化在编码层和解码层顺序是相逆的
# 权重参数矩阵维度是每层的 输入*输出,偏置参数维度取决于输出层的单元数
weights = {
    'encoder_h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
    'encoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
    'decoder_h1': tf.Variable(tf.random_normal([n_hidden_2, n_hidden_1])),
    'decoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_input])),
}
biases = {
    'encoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'encoder_b2': tf.Variable(tf.random_normal([n_hidden_2])),
    'decoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'decoder_b2': tf.Variable(tf.random_normal([n_input])),
}


# 定义有压缩函数,每一层结构都是 xW + b
# 构建编码器
def encoder(x):
    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']),
                                   biases['encoder_b1']))
    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['encoder_h2']),
                                   biases['encoder_b2']))
    return layer_2


# 定义解压函数
# 构建解码器
def decoder(x):
    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']),
                                   biases['decoder_b1']))
    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['decoder_h2']),
                                   biases['decoder_b2']))
    return layer_2

# 构建模型
encoder_op = encoder(X)
decoder_op = decoder(encoder_op)

# 预测
y_pred = decoder_op #得出预测值
y_true = X          #输入值 即得出真实值

# 定义代价函数和优化器
cost = tf.reduce_mean(tf.pow(y_true - y_pred, 2))  #最小二乘法 平方差取平均
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)    #优化器采用 AdamOptimizer 或者 RMSPropOptimizer

#训练数据和评估模型
with tf.Session() as sess:
    # tf.initialize_all_variables() no long valid from
    # 2017-03-02 if using tensorflow >= 0.12
    # 检测当前TF版本
    if int((tf.__version__).split('.')[1]) < 12 and int((tf.__version__).split('.')[0]) < 1:
        init = tf.initialize_all_variables()
    else:
        init = tf.global_variables_initializer()
    sess.run(init)

    # 首先计算总批数,保证每次循环训练集中的每个样本都参与训练,不同于批量训练
    total_batch = int(mnist.train.num_examples/batch_size) #总批数
    for epoch in range(training_epochs):
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)  # max(x) = 1, min(x) = 0
            # Run optimization op (backprop) and cost op (to get loss value)
            _, c = sess.run([optimizer, cost], feed_dict={X: batch_xs})
        if epoch % display_step == 0:
            print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(c))
    print("Optimization Finished!")

    #对测试集应用训练好的自动编码网络
    encode_decode = sess.run(y_pred, feed_dict={X: mnist.test.images[:examples_to_show]})
    #比较测试集原始图片和自动编码网络的重建结果
    f, a = plt.subplots(2, 10, figsize=(10, 2))
    for i in range(examples_to_show):
        a[0][i].imshow(np.reshape(mnist.test.images[i], (28, 28)))  #测试集
        a[1][i].imshow(np.reshape(encode_decode[i], (28, 28)))         #重建结果
    plt.show()
    # plt.draw()
    # plt.waitforbuttonpress()

print('Finish!')

########################################################################################

  首先,导入将要使用到的各种库和数据集,定义各个参数如学习率、训练迭代次数等,清晰明了便于后期修改。由于自编码器的神经网络结构非常有规律性,都是xW + b的结构,故将每一层的权重W和偏置b的变量tf.Variable统一置于一个字典中,通过字典的key值更加清晰明了的描述。模型构建思路上,将编码器部分和解码器部分分开构建,每一层的激活函数使用Sigmoid函数,编码器通常与编码器使用同样的激活函数。通常编码器部分和解码器部分是一个互逆的过程,例如我们设计将784维降至256维再降至128维的编码器,解码器对应的就是从128维解码至256维再解码至784维。定义代价函数,代价函数表示为解码器的输出与原始输入的最小二乘法表达,优化器采用AdamOptimizer训练阶段每次循环将所有的训练数据都参与训练。经过训练,最终将训练结果与原数据可视化进行对照,如下图,还原度较高。如果增大训练循环次数或者增加自编码器的层数,可以得到更好的还原效果。


########################################################################################


########################################################################################

Encoder

Encoder编码器工作原理与AutoEncoder相同,我们将编码得到的低维“特征值”在低维空间中可视化出来,直观显示数据的聚类效果。具体地说,将784维的MNIST数据一步步的从784到128到64到10最后降至2维,在2维坐标系中展示遇上一个例子不同的是,在编码器的最后一层中我们不采用Sigmoid激活函数,而是将采用默认的线性激活函数,使输出为(-∞,+∞)。

########################################################################################

# -*- coding:utf-8 -*-
# ==============================================================================
# 20171115
# HelloZEX
# 编码网络Encoder
# ==============================================================================

import tensorflow as tf
import matplotlib.pyplot as plt

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_Labels_Images", one_hot=False)

learning_rate = 0.01
training_epochs = 10
batch_size = 256
display_step = 1
n_input = 784
X = tf.placeholder("float", [None, n_input])

n_hidden_1 = 128
n_hidden_2 = 64
n_hidden_3 = 10
n_hidden_4 = 2
weights = {
    'encoder_h1': tf.Variable(tf.truncated_normal([n_input, n_hidden_1],)),
    'encoder_h2': tf.Variable(tf.truncated_normal([n_hidden_1, n_hidden_2],)),
    'encoder_h3': tf.Variable(tf.truncated_normal([n_hidden_2, n_hidden_3],)),
    'encoder_h4': tf.Variable(tf.truncated_normal([n_hidden_3, n_hidden_4],)),
    'decoder_h1': tf.Variable(tf.truncated_normal([n_hidden_4, n_hidden_3],)),
    'decoder_h2': tf.Variable(tf.truncated_normal([n_hidden_3, n_hidden_2],)),
    'decoder_h3': tf.Variable(tf.truncated_normal([n_hidden_2, n_hidden_1],)),
    'decoder_h4': tf.Variable(tf.truncated_normal([n_hidden_1, n_input],)),
}
biases = {
    'encoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'encoder_b2': tf.Variable(tf.random_normal([n_hidden_2])),
    'encoder_b3': tf.Variable(tf.random_normal([n_hidden_3])),
    'encoder_b4': tf.Variable(tf.random_normal([n_hidden_4])),
    'decoder_b1': tf.Variable(tf.random_normal([n_hidden_3])),
    'decoder_b2': tf.Variable(tf.random_normal([n_hidden_2])),
    'decoder_b3': tf.Variable(tf.random_normal([n_hidden_1])),
    'decoder_b4': tf.Variable(tf.random_normal([n_input])),
}
def encoder(x):
    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']),
                                   biases['encoder_b1']))
    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['encoder_h2']),
                                   biases['encoder_b2']))
    layer_3 = tf.nn.sigmoid(tf.add(tf.matmul(layer_2, weights['encoder_h3']),
                                   biases['encoder_b3']))
    # 为了便于编码层的输出,编码层随后一层不使用激活函数
    layer_4 = tf.add(tf.matmul(layer_3, weights['encoder_h4']),
                                    biases['encoder_b4'])
    return layer_4

def decoder(x):
    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']),
                                   biases['decoder_b1']))
    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['decoder_h2']),
                                   biases['decoder_b2']))
    layer_3 = tf.nn.sigmoid(tf.add(tf.matmul(layer_2, weights['decoder_h3']),
                                biases['decoder_b3']))
    layer_4 = tf.nn.sigmoid(tf.add(tf.matmul(layer_3, weights['decoder_h4']),
                                biases['decoder_b4']))
    return layer_4

encoder_op = encoder(X)
decoder_op = decoder(encoder_op)

y_pred = decoder_op
y_true = X

cost = tf.reduce_mean(tf.pow(y_true - y_pred, 2))
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)

with tf.Session() as sess:
    # tf.initialize_all_variables() no long valid from
    # 2017-03-02 if using tensorflow >= 0.12
    if int((tf.__version__).split('.')[1]) < 12 and int((tf.__version__).split('.')[0]) < 1:
        init = tf.initialize_all_variables()
    else:
        init = tf.global_variables_initializer()
    sess.run(init)
    total_batch = int(mnist.train.num_examples/batch_size)
    for epoch in range(training_epochs):
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)  # max(x) = 1, min(x) = 0
            _, c = sess.run([optimizer, cost], feed_dict={X: batch_xs})
        if epoch % display_step == 0:
            print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(c))
    print("Optimization Finished!")

    encoder_result = sess.run(encoder_op, feed_dict={X: mnist.test.images})
    plt.scatter(encoder_result[:, 0], encoder_result[:, 1], c=mnist.test.labels)
    plt.colorbar()
    plt.show()

########################################################################################


由结果可知,2维编码特征有较好的聚类效果,图中每个颜色代表了一个数字,聚集性很好。

当然,本次实验所得到的结果只是对AutoEncoder做一个简单的介绍,要想得到期望的效果,还应该设计更加复杂的自编码器结构,得到区分性更好的特征。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TensorFlow在MNIST中的应用-无监督学习-自编码器(autoencoder)和encoder 的相关文章

随机推荐

  • Ubuntu22.10 安装微信方法

    Ubuntu22 10 安装微信方法 Ubuntu操作系统中 我尝试过用wine方式安装数次都没有能够启动成功 方法如下 在Ubuntu上安装微信需要使用Wine Wine是一款可以在Linux系统上运行Windows应用程序的兼容层 以下
  • 修改redis配置文件重新启动redis服务启动不了

    一 迁移一个新的配置文件 cat redis conf grep v grep v gt redis test conf 二 修改redis test conf配置 三 启动 redis server etc redis test conf
  • Springboot结合前端上传图片保存到数据库读取

    前言 最近在做一个前后端分离系统 也是闲的无聊做个好玩的练练手 就突然想着之前想了一天的问题 前端怎么去发送图片到后端保存 不是专业前端 轻点喷 图片到底是保存在本地还是存在oss上 保存图片的方式又是什么 这些问题想到我头皮发麻 最后 还
  • 学习经验分享之五:YOLOv5数据集划分以及YOLO格式转换

    问 题 有不少学YOLOv5算法的朋友咨询我 发现部分朋友犯了一个很大的错误 就是只是划分了训练集和验证集 没有测试集 并且没有意识到自己的实验设置是错误的 不科学的 这是非常可怕的 意味着可能前期的工作都白做了 浪费了宝贵的时间和精力 部
  • Linux——进程的四大特性

    一 进程的四大特性 竞争性 独立性 并行性 并发性 1 竞争性 系统进程数码众多 而CPU的资源只有固定的那些 很少 比如说CPU 一般情况下CPU只有一个 所以进程之间是具有竞争属性的 为了高效的完成任务 更合理竞争相关的资源 便具有了优
  • IT工程师学习方法和发展路线

    前言 从需求 即招聘 面试入手 了解行业所需 再到个人部分 学习大佬们的学习方法 书写自己的简历 提升自我技能 或通过考证锻炼学习的学习方法 或通过技能提高工作效率 简述几个方面的特点 梳理下发展路线 通过利器提高办公效率 Tips Mar
  • 区块链基于电商的发展

    区块链技术的发展现状 2008年10月31日 中本聪 Satoshi Nakamoto 的比特币白皮书正式发布 标 志着基于区块链技术的第一个应用比特币 一个去中心化的电子现金系统 正式诞生 这一应用的诞生向世人展示了区块链技术的巨大价值和
  • CLR Via 读书笔记

    CLR Via 读书笔记 第四章 类型基础 记录C 学习过程中的一些语法知识 2023 9 3 第四章 类型基础 点击跳转
  • Mathsphere Note: 好用的Markdown for Latex 文档编辑器

    背景描述 Markdown是一种轻量化的标记语言 非常适合于撰写技术博客类文档 而Markdown for Latex顾名思义 是在Markdown语法的基础上做了增量 适配了Latex的语法 能够对论文进行排版 本文将简要介绍一款Mark
  • JHipster介绍:一个适用于Java和JavaScript的全栈框架

    JHipster介绍 Java和JavaScript的全栈框架 JHipster是一个用于生成混合Java和JavaScript应用程序的成熟框架 它支持你所喜爱的开发工具 并提供监控和其他开箱即用的管理功能 JHipster是一个历史悠久
  • 数据库中几种易混淆的字符串类型

    目录 1 char 2 nchar 3 varchar 4 nvarchar 总结 在数据库中有char varchar nchar nvarchar等几种类型 其中这四种非常类似 但表示的意义稍有不同 1 char char 是普通字符编
  • 解决cv2没有face模块

    人脸识别报错解决 AttributeError module cv2 cv2 has no attribute face 人脸识别报错如下 AttributeError module cv2 cv2 has no attribute fac
  • Scrapy介绍及入门

    一 Scrapy简介 Scrapy是一个为了爬取网站数据 提取结构性数据而编写的应用框架 可以应用在包括数据挖掘 信息处理或存储历史数据等一系列的程序中 其最初是为了页面抓取 更确切来说 网络抓取 所设计的 也可以应用在获取API所返回的数
  • 面试官:SPA(单页应用)首屏加载速度慢怎么解决?

    一 什么是首屏加载 首屏时间 First Contentful Paint 指的是浏览器从响应用户输入网址地址 到首屏内容渲染完成的时间 此时整个网页不一定要全部渲染完成 但需要展示当前视窗需要的内容 首屏加载可以说是用户体验中最重要的环节
  • wps没有卸载干净怎么解决_WPS云文档链接分享后对方没有访问权限?解决办法在此...

    互联网时代的办公 当然也离不开网络 当下盛行远程办公 大家可以随时随地办公 实时分享工作进度非常的方便 要想远程办公最离不开的应该就是云文档 只要登录同一个账号 大家可以共同编辑同一个文档 也可以分享给其他人来实现实时共享工作进度 以及稳当
  • 自从我这样撸代码以后,公司网页的浏览量提高了107%!

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由腾讯IVWEB团队 发表于云 社区专栏 作者 yangchunwen HTTP协议是前端性能乃至安全中一个非常重要的话题 最近在看 web性能权威指南 High Perform
  • Cisco Packet Tracer 实验:生成树配置

    实验目的 1 理解广播风暴的成因 2 掌握STP和RSTP原理及配置方法 实验内容 实验描述 学校为了开展计算机教学和网络办公 建立的一个计算机教室和一个校办公区 这两处的计算机网络通过两台交换机互联组成内部校园网 为了提高网络的可靠性 作
  • Navicat Premium 连接 MySQL 8.0 报错“1251”分析解决

    人闲太久 努力一下就以为是在拼命 一 问题 Navicat Premium 连接 MySQL 8 0 报错 1251 Client does not support authentication protocol requested by
  • 如何自定义sort函数中的比较函数

    在做剑指offer时 有一道题 题目描述 输入一个正整数数组 把数组里所有数字拼接起来排成一个数 打印能拼接出的所有数字中最小的一个 例如输入数组 3 32 321 则打印出这三个数字能排成的最小数字为321323 思路 自定义比较器 若a
  • TensorFlow在MNIST中的应用-无监督学习-自编码器(autoencoder)和encoder

    参考 TensorFlow技术解析与实战 TensorFlow上实现AutoEncoder自编码器 前面讲到的都是有监督学习 他的重要特征是数据都是有标记的 无标记的数据应该用什么样的网络模型来学习呢 这里用一个叫做 自编码网络 的网络模型