江门市或遂二手车交易网

用 Python 训练本身的语音识别体系,这波操作稳了

原标题:用 Python 训练本身的语音识别体系,这波操作稳了

建德市茄偏建材公司

作者 | 李秋键

责编 | Carol

封图 | CSDN 付费下载自视觉中国

近几年来语音识别技术得到了快捷发展,从手机中的Siri语音智能助手、微柔的幼娜以及各栽平台的智能音箱等等,各栽语音识别的项现在得到了普及行使。

语音识别属于感知智能,而让机器从浅易的识别语音到理解语音,则上升到了认知智能层面,机器的自然说话理解能力如何,也成为了其是否有灵敏的标志,而自然说话理解正是现在难点。

同时考虑到现在大无数的语音识别平台都是借助于智能云,对于语音识别的训练对于大无数人而言还较为奥秘,故今天吾们将行使python搭建本身的语音识别体系。

最后模型的识别成果如下:

实验前的准备

最先吾们操纵的python版本是3.6.5所用到的库有cv2库用来图像处理;

Numpy库用来矩阵运算;Keras框架用来训练和添载模型。Librosa和python_speech_features库用于挑取音频特征。Glob和pickle库用来读取本地数据集。

数据集准备

最先数据集操纵的是清华大学的thchs30中文数据。

这些录音按照其文本内容分成了四片面,A(句子的ID是1~250),B(句子的ID是251~500),C(501~750),D(751~1000)。ABC三组包括30幼我的10893句发音,用来做训练,D包括10幼我的2496句发音,用来做测试。

data文件夹中包含(.wav文件和.trn文件;trn文件里存放的是.wav文件的文字描述:第一走为词,第二走为拼音,第三走为音素);

数据集如下:

模型训练

1、挑取语音数据集的MFCC特征:

起祖先的声音是始末声道产生的,声道的形状决定了发出怎样的声音。倘若吾们能够实在的清新这个形状,那么吾们就能够对产生的音素进走实在的描述。声道的形状在语音短时功率谱的包络中表现出来。而MFCCs就是一栽实在描述这个包络的一栽特征。

其中挑取的MFCC特征如下图可见。

故吾们在读取数据集的基础上,要将其语音特征挑取存储以方便添载入迷经网络进走训练。

其对答的代码如下:

#读取数据集文件

text_paths = glob.glob( 'data/*.trn')

total = len(text_paths)

print(total)

with open(text_paths[ 0], 'r', encoding= 'utf8') as fr:

lines= fr.readlines

print( lines)

#数据集文件trn内容读取保存到数组中

texts = []

paths = []

forpathintext_paths:

with open( path, 'r', encoding= 'utf8') as fr:

lines= fr.readlines

line = lines[ 0].strip( 'n').replace( ' ', '')

texts.append(line)

paths.append( path.rstrip( '.trn'))

print(paths[ 0], texts[ 0])

#定义mfcc数

mfcc_dim = 13

#按照数据集标定的音素读入

def load_and_trim( path):

audio, sr = librosa. load( path)

energy = librosa.feature.rmse(audio)

frames = np.nonzero(energy >= np. max(energy) / 5)

indices = librosa.core.frames_to_samples(frames)[ 1]

audio = audio[indices[ 0]:indices[ -1]] ifindices.size elseaudio[ 0: 0]

returnaudio, sr

#挑取音频特征并存储

features = []

fori intqdm(range(total)):

path= paths[i]

audio, sr = load_and_trim( path)

features.append(mfcc(audio, sr, numcep=mfcc_dim, nfft= 551))

print( len(features), features[ 0].shape)

2、神经网络预处理:

在进走神经网络添载训练前,吾们必要对读取的MFCC特征进走归一化,主要现在标是为了添快拘谨,挑高成果和缩短作梗。然后处理益数据集和标签定义输入和输出即可。

对答代码如下:

#随机选择100个数据集

samples = random.sample(features, 100)

samples = np.vstack(samples)

#平均MFCC的值为了归一化处理

mfcc_mean = np.mean(samples, axis=0)

#计算标准差为了归一化

mfcc_std = np.std(samples, axis=0)

print(mfcc_mean)

print(mfcc_std)

#归一化特征

features = [(feature - mfcc_mean) / (mfcc_std 1e-14) for feature in features]

#将数据集读入的标签和对答id存储列外

chars = {}

for text in texts:

for c in text:

chars[c] = chars.get(c, 0) 1

chars = sorted(chars.items, key=lambda x: x[1], reverse=True)

chars = [char[0] for char in chars]

print(len(chars), chars[:100])

char2id = {c: i for i, c in enumerate(chars)}

