0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何在聲音頻譜嵌入中加入記憶機制

zhKF_jqr_AI ? 來源:lq ? 2018-12-13 08:48 ? 次閱讀

編者按:Kanda機器學習工程師Daniel Rothmann撰寫的機器聽覺系列第四篇,講解如何在聲音頻譜嵌入中加入記憶機制。

歡迎回來!這一系列文章將詳細介紹奧胡斯大學和智能揚聲器生產商Dynaudio A/S合作開發(fā)的實時音頻信號處理框架。

如果你錯過了之前的文章,可以點擊下面的鏈接查看:

AI在音頻處理上的潛力

基于頻譜圖和CNN處理音頻有何問題?

基于自編碼器學習聲音嵌入表示

在上一篇文章中,我們介紹了人類是如何體驗聲音的,在耳蝸形成頻譜印象,接著由腦干核團“編碼”,并借鑒其思路,基于自編碼器學習聲音頻譜嵌入。在這篇文章中,我們將探索如何構建用來理解聲音的人工神經網絡,并在頻譜聲音嵌入生成中集成記憶。

余音記憶

聲音事件的含義,很大程度上源于頻譜特征間的時域相互關系。

有一個事實可以作為例證,取決于語音的時域上下文的不同,人類聽覺系統(tǒng)會以不同方式編碼同樣的音位1。這意味著,取決于之前的語音,音位/e/在神經方面可能意味著完全不同的東西。

進行聲音分析時,記憶很關鍵。因為只有在某處實際存儲了之前的印象,才可能將之前的印象與“此刻”的印象相比較。

人類的短期記憶組件既包括感官記憶也包括工作記憶2。人類對聲音的感知依靠聽覺感官記憶(有時稱為余音記憶)。C. Alain等將聽覺感官記憶描述為“聽覺感知的關鍵初始階段,使聽者可以整合傳入的聽覺信息和存儲的之前的聽覺事件的表示”2。

從計算的角度出發(fā),我們可以將余音記憶視作即刻聽覺印象的短期緩沖區(qū)。

余音記憶的持續(xù)時間有所爭議。D. Massaro基于純音和語音元音掩碼的研究主張持續(xù)時間約為250毫秒,而A. Treisman則根據雙耳分聽試驗主張持續(xù)時間約為4秒3。從在神經網絡中借鑒余音記憶思路的角度出發(fā),我們不必糾結感官存儲的余音記憶的固定時長。我們可以在神經網絡上測試幾秒鐘范圍內的記憶的效果。

進入循環(huán)

在數字化頻譜表示中可以相當直截了當地實現感官記憶。我們可以簡單地分配一個環(huán)形緩沖區(qū)用來儲存之前時步的頻譜,儲存頻譜的數量預先定義。

環(huán)形緩沖區(qū)是一種數據結構,其中包含一個視作環(huán)形的數組,窮盡數組長度后索引循環(huán)往復為04.

在我們的例子中,可以使用一個長度由所需記憶量決定的多維數組,環(huán)形緩沖區(qū)的每個索引指向某一特定時步的完整頻率頻譜。計算出新頻譜后,將其寫入緩沖區(qū),如果緩沖區(qū)已滿,就覆蓋最舊的時步。

在填充緩沖區(qū)的過程中,我們會更新兩個指針:標記最新加入元素的尾指針,和標記最舊元素的頭指針(即緩沖區(qū)的開始)4。

下面是一個環(huán)形緩沖區(qū)的Python實現的例子(作者為Eric Wieser):

class CircularBuffer(): # 初始化NumPy數組和頭/尾指針 def __init__(self, capacity, dtype=float): self._buffer = np.zeros(capacity, dtype) self._head_index = 0 self._tail_index = 0 self._capacity = capacity # 確保頭指針和尾指針循環(huán)往復 def fix_indices(self): if self._head_index >= self._capacity: self._head_index -= self._capacity self._tail_index -= self._capacity elif self._head_index < 0: ? ? ? ? ? ?self._head_index += self._capacity ? ? ? ? ? ?self._tail_index += self._capacity ? ?# 在緩沖區(qū)中插入新值,如緩沖區(qū)已滿,覆蓋舊值 ? ?def insert(self, value): ? ? ? ?if self.is_full(): ? ? ? ? ? ?self._head_index += 1 ? ? ? ?self._buffer[self._tail_index % self._capacity] = value ? ? ? ?self._tail_index += 1 ? ? ? ?self.fix_indices()

降低輸入尺寸

為了存儲一整秒的頻率頻譜(每時步5毫秒),我們需要一個包含200個元素的緩沖區(qū),其中每個元素包含頻率幅度的數組。如果我們需要類人的頻譜解析度,這些數組將包含3500個值。然后200個時步就需要處理700000個值。

將長度為700000的輸入傳給人工神經網絡,在算力上太昂貴了。降低頻譜和時域解析度,或者保存更短時期的頻譜信息,可以緩解這一問題。

