基于LSTM的语音分类(原理加代码)

目录

1、实现目标

原始数据为200个音频文件,分别为真实人说话的声音,和机器合成的声音。
实现目标为成功将两种声音进行分类。

此贴记录了,实现的整个流程包括每一部分的代码以及背后的数学原理和方法的简介,以及每一部分出现的问题和坑点解决办法以及我的一些理解和疑惑。

希望这个帖子可以给做LSTM网络的朋友们一些参考。

2、数据读取

读取音频文件,并将音频文件转换成mfcc特征

import scipy.io.wavfile as wav
import librosa
from python_speech_features import mfcc
"""
librosa和python_speech_features是语音识别领域最常用的两个包,但是librosa的速度相对比较慢,尤其在读取音频数据上,并且要慢不少,而wav.read比较快然而会报错,主要的一个错误是下面这个:
ValueError: Incomplete wav chunk.
查了一下这个主要是wav是经过后期格式转换或者处理过的情况,导致文件wav文件信息不完整,总之这里会报错。网上给的解决办法是将WAV文件转换成PCM文件,或者使用librosa读取。

这里我使用了一个异常处理的语句,首先使用更快的wav.read()方法读取文件,如果报错则转换为librosa.load()方法。

python_speech_features.mfcc主要用于将音频转换成mfcc特征。
python_speech_features.base.mfcc(signal, samplerate=16000, winlen=0.025, winstep=0.01, numcep=13, nfilt=26, nfft=512, lowfreq=0, highfreq=None, preemph=0.97, ceplifter=22, appendEnergy=True, winfunc=<function <lambda>>)
同样的使用librosa.features.mfcc也可以提取mfcc特征
librosa.features.mfcc(y=None,sr=22050,S=None,n_mfcc=20,dct_type=2,norm='ortho',**kwargs)
"""
def def_wav_read_mfcc(file_name):
    try:
        fs, audio = wav.read(file_name)
        # return fs:采样频率, data:数据
        processed_audio = mfcc(audio, samplerate=fs, nfft = 2048)
    except ValueError:
        audio, fs = librosa.load(file_name)
        # return y:数据, sr:采样频率
       	"""
       	load(
    	path,
    	sr=22050,
    	mono=True,
    	offset=0.0,
    	duration=None,
    	dtype=np.float32,
    	res_type="kaiser_best",
			):
        """
        processed_audio = mfcc(audio, samplerate=fs, nfft = 2048)
    return processed_audio

关于MFCC:
1、什么是MFCC?
MFCC:Mel频率倒谱系数(Mel Frequency Cepstrum Coefficient,MFCC)的缩写.Mel频率是基于人耳听觉特性提出来的,它与Hz频率成非线性对应关系.Mel频率倒谱系数(MFCC)则是利用它们之间的这种关系,计算得到的Hz频谱特征。

2、MFCC的过程和步骤?
这个网上有太多太多讲解了,详情请移步:
语音识别——MFCC理解
MFCC过程

3、为什么要将语音信息的时间序列转换成MFCC序列?
学过《信号与系统》的都知道一般对于连续时间信号处理的时候都会对其进行傅里叶变换转换成频域的信号进行处理。转换到频域中进行处理是为了便于对信号进行分析和处理。至于这个是为什么,详见《信号与系统》;
个人的理解MFCC就是先将时间序列分割成一小段一小段的状态,然后再在每一段进行nfft然后在频域进行处理最后提取出特征;
形象一点说明,就类似:语音“hello”,将一个hello在时间维度上拆解成单音音素,h,e,l,l,o(当然每个音节长度肯定不是一样的,这里只是方便说明将其拆解成五个音素,实际上每个音素之间还由重叠的部分,因此MFCC的帧移也都是1/3或者1/2存在一定的重叠。),对于这五个因素,对于“h”这一段因素进行傅里叶变换,然后再在频域对其进行分析。

下面是mfcc函数中内部每个param的注解,以及函数的api

