Pythonを使用して独自の音声認識システムをトレーニングします。この操作の波は安定しています

Pythonを使用して独自の音声認識システムをトレーニングします。この操作の波は安定しています

近年、音声認識技術は急速に発展しており、携帯電話のSiri音声インテリジェントアシスタント、MicrosoftのCortana、さまざまなプラットフォームのスマートスピーカーなど、さまざまな音声認識プロジェクトが広く使用されています。

音声認識は知覚知能に属しますが、機械が単純な音声認識から音声理解へと移行できるようにすると、認知知能のレベルにまで上がります。機械が自然言語を理解する能力は、その機械が知的であるかどうかの指標にもなり、自然言語理解はまさに現在の難題です。

同時に、現在の音声認識プラットフォームのほとんどがインテリジェントクラウドに依存していることを考えると、音声認識のトレーニングはほとんどの人にとってまだ比較的謎めいています。そこで、今日は Python を使用して独自の音声認識システムを構築します。

最終モデルの認識効果は次のとおりです。

[[396315]]

実験前の準備

まず、使用する Python のバージョンは 3.6.5 で、使用するライブラリは画像処理用の cv2 ライブラリです。

Numpy ライブラリは行列演算に使用され、Keras フレームワークはモデルのトレーニングと読み込みに使用されます。 Librosa およ​​び python_speech_features ライブラリは、オーディオ機能の抽出に使用されます。 glob および pickle ライブラリは、ローカル データセットを読み取るために使用されます。

[[396316]]

データセットの準備 まず、データセットでは清華大学の thchs30 中国データを使用します。

これらの録音は、テキストの内容に応じて、A(文IDは1〜250)、B(文IDは251〜500)、C(501〜750)、D(751〜1000)の4つの部分に分かれています。グループ A、B、C にはトレーニング用に 30 人の発音文 10,893 個が含まれ、グループ D にはテスト用に 10 人の発音文 2,496 個が含まれます。

データ フォルダーには、.wav ファイルと .trn ファイルが含まれます。trn ファイルには、.wav ファイルのテキスト記述が含まれます。最初の行は単語、2 行目はピンイン、3 行目は音素です。

データセットは次のとおりです。

[[396317]]

モデルトレーニング

1. 音声データセットのMFCC特徴を抽出する:
まず、人間の声は声道を通じて発せられ、声道の形状によってどのような音が発せられるかが決まります。この形状を正確に知ることができれば、生成された音素を正確に記述することができます。声道の形状は、音声の短時間パワースペクトルのエンベロープで明らかにされます。 MFCC は、このエンベロープを正確に記述する機能です。

抽出された MFCC 特徴を下図に示します。

したがって、データセットの読み取りに基づいて、その音声特徴を抽出して保存し、トレーニングのためにニューラル ネットワークにロードしやすくする必要があります。

対応するコードは次のとおりです。

  1. #データセットファイルを読み取る 
  2.  
  3. text_paths = glob.glob( 'data/*.trn' )
  4.  
  5. 合計 = len(テキストパス)
  6.  
  7. 印刷(合計)
  8.  
  9. open(text_paths[ 0 ], 'r' , encoding= 'utf8' ) を fr として実行します:
  10.  
  11. 行 = fr.readlines
  12.  
  13. 印刷(行)
  14.  
  15. #データセットファイルtrnの内容を読み取り、配列に保存します 
  16.  
  17. テキスト =
  18.  
  19. パス =
  20.  
  21. text_paths内のパスの場合:
  22.  
  23. open(path, 'r' , encoding= 'utf8' ) を fr として実行します:
  24.  
  25. 行 = fr.readlines
  26.  
  27. 行 = 行[ 0 ].strip( '\n' ).replace( ' ' , '' )
  28.  
  29. テキスト.append(行)
  30.  
  31. パスを追加します(path.rstrip( '.trn' ))
  32.  
  33. 印刷(パス[ 0 ]、テキスト[ 0 ])
  34.  
  35. #mfccの数を定義する 
  36.  
  37. mfcc_dim = 13  
  38.  
  39. #データセットのキャリブレーションに基づいて音素を読み取る 
  40.  
  41. def load_and_trim(パス):
  42.  
  43. オーディオ、sr = librosa.load(パス)
  44.  
  45. エネルギー = librosa.feature.rmse(オーディオ)
  46.  
  47. フレーム = np.nonzero(エネルギー >= np.max(エネルギー) / 5 )
  48.  
  49. インデックス = librosa.core.frames_to_samples(フレーム)[ 1 ]
  50.  
  51. audio = audio[indices[ 0 ]:indices[- 1 ]] indices.size場合audio[ 0 : 0 ]
  52.  
  53. オーディオを返す、SR
  54.  
  55. #オーディオの特徴を抽出して保存する 
  56.  
  57. 特徴 =
  58.  
  59. itqdm(範囲(合計))場合:
  60.  
  61. パス = パス[i]
  62.  
  63. オーディオ、sr = load_and_trim(パス)
  64.  
  65. 機能を追加します(mfcc(オーディオ、sr、numcep=mfcc_dim、nfft= 551 ))
  66.  
  67. 印刷(len(特徴), 特徴[ 0 ].shape)

