简单自编码器实现
在我们使用TensorFlow进行深度学习训练时,很多时候都是与Numpy数据打招呼,例如我们csv或者照片数据等。
但是我们都知道,TensorFlow训练时都是使用Tensor来存储变量的,并且网络输出的结果也是Tensor。
一般情况下我们不会感受到Numpy与Tensor之间的区别,因为TensorFlow网络在输入Numpy数据时会自动转换为Tensor来处理。
但是在输出网络时,输出的结果仍为Tensor,当我们要用这些结果去执行只能由Numpy数据来执行的操作时就会出现莫名其妙的错误。
例如,当我想要用自编码器与解码器输出的结果使用matplotlib显示时就会报错
https://www.cnblogs.com/xiaosongshine/p/10627926.html
实现:
对库的导入
import tensorflow as tf
import matplotlib.pyplot as plt
import os
%matplotlib inline
os.environ['PATH']+=os.pathsep+'D:/Graphviz/bin/'
#os.environ["CUDA_VISIBLE_DEVICES"] = "0"#使用GPU训练 不指定常出问题,指定了有时候也出问题会爆内存?
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"#使用CPU进行训练
测试tensorflow2的版本
tf.__version__ #'2.0.0'
读入数据
(x_train,_),(x_test, _) = tf.keras.datasets.mnist.load_data()
查看数据的形状和测试数据类型
x_train.shape,x_test.shape#((60000, 28, 28), (10000, 28, 28))
type(x_test)#numpy.ndarray
把读入数据转换成全连接层的输入数据
x_train =x_train.reshape(x_train.shape[0],-1)
x_test=x_test.reshape(x_test.shape[0],-1)
x_train.shape, x_test.shape#((60000, 784), (10000, 784))
对数据进行归一化,并且tf.cast把numpy转换成tensor
x_train=tf.cast(x_train,tf.float32)/255
x_test=tf.cast(x_test,tf.float32)/255
type(x_test)#tensorflow.python.framework.ops.EagerTensor
定义输入层的尺寸,hidden是全连接层的encode层的输出尺寸,787个向量输入,32个向量输出
input_size=784
hidden_size =32
output_size =784
定义神经网络的layer
# 输入层 encode
input = tf.keras.layers.Input(shape=(input_size,))# 输入神经网络的尺寸 定义一个输入层
en = tf.keras.layers.Dense(hidden_size,activation='relu')(input)#编码器的输出层
#decode 输入en 输出尺寸output_size进行解码
de =tf.keras.layers.Dense(output_size,activation='sigmoid')(en)#dense全连接层
#定义一个模型 定义输入输出
model = tf.keras.Model(inputs=input,outputs=de)
model.summary()#查看网络层结构
tf.keras.utils.plot_model(model, show_shapes=True)#可视化网络结构
对网络进行编译,设置参数
model.compile(optimizer='adam',#优化算法
loss='mse')#均方差
type(x_train)
进行训练
model.fit(x_train,x_train,
epochs=50,
batch_size=256,
shuffle=True,
validation_data=(x_test,x_test)
)
# 查看层数
model.layers
#[<tensorflow.python.keras.engine.input_layer.InputLayer at 0x1ffd2eb6908>,
# <tensorflow.python.keras.layers.core.Dense at 0x1ffd2eb66c8>,
# <tensorflow.python.keras.layers.core.Dense at 0x1ffd2f07e48>]
以下对上述过程训练结果进行测试
先定义一个输入模型,对输入数据进行编码
# 输入层
encode = tf.keras.Model(inputs=input, outputs=en)#把上面的encode建立了一个模型
定义一个输出模型,对输入数据进行解码
#解码 输入decode
input_de=tf.keras.layers.Input(shape=(hidden_size,))#定义一个输入网络层
oputput_de=model.layers[-1](input_de)#-1指用model最后一层训练好的网络
decode = tf.keras.Model(inputs=input_de, outputs=oputput_de)#定义一个(解码)输出模型
#decode = tf.keras.Model(inputs=input_de, outputs=de)不可行
进行输入编码
encode_test = encode(x_test)数据输入模型
encode_test.shape查看数据变化
#TensorShape([10000, 32])未编码前是(10000, 784))是numpy类型数据。
把编码过的数据输入解码器解码
decode_test=decode.predict(encode_test)
decode_test.shape#(10000, 784)对数据进行了还原
#是numpy数据,用plt绘画的话,reshape要把数据转变为numpy才可以
对数据进行显示对比
n=10#显示十张图片
x_test = x_test.numpy()#把tensor数据转变为numpy数据
# numpy转tensor方法为:tensor_data = tf.cast(numpy_data, dtype=tf.float32)#numpy转张量
plt.figure(figsize =(20, 4))#设定画布
for i in range(1, n):
ax = plt.subplot(2, n, i )
plt.imshow(x_test[i].reshape(28,28))#必须是numpy数据才能进行reshape
ax = plt.subplot(2, n, i + n )
plt.imshow(decode_test[i].reshape(28,28))
结果如下