def mfcc(signal,
		# 用来计算特征的音频信号,应该是一个N*1的数组
		samplerate=16000,
		# 音频的采样率
		winlen=0.025,
		# 分析窗口的长度,以秒为单位,默认值是0.025秒(25毫秒)
		winstep=0.01,
		# 连续窗口之间的步长(以秒为单位),缺省值是0.01秒(10毫秒)
		numcep=13,
		# 返回的倒频谱数,默认为13
        nfilt=26,
        # 过滤器数量,默认为26。
        nfft=512,
        # FFT的大小,默认是512。
        lowfreq=0,
        # MEL滤波器的最低带边。以Hz为单位,默认为0。
        highfreq=None,
        # MEL滤波器的最高带边。以Hz为单位,默认为samplerate/2
        preemph=0.97,
        # 采用以preemph为系数的预强调滤波器。0是无滤波器。默认是0.97。
        ceplifter=22,
        # 对最终倒谱系数应用一个提升器。默认是22。
        appendEnergy=True,
        # 如果这是真的,第0倒谱系数就被替换为总坐标系能量的对数。
        winfunc=lambda x:numpy.ones((x,)))
        # 应用到每一帧的分析窗口。默认情况下不应用任何窗口。可以在这里使用numpy窗口函数,例如winfunc=numpy.hamming

		return feat

函数最后返回的是频率信号的特征。

举个例子,原来的信号是[x1,x2,…xn]
经过MFCC后的信号应该是 [ [f11,f12,…,f113], [f21,f22,…,f213]…[fm1,fm2,…,fm13] ] 的形式
这里m应该取决于你原来信号中n的大小,原来信号的采样频率和分析窗口的长度的大小,以及帧移等参数。例如:本文所使用的wav文件。

读取后长度为22k的采样率,大约400w的数据,双声道,经过MFCC转换后,变成了一个(18188. 13)的特征序列。

具体计算过程移步:
MFCC特征提取详细计算过程

3、数据预处理

预读取数据

在训练过程需要获取数据,训练数据的加载方法通常有两种,其一是形如样本集比较小的情况,可以先将数据全部加载,再进行训练,另外一种是一个batch加载,加载一个完毕后训练再加载,这种方式无论多少数据,只要设置batch合适就不会出现内存不够用的情况,也不会报错。

def get_batch_for_train(label):
    Wav = []
    for j in range(200):
        wav = gf.def_wav_read_mfcc(data[j])
        # 将音频信号转换成mfcc的格式
        wav1 = wav[:10000]
        # 为了保证输入数据一样大小,只取读取音频转换成mfcc后前10000个数据
        # print(wav1,i)
        Wav.append(wav1)
        print("Conversion to MFCC:",j+1)
    label_for_train = label[0:199]
    return Wav, label_for_train
label = []
# label为外部手动标注后,csv文件导入
Wav,label_for_train = get_batch_for_train(label)

这里label是一个二维数组,里面对应200个一维数组,其中1代表音频为真人,0代表合成音。为了保证输入训练集的数据格式一致,取MFCC序列前10000个作为作为训练数据。

因为只是简单的分类,这里 label 是手动标注的然后储存再一个csv文件中,对应文件在文件夹的顺序。所以没有音频的 label 的抽取过程,关于如何给音频标注并且抽取label的方法请移步:

praat使用入门演示
结合Praat进行语音实验的步骤
根据标注区域提取需要部分的语音特征参数

上面演示的帖子用的HTK,个人推荐用praat。

LSTM参数设定

基本的LSTM参数设定,没必要再提。

n_inputs = 13
# 输入一行,一行有13个数据,是由mfcc变换得到的
max_time = 10000
# 每个训练数据取前10000个向量作为训练数据
lstm_size = 78
# 隐层单元
n_classes = 1
# 预测1个值
batch_size = 20
# 每批次1个样本
n_batch = len(Wav) // batch_size
# 计算一共有多少个批次
nums_samples = len(Wav)
n = 10000

数据预处理

# 对原始的mfcc数据进行归一化
for i in range(len(Wav)):
    scaler = MinMaxScaler(feature_range=(0, 1))
    Wav[i] = scaler.fit_transform(Wav[i])
    print("scaler:",i)
for i in range(len(Wav)):
    Wav[i] = Wav[i].tolist()
# 生成的 Wav[] 里面放的是 array(15000×13)因此用循环将向量转换成列表
Wav_tensor = tf1.convert_to_tensor(Wav)
label_tensor = tf1.convert_to_tensor(label_for_train)
print("Success construct Wav_tensor")

为什么要对MFCC序列进行归一化?
归一化是大多数深度学习都需要进行的一个步骤。