2. ニューラルネットワークの前処理:
ニューラル ネットワークをロードしてトレーニングする前に、読み込んだ MFCC 機能を正規化する必要があります。主な目的は、収束を高速化し、効果を向上させ、干渉を減らすことです。次に、データ セットとラベルを処理して、入力と出力を定義します。

対応するコードは次のとおりです。

  1. #ランダムに100個のデータセットを選択 
  2.  
  3. サンプル = ランダム.サンプル(特徴、 100 )
  4.  
  5. サンプル = np.vstack(サンプル)
  6.  
  7. #正規化のための平均 MFCC 値 
  8.  
  9. mfcc_mean = np.mean(サンプル、軸= 0 )
  10.  
  11. # 正規化のための標準偏差を計算する 
  12.  
  13. mfcc_std = np.std(サンプル、軸= 0 )
  14.  
  15. 印刷(mfcc_mean)
  16.  
  17. 印刷(mfcc_std)
  18.  
  19. #機能を正規化する 
  20.  
  21. 特徴 = [(特徴 - mfcc_mean) / (mfcc_std + 1e - 14 )特徴内の特徴の場合]
  22.  
  23. #データセットに読み込まれたラベルと対応するIDを保存します 
  24.  
  25. 文字 = {}
  26.  
  27. テキスト内のテキストの場合:
  28.  
  29. テキスト内のcの場合:
  30.  
  31. 文字[c] = 文字.get(c, 0 ) + 1  
  32.  
  33. chars = sorted(chars.items, key= lambda x: x[ 1 ], reverse= True ) です。
  34.  
  35. chars = [ chars内のchar [ 0 ] ]
  36.  
  37. print (len(chars), chars[: 100 ])
  38.  
  39. char2id = {c: i for i, c in enumerate(chars)}
  40.  
  41. id2char = {i: c for i, c in enumerate(chars)}
  42.  
  43. data_index = np.arange(合計)
  44.  
  45. np.random.shuffle(データインデックス)
  46.  
  47. train_size = int( 0.9 * 合計)
  48.  
  49. test_size = 合計 - train_size
  50.  
  51. トレーニングインデックス = データインデックス[:トレーニングサイズ]
  52.  
  53. test_index = data_index[train_size:]
  54.  
  55. #ニューラルネットワークの入力と出力X、Y読み取りデータセット機能 
  56.  
  57. X_train = [ train_index内のifeatures[i]]
  58.  
  59. Y_train = [texts[i] for i in train_index]
  60.  
  61. X_test = [features[i] for i in test_index]
  62.  
  63. Y_test = [texts[i] for i in test_index]

3. ニューラルネットワーク関数の定義:
これらには、トレーニング バッチ、畳み込み層関数、正規化関数、活性化層関数などが含まれます。

最初の次元はセグメントの数です。元の音声が長いほど、最初の次元は大きくなります。2 番目の次元は MFCC 機能の次元です。元の音声の数値表現を取得した後、WaveNet を使用して実装できます。 MFCC 特徴は 1 次元シーケンスであるため、畳み込みには Conv1D が使用されます。 因果関係とは、畳み込みの出力が現在の位置より前の入力にのみ関連していること、つまり将来の特徴は使用されないことを意味します。畳み込みの位置を前方にシフトすると理解できます。 WaveNet モデルの構造は次のとおりです。

