4. 稀疏自编码
假设我们只有一个没有类别标签的训练样本集合{x(1),x(2)...},一个自编码神经网络就是一种非监督学习算法,它使用BP算法,并将目标值设为: y(i)=x(i)。
我们的目标是希望得到hW,b(X)≈x。用aj(2)(x)表示输入向量x对隐藏层单元j的激活值。则j的平均激活值:
为了达到稀疏性,也即用最少(最稀疏)的隐藏单元来表示输入层的特征(也即,对每一个输入X, 其特征表示是稀疏的),我们希望所有隐藏层单元平均激活值接近于0.于是应用KL距离:
其中为了方便书写:
其中,
是稀疏参数,一般来说选一个很小的数,如0.05。
这样,神经网络整体代价函数就可以表示为:
,其中J(W,b)是BP自身的损失函数,预测损失+参数L2正则(减小权重的幅度,防止过度拟合)
这样,一个稀疏自编码器就完成了。
代码:
Sparse自编码 Autoencoder, 基本按照标准公式实现##### 设置网络参数 #####
p = 0.05 # 使大部分神经元的激活值(所有神经元的激活值的平均值)接近这个p值
beta = 3 # 控制KL散度所占的比重input_dim = 784
encoding_dim = 64
lambda_val = 0.001 # J(W,b)自带的对W进行的L2正则,weight decayepochs = 50
batch_size = 1024# 自定义正则项函数, 计算KL散度
def sparse_reg(activity_matrix):activity_matrix = K.softmax(activity_matrix, axis=0) # 把激活值先用softmax归一化p_hat = K.mean(activity_matrix, axis=0) # 将第j个神经元在batch_size个输入下所有的输出激活值取平均print('p_hat=', p_hat)KLD = p*(K.log(p/p_hat))+(1-p)*(K.log((1-p)/(1-p_hat))) # 计算KL散度print('KLD=', KLD)return beta*K.sum(KLD) # 所有神经元的KL散度相加并乘以betainput_img = Input(shape=(input_dim,))h = Dense(encoding_dim,activation='relu',kernel_regularizer=regularizers.l2(lambda_val/2),activity_regularizer=sparse_reg)(input_img)r = Dense(input_dim, activation='sigmoid',kernel_regularizer=regularizers.l2(lambda_val/2),activity_regularizer=sparse_reg)(h)# sparse AE模型
autoencoder = Model(inputs=input_img, outputs=r)
autoencoder.compile(optimizer='adam', loss='binary_crossentropy')
#输出模型结构
print(autoencoder.summary())# 注意:输出是干净的X_train
history = autoencoder.fit(X_train, X_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(X_test, X_test))#编码过程: 取出编码部分
conv_encoder = Model(input_img, h)
#在测试集上进行编码输出,输出图形的编码形式(64维度)
encoded_imgs = conv_encoder.predict(X_test)n = 10
plt.figure(figsize=(20, 8))
for i in range(n):ax = plt.subplot(1, n, i+1)plt.imshow(encoded_imgs[i].reshape(4, 16).T)plt.gray()ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)
plt.show()#解码过程:
#Predict on the test set
decoded_imgs = autoencoder.predict(X_test)
生成的编码图像(64维)
变稀疏了吗?