归一化后加快了梯度下降求最优解的速度且有可能提高训练出模型的精度。
如果不进行归一化,对于训练数据结果可能是很准确的,但是每次的测试效果并不好。同时,收敛速度很慢。

对于语音信号,转换成MFCC特征序列后,对各个维度进行均值归一化会起到信道补偿的作用。消除不同声音信号由于幅值,干扰等因素而造成过拟合的或者训练较慢。
关于语音信号信道补偿方面的知识有兴趣的可以查看论文。
常用的归一化方法?
1、min-max标准化(Min-Max Normalization)
对原始数据的线性变换,使结果值映射到[0 - 1]之间
在这里插入图片描述
2、Z-score标准化方法
原始数据的均值(mean)和标准差(standard deviation)进行数据的标准化。经过处理的数据符合标准正态分布,即均值为0,标准差为1。
在这里插入图片描述
关于不同归一化方法和该方法的优缺点,详见下表:
在这里插入图片描述
图片来自知乎匿名用户
其实大多数语音信号处理MFCC后接归一化一般都是Min-Max方法。甚至大多数循环神经网络进行训练的数据使用的归一化方法都是Min-Max方法

获取数据集
这一部分没什么好说的,标准操作。

x_batch, y_batch = get_batch(Wav_tensor, label_tensor, batch_size)
# 生成每一个批次用于训练的数据集
x_batch_test, y_batch_test = get_batch(Wav_tensor, label_tensor, 100)
# 生成每一个批次用于测试的数据集
x_batch = tf1.convert_to_tensor(x_batch)
y_batch = tf1.convert_to_tensor(y_batch)
x = tf1.placeholder(tf1.float32, [None, 10000, 13])
y = tf1.placeholder(tf1.float32, [None, 1])

4、LSTM网络

def lstm_model(X, weights, biases):
    inputs = tf1.reshape(X, [-1, max_time, n_inputs])
    lstm_cell_1 = tf.keras.layers.LSTMCell(lstm_size)
    outputs_1, final_state_1= tf1.nn.dynamic_rnn(lstm_cell_1, inputs, dtype=tf1.float32)
    lstm_cell_2 = tf.keras.layers.LSTMCell(lstm_size)
    outputs_2, final_state_2= tf1.nn.dynamic_rnn(lstm_cell_2, outputs_1, dtype=tf1.float32)
    lstm_cell_3 = tf.keras.layers.LSTMCell(lstm_size)
    outputs_3, final_state_3= tf1.nn.dynamic_rnn(lstm_cell_3, outputs_2, dtype=tf1.float32)
    lstm_cell_4 = tf.keras.layers.LSTMCell(13)
    outputs, final_state= tf1.nn.dynamic_rnn(lstm_cell_4, outputs_3, dtype=tf1.float32)
    result = tf.nn.sigmoid(tf1.matmul(final_state[0], weights) + biases)
    return result
weights = tf1.Variable(tf1.truncated_normal([13, n_classes], stddev=0.1))
biases = tf1.Variable(tf1.constant(0.1, shape=[n_classes]))
prediction = lstm_model(x,weights,biases)

我设定的LSTM网络是一个四层的网络。LSTM网络中需要设置的最主要的参数为每个节点的单元数,和LSTM网络的层数。

关于层数

对于一个LSTM网络,通常为1~4层,对于比较复杂的信息,可以采用3/4层的网络结构。但是层数越多可能效果反而不好,例如,对于本文所涉及的音频信号,使用三层网络训练500轮后的准确率达到93%,而四层网络经过500轮训练后准确率只有86%。

关于网络层数选择问题一般网上给出的答案都是通过经验一点一点调整。

我的建议是对于比较复杂的信息,可以先构建一个两层的看看效果,再试试三层的网络;而对于不是很复杂的信息,可以直接使用单层的LSTM网络观察下效果

关于节点

每一层LSTM网络都要设定单元数,这个参数通常也是通过经验来选取,网上并没有太好的系统性的办法选择这个参数,看了不少帖子加上自己的尝试,最好设定每一层的单元数为输入数据维数的二倍或者四倍,以这个为基准逐渐测试调整。这里我的每一层单元数选择为78,输入MFCC为13,78为13的六倍。单元数越多,训练速度越慢,同时也不能保证一定提高训练模型的精度和准确度。我还测试了单元数为52和26的网络,经过500轮训练准确度分别为89%和85%(当然一次训练结果也不能说明什么,而且500轮的时候也没有完全收敛)。