詳細は以下の通りです。

  1. バッチサイズ = 16  
  2.  
  3. #トレーニングバッチの生成を定義し、一度に16をトレーニングします 
  4.  
  5. バッチジェネレータを定義します(x, y, batch_size=batch_size):
  6.  
  7. オフセット = 0  
  8.  
  9. その間 真実
  10.  
  11. オフセット += バッチサイズ
  12.  
  13. offset == batch_sizeまたはoffset >= len(x)の場合:
  14.  
  15. データインデックス = np.arange(len(x))
  16.  
  17. np.random.shuffle(データインデックス)
  18.  
  19. x = [x[i] (データインデックス内のi場合)]
  20.  
  21. y = [y[i] (データインデックス内のi場合)]
  22.  
  23. オフセット = バッチサイズ
  24.  
  25. X_data = x[オフセット - バッチサイズ: オフセット]
  26.  
  27. Y_data = y[オフセット - バッチサイズ: オフセット]
  28.  
  29. X_maxlen = max([X_data[i].shape[ 0 ] i範囲(batch_size)])
  30.  
  31. Y_maxlen = max([len(Y_data[i]) for i in range(batch_size)])
  32.  
  33. X_batch = np.zeros([batch_size, X_maxlen, mfcc_dim])
  34.  
  35. Y_batch = np.ones([batch_size, Y_maxlen]) * len(char2id)
  36.  
  37. X_length = np.zeros([batch_size, 1 ], dtype= 'int32' )
  38.  
  39. Y_length = np.zeros([batch_size, 1 ], dtype= 'int32' )
  40.  
  41. i が範囲(batch_size)の場合:
  42.  
  43. X_length[i, 0 ] = X_data[i].shape[ 0 ]
  44.  
  45. X_バッチ[i, :X_長さ[i, 0 ], :] = X_データ[i]
  46.  
  47. Y_長さ[i, 0 ] = len(Y_データ[i])
  48.  
  49. Y_batch[i, :Y_length[i, 0 ]] = [char2id[c]cY_data[i]]
  50.  
  51. 入力 = { 'X' : X_バッチ、 'Y' : Y_バッチ、 'X_長さ' : X_長さ、 'Y_長さ' : Y_長さ}
  52.  
  53. 出力 = { 'ctc' : np.zeros([batch_size])}
  54.  
  55. エポック = 50  
  56.  
  57. ブロック数 = 3  
  58.  
  59. フィルター = 128  
  60.  
  61. X = 入力(形状=( None 、 mfcc_dim,)、 dtype= 'float32' 、 名前= 'X' )
  62.  
  63. Y = 入力(形状=(なし,), dtype= 'float32' , 名前= 'Y' )
  64.  
  65. X_length = 入力(形状=( 1 ,), dtype= 'int32' , 名前= 'X_length' )
  66.  
  67. Y_length = 入力(shape=( 1 ,), dtype= 'int32' , name= 'Y_length' )
  68.  
  69. #畳み込み1層 
  70.  
  71. def conv1d(入力、フィルター、カーネルサイズ、膨張率):
  72.  
  73. return Conv1D(filters=filters, kernel_size=kernel_size, strides= 1 , padding= 'causal' , activation= None ,
  74.  
  75. dilation_rate=dilation_rate)(入力)
  76.  
  77. #標準化機能 
  78.  
  79. def batchnorm(入力):
  80.  
  81. BatchNormalization(入力)を返す
  82.  
  83. #活性化層機能 
  84.  
  85. def activation(入力, activation):
  86.  
  87. アクティベーション(アクティベーション)(入力)を返す
  88.  
  89. #全結合層関数 
  90.  
  91. def res_block(入力、フィルター、カーネルサイズ、膨張率):
  92.  
  93. hf = activation(batchnorm(conv1d(入力、フィルター、カーネルサイズ、膨張率))、 'tanh' )
  94.  
  95. hg = activation(batchnorm(conv1d(入力、フィルター、カーネルサイズ、膨張率))、 'シグモイド' )
  96.  
  97. h0 = 乗算([hf, hg])
  98.  
  99. ha = activation(batchnorm(conv1d(h0, フィルター, 1 , 1 )), 'tanh' )
  100.  
  101. hs = activation(batchnorm(conv1d(h0, フィルター, 1 , 1 )), 'tanh' )
  102.  
  103. Add([ha, inputs]), hsを返す
  104.  
  105. h0 = activation(batchnorm(conv1d(X, フィルター, 1 , 1 )), 'tanh' )
  106.  
  107. ショートカット =
  108.  
  109. i が範囲(num_blocks)の場合:
  110.  
  111. r[ 1 , 2 , 4 , 8 , 16 ]場合:
  112.  
  113. h0, s = res_block(h0, フィルター, 7 , r)
  114.  
  115. ショートカット.append(s)
  116.  
  117. h1 = activation(Add(shortcut), 'relu' )
  118.  
  119. h1 = activation(batchnorm(conv1d(h1, フィルター, 1 , 1 )), 'relu' )
  120.  
  121. #softmax損失関数の出力結果 
  122.  
  123. Y_pred = activation(batchnorm(conv1d(h1, len(char2id) + 1 , 1 , 1 )), 'softmax' )
  124.  
  125. sub_model = モデル(入力=X、出力=Y_pred)
  126.  
  127. #損失関数を計算する 
  128.  
  129. calc_ctc_loss (引数):
  130.  
  131. y、yp、ypl、yl = 引数
  132.  
  133. K.ctc_batch_cost(y, yp, ypl, yl)を返す

