學習資料:
1. slp ch10.3
2. daney povey kaldi lecture3
3. 官方決策樹三個文件、hmm文件
4. 愛丁堡大學cdhmm-ppt
5. **《tree-based state tying for high accuracy acoustic modelling》s.j.young
6. **《decision tree-based state tying for acoustic modelling》這個裡面有一些具體的公式推導
個人感悟:
決策樹這一塊的理論倒沒有多少,公式更是少之又少。關鍵在於如何用**實現,所以值得把主要精力花在看**上。自己在學習這一塊的時候,對指令碼train_deltas.sh用到的程式,採取從上到下逐一攻破的方法。首先看看文獻1,5,6,4, 明白決策樹工作的大致原理、思路;然後看kaldi官方文件,第一遍可能對文件的寫作框架、所提到的程式幾乎沒什麼感覺;然後就開始逐一攻破程式。看不懂**就去看文件,看不懂文件就去看原理,看不懂原理又去看**實現了什麼,**、文件、原理、**、文件、類、**、類、文件,多次重複迭代,直到逐漸弄明白到底發生了什麼,**做了什麼。
看完之後,自己試著總結一下,就當再次複習下,順一順自己的思路。解碼那部分乙個月前剛看過,自己就已經忘得差不多了,所以還是很有必要總結總結、複習複習。
決策樹這塊核心的就是三個程式和相關的幾個類,所以準備乙個筆記寫乙個程式吧。
在這個筆記中,我會首先介紹與決策樹相關的幾個資料結構和統計量,然後介紹累積統計量的主程式和主要函式。
在看決策樹的統計量累積相關的**之前,有必要先搞明白eventmap相關的eventtype這一資料結構。這一塊建議多閱讀官方文件《decision tree internals》。
我們知道決策樹用於對三音素gmm聲學模型進行狀態繫結,那麼問題來了:「用什麼資料結構表示三音素呢?」
一種方法是用一對數表示三音素的位置和該位置上的音素,也就是(三音素位置,該位置上的音素),用c++表示就是pair
,第乙個int取0,1,2,分別代表三音素的三個位置,第二個int取音素的編號,把這三對數放在一起就可以描述三音素了,用c++表示就是由pair
組成的vector。
此外,除了知道三音素三個位置上的音素各是什麼,我們還想知道乙個hmm狀態是三音素的第幾個hmm狀態,前面使用(位置,音素)對來表示三音素,能不能也用一對數表示hmm狀態資訊?當然可以,此時只要把位置置為-1即可,也就是用pair
表示hmm狀態資訊,第乙個int取-1,表示這一對數表示的是hmm狀態資訊;第二個int取hmm狀態編號,表示這是該三音素的第幾個hmm狀態(對於三狀態hmm,第二個int取0,1,2)。
表示三音素的三對數和表示hmm狀態的一對數放在一起,這四對數就可以描述三音素及hmm狀態。在kaldi中用eventtype表示這一資料結構:
typedef
std::vector
<:pair> eventtype;
這裡的eventkeytype和eventvaluetype都是int32的別名,這樣命名的話**更容易被理解。
舉個例子,假設我們當前的三音素是a/b/c;假設音素a,b,c的編號分別是10,11,12;假設我們用的是標準的3狀態hmm拓撲結構;那麼該三音素的第二個hmm狀態可表示為:
eventtype e = ;
這裡的-1我們通常用常量kpdfclass=-1來表示。上面這行可能不是合法的c++**,只是為了說明問題。
這一塊建議閱讀官方文件《clustering mechanisms in kaldi》。
clusterable是乙個純虛類,作為kaldi聚類機制的統一介面。在三音素決策樹狀態繫結這一塊,我們主要用到的是繼承自該基類的guassclusterable。
clusteralbe物件的主要作用是把統計量累加在一起,和計算目標函式。下面對這句話進行說明。
在forced alignment之後,從左到右掃瞄對齊資料,我們能從中得到(三音素及hmm狀態)和其對應的特徵向量,也就是得到乙個eventtype和其對應的特徵向量。在掃瞄過所有訓練資料後,出現的每個eventtype會對應多個特徵向量。
目標函式,就是**中所提到的狀態集s的似然l(s),根據l(s)的計算公式,我們需要知道狀態集s產生的所有觀測(也就是特徵向量集)的協方差,對角協方差的對角線上是特徵向量集每一維的方差,要想知道每一維的方差就需要知道特徵向量集的和以及特徵向量集的平方和(d(x)=e(x^2)-(ex)^2);計算l(s)除了要知道協方差,還需要知道狀態集s產生的特徵向量的個數,也就是狀態集s出現的次數,因為kaldi中使用的是viterbi訓練,得到對齊後,我們就不需要計算posterior概率,可以用狀態集s對應的特徵向量的個數代替posterior概率。
(時刻記得乙個eventtype表示乙個三音素和hmm狀態id)
於是,我們就可以發現,與乙個eventtype相關的統計量包括該eventtype對應的特徵向量的個數、這些特徵向量的累加、這些特徵向量的平方的累加。這三個值,就是guassclusterable中需要儲存的統計量,並且根據這三個統計量可以計算該eventtype的似然。如果把多個eventtype的統計量累加在一起,就可以計算這些eventtype組成的狀態集的似然,因為乙個eventtype實際就是乙個狀態state。
在掃瞄對齊資料累積統計量時,乙個eventtype對應乙個clusterable物件(確切來說是gaussclusterable物件)。在這個gausscluterable物件中,成員count_儲存著該eventtype出現的次數,成員stats_矩陣的第一行儲存著該eventtype對應的所有特徵向量的和,stats_矩陣的第二行儲存著該eventtype對應的所有特徵向量的平方之和。
在構建決策樹時,我們需要知道的所有資訊就是從訓練資料的對齊中得到的所有eventtype(三音素+hmm狀態id),和每個eventtype對應的clusterable物件。很自然的,我們可以把這兩者的對應關係儲存成乙個對pair
,然後把所有的這些對儲存成乙個vector,所以構建決策樹所用到的統計量可以表示成:
typedef
std::vector
<:pair> buildtreestatstype;
acc-tree-stats $context_opts \
--ci-phones=$ciphonelist
$alidir/final.mdl "$feats" \
"ark:gunzip -c $alidir/ali.job.gz|"
$dir/job.treeacc
void accumulatetreestats(const transitionmodel &trans_model,
const accumulatetreestatsinfo &info,
const
std::vector
&alignment,
const matrix&features,
std::map
*stats)
主要功能:這個函式拿到一句話的特徵序列和對齊序列後,從對齊序列(transition-id序列)能夠得到對應的音素序列(splittophones())。然後從左到右掃瞄該音素序列(for i=..),對每乙個三音素,又由transition-id得到這個三音素的hmm狀態id,這樣就得到了乙個個eventtype。對齊序列中的乙個transition-id對應乙個eventtype,這個transition-id對應的特徵向量就是屬於該eventtype的資料,用該event type對應的gaussclusterable物件累積相關的統計量。
對所有的特徵資料、對齊資料執行這個函式後,我們就從訓練資料中得到了所有的eventtype(注意並不是所有的三音素都會在訓練資料中出現)和該event type對應的統計量。這些統計量可以被用於自動產生問題集、構建決策樹。
建議自己舉乙個特徵序列+對齊序列的例子,從左到右掃瞄這個例子來理解這個函式的**。不舉具體的例子來對應這個函式的**,我個人很難理解這個函式到底在講什麼,因為很容易被i,j,center_position等變數搞暈。
下面是我在學習這個程式時的筆記草稿,主要包括乙個例子。希望有一些借鑑意義。
決策樹和CART決策樹
首先簡單介紹下決策樹 說到決策樹肯定離不開資訊熵 什麼是資訊熵 不要被這名字唬住,其實很簡單 乙個不太可能的時間居然發生了,要比乙個非常可能的時間發生提供更多的資訊。訊息說 今天早上太陽公升起 資訊量是很少的,以至於沒有必要傳送。但另一條訊息說 今天早上日食 資訊量就很豐富。概率越大資訊量就越少,與...
決策樹(二)決策樹回歸
回歸 決策樹也可以用於執行回歸任務。我們首先用sk learn的decisiontreeregressor類構造一顆回歸決策樹,並在乙個帶雜訊的二次方資料集上進行訓練,指定max depth 2 import numpy as np quadratic training set noise np.r...
決策樹01 決策樹的原理
此筆記根據 machine learning in action 和周志華教授的 機器學習 所作。缺點 可能會產生過度匹配問題。適用資料型別 數值型和標稱型 machine learning in action if so return 類標籤 else 尋找劃分資料集的最好特徵 劃分資料集 建立分...