关于网络结构

tf.keras.layers.LSTMCell(unit)

这个api是构建 LSTM 网络基本结构 cell 的函数。
每一层可以定义一个 cell,对于一个四层的网络就可以定义四个 cell。定义的 cell 只是一个单独的静态的节点。
需要使用

tf1.nn.dynamic_rnn(lstm_cell_1, inputs, dtype=tf1.float32)

进行迭代,将整个序列循环输入,该函数输出结果为outputs 和 final_state,分别为输入的每一个序列经过 LSTM_CELL 的值,也就是LSTM原理图中的 ht

5、网络优化训练方法

cross_entropy = tf1.reduce_mean(tf1.square(y - prediction))
# 使用AdamOptimizer进行优化
train_step = tf1.train.AdamOptimizer(1e-3).minimize(cross_entropy)
correct_prediction = tf1.equal(y,tf.round(prediction))#argmax返回一维张量中最大的值所在的位置
# 求准确率
accuracy = tf1.reduce_mean(tf1.cast(correct_prediction,tf1.float32))#把correct_prediction变为float32类型
# 初始化
# model.fit(x_batch,y_batch,epochs=epochs,batch_size = batch_size)
# loss_and_metrics = model.evaluate(x_batch_test,y_batch_test)
# print(loss_and_metrics)
init = tf1.global_variables_initializer()
config = tf1.ConfigProto()
config.gpu_options.allocator_type = "BFC"
saver = tf1.train.Saver()
with tf1.Session() as sess:
    with tf1.device('/gpu:0'):
        sess.run(init)
        loss = []
        checkpoint_steps = 100
        for i in range(400):
            x_batch_data = sess.run(x_batch)
            y_batch_data = sess.run(y_batch)
            x_batch_test_data = sess.run(x_batch_test)
            y_batch_test_data = sess.run(y_batch_test)
            sess.run(train_step, feed_dict={x: x_batch_data, y: y_batch_data})
            # 进行学习
            # 本次学习的数据
            pred_X1 = sess.run(prediction, feed_dict={x: x_batch_data})
            # 预测模型输入测试数据获得的结果
            # pred_X = sess.run(prediction, feed_dict={x: x_batch_test_data})
            # 预测模型输入训练数据获得的结果
            pred_X1 = pred_X1[0]
            pred_X1 = pred_X1[0]
            if pred_X1 >= 0.5:
                print("This sound is True.")
            else:
                print("This sound is False.")
            y_batch_data = y_batch_data[0]
            if y_batch_data[0] >= 0.5:
                y_r = True
            else:
                y_r = False
            print("prediction",i,":",prediction,";  ","real value:",y_batch_data,";  ","test result:",pred_X1)
            print("test results:",pred_X1,";  ","real value:",y_batch_data)
            if (i + 1) % 10 == 0:
                cross_entropy_new = sess.run(cross_entropy,feed_dict={x: x_batch_test_data, y: y_batch_test_data})
                accurace = sess.run(accuracy,feed_dict={x: x_batch_test_data, y: y_batch_test_data})
                loss.append(cross_entropy_new)
                print("accurace:",cross_entropy_new,accurace,"Iteration",i+1)

            if (i + 1) % checkpoint_steps == 0:
                saver.save(sess, "save1/model.ckpt", global_step=i + 1)
                print("Success save.")
    k = len(loss)
    t = []
    for i in range(k):
        t.append(i)
    print(t)
    plt.plot(t, loss, 'k-', label='Data', linewidth=2)
    font1 = {'size': 18}
    plt.legend(loc=4, prop=font1)
    plt.xlabel(u'Iteration', size=24)
    plt.ylabel(u'Loss', size=24)
    plt.show()
    saver.save(sess, "save1/model.ckpt")

6、微调整后全部代码

import tensorflow.compat.v1 as tf1
import tensorflow as tf
from pylab import*
import os
from sklearn.preprocessing import MinMaxScaler
import scipy.io.wavfile as wav
import librosa
from python_speech_features import mfcc
tf1.disable_eager_execution()