4. モデルのトレーニング:
トレーニングのプロセスは次のようになります。

  1. ctc_loss = Lambda(calc_ctc_loss, output_shape=( 1 ,), name= 'ctc' )([Y, Y_pred, X_length, Y_length])
  2.  
  3. # モデルのトレーニングをロードする 
  4.  
  5. モデル = モデル(入力=[X, Y, X_length, Y_length], 出力=ctc_loss)
  6.  
  7. #オプティマイザーを作成する 
  8.  
  9. オプティマイザー = SGD(lr= 0.02 、モメンタム= 0.9 、ネステロフ= True 、クリップノルム= 5 )
  10.  
  11. #モデルをアクティブにして計算を開始する 
  12.  
  13. model.compile(loss={ 'ctc' : lambda ctc_true, ctc_pred: ctc_pred}, optimizer=optimizer)
  14.  
  15. チェックポインター = ModelCheckpoint(ファイルパス = 'asr.h5' 、詳細 = 0 )
  16.  
  17. lr_decay = ReduceLROnPlateau(モニター= '損失' 、係数= 0.2 、忍耐= 1 、min_lr= 0.000 )
  18.  
  19. #トレーニング開始 
  20.  
  21. 履歴 = model.fit_generator(
  22.  
  23. ジェネレータ = batch_generator(X_train, Y_train)、
  24.  
  25. steps_per_epoch=len(X_train) // バッチサイズ、
  26.  
  27. エポック=時代、
  28.  
  29. 検証データ = バッチジェネレータ(X_test, Y_test)、
  30.  
  31. validation_steps=len(X_test) // バッチサイズ、
  32.  
  33. コールバック=[チェックポインタ、lr_decay])
  34.  
  35. #モデルを保存 
  36.  
  37. サブモデルを保存します( 'asr.h5' )
  38.  
  39. #pl=pkl に単語を保存します 
  40.  
  41. open( 'dictionary.pkl' , 'wb' ) を fw として実行します:
  42.  
  43. pickle.dump([char2id, id2char, mfcc_mean, mfcc_std], fw)
  44.  
  45. train_loss = history.history[ '損失' ]
  46.  
  47. 有効な損失 = history.history[ 'val_loss' ]
  48.  
  49. plt.plot(np.linspace( 1 , エポック, エポック), train_loss, ラベル= 'train' )
  50.  
  51. plt.plot(np.linspace( 1 , エポック, エポック), valid_loss, ラベル= 'valid' )
  52.  
  53. plt.legend(loc= '右上' )
  54.  
  55. plt.xlabel( 'エポック' )
  56.  
  57. plt.ylabel( '損失' )
  58.  
  59. plt.show

[[396319]]

モデルのテスト
音声データセットによって生成された辞書を読み取り、モデルを呼び出して音声の特徴を認識します。