id2char = {i: c for i, c in enumerate(chars)}

data_index = np.arange(total)

np.random.shuffle(data_index)

train_size = int(0.9 * total)

test_size = total - train_size

train_index = data_index[:train_size]

test_index = data_index[train_size:]

#神经网络输入和输出X,Y的读入数据集特征

X_train = [features[i] for i in train_index]

Y_train = [texts[i] for i in train_index]

X_test = [features[i] for i in test_index]

Y_test = [texts[i] for i in test_index]

3、神经网络函数定义:

其中包括训练的批次,卷积层函数、标准化函数、激活层函数等等。

其中第⼀个维度为⼩⽚段的个数,原起语⾳越长,第⼀个维度也越⼤, 第⼆个维度为 MFCC 特征的维度。得到原起语⾳的数值外⽰后,就能够使⽤ WaveNet 实现。原由 MFCC 特征为⼀维序列,因而使⽤ Conv1D 进⾏卷积。 因果是指,卷积的输出只和现在位置之前的输⼊相关,即不使⽤异日的 特征,能够理解为将卷积的位置向前偏移。WaveNet 模型组织如下所⽰:

详细如下可见:

batch_size = 16

#定义训练批次的产生,一次训练16个

defbatch_generator(x, y, batch_size=batch_size):

offset = 0

whileTrue:

offset = batch_size

ifoffset == batch_size oroffset >= len(x):

data_index = np.arange(len(x))

np.random.shuffle(data_index)

x = [x[i] fori indata_index]

y = [y[i] fori indata_index]

offset = batch_size

X_data = x[offset - batch_size: offset]

Y_data = y[offset - batch_size: offset]

X_maxlen = max([X_data[i].shape[ 0] fori inrange(batch_size)])

Y_maxlen = max([len(Y_data[i]) fori inrange(batch_size)])

X_batch = np.zeros([batch_size, X_maxlen, mfcc_dim])

Y_batch = np.ones([batch_size, Y_maxlen]) * len(char2id)

X_length = np.zeros([batch_size, 1], dtype= 'int32')

Y_length = np.zeros([batch_size, 1], dtype= 'int32')

fori inrange(batch_size):

X_length[i, 0] = X_data[i].shape[ 0]

X_batch[i, :X_length[i, 0], :] = X_data[i]

Y_length[i, 0] = len(Y_data[i])

Y_batch[i, :Y_length[i, 0]] = [char2id[c] forc inY_data[i]]

inputs = { 'X': X_batch, 'Y': Y_batch, 'X_length': X_length, 'Y_length': Y_length}

outputs = { 'ctc': np.zeros([batch_size])}

epochs = 50

num_blocks = 3

filters = 128

X = Input(shape=( None, mfcc_dim,), dtype= 'float32', name= 'X')

Y = Input(shape=( None,), dtype= 'float32', name= 'Y')

X_length = Input(shape=( 1,), dtype= 'int32', name= 'X_length')

Y_length = Input(shape=( 1,), dtype= 'int32', name= 'Y_length')

#卷积1层

defconv1d(inputs, filters, kernel_size, dilation_rate):

returnConv1D(filters=filters, kernel_size=kernel_size, strides= 1, padding= 'causal', activation= None,

dilation_rate=dilation_rate)(inputs)

#标准化函数

defbatchnorm(inputs):

returnBatchNormalization(inputs)

#激活层函数

defactivation(inputs, activation):

returnActivation(activation)(inputs)

#全连接层函数

defres_block(inputs, filters, kernel_size, dilation_rate):

hf = activation(batchnorm(conv1d(inputs, filters, kernel_size, dilation_rate)), 'tanh')

hg = activation(batchnorm(conv1d(inputs, filters, kernel_size, dilation_rate)), 'sigmoid')

h0 = Multiply([hf, hg])

ha = activation(batchnorm(conv1d(h0, filters, 1, 1)), 'tanh')

hs = activation(batchnorm(conv1d(h0, filters,汽车图片 1, 1)), 'tanh')

returnAdd([ha, inputs]), hs

h0 = activation(batchnorm(conv1d(X, filters, 1, 1)), 'tanh')

shortcut = []

fori inrange(num_blocks):

forr in[ 1, 2, 4, 8, 16]:

h0, s = res_block(h0, filters, 7, r)

shortcut.append(s)

h1 = activation(Add(shortcut), 'relu')

h1 = activation(batchnorm(conv1d(h1, filters, 1, 1)), 'relu')

#softmax亏损函数输出终局

Y_pred = activation(batchnorm(conv1d(h1, len(char2id) 1, 1, 1)), 'softmax')

sub_model = Model(inputs=X, outputs=Y_pred)