def def_wav_read_mfcc(file_name):
    try:
        fs, audio = wav.read(file_name)
        processed_audio = mfcc(audio, samplerate=fs, nfft = 2048)
    except ValueError:
        audio, fs = librosa.load(file_name)
        processed_audio = mfcc(audio, samplerate=fs, nfft = 2048)
    return processed_audio
# 训练数据的文件夹
file_path = r'D:\gongyong\alibaba\test'
# 路径拼接
data = [os.path.join(file_path,i) for i in os.listdir(file_path)]
# 定义每个文件的标签
label = [[0],[0],[0],[0],[0],[0],[0],[1],[1],[0],[0],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[0],[1],[0],[1],[0],[0],[1],[1],[1],[1],[1],[1],[1],[1],[1],[1],[1],[1],[1],[0],[0],[0],[1],[1],[0],[0],[1],[1],[0],[1],[1],[0],[1],[0],[1],[1],[1],[1],[1],[1],[0],[0],[0],[0],[0],[1],[0],[1],[1],[1],[0],[1],[1],[1],[0],[0],[1],[0],[1],[0],[1],[1],[1],[0],[1],[0],[0],[0],[0],[0],[1],[1],[1],[0],[1],[0],[1],[0],[0],[0],[1],[1],[1],[1],[0],[0],[0],[0],[1],[0],[0],[1],[0],[0],[1],[0],[1],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[1],[1],[0],[1],[1],[0],[1],[1],[0],[1],[1],[1],[1],[1],[1],[1],[1],[0],[1],[1],[0],[1],[1],[1],[0],[0],[1],[1],[0],[1],[1],[1],[1],[0],[1],[1],[1],[0],[0],[0],[1],[0],[1],[0],[1],[1],[0],[0],[0],[1],[0],[1],[0],[0],[1],[1],[0],[1],[1],[0],[1],[0],[0],[0],[0]]

def get_batch_for_train(i):
    Wav = []
    for j in range(i,198+i):
        wav = gf.def_wav_read_mfcc(data[j])
        wav1 = wav[:5000]
        Wav.append(wav1)
        print("Conversion to MFCC:",j+1)
    label_for_train = label[i:i+198]
    return Wav, label_for_train
Wav,label_for_train = get_batch_for_train(0)
n_inputs = 13
max_time = 5000
lstm_size = 78
n_classes = 1
batch_size = 20
n_batch = len(Wav) // batch_size
nums_samples = len(Wav)
n = 5000

for i in range(len(Wav)):
    scaler = MinMaxScaler(feature_range=(0, 1))
    Wav[i] = scaler.fit_transform(Wav[i])
# 生成的 Wav[] 里面放的是 array(15000×13)因此用循环将向量转换成列表
for i in range(len(Wav)):
    Wav[i] = Wav[i].tolist()
Wav_tensor = tf1.convert_to_tensor(Wav)
label_tensor = tf1.convert_to_tensor(label_for_train)
print("Success construct Wav_tensor")

def get_batch(data, label, batch_size):
    input_queue = tf1.data.Dataset.from_tensor_slices(data).repeat()
    input_queue_y = tf1.data.Dataset.from_tensor_slices(label).repeat()
    x_batch = input_queue.batch(batch_size)
    y_batch = input_queue_y.batch(batch_size)
    batch_x = tf.compat.v1.data.make_one_shot_iterator(x_batch)
    x_batch = batch_x.get_next()
    batch_y = tf.compat.v1.data.make_one_shot_iterator(y_batch)
    y_batch = batch_y.get_next()
    return x_batch, y_batch

x_batch, y_batch = get_batch(Wav_tensor, label_tensor, batch_size)
x_batch_test, y_batch_test = get_batch(Wav_tensor, label_tensor, 100)
x_batch = tf1.convert_to_tensor(x_batch)
y_batch = tf1.convert_to_tensor(y_batch)

x = tf1.placeholder(tf1.float32, [None, 5000, 13])
y = tf1.placeholder(tf1.float32, [None, 1])

