Keras lstm+ctc学习心得

 

主要内容

记录了一些自己在用keras简单实现lstm+ctc中觉得需要注意的点。

lstm和ctc的相关原理不再赘述,附以下两个链接,可供参考。

人人都能看懂的LSTM

一文读懂CRNN+CTC文字识别

Layer 输入输出shape

有的时候,虽然感觉原理看了个大概,但实际操作起来还是有点无从下手,所以如果对网络每一层layer中输入输出的shape有着清晰的了解,对于网络的代码实现会有很大帮助。

LSTM层

lstm = LSTM(units=40, return_sequences=True)

输入shape为(batch_size, time_steps, step_length)

输出shape为(batch_size, time_steps, units)

这里的time_steps可以是提取语音特征mfcc的帧数,step_length则是一帧mfcc的特征数

Dense层

dense = Dense(n_classes, activation='softmax')(lstm)

输入shape为(batch_size, time_steps, units)

输出shape为(batch_size, time_steps, n_classes)

这里的n_classes是音素的个数,如26个英文字母+1个space+1个blank

CTC loss

keras自带ctc loss函数为keras.backend.ctc_batch_cost,需要Lambda层进行层封装。

import keras.backend as K
def ctc_lambda_func(args):
    y_pred, labels, input_length, label_length = args
    return K.ctc_batch_cost(labels, y_pred, input_length, label_length)
loss = Lambda(ctc_lambda_func, output_shape=(1, ), name='ctc')\
             ([dense, label_true, input_length, label_length])

这里的input_length的shape为(batch_size, 1),元素为训练数据的time_steps

           label_length的shape为(batch_size, 1),元素为训练数据的max_string_length

模型构建

我们需要构建两个模型base_model和model

base_model 以 dense 作为输出,用于训练好之后的预测

model 以 loss 作为输出,用于训练参数

以下模型使用 GRU,同 LSTM相似

input = Input(shape=(time_steps, step_length))
gru = Bidirectional(GRU(units=40, return_sequences=True), merge_mode='concat')(input)
dense = Dense(n_classes, activation='softmax')(gru)
base_model = Model(inputs=input, outputs=dense)

label_true = Input(shape=[max_label_length])
input_length = Input(shape=[1])
label_length = Input(shape=[1])
loss = Lambda(ctc_lambda_func, output_shape=(1, ), name='ctc')\
             ([dense, label_true, input_length, label_length])
model = Model(inputs=[input, label_true, input_length, label_length], outputs=loss)

模型训练

首先我们需要model.compile中使用自己定义的ctc_loss损失函数

model.compile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer='adadelta')

模型的损失函数参数为模型输出y_pred和真实标签y_true, 由于我们的model输出已经是ctc_loss,所以直接将y_pred作为loss

fittedModel = model.fit([input, labels, input_length, label_length], np.ones(1), batch_size=1, epochs=100,
                        verbose=2)

由于真实标签 labels 已经作为输入参与到 layer 层计算中,因此 model.fit 中的 y 只需要随意赋值,与 batch_size 大小保持一致

模型测试

训练好 model 后, 使用 base_model 进行预测

y_pred = base_model.predict(input_test)

使用 ctc_decode 对 y_pred 进行解码

decode = K.get_value(K.ctc_decode(y_pred, input_length=np.ones(y_pred.shape[0]) * y_pred.shape[1], greedy=True)[0][0])

这里的 decode 是对应类别的下标,根据下标转换成实际类别即可

 

简单代码实现

from keras.models import  Model
from keras.layers import GRU, Dense, Bidirectional, Input, Lambda
from python_speech_features import *
import keras.backend as K
import numpy as np
import scipy.io.wavfile as wav



def ctc_lambda_func(args):
    y_pred, labels, input_length, label_length = args
    return K.ctc_batch_cost(labels, y_pred, input_length, label_length)


def get_audio_feature(audio_path):

    fs, audio = wav.read(audio_path)
    print(fs)
    print(audio.shape)

    # 提取mfcc特征
    wav_feature = mfcc(audio, fs, nfft=int(0.025*fs), winfunc=np.hamming)
    # delta
    d_mfcc_feat1 = delta(wav_feature, 1)
    d_mfcc_feat2 = delta(wav_feature, 2)
    feature = np.hstack((wav_feature, d_mfcc_feat1, d_mfcc_feat2))

    return feature