#计算亏损函数

defcalc_ctc_loss(args):

y, yp, ypl, yl = args

returnK.ctc_batch_cost(y, yp, ypl, yl)

4、模型的训练:

训练的过程如下可见:

ctc_loss = Lambda(calc_ctc_loss, output_shape=( 1,), name= 'ctc')([Y, Y_pred, X_length, Y_length])

#添载模型训练

model = Model(inputs=[X, Y, X_length, Y_length], outputs=ctc_loss)

#竖立优化器

optimizer = SGD(lr= 0.02, momentum= 0.9, nesterov=True, clipnorm= 5)

#激活模型开起计算

model.compile(loss={ 'ctc': lambda ctc_true, ctc_pred: ctc_pred}, optimizer=optimizer)

checkpointer = ModelCheckpoint(filepath= 'asr.h5', verbose= 0)

lr_decay = ReduceLROnPlateau(monitor= 'loss', factor= 0.2, patience= 1, min_lr= 0.000)

#开起训练

history = model.fit_generator(

generator=batch_generator(X_train, Y_train),

steps_per_epoch=len(X_train) // batch_size,

epochs=epochs,

validation_data=batch_generator(X_test, Y_test),

validation_steps=len(X_test) // batch_size,

callbacks=[checkpointer, lr_decay])

#保存模型

sub_model.save( 'asr.h5')

#将字保存在pl=pkl中

with open( 'dictionary.pkl', 'wb') asfw:

pickle. dump( [char2id, id2char, mfcc_mean, mfcc_std], fw)

train_loss = history.history[ 'loss']

valid_loss = history.history[ 'val_loss']

plt.plot(np.linspace( 1, epochs, epochs), train_loss, label= 'train')

plt.plot(np.linspace( 1, epochs, epochs), valid_loss, label= 'valid')

plt.legend(loc= 'upper right')

plt.xlabel( 'Epoch')

plt.ylabel( 'Loss')

plt.show

测试模型

读取吾们语音数据集生成的字典,始末调用模型来对音频特征识别。

代码如下:

wavs = glob.glob('A2_103.wav')

print(wavs)

with open('dictionary.pkl', 'rb') as fr:

[char2id, id2char, mfcc_mean, mfcc_std] = pickle.load(fr)

mfcc_dim = 13

model = load_model('asr.h5')

index = np.random.randint(len(wavs))

print(wavs[index])

audio, sr = librosa.load(wavs[index])

energy = librosa.feature.rmse(audio)

frames = np.nonzero(energy >= np.max(energy) / 5)

indices = librosa.core.frames_to_samples(frames)[1]

audio = audio[indices[0]:indices[-1]] if indices.size elseaudio[0:0]

X_data = mfcc(audio, sr, numcep=mfcc_dim, nfft=551)

X_data = (X_data - mfcc_mean) / (mfcc_std 1e-14)

print(X_data.shape)

pred = model.predict(np.expand_dims(X_data, axis=0))

pred_ids = K.eval(K.ctc_decode(pred, [X_data.shape[0]], greedy=False, beam_width=10, top_paths=1)[0][0])

pred_ids = pred_ids.flatten.tolist

print(''.join([id2char[i] for i in pred_ids]))

yield (inputs, outputs)

到这边,吾们集体的程序就搭建完善,下面为吾们程序的运走终局:

源码地址:

https://pan.baidu.com/s/1tFlZkMJmrMTD05cd_zxmAg

挑取码:ndrr

数据集必要自走下载。

作者简介:

李秋键,CSDN博客行家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap竞赛获奖等等。

作者简介:

李秋键,CSDN博客行家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap竞赛获奖等等。

最迷人的总是最危险。交易的短线高利润,总是伴随着重仓满仓,往往会一次止损使所有积累功亏一篑。想要抓住市场每一次涨跌的波动,就必然伴随着频繁交易,往往赚到的利润还凑不够手续费。所以对思路的坚守,既能降低交易频率,又能大概率的把握到利润,即使有偶尔的止损,也是在可控风险之下。

游戏的意义在于他能给人们带来幸福,如果你把东西和其他东西混合太多,他将失去他自己的意义,大声说,好吧,我是大三学生,我每天都会和你分享比赛中的流言蜚语。

新华社新加坡6月4日电(记者蔡蜀亚)新加坡卫生部4日宣布,截至当天12时,新加坡新增新冠确诊病例517例,累计确诊36922例;新增治愈病例322例,累计治愈23904例;累计死亡24例。

原标题:“二师兄”飞不动了!5月CPI涨幅重返“2时代”,猪周期进入后半场,降准、降息仍有可能