def lstm_model(X, weights, biases):
    inputs = tf1.reshape(X, [-1, max_time, n_inputs])
    lstm_cell_1 = tf.keras.layers.LSTMCell(lstm_size)
    outputs_1, final_state_1= tf1.nn.dynamic_rnn(lstm_cell_1, inputs, dtype=tf1.float32)
    lstm_cell_2 = tf.keras.layers.LSTMCell(lstm_size)
    outputs_2, final_state_2= tf1.nn.dynamic_rnn(lstm_cell_2, outputs_1, dtype=tf1.float32)
    lstm_cell_3 = tf.keras.layers.LSTMCell(lstm_size)
    outputs_3, final_state_3= tf1.nn.dynamic_rnn(lstm_cell_3, outputs_2, dtype=tf1.float32)
    lstm_cell_4 = tf.keras.layers.LSTMCell(13)
    outputs, final_state= tf1.nn.dynamic_rnn(lstm_cell_4, outputs_3, dtype=tf1.float32)
    result = tf.nn.sigmoid(tf1.matmul(final_state[0], weights) + biases)
    return result

weights = tf1.Variable(tf1.truncated_normal([13, n_classes], stddev=0.1))
biases = tf1.Variable(tf1.constant(0.1, shape=[n_classes]))
prediction = lstm_model(x,weights,biases)
cross_entropy = tf1.reduce_mean(tf1.square(y - prediction),name ="cross_entropy" )
train_step = tf1.train.AdamOptimizer(1e-3).minimize(cross_entropy)
correct_prediction = tf1.equal(y,tf.round(prediction))
accuracy = tf1.reduce_mean(tf1.cast(correct_prediction,tf1.float32),name = "accuracy")
init = tf1.global_variables_initializer()
config = tf1.ConfigProto()
config.gpu_options.allocator_type = "BFC"


saver = tf1.train.Saver()
with tf1.Session() as sess:
    with tf1.device('/gpu:0'):
        sess.run(init)
        loss = []
        checkpoint_steps = 100
        for i in range(600):
            x_batch_data = sess.run(x_batch)
            y_batch_data = sess.run(y_batch)
            x_batch_test_data = sess.run(x_batch_test)
            y_batch_test_data = sess.run(y_batch_test)
            sess.run(train_step, feed_dict={x: x_batch_data, y: y_batch_data})
            pred_X1 = sess.run(prediction, feed_dict={x: x_batch_data})
            pred_X1 = pred_X1[0]
            if pred_X1 >= 0.5:
                print("This sound is True.")
            else:
                print("This sound is False.")
            y_batch_data = y_batch_data[0]
            if y_batch_data[0] >= 0.5:
                y_r = True
            else:
                y_r = False
            print("prediction",i,":",prediction,";  ","real value:",y_batch_data,";  ","test result:",pred_X1)
            print("test results:",pred_X1,";  ","real value:",y_batch_data)
            if (i + 1) % 10 == 0:
                cross_entropy_new = sess.run(cross_entropy,feed_dict={x: x_batch_test_data, y: y_batch_test_data})
                accurace = sess.run(accuracy,feed_dict={x: x_batch_test_data, y: y_batch_test_data})
                loss.append(cross_entropy_new)
                print("accurace:",cross_entropy_new,accurace,"Iteration",i+1)

            if (i + 1) % checkpoint_steps == 0:
                saver.save(sess, "save1/model.ckpt", global_step=i + 1)
                print("Success save.")
    k = len(loss)
    t = []
    for i in range(k):
        t.append(i)
    print(t)
    plt.plot(t, loss, 'k-', label='Data', linewidth=2)
    font1 = {'size': 18}
    plt.legend(loc=4, prop=font1)
    plt.xlabel(u'Iteration', size=24)
    plt.ylabel(u'Loss', size=24)
    plt.show()
    saver.save(sess, "save1/model.ckpt")

7、训练结果

实验情况下,训练一共进行了600轮,每次batch_size 为20,总共的训练数据为200个。
首先是一开始的9轮训练结果:

每一轮训练feed 20个训练数据,训练完后会输入一个数据测试这个数据的 prediction 以及数据数据真实信息。我都将其在结果中print出来。

训练中每一个数据的 prediction 以0.5作为阈值(因为是二分类),大于0.5会判定为真,小于0.5会判定为假。

经过9轮训练后会feed一个100个数据的测试数据,用于检测训练准确度(accurace),因为数据有限,所以还是智能从200个数据中选择作为测试数据。