コードは次のとおりです。

  1. wavs = glob.glob( 'A2_103.wav' )
  2.  
  3. 印刷(wavs)
  4.  
  5. open( 'dictionary.pkl' , 'rb' ) を fr として実行します:
  6.  
  7. [char2id、id2char、mfcc_mean、mfcc_std] = pickle.load(fr)
  8.  
  9. mfcc_dim = 13  
  10.  
  11. モデル = load_model( 'asr.h5' )
  12.  
  13. インデックス = np.random.randint(len(wavs))
  14.  
  15. 印刷(wavs[インデックス])
  16.  
  17. オーディオ、sr = librosa.load(wavs[index])
  18.  
  19. エネルギー = librosa.feature.rmse(オーディオ)
  20.  
  21. フレーム = np.nonzero(エネルギー >= np.max(エネルギー) / 5 )
  22.  
  23. インデックス = librosa.core.frames_to_samples(フレーム)[ 1 ]
  24.  
  25. audio = audio[indices[ 0 ]:indices[- 1 ]] indices.size場合audio[ 0 : 0 ]
  26.  
  27. X_data = mfcc(オーディオ、sr、numcep=mfcc_dim、nfft= 551 )
  28.  
  29. X_データ = (X_データ - mfcc_mean) / (mfcc_std + 1e - 14 )
  30.  
  31. 印刷(X_data.shape)
  32.  
  33. pred = model.predict(np.expand_dims(X_data, axis= 0 ))
  34.  
  35. pred_ids = K.eval(K.ctc_decode(pred, [X_data.shape[ 0 ]], greedy= False , beam_width= 10 , top_paths= 1 )[ 0 ][ 0 ])
  36.  
  37. pred_ids = pred_ids.flatten.tolist
  38.  
  39. print ( '' .join([id2char[i] for i in pred_ids]))
  40.  
  41. 収量(入力、出力)

この時点で、全体的なプログラムが構築されました。プログラムの結果は次のとおりです。

ソースコードアドレス:

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

抽出コード: ndrr

データセットは自分でダウンロードする必要があります。

<<:  ドローン操縦開始!この国は迎撃のための航空システムを開発している

>>:  トランスフォーマーベースの効率的で低遅延のストリーミング音声認識モデル

ブログ    
ブログ    

推薦する

建設業界における人工知能のメリット

建設における AI は、設計、入札、資金調達、調達、建設、運用、資産管理、ビジネス モデルの変革など...

製造業の変革を促進、産業改革のためのAI主導ソリューション

製造業において、インダストリー 4.0 は単なる流行語ではなく、新たな現実となっています。新型コロナ...

Google Bardは「防御を突破」し、自然言語を使ってロックを解除、インジェクションによるデータ漏洩のリスクを示唆

大規模言語モデルは、テキストを生成する際にプロンプ​​トワードに大きく依存します。この攻撃技は、プロ...

マスク氏、マイクロソフトを非難「OpenAIはあなたのツールではない」

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

概要: インターネット時代です!人工知能に関する4つの大きな誤解

インターネットは現在、非常に急速に発展しており、特に過去2年間で、人工知能はインターネットのトレンド...

AIが仕事や生活を奪ったら、人類の未来はどうなるのでしょうか?

AIの発展は、人間の仕事の効率を向上させ、人間の働き方を変え、さらには人類の発展の方向を導く上で大...

マイクロソフト、中小企業向けにCopilot AIアシスタントを導入、個人向けにプレミアムサービスを開始

マイクロソフトは火曜日、中小企業が同社の生産性向上アプリ内で仮想アシスタント「Copilot」を利用...

スタンフォード大学の美容博士の起業プロジェクトは大成功! AIビデオ生成がトップストリーマーとしてデビュー

スタンフォード大学の中国人博士が休学して起業したところ、AI界でたちまち人気に!この新製品はAIによ...

人工知能が「怠け者」社員147人を解雇、「労働者」は追い詰められている

人工知能やロボットがSF小説に登場して以来、人類は人工知能と共存する未来社会に不安を抱いてきた。映画...

...

OpenAIがChatGPTに「ドラゴン退治のテクニック」を直接教える!公式のヒントエンジニアリングガイドはこちら

Prompt プロジェクトをどのように説明すればよいでしょうか? ChatGPT を初めて使用する初...

約100機のドローンが「爆発」し、重慶の建物に墜落した!プログラムエラー、ホストクラッシュ

ドローンが墜落することは珍しくありませんが、数十機、あるいは数百機ものドローンが同時に墜落したらどう...

AI + データサイエンス: スポーツ業界を変える6つの方法

[[329380]]テクノロジーの発展に伴い、人工知能とデータサイエンスはスポーツの分野でますます重...

...

CLImF アルゴリズムを使用して推奨システムを設計する方法

[51CTO.com からのオリジナル記事] 2010 年以降、レコメンデーション システムの分野で...