語音是人類最天然的交互方式。計算機發明以後讓機器可以「聽懂」人類的語言、理解語言含義,並能作出正確回答就成爲了人們追求的目標。這個過程主要採用了 3 種技術,即自動語音識別(automatic speech recognition,
ASR)、天然語言處理(natural language processing,
NLP)和語音合成(speech synthesis,SS)。語音識別技術的目的是讓機器能聽懂人類的語音,是一個典型的交叉學科任務。前端
語音識別系統模型由聲學模型和語言模型兩個部分組成,聲學模型對應於語音到音素的機率計算,語言模型對應於音素到文字的機率計算。
一個連續語音識別系統大體能夠由四個部分組成:特徵提取,聲學模型,語言模型和解碼部分。具體過程是首先從語音數據中通過提取獲得聲學特徵,而後通過模型訓練統計獲得一個聲學模型,做爲識別的模板,並結合語言模型通過解碼處理獲得一個識別結果。
聲學模型是語音識別系統中關鍵的部分,它的做用是對聲學單元產生的特徵序列進行描述,對語音信號進行了分類。咱們能夠用聲學模型來計算一段觀測到的特徵矢量屬於各個聲學單元的機率並根據似然準則將特徵序列轉化爲狀態序列。
本文數據集地址 清華大學THCHS30中文語音數據集。
詳細代碼教程 中文語音識別
python
神經網絡不能將音頻做爲輸入進行訓練,因此第一步咱們要對音頻數據進行特徵提取。常見的特徵提取都是基於人類的發聲機理和聽覺感知,從發聲機理到聽覺感知認識聲音的本質。
經常使用的一些聲學特徵以下:
(1) 線性預測係數(LPC),線性預測分析是模擬人類的發聲原理,經過分析聲道短管級聯的模型獲得的。假設系統的傳遞函數跟全極點的數字濾波器是類似的,一般用 12一16個極點就能夠描述語音信號的特徵。因此對於 n 時刻的語音信號,
咱們能夠用以前時刻的信號的線性組合近似的模擬。而後計算語音信號的採樣值和線性預測的採樣值,並讓這二者之間達到均方的偏差(MSE)最小,就能夠獲得 LPC 。
(2) 感知線性預測(PLP),PLP 是一種基於聽覺模型的特徵參數。該參數是一種等效於 LPC 的特徵,也是全極點模型預測多項式的一組係數。不一樣之處是
PLP 是基於入耳昕覺,經過計算應用到頻譜分析中,將輸入語音信號通過入耳聽覺模型處理,替代 LPC 所用的時域信號,這樣的優勢是有利於抗噪語音特徵的提取。
(3)梅爾頻率倒譜系數(MFCC), MFCC 也是基於入耳聽覺特性,梅爾頻
率倒譜頻帶劃分是在 Mel刻度上等距劃的,Mel頻率的尺度值與實際頻率的對數分佈關係更符合人耳的聽覺特性,因此可使得語音信號有着更好的表示。
(5)基於濾波器組的特徵 Fbank(Filter bank), Fbank 特徵提取方法就是至關
於 MFCC 去掉最後一步的離散餘弦變換,跟 MFCC 特徵, Fbank 特徵保留了更多的原始語音數據。
(6)語譜圖(Spectrogram),語譜圖就是語音頻譜圖,通常是經過處理接收的時域信號獲得頻譜圖,所以只要有足夠時間長度的時域信號就可。語譜圖的特色是觀察語音不一樣頻段的信號強度,能夠看出隨時間的變化狀況。
本文就是經過將語譜圖做爲特徵輸入,利用 CNN 進行圖像處理進行訓練。語譜圖能夠理解爲在一段時間內的頻譜圖疊加而成,所以提取語譜圖的主要步驟分爲:分幀、加窗、快速傅立葉變換(FFT)。
git
第一步,咱們須要找到利用 scipy 模塊將音頻轉化爲有用的信息, fs 爲採樣頻率, wavsignal 爲語音數據。咱們的數據集的 fs 均爲16khz 。github
import scipy.io.wavfile as wav filepath = 'test.wav' fs, wavsignal = wav.read(filepath)
語音信號在宏觀上是不平穩的,在微觀上是平穩的,具備短時平穩性(10—30ms內能夠認爲語音信號近似不變爲一個音素的發音),通常狀況下取 25ms 。
爲了處理語音信號,咱們要對語音信號進行加窗,也就是一次僅處理窗中的數據。由於實際的語音信號是很長的,咱們不能也沒必要對很是長的數據進行一次性處理。明智的解決辦法就是每次取一段數據,進行分析,而後再取下一段數據,再進行分析。咱們的加窗操做指的就是漢明窗操做,原理就是把一幀內的數據乘以一個函數 並獲得新的一幀數據。公式下文已給出。
怎麼僅取一段數據呢?由於以後咱們會對漢明窗中的數據進行快速傅立葉變換(FFT),它假設一個窗內的信號是表明一個週期的信號(也就是說窗的左端和右端大體能夠連續),而一般一小段音頻數據沒有明顯的週期性,加上漢明窗後,數據就比較接近周期函數了。
因爲加上漢明窗,只有中間的數據體現出來了,兩邊的數據信息丟失了,因此等會移窗的時候會有重疊的部分,當窗口取了 25ms 時,步長能夠取 10ms (其中 a 的值通常取0.46)。
公式爲:
代碼爲:算法
import numpy as np x=np.linspace(0, 400 - 1, 400, dtype = np.int64)#返回區間內的均勻數字 w = 0.54 - 0.46 * np.cos(2 * np.pi * (x) / (400 - 1)) time_window = 25 window_length = fs // 1000 * time_window # 分幀 p_begin = 0 p_end = p_begin + window_length frame = wavsignal[p_begin:p_end] plt.figure(figsize=(15, 5)) ax4 = plt.subplot(121) ax4.set_title('the original picture of one frame') ax4.plot(frame) # 加窗 frame = frame * w ax5 = plt.subplot(122) ax5.set_title('after hanmming') ax5.plot(frame) plt.show()
語音信號在時域上比較難看出其特性,因此一般轉換爲頻域上的能量分佈,因此咱們對每幀通過窗函數處理的信號作快速傅立葉變換將時域圖轉換成各幀的頻譜,而後咱們能夠對每一個窗口的頻譜疊加獲得語譜圖。
代碼爲:網絡
from scipy.fftpack import fft # 進行快速傅里葉變換 frame_fft = np.abs(fft(frame))[:200] plt.plot(frame_fft) plt.show() # 取對數,求db frame_log = np.log(frame_fft) plt.plot(frame_log) plt.show()
談及語音識別,若是這裏有一個剪輯音頻的數據集和對應的轉錄,而咱們不知道怎麼把轉錄中的字符和音頻中的音素對齊,這會大大增長了訓練語音識別器的難度。若是不對數據進行調整處理,那就意味着不能用一些簡單方法進行訓練。對此,咱們能夠選擇的第一個方法是制定一項規則,如「一個字符對應十個音素輸入」,但人們的語速千差萬別,這種作法很容易出現紕漏。爲了保證模型的可靠性,第二種方法,即手動對齊每一個字符在音頻中的位置,訓練的模型性能效果更佳,由於咱們能知道每一個輸入時間步長的真實信息。但它的缺點也很明顯——即使是大小合適的數據集,這樣的作法依然很是耗時。事實上,制定規則準確率不佳、手動調試用時過長不只僅出如今語音識別領域,其它工做,如手寫識別、在視頻中添加動做標記,一樣會面對這些問題。
這種場景下,正是 CTC 用武之地。 CTC 是一種讓網絡自動學會對齊的好方法,十分適合語音識別和書寫識別。爲了描述地更形象一些,咱們能夠把輸入序列(音頻)映射爲X=[x1,x2,…,xT],其相應的輸出序列(轉錄)即爲Y=[y1,y2,…,yU]。這以後,將字符與音素對齊的操做就至關於在X和Y之間創建一個準確的映射,詳細內容可見CTC經典文章。
損失函數部分代碼:app
def ctc_lambda(args): labels, y_pred, input_length, label_length = args y_pred = y_pred[:, :, :] return K.ctc_batch_cost(labels, y_pred, input_length, label_length)
解碼部分代碼:機器學習
#num_result爲模型預測結果,num2word 對應拼音列表。 def decode_ctc(num_result, num2word): result = num_result[:, :, :] in_len = np.zeros((1), dtype = np.int32) in_len[0] = result.shape[1]; r = K.ctc_decode(result, in_len, greedy = True, beam_width=10, top_paths=1) r1 = K.get_value(r[0][0]) r1 = r1[0] text = [] for i in r1: text.append(num2word[i]) return r1, text
模型主要利用 CNN 來處理圖像並經過最大值池化來提取主要特徵加入定義好的 CTC 損失函數來進行訓練。當有了輸入和標籤的話,模型構造就能夠本身進行設定,若是準確率得以提高,那麼都是可取的。有興趣也能夠加入LSTM 等網絡結構,關於 CNN 和池化操做網上資料不少,這裏就再也不贅述了。有興趣的讀者能夠參考往期的卷積神經網絡 AlexNet 。
代碼:ide
class Amodel(): """docstring for Amodel.""" def __init__(self, vocab_size): super(Amodel, self).__init__() self.vocab_size = vocab_size self._model_init() self._ctc_init() self.opt_init() def _model_init(self): self.inputs = Input(name='the_inputs', shape=(None, 200, 1)) self.h1 = cnn_cell(32, self.inputs) self.h2 = cnn_cell(64, self.h1) self.h3 = cnn_cell(128, self.h2) self.h4 = cnn_cell(128, self.h3, pool=False) # 200 / 8 * 128 = 3200 self.h6 = Reshape((-1, 3200))(self.h4) self.h7 = dense(256)(self.h6) self.outputs = dense(self.vocab_size, activation='softmax')(self.h7) self.model = Model(inputs=self.inputs, outputs=self.outputs) def _ctc_init(self): self.labels = Input(name='the_labels', shape=[None], dtype='float32') self.input_length = Input(name='input_length', shape=[1], dtype='int64') self.label_length = Input(name='label_length', shape=[1], dtype='int64') self.loss_out = Lambda(ctc_lambda, output_shape=(1,), name='ctc')\ ([self.labels, self.outputs, self.input_length, self.label_length]) self.ctc_model = Model(inputs=[self.labels, self.inputs, self.input_length, self.label_length], outputs=self.loss_out) def opt_init(self): opt = Adam(lr = 0.0008, beta_1 = 0.9, beta_2 = 0.999, decay = 0.01, epsilon = 10e-8) self.ctc_model.compile(loss={'ctc': lambda y_true, output: output}, optimizer=opt)
統計語言模型是天然語言處理的基礎,它是一種具備必定上下文相關特性的數學模型,本質上也是機率圖模型的一種,而且普遍應用於機器翻譯、語音識別、拼音輸入、圖像文字識別、拼寫糾錯、查找錯別字和搜索引擎等。在不少任務中,計算機須要知道一個文字序列是否能構成一個你們理解、無錯別字且有意義的句子,好比這幾句話:
許多人可能不太清楚到底機器學習是什麼,而它事實上已經成爲咱們平常生活中不可或缺的重要組成部分。 不太清楚許多人可能機器學習是什麼到底,而它成爲已經平常咱們生活中組成部分不可或缺的重要。 不清太多人機可楚器學許能習是麼到什底,而已常我它成經日爲們組生中成活部不重可的或缺分要。
第一個句子符合語法規範,詞義清楚,第二個句子詞義尚且還清楚,第三個連詞義都模模糊糊了。這正是從基於規則角度去理解的,在上個世紀70年代之前,科學家們也是這樣想的。而以後,賈里尼克使用了一個簡單的統計模型就解決了這個問題。從統計角度來看,第一個句子的機率很大,好比是 ,而第二個其次,好比是 ,第三個最小,好比是 。按照這種模型,第一個句子出現的機率是第二個的 10 的 20 次方倍,更不用說第三個句子了,因此第一個句子最符合常理。
假設 S 爲生成的句子,有一連串的詞w1,w2,…wn構成,則句子 S 出現的機率爲:
因爲計算機內存空間和算力的限制,咱們明顯須要更加合理的運算方法。通常來講,僅考慮與前一個詞有關,就能夠有着至關不錯的準確率,在實際使用中,一般考慮與前兩個詞有關就足夠了,極少狀況下才考慮與前三個有關,所以咱們能夠選擇採起下列這個公式:
而 P 咱們能夠經過爬取資料統計詞頻來進行計算機率。
拼音轉漢字的算法是動態規劃,跟尋找最短路徑的算法基本相同。咱們能夠將漢語輸入當作一個通訊問題,每個拼音能夠對應多個漢字,而每一個漢字一次只讀一個音,把每個拼音對應的字從左到有連起來,就成爲了一張有向圖。
聲學模型測試:
語言模型測試:
因爲模型簡單和數據集過少,模型效果並非很好。
項目源碼地址:https://momodel.cn/explore/5d5b589e1afd9472fe093a9e?type=app
論文:語音識別技術的研究進展與展望
博客:ASRT_SpeechRecognition
博客:DeepSpeechRecognition
Mo(網址:momodel.cn)是一個支持 Python 的人工智能在線建模平臺,能幫助你快速開發、訓練並部署模型。
Mo 人工智能俱樂部 是由網站的研發與產品設計團隊發起、致力於下降人工智能開發與使用門檻的俱樂部。團隊具有大數據處理分析、可視化與數據建模經驗,已承擔多領域智能項目,具有從底層到前端的全線設計開發能力。主要研究方向爲大數據管理分析與人工智能技術,並以此來促進數據驅動的科學研究。
目前俱樂部每週六在杭州舉辦以機器學習爲主題的線下技術沙龍活動,不按期進行論文分享與學術交流。但願能匯聚來自各行各業對人工智能感興趣的朋友,不斷交流共同成長,推進人工智能民主化、應用普及化。