def get_audio_label(filepath):

    SPACE_TOKEN = '<space>'
    SPACE_INDEX = 0
    FIRST_INDEX = ord('a') - 1

    with open(filepath, 'r') as f:
        line = f.readlines()[0].strip()
        # 空格字符转换成两个空格字符
        targets = line.replace(' ', '  ')
        # 按空格切分,两个空格之间为''
        targets = targets.split(' ')
        # 将''转换成空格token
        targets = np.hstack([SPACE_TOKEN if x == '' else list(x) for x in targets])
        print(targets)
        # 将 token转换成数字
        targets = np.hstack([SPACE_INDEX if x == SPACE_TOKEN else ord(x) - FIRST_INDEX
                             for x in targets])
        return targets

def decode_ctc(out):
    batch_size, decode_len = out.shape[0], out.shape[1]
    for i in range(batch_size):
        pre = ''.join([' ' if x == 0 else chr(x + ord('a') - 1) for x in out[i]])
        print(pre)

feature = get_audio_feature('001.wav')
feature = feature[np.newaxis, :]
print(feature.shape)
labels = get_audio_label('label.txt')
labels = labels[np.newaxis, :]
print(labels.shape)
max_label_length = labels.shape[1]
il = np.ones(1) * feature.shape[1]
print(il.shape)
ll = np.ones(1) * max_label_length
print(ll.shape)

time_step, step_length = feature.shape[1], feature.shape[2]
n_classes = 26 + 1 + 1

input = Input(shape=(time_step, step_length))
gru = Bidirectional(GRU(units=40, return_sequences=True), merge_mode='concat')(input)
dense = Dense(n_classes, activation='softmax')(gru)
base_model = Model(inputs=input, outputs=dense)

label_true = Input(shape=[max_label_length])
input_length = Input(shape=[1])
label_length = Input(shape=[1])
loss = Lambda(ctc_lambda_func, output_shape=(1, ), name='ctc')\
             ([dense, label_true, input_length, label_length])
model = Model(inputs=[input, label_true, input_length, label_length], outputs=loss)

model.compile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer='adadelta')
# model.summary()

fittedModel = model.fit([feature, labels, il, ll], np.ones(1), batch_size=1, epochs=100,
                        verbose=2)
model.save('lstm_ctc.h5')


base_model.load_weights('lstm_ctc.h5')
y_pred = base_model.predict(feature)
decode = K.ctc_decode(y_pred, input_length=np.ones(y_pred.shape[0]) * y_pred.shape[1], greedy=True)
out = K.get_value(decode[0][0])
decode_ctc(out)

 

部分代码参考

https://blog.csdn.net/yifen4234/article/details/80334516

 

 

 

 

 

 

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Python是一种高级编程语言,Keras是一个用于构建神经网络模型的深度学习库,CNN代表卷积神经网络,LSTM代表长短期记忆。Python的流行性使得它成为使用Keras库构建神经网络模型的理想选择。 卷积神经网络(CNN)是一种前馈神经网络,常用于计算机视觉任务。其核心思想是通过卷积运算来提取图像的特征。CNN在图像识别、物体检测和语义分割等任务中表现出色。 长短期记忆(LSTM)是一种适用于处理序列数据的循环神经网络(RNN)的特殊类型。与普通的RNN相比,LSTM能够更好地捕捉到长期依赖关系。LSTM通过控制记忆单元来处理序列中的信息,对于许多自然语言处理任务,如语言建模和机器翻译,LSTM是一个非常强大的工具。 在使用Keras库时,借助Python的灵活性和易用性,我们可以轻松地利用CNN和LSTM来构建复杂的深度学习模型。Keras库提供了丰富的高级API和多种预训练模型,可以帮助我们快速搭建和训练模型。 例如,我们可以使用Keras库中的layers模块来创建CNN模型的卷积层和池化层,然后使用LSTM层来处理时序数据。在构建模型时,我们可以选择性地添加Batch Normalization层或Dropout层来提高模型的泛化能力。 使用Keras库可以进行模型的编译、训练和评估等操作,还可以进行模型的保存和加载。同时,Keras库还提供了方便的可视化工具,如TensorBoard,可以帮助我们更好地理解和分析模型的结构和性能。 综上所述,Python、Keras、CNN和LSTM是一组强大的工具和技术,可以用于构建和训练复杂的深度学习模型,解决图像识别、自然语言处理和其他各种任务。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值