我們也可以借鑒Wavenet架構,使用空洞因果卷積(dilated causal convolutions)以優(yōu)化原始音頻樣本中的大量序列數據的分析。如A. Van Den Oord等所言,空洞卷積是應用于大于自身長度的區(qū)域,以特定步驟跳過輸入值的過濾器5。

最近傳入的頻率數據在瞬時聲音分析中起決定性作用,根據這一假定,我們可以用空洞頻譜緩沖區(qū)來降低算力記憶的大小。

空洞緩沖區(qū)的值可以直接選擇單個值,也可以組合若干時步,提取平均數或中位數。

空洞頻譜緩沖區(qū)背后的動機是在記憶中保留最近的頻譜印象的同時,以高效的方式同時保持關于上下文的部分信息。

下面是使用Gammatone濾波器組構造空洞頻譜的代碼片段。注意這里使用的是離線處理,不過濾波器組也同樣可以實時應用,在環(huán)形緩沖區(qū)中插入頻譜幀。

from gammatone import gtgramimport numpy as npclass GammatoneFilterbank: def __init__(self, sample_rate, window_time, hop_time, num_filters, cutoff_low): self.sample_rate = sample_rate self.window_time = window_time self.hop_time = hop_time self.num_filters = num_filters self.cutoff_low = cutoff_low def make_spectrogram(self, audio_samples): return gtgram.gtgram(audio_samples, self.sample_rate, self.window_time, self.hop_time, self.num_filters, self.cutoff_low) def make_dilated_spectral_frames(self, audio_samples, num_frames, dilation_factor): spectrogram = self.make_spectrogram(audio_samples) spectrogram = np.swapaxes(spectrogram, 0, 1) dilated_frames = np.zeros((len(spectrogram), num_frames, len(spectrogram[0]))) for i in range(len(spectrogram)): for j in range(num_frames): dilation = np.power(dilation_factor, j) if i - dilation < 0: ? ? ? ? ? ? ? ? ? ?dilated_frames[i][j] = spectrogram[0] ? ? ? ? ? ? ? ?else: ? ? ? ? ? ? ? ? ? ?dilated_frames[i][j] = spectrogram[i - dilation] ? ? ? ?return dilated_frames

可視化空洞頻譜緩沖區(qū)

嵌入緩沖區(qū)

在人類記憶的許多模式中,感官記憶經過選擇性記憶這個過濾器,以避免短時記憶信息過載3。由于人類的認知資源有限,分配注意力到特定聽覺感知以優(yōu)化心智能量的消耗是一項優(yōu)勢。

我們可以通過擴展自編碼器神經網絡架構實現這一方法?;谶@一架構,我們可以給它傳入空洞頻率頻譜緩沖,以生成嵌入,而不是僅僅傳入瞬時頻率信息,這就結合了感官聲音記憶和選擇性注意瓶頸。為了處理序列化信息,我們可以使用序列到序列自編碼器架構6。

序列到序列(Seq2Seq)模型通常使用LSTM單元編碼序列數據(例如,一個英語句子)為內部表示(該表示包含整個句子的壓縮“含義”)。這個內部表示之后可以解碼回一個序列(例如,一個含義相同的西班牙語句子)7。

以這種方式得到的聲音嵌入,可以使用算力負擔低的簡單前饋神經網絡分析、處理。

據下圖所示訓練完網絡后,右半部分(解碼部分)可以“砍掉”,從而得到一個編碼時域頻率信息至壓縮空間的網絡。在這一領域,Y. Chung等的Audio Word2Vec取得了優(yōu)秀的結果,通過應用Seq2Seq自動編碼器架構成功生成了可以描述語音錄音的序列化語音結構的嵌入6。使用更多樣化的輸入數據,它可以生成以更一般的方式描述聲音的嵌入。

基于Keras

依照之前描述的方法,我們用Keras實現一個生成音頻嵌入的Seq2Seq自動編碼器。我將它稱為聽者網絡,因為它的目的是“聽取”傳入的聲音序列,并將它壓縮為一個更緊湊的有意義表示,以供分析和處理。

我們使用了UrbanSound8K數據集(包含3小時左右的音頻)訓練這個網絡。UrbanSound8K數據集包含歸好類的環(huán)境音片段。我們使用Gammatone濾波器組處理聲音,并將其分割為8時步的空洞頻譜緩沖區(qū)(每個包含100個頻譜濾波器)。

from keras.models import Modelfrom keras.layers import Input, LSTM, RepeatVectordef prepare_listener(timesteps, input_dim, latent_dim, optimizer_type, loss_type): inputs = Input(shape=(timesteps, input_dim)) encoded = LSTM(int(input_dim / 2), activation="relu", return_sequences=True)(inputs) encoded = LSTM(latent_dim, activation="relu", return_sequences=False)(encoded) decoded = RepeatVector(timesteps)(encoded) decoded = LSTM(int(input_dim / 2), activation="relu", return_sequences=True)(decoded) decoded = LSTM(input_dim, return_sequences=True)(decoded) autoencoder = Model(inputs, decoded) encoder = Model(inputs, encoded) autoencoder.compile(optimizer=optimizer_type, loss=loss_type, metrics=['acc']) return autoencoder, encoder