021-06-02 08:29:22.912885: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1102]      0 
2021-06-02 08:29:22.913128: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] 0:   N 
2021-06-02 08:29:22.913543: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1241] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 8778 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1080 Ti, pci bus id: 0000:01:00.0, compute capability: 6.1)
2021-06-02 08:29:41.610405: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library cublas64_10.dll


This sound is True.
prediction 0 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.5203589
test results: 0.5203589 ;   real value: [0]
This sound is True.
prediction 1 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.5219081
test results: 0.5219081 ;   real value: [1]
This sound is True.
prediction 2 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.5224992
test results: 0.5224992 ;   real value: [0]
This sound is True.
prediction 3 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.52283925
test results: 0.52283925 ;   real value: [1]
This sound is True.
prediction 4 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.5214712
test results: 0.5214712 ;   real value: [0]
This sound is True.
prediction 5 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.5196552
test results: 0.5196552 ;   real value: [0]
This sound is True.
prediction 6 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.5223932
test results: 0.5223932 ;   real value: [0]
This sound is True.
prediction 7 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.5223526
test results: 0.5223526 ;   real value: [0]
This sound is True.
prediction 8 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.51998186
test results: 0.51998186 ;   real value: [0]
This sound is True.
prediction 9 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.521213
test results: 0.521213 ;   real value: [1]
accurace: 0.25239557 0.45 Iteration 10

可以看到一开始训练结果很不好,模型经常出错,准确率不足 50%。

......
This sound is True.
prediction 295 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.7635482
test results: 0.7635482 ;   real value: [1]
This sound is False.
prediction 296 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.45773864
test results: 0.45773864 ;   real value: [0]
This sound is False.
prediction 297 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.26252943
test results: 0.26252943 ;   real value: [0]
This sound is True.
prediction 298 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.7385411
test results: 0.7385411 ;   real value: [1]
This sound is False.
prediction 299 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.26162377
test results: 0.26162377 ;   real value: [0]
accurace: 0.17305532 0.79 Iteration 300
......

这是训练进行到300轮的时候得到的结果,可以看到模型已经初步可以分辨出一个声音是否为真实人声所发出,准确率接近 80%。

accurace: 0.06575013 0.94 Iteration 560
This sound is True.

prediction 560 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.91910297
test results: 0.91910297 ;   real value: [1]
This sound is False.
prediction 561 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.075698264
test results: 0.075698264 ;   real value: [0]
This sound is False.
prediction 562 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.0627733
test results: 0.0627733 ;   real value: [0]
This sound is False.
prediction 563 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.06795688
test results: 0.06795688 ;   real value: [0]
This sound is True.
prediction 564 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.91748345
test results: 0.91748345 ;   real value: [1]
This sound is True.
prediction 565 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.9201841
test results: 0.9201841 ;   real value: [1]
This sound is True.
prediction 566 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.9072993
test results: 0.9072993 ;   real value: [1]
This sound is False.
prediction 567 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.09212953
test results: 0.09212953 ;   real value: [0]
This sound is True.
prediction 568 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.859436
test results: 0.859436 ;   real value: [1]
This sound is False.
prediction 569 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.07052874
test results: 0.07052874 ;   real value: [0]
accurace: 0.059860297 0.94 Iteration 570
This sound is False.
prediction 570 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.36494917
test results: 0.36494917 ;   real value: [0]
This sound is False.
prediction 571 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.07560991
test results: 0.07560991 ;   real value: [0]
This sound is True.
prediction 572 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.9007882
test results: 0.9007882 ;   real value: [1]
This sound is False.
prediction 573 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.120180726
test results: 0.120180726 ;   real value: [0]
This sound is False.
prediction 574 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.08634065
test results: 0.08634065 ;   real value: [0]
This sound is True.
prediction 575 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.8615584
test results: 0.8615584 ;   real value: [1]
This sound is True.
prediction 576 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.913276
test results: 0.913276 ;   real value: [1]
This sound is True.
prediction 577 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.7550906
test results: 0.7550906 ;   real value: [1]
This sound is False.
prediction 578 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.1426152
test results: 0.1426152 ;   real value: [0]
This sound is False.
prediction 579 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.09808846
test results: 0.09808846 ;   real value: [0]

accurace: 0.0501078 0.93 Iteration 580
This sound is True.

