浅度自编码器(基于深度学习深层自编码器)
浅度自编码器(基于深度学习深层自编码器)(train_X train_y) (test_X test_y) = mnist.load_data() train_X = train_X.astype('float32') / 255. test_X = test_X.astype('float32') / 255. print('X_train: ' str(train_X.shape)) print('Y_train: ' str(train_y.shape)) print('X_test: ' str(test_X.shape)) print('Y_test: ' str(test_y.shape)) for i in range(3): plt.subplot(1 3 i 1) p
本文介绍了使用自动编码器对语音信号进行降噪,不会涉及数学细节,只给一个初步了解。
自编码器是一种简单的人工神经网络 (ANN),经过训练可以学习输入数据的编码表示,这种无监督机制不需要标签。自编码器由两个神经网络组成,前半部分称为编码器,后半部分称为解码器。两个神经网络都由具有激活函数的单个或多个隐藏层组成。编码器和解码器的隐藏层数量通常是对称的,以确保输出的维度与输入的维度一致,如下图所示。
编码器获取输入数据,从数据中学习重要特征并输出输入的向量表示。编码器利用卷积/或最大池层以降低输入数据的维度。
与编码器不同,解码器将低维数据扩展到高维。误差函数一般如下
误差用于反向传播以更新解码器和编码器的隐藏层中的权重等参数。一般自编码器可用于数据降维,也可应用于异常检测和机器翻译中,本文将重点介绍可用于信号降噪的自编码器,首先看一下自编码器降噪的一种信号。
实际上,信号可以是声学、电磁射频、图像/视频等信号,在本文中将重点研究语音声学信号,输入时为了便于理解,将一维声学信号转换为梅尔谱图。
在本实验中,主要使用 `librosa` 和 `soundfile` 模块进行声学处理,`tensorflow` 和 `keras` 模块用于训练自编码器。首先导入相关模块:
import os
import matplotlib
import pylab
import librosa
import librosa.display
import soundfile as sf
import numpy as np
import matplotlib.pyplot as plt
import keras
from keras.datasets import mnist
from keras.layers import Dense Flatten Reshape Input InputLayer
from keras.models import Sequential Model
from keras.layers import Conv2D MaxPooling2D Conv2DTranspose
from tqdm.keras import TqdmCallback
import tensorflow as tf
from keras.backend import clear_session
首先我们先用简单的MNIST数据集搞一下
(train_X train_y) (test_X test_y) = mnist.load_data()
train_X = train_X.astype('float32') / 255.
test_X = test_X.astype('float32') / 255.
print('X_train: ' str(train_X.shape))
print('Y_train: ' str(train_y.shape))
print('X_test: ' str(test_X.shape))
print('Y_test: ' str(test_y.shape))
for i in range(3):
plt.subplot(1 3 i 1)
plt.imshow(train_X[i] cmap=plt.get_cmap('gray'))
X_train: (60000 28 28) Y_train: (60000 ) X_test: (10000 28 28) Y_test: (10000 )
在MNIST数据集中添加一些椒盐噪声
noise_factor = 0.2
train_X_noisy = train_X noise_factor * tf.random.normal(shape=train_X.shape)
test_X_noisy = test_X noise_factor * tf.random.normal(shape=test_X.shape)
train_X_noisy = tf.clip_by_value(train_X_noisy clip_value_min=0. clip_value_max=1.).numpy()
test_X_noisy = tf.clip_by_value(test_X_noisy clip_value_min=0. clip_value_max=1.).numpy()
查看一下带噪图像
n = 10
plt.figure(figsize=(20 2))
for i in range(n):
ax = plt.subplot(1 n i 1)
plt.title("original noise")
plt.imshow(tf.squeeze(test_X_noisy[i]))
plt.gray()
plt.show()
接下来构建自编码器
def build_autoencoder(img_shape code_size):
# 编码器
encoder = Sequential()
encoder.add(InputLayer(img_shape))
encoder.add(Flatten())
encoder.add(Dense(code_size activation='relu'))
# 解码器
decoder = Sequential()
decoder.add(InputLayer((code_size )))
decoder.add(Dense(np.prod(img_shape)))
decoder.add(Reshape(img_shape))
return encoder decoder
IMG_SHAPE = train_X[0].shape
encoder decoder = build_autoencoder(IMG_SHAPE 1000)
inp = Input(IMG_SHAPE)
code = encoder(inp)
reconstruction = decoder(code)
autoencoder = Model(inp reconstruction)
autoencoder.compile(optimizer='adamax' loss='mse')
print(autoencoder.summary())
开始训练
history = autoencoder.fit(x=train_X_noisy y=train_X epochs=30
validation_data=[test_X_noisy test_X])
看一下训练过程
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train' 'test'] loc='upper left')
plt.show()
带噪图像与重建后的图像
img = train_X_noisy[0]
code = encoder.predict(img[None])[0]
reco = decoder.predict(code[None])[0]
plt.subplot(1 2 1)
plt.title("Noise")
plt.imshow(img)
plt.subplot(1 2 2)
plt.title("Reconstructed")
plt.imshow(reco)
接下来我们进行语音信号的降噪
首先导入语音信号
sig fs = librosa.load('./audio/hello.wav')
save_path = 'hello.jpg'
pylab.axis('off')
pylab.axes([0. 0. 1. 1.] frameon=False xticks=[] yticks=[])
M = librosa.feature.melspectrogram(y=sig sr=fs)
librosa.display.specshow(librosa.power_to_db(M ref=np.max))
pylab.savefig(save_path bbox_inches=None pad_inches=0)
pylab.close()
看一下Mel谱谱图
plt.figure()
librosa.display.specshow(librosa.power_to_db(M ref=np.max))
plt.colorbar()
将Mel谱转换回幅度谱图,并将其保存为 wav 文件
S = librosa.feature.inverse.mel_to_stft(M)
y = librosa.griffinlim(S)
sf.write('./audio/reconstructed_hello.wav' y fs)
在Mel谱中加入椒盐噪声
from skimage.util import random_noise
noise_img = random_noise(M mode='s&p' amount=0.2)
noise_img = np.array(255*noise_img dtype = 'float32')
带噪谱图
plt.figure()
librosa.display.specshow(librosa.power_to_db(noise_img ref=np.max))
plt.colorbar()
train_x = noise_img[np.newaxis : :]
train_y = M[np.newaxis : :]
建立多层自编码器
def build_autoencoder(img_shape code_size):
# 编码器
encoder = Sequential()
encoder.add(InputLayer(img_shape))
encoder.add(Flatten())
encoder.add(Dense(code_size activation='relu'))
encoder.add(Dense(code_size activation='relu'))
# 解码器
decoder = Sequential()
decoder.add(InputLayer((code_size )))
encoder.add(Dense(code_size activation='relu'))
decoder.add(Dense(np.prod(img_shape))) # np.prod(img_shape) is the same as 32*32*3 it's more generic than saying 3072
decoder.add(Reshape(img_shape))
return encoder decoder
IMG_SHAPE = train_x[0].shape
encoder decoder = build_autoencoder(IMG_SHAPE 1000)
inp = Input(IMG_SHAPE)
code = encoder(inp)
reconstruction = decoder(code)
autoencoder = Model(inp reconstruction)
autoencoder.compile(optimizer='adamax' loss='mse')
开始训练
history = autoencoder.fit(x=train_x y=train_y epochs=100)
可视化
img = noise_img
code = encoder.predict(img[None])[0]
reco = decoder.predict(code[None])[0]
plt.subplot(1 3 1)
plt.title("Noise")
plt.imshow(img)
plt.subplot(1 3 2)
plt.title("Actual")
plt.imshow(M)
plt.subplot(1 3 3)
plt.title("Reconstructed")
plt.imshow(reco)
还可以重构回时域
# recon_S = librosa.feature.inverse.mel_to_stft(reco*255)
# recon_y = librosa.griffinlim(recon_S)
# # write output
# sf.write('reconstructed_noise_hello.wav' recon_y fs)
哈哈,还可以试试猫/狗的语音信号降噪
此外,还可以利用卷积自动编码器对猫/狗的语音信号降噪
后续会讲解
基于自编码器的语音信号降噪 - 哥廷根数学学派的文章 - 知乎 https://zhuanlan.zhihu.com/p/556513015