網絡架構

聽者網絡的損失函數使用均方誤差,優(yōu)化算法使用Adagrad,在一張NVIDIA GTX 1070上訓練了50個epoch,達到了42%的重建精確度。因為訓練耗時比較長,所以我在訓練進度看起來還沒有飽和的時候就停止了訓練。我很想知道,基于更大的數據集和更多算力資源訓練后這一模型表現如何。

肯定還有很多可以改進的地方,不過下面的圖像表明,在3.2的壓縮率下,模型捕捉到了輸入序列的大致結構。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 頻譜
    +關注

    關注

    7

    文章

    873

    瀏覽量

    45527
  • 數字化
    +關注

    關注

    8

    文章

    8441

    瀏覽量

    61534
  • 機器學習
    +關注

    關注

    66

    文章

    8320

    瀏覽量

    132165

原文標題:機器聽覺:四、在自編碼器架構中加入記憶機制

文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Protel在線教程:如何在PCB文件中加漢字

    Protel在線教程:如何在PCB文件中加漢字 在PCB文件上面加上漢字一直都是很多網友比較感興趣的事情。PROTEL早期的版本加
    發(fā)表于 04-22 09:09 ?4145次閱讀
    Protel在線教程:如<b class='flag-5'>何在</b>PCB文件<b class='flag-5'>中加</b>漢字

    請問如何在PSoC Creator中加入USB?

    何在 PSoC Creator 中加入 USB?
    發(fā)表于 05-20 06:43

    請教各位大俠如何在protel99中加入圖片或公司LOGO

    教各位大俠如何在protel99中加入圖片或公司LOGO
    發(fā)表于 11-26 13:33

    何在cadence中加入中文絲印

    何在cadence中加入中文絲?????謝謝
    發(fā)表于 12-21 12:13

    何在protues元件庫中加入AD7755?

    何在protues元件庫中加入AD7755
    發(fā)表于 04-18 10:20

    【求助】labview圖像顯示中加入標簽的問題

    做了一個小程序,測兩個圓圓心的距離,第一幅圖是用視覺助手做出來的,可以看到在顯示的部分會有所標記,但是生成LABVIEW程序后類似的標記沒有了,想問一下如何在LABVIEW圖像顯示中加入這種點、線
    發(fā)表于 04-22 20:46

    何在根文件系統(tǒng)中加入ssh命令?

    想要在根文件系統(tǒng)中加入ssh命令,這個應該怎么辦?
    發(fā)表于 10-24 02:23

    protuse中加入別的元器件的dll無效

    想在protuse8.0中加入LCD12864,已經在其DODELS中加入LCD12864A.DLL,但是在軟件中仍然找不到該液晶,請問何解?
    發(fā)表于 11-19 22:20

    請問如何在SoC設計中加入音頻處理功能?

    何在SoC設計中加入音頻處理功能?
    發(fā)表于 06-03 06:36

    如何快速高效的在自己的設備中加入國密算法

    如今國密系列算法的應用已不僅僅局限于金融和電信等領域,諸如車載設備,消費類電子設備等越來越多的產品開始要求有國密算法的支持。但是國密算法的開源資料和應用案例少之又少,如何快速高效的在自己的設備中加入
    發(fā)表于 12-21 06:42

    請問如何在RTTHREAD STUDIO 中加入W601 MCU?

    請問如何在RTTHREAD STUDIO 中加入W601 MCU?
    發(fā)表于 02-22 14:16

    何在單片機程序中加入中斷使計時器和蜂鳴器同時停止工作?

    何在程序中加入中斷使計時器和蜂鳴器同時停止工作??
    發(fā)表于 09-26 07:17

    何在XHTML網頁中加入CSS詳細的五種方式說明

    本文檔的主要內容詳細介紹的是如何在XHTML網頁中加入CSS詳細的五種方式說明資料免費下載。
    發(fā)表于 06-13 16:58 ?5次下載

    STM32程序HEX文件中加入固件版本信息

    使用MDK編譯器,讓STM32程序HEX文件中加入固件版本信息。
    的頭像 發(fā)表于 08-14 16:13 ?4256次閱讀

    怎么在直流電源中加入噪聲

    在直流電源中加入噪聲可以是為了模擬真實世界中的噪聲環(huán)境,也可以用于某些實驗中的需要。本文將詳細介紹在直流電源中加入噪聲的方法和技巧,并探討其可能的應用。 首先,讓我們先了解噪聲的類型和特性。噪聲是一
    的頭像 發(fā)表于 01-16 11:00 ?948次閱讀