Hello,又是一个分享的日子,上期博主介绍了巨人肩膀上的迁移学习(2)---图像回归,并介绍了图像在进入神经网络前的预处理工作。今天博主给大家分享的是深度学习的压缩去噪利器---自编码器(AutoEncoder)。
这一期我们将分别利用CNN卷积神经网路和BP神经网络去搭建4种自编码器。博主也在往期的推文中也介绍了CNN卷积神经网络和BP神经网路的原理,还不熟悉CNN卷积神经网络原理的小伙伴可以翻一下:什么?卷积层会变胖?人工智能之光---CNN卷积神经网络(原理篇),深度学习开端---BP神经网络,这里博主就不进行过多的赘述了。
本文内容概要:
1.自编码器原理
2.多层自编码器
3.卷积自编码器
4.正则自编码器
4.1稀疏自编码器
4.2去噪自编码器
自编码器
原理
自编码器是由nathan hubens提出的一种输入等于输出的神经网络模型,可能大家会疑惑为什么要训练一个这样的模型,毕竟输入等于输出在大家看来就是一件多此一举的事情。这里博主先给大家上一个模型图让大家感受一下。
上图是由BP神经网络组成的最简单的自编码器,只有三层结构,中间的隐藏层才是我们所需要关注的地方,以隐藏层为界限,左边为编码器(encoder), 右边为解码器(decoder),所以在训练过程中,输入才能在经过编码后再解码,还原成原来的模样。
对传统机器学习有所了解的小伙伴应该都知道PCA(主成分分析),它是用来对数据进行降维的。不了解的小伙伴也没关系,我们现在学习的自编码器也有这个功能,所以学完之后再看PCA兴许会理解地更加深刻些。
现在我们看回上图,假如我们通过一组数据训练出了我们的自编码器,然后我们拆掉自编码器的解码器(decoder),就可以用剩下的编码器(encoder)来表征我们的数据了。隐藏层的神经元数目远低于输入层,那么就相当于我们用更少的特征(神经元)去表征我们的输入数据,从而达到降维压缩的功能。
接着,我们在文章开头提到过自编码器还有降噪的功能,那它是如何实现这个功能的呢?在此之前博主先给大家介绍下这期使用的数据集----minist手写体,这是keras自带的数据集,如下图。
这个数据集就是手写数字0~9的图像集合,上图第一行就是加噪后的手写体数据集,第二行则是原本的手写体数据集。我们把加噪后的数据集当成输入,原本的数据集当做输出,训练一个自编码器,让它在训练过程中学习数据的规律,从而把噪声去掉。这就是博主所说的去噪功能。
到这里,博主就已经把自编码器的原理和功能给大家讲清楚了。接下来,我们更进一步介绍几种有用的自编码器。
普通自编码器:就是文章开头讲的最简单的自编码器。
多层自编码器:多个BP神经网络隐藏层组成自编码器。
卷积自编码器:由CNN卷积神经网络组成的自编码器
正则自编码器
4.1稀疏自编码器:稀疏自编码器就是普通自编码器的隐藏层加一个L1正则项,也就是一个训练惩罚项,这样我们训练出的编码器(encoder)表征的特征更加的稀疏,从而能得到少且有用的特征项。这也是为啥用L1正则项而不用L2正则项的原因。至于L1,L2正则项的原理,博主在之前的推文码前须知---TensorFlow超参数的设置有提及,还不熟悉的小伙伴可以去翻阅一下。
4.2降噪自编码器:降噪自编码器就是输入换成了加噪的数据集,输出用原数据集去训练的自编码器,目的是习得降噪功能。
实验
实验环境
Anaconda Python 3.7
Jupyter Notebook
Keras
开发环境安装在之前的推文中已经介绍,还没安装的小伙伴可以翻一下。
Python开发环境---Windows与服务器篇
Python深度学习开发环境---Keras
实验流程
加载图像数据
图像数据预处理
构建自编码器模型
训练模型
查看模型编解码效果
训练过程可视化
代码
普通自编码核心代码
input_size = 784
hidden_size = 128
code_size = 64
x = Input(shape=(input_size,))
h = Dense(hidden_size, activation='relu')(x)
r = Dense(output_size, activation='sigmoid')(h)
autoencoder = Model(inputs=x, outputs=r)
autoencoder.compile(optimizer='adam', loss='mse')
多层自编码核心代码
input_size = 784
hidden_size = 128
code_size = 64
x = Input(shape=(input_size,))
hidden_1 = Dense(hidden_size, activation='relu')(x)
h = Dense(code_size, activation='relu')(hidden_1)
hidden_2 = Dense(hidden_size, activation='relu')(h)
r = Dense(input_size, activation='sigmoid')(hidden_2)
autoencoder = Model(inputs=x, outputs=r)
autoencoder.compile(optimizer='adam', loss='mse')
其中, fi是模型预测值,yi是实际值,通过计算两者的均方误差来衡量模型的有效性。
卷积自编码器核心代码
x = Input(shape=(28, 28,1))
# 编码器
conv1_1 = Conv2D(16, (3, 3), activation='relu', padding='same')(x)
pool1 = MaxPooling2D((2, 2), padding='same')(conv1_1)
conv1_2 = Conv2D(8, (3, 3), activation='relu', padding='same')(pool1)
pool2 = MaxPooling2D((2, 2), padding='same')(conv1_2)
conv1_3 = Conv2D(8, (3, 3), activation='relu', padding='same')(pool2)
h = MaxPooling2D((2, 2), padding='same')(conv1_3)
# 解码器
conv2_1 = Conv2D(8, (3, 3), activation='relu', padding='same')(h)
up1 = UpSampling2D((2, 2))(conv2_1)
conv2_2 = Conv2D(8, (3, 3), activation='relu', padding='same')(up1)
up2 = UpSampling2D((2, 2))(conv2_2)
conv2_3 = Conv2D(16, (3, 3), activation='relu')(up2)
up3 = UpSampling2D((2, 2))(conv2_3)
r = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(up3)
autoencoder = Model(inputs=x, outputs=r)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
UpSampling2D:上采样层,与MaxPooling2D相对应。
稀疏自编码器核心代码
input_size = 784
hidden_size = 32
output_size = 784
x = Input(shape=(input_size,))
h = Dense(hidden_size, activation='relu', activity_regularizer=regularizers.l1(10e-5))(x)
r = Dense(output_size, activation='sigmoid')(h)
autoencoder = Model(inputs=x, outputs=r)
autoencoder.compile(optimizer='adam', loss='mse')
去噪自编码器核心代码
x = Input(shape=(28, 28, 1))
# 编码器
conv1_1 = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
pool1 = MaxPooling2D((2, 2), padding='same')(conv1_1)
conv1_2 = Conv2D(32, (3, 3), activation='relu', padding='same')(pool1)
h = MaxPooling2D((2, 2), padding='same')(conv1_2)
# 解码器
conv2_1 = Conv2D(32, (3, 3), activation='relu',padding='same')(h)
up1 = UpSampling2D((2, 2))(conv2_1)
conv2_2 = Conv2D(32, (3, 3), activation='relu', padding='same')(up1)
up2 = UpSampling2D((2, 2))(conv2_2)
r = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(up2)
autoencoder = Model(inputs=x, outputs=r)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
epochs = 3
batch_size = 128
history = autoencoder.fit(X_train_noisy, # 加噪数据集
X_train, # 原数据集
batch_size=batch_size,
epochs=epochs, verbose=1,
validation_data=(X_test_noisy, X_test))
参数
Dense: 全连接层。
CNN2D:2维卷积神经网络,常用于处理图像。
Dropout: 以一定概率放弃两层之间的一些神经元链接,防止过拟合,可以加在网络层与层之间。
optimizer: 优化器,梯度下降的优化方法
这些都在之前的推文中有所介绍,小伙伴们可以去翻阅一下。
码前须知---TensorFlow超参数的设置
activation: 激励函数,‘linear’一般用在回归任务的输出层,而‘softmax’一般用在分类任务的输出层。
validation_split: 切分一定比例的训练集作为验证集
epochs 与 batch_size:前者是迭代次数,后者是用来更新梯度的批数据的大小,iteration = epochs / batch_size, 也就是完成一个epoch需要跑多少个batch。这这两个参数可以用控制变量法来调参,控制一个参数,调另外一个,看损失曲线的变化。
小伙伴们可以去keras官网查看更多的参数含义与用途,博主也会在后续的课程中通过实验的方法将这些参数涉及进来,让大家的知识点串联起来。
Keras官网
https://keras.io/
Git链接
代码
https://github.com/ChileWang0228/DeepLearningTutorial/blob/master/AutoEncoder/AutoEncoder.ipynb
训练结果
普通自编码器
解码效果
训练过程
训练过程
训练过程
去噪自编码器
解码效果
训练过程
代码实践视频
视频卡顿?bilibili值得拥有~(っ•̀ω•́)っ✎⁾⁾ 我爱学习
https://www.bilibili.com/video/av61286570/
总结
好了,到这里,我们就已经将自编码器的知识点讲完了。大家在掌握了整个流程之后,就可以在博主的代码上修修补补,训练自己的自编码器模型了。
下一期,博主给大家介绍常见的激励函数和损失函数,敬请期待吧~
如果本期推文有用,那就点个赞吧,你们的点赞是博主持续更新的动力,感谢每一位小伙伴的关注~
图片来源于网络,侵删
留言