prediction 580 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.6597431
test results: 0.6597431 ;   real value: [0]
This sound is True.
prediction 581 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.8686691
test results: 0.8686691 ;   real value: [1]
This sound is True.
prediction 582 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.8718832
test results: 0.8718832 ;   real value: [1]
This sound is False.
prediction 583 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.059126984
test results: 0.059126984 ;   real value: [0]
This sound is False.
prediction 584 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.06886757
test results: 0.06886757 ;   real value: [0]
This sound is False.
prediction 585 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.071423374
test results: 0.071423374 ;   real value: [0]
This sound is True.
prediction 586 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.92569304
test results: 0.92569304 ;   real value: [1]
This sound is True.
prediction 587 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [1] ;   test result: 0.9332909
test results: 0.9332909 ;   real value: [1]
This sound is False.
prediction 588 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.2163508
test results: 0.2163508 ;   real value: [0]
This sound is False.
prediction 589 : Tensor("prediction:0", shape=(None, 1), dtype=float32) ;   real value: [0] ;   test result: 0.05939826

test results: 0.05939826 ;   real value: [0]
accurace: 0.048520066 0.94 Iteration 590

最后接近 589 轮训练处往前我截取了3次大范围的测试结果,可以发现准确率已经可以达到94%,并且预测的值也是十分接近实际结果的。实际上每次测试数据为100个,因此连续的两次测试意味着200个数据全部通过这个模型,有190个判断结果为正确的。

事实上训练结果到600轮的时候也还没有完全收敛,但越往后模型收敛速度越慢,一方面受制于训练数据不足,另一方面受制于网络结构和参数还没有经过优化调整。

但是总归可以展现出一个LSTM网络搭建的过程和训练的效果。

最后是loss随着测试轮数的增加的变化曲线图
在这里插入图片描述

8、总结

有几个小经验可以分享一下:
1、一开始训练无法收敛是正常的,让它跑个一两百轮先看看,尤其对于复杂数据;

2、无论如何先让你的程序跑起来,在考虑调整的问题,例如,虽然输出结果都是0或者完全和预想的不一样也不要紧,只要程序能跑就说明没有大的语法错误,而这时候你需要逐步的完善你的网络结构和数据处理,优化算法等操作,这样一步一步来能避免很多的问题;

3、如果你只是测试,或者只测试一段训练的结果,可以忽视这条。而训练好的模型你还需要使用的话,请为一些关键操作命名。例如:

cross_entropy = tf1.reduce_mean(tf1.square(y - prediction),name ="cross_entropy" )

而训练好的模型调用是不需要重新搭建网络的(如果在此基础上重新训练另说),只需要准备数据的代码即可,

with tf1.Session() as sess:
    sess.run(init)
    new_saver = tf1.train.import_meta_graph('save2/model.ckpt-600.meta')
    # 加载meta文件中的图,以及图上定义的结点参数包括权重偏置项等需要训练的参数,也包括训练过程生成的中间参数,所有参数都是通过graph调用接口
    new_saver.restore(sess,'save2/model.ckpt-600')
    # 恢复模型
    new_saver.restore(sess, tf1.train.latest_checkpoint('save2'))
    graph = tf1.get_default_graph()
    # 获取图
    print("Success!~")
    accurace = graph.get_tensor_by_name("accuracy:0")
    """
    graph.get_tensor_by_name用于获取接口和中间参数,例如:
	accuracy = tf1.reduce_mean(tf1.cast(correct_prediction,tf1.float32),name = "accuracy")
	这里给accuracy命名为accuracy,那么在使用模型的时候就可以通过:
	graph.get_tensor_by_name("accuracy:0")调用accuracy这个操作,当然这种方法必须要求使用者链接训练该模型时候的网络结构,feed的数据必须和原数据一样
	```
    """

另外,如果不是要进行迁移学习的话,只是使用训练好的模型或者继续训练不要重新去建网络结构,尤其是x,y!!!这是初学者常犯的错误!!!
正确的操作应该是:
训练的时候定义好各个接口:

x = tf1.placeholder(tf1.float32, [None, 5000, 13],name = "x")
y = tf1.placeholder(tf1.float32, [None, 1],name = "y")

使用的时候通过

graph.get_tensor_by_name("x:0")

获取,然后将数据feed进去。

先这样后面继续更新完善。

评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值