使用自定義字典 Sphinx-4 和文本處理工具從交談中提取相關數據

轉載自:http://www.ibm.com/developerworks/cn/opensource/os-sphinxspeechrec/

使用開源 Sphinx-4 語音識別包,以接近實時的速度捕捉語音交談中的字母和數字,從而創建註釋。使用自定義 Sphinx-4 字典文件提取語音字符和數字的可能匹配。處理文本以獲得更有條理的值(例如電話號碼和縮略詞),並通過搜索引擎查找和本地數據庫創建會議註釋程序。

卡內基梅隆大學的 Sphinx 項目爲開發人員和用戶創建了開源語音識別工具。本文將使用 Sphinx-4 代碼庫爲小型常用字母和數字字典提供自動識別。通過把語音信息轉換爲文本並處理具有特定數據結構的字符串(例如電話號碼和縮略詞),可以爲語言交談自動創建描述性註釋。

此項目的應用領域之一是電話會議註釋應用程序。下次參加開發會議時,請啓動交談註釋程序,然後可以在發表會議演講時根據電話號碼自動查找個人,也可以根據 Web 搜索引擎查看最新的縮略詞。您不必停止正在做的事情就可以輸入會議中提到的最新縮略詞或員工編號來查找相關數據。Sphinx-4 和本文構建的交談註釋程序可以爲您完成大部分繁瑣的工作。

要求

硬件

Sphinx 非常佔用資源,因此,需要配備高速硬件纔能有效利用該軟件。必須配備大量專用內存才能提供有用性能,因此要求在至少配有 1 GB RAM 的 Intel® Pentium® 4-class 計算機上運行 Sphinx 應用程序。相比之下,文本處理的硬件要求微不足道,並且可以在同一臺計算機上運行,而不會影響語音識別處理的性能。

軟件

可以在運行 Linux® 或 Microsoft® Windows® 的硬件上運行本文中創建的應用程序。Sphinx-4 使用最新的 JDK 和 Apache Ant 來創建自定義語法處理器。需要使用 Perl 及相關的查找模塊。

安裝 Sphinx-4

Sphinx 提供了多種形式,可實現各種類型的語音識別和功能。本文將使用 Sphinx-4 包,這是最具用戶友好性和開發人員友好性的最新版本。Sphinx-4 的安裝較爲嚴格,因此考慮安裝說明中強調的重點步驟:

  1. 下載並解壓縮 Apache Ant。
  2. 下載並解壓縮 Sun JDK(撰寫本文時,V1.6.0_02 是最新版本)。
  3. 下載並解壓縮 Sphinx-4 源代碼包,因爲將修改其中一個演示程序來達到我們的目的。
  4. 用下列命令設置環境變量:
    export ANT_HOME=${PWD}/apache-ant-1.7.0
    export JAVA_HOME=${PWD}/jdk1.6.0_02
    export PATH=${PATH}:${ANT_HOME}/bin
    

    對於 Windows,可能需要在 Control Panel > System > Advanced > Environment variables 下設置環境變量。
  5. 切換到 sphinx4-beta 目錄,然後切換到 lib 子目錄。
  6. 通過運行 jsapi.sh shell 腳本激活 JSAPI 二進制許可證。Sphinx-4 將通過二進制許可證來提供對 JSAPI 的支持,因此需要接受協議。
  7. 可能要求您安裝 uudecode 來解壓縮 JSAPI 要求的組件。大多數 Linux 發行版都提供了以某種形式包含 uudecode 的包,因此如果需要安裝 uudecode,請先考慮查看可用包。對於 Windows,雙擊 jsapi.exe 文件並接受許可證協議。
  8. 退出並切換到主 Sphinx4 目錄。
  9. 運行 ant 命令,然後構建過程應當開始。

狀態消息 “BUILD SUCCESSFUL” 表示您已經正確設置環境並且已經準備執行修改步驟。如果收到其他消息,請查看構建目錄和環境變量,或者查閱 Apache Ant 和 Sphinx-4 文檔以獲得環境的詳細安裝說明。

 

從與說話者無關的語音中提取字母和數字的策略

要實現與說話者不相關的大型詞彙表識別,語言識別技術還要 2 到 10 年的路要走。市場中現有的所有用戶級軟件幾乎都不能記錄會議中的多種語音,包括重疊語音、全球範圍的口音及各種技術詞彙表和口語詞彙表。Sphinx 特別是 Sphinx-4 包提供了所有必需選項,可以在與說話者不相關的環境中可靠識別非常小(但仍然有用)的詞彙表。

我們已經指定了有限的詞彙表:字母 A 到 Z 及數字 0 到 9。我們的策略是僅提取說出這些字母或數字的所有位置。通常將這種方法稱爲單詞定位(word spotting)。雖然 Sphinx-4 目前不支持單詞定位,但是仍然可以通過強制所有發音至少在語法上匹配一個單詞來獲得有用的結果。有了通過猜測獲得的字母和數字列表後,就可以應用標準文本處理工具和信息查找來提取有用信息。

自定義字典,修改 Hello World 示例

創建字典文件

創建 pseudo 單詞定位設置的第一步是構建所需的字典文件。在 Sphinx-4 字典樹中,有一個名爲 bld/models/edu/cmu/sphinx/model/acoustic/WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz/dict/ 的目錄。此目錄包含 alpha.dict 和 digit.dict 字典文件。乍看之下,結合這兩個字典文件似乎將生成所需文件。但是,事實並非如此,因爲我們需要通過同一個目錄中的 cmudict.0.6d 文件構建字典文件。

切換到 bld/models/edu/cmu/sphinx/model/acoustic/WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz/dict/ 目錄併發出下列命令構建所需字典文件:

perl -ne 'print if( /^[A-Z]/ / )'                       cmudict* >  alN.dict
perl -ne 'print if(/^(ZERO|ONE|TWO|THREE|FOUR)[ (]/)'   cmudict* >> alN.dict
perl -ne 'print if(/^(FIVE|SIX|SEVEN|EIGHT|NINE)[ (]/)' cmudict* >> alN.dict

清單 1 顯示了用簡單字母和數字作爲字典惟一內容創建的 alN.dict 文件。


清單 1. alN.dict 字典文件中的片段

                
...
W                    D AH B AH L Y UW
X                    EH K S
Y                    W AY
Z                    Z IY
FOUR                 F AO R
ONE                  HH W AH N
ONE(2)               W AH N
THREE                TH R IY
...

修改 Hello World 示例

Sphinx-4 提供了許多配置選項,幾乎可以滿足語音識別領域中的所有需求。出於演示目的,最有效的方法是簡單地修改現有 Hello World 示例。在 Sphinx-4 根目錄下,切換到 demo/sphinx/helloworld 目錄,然後編輯 helloworld.config.xml 文件。清單 2 顯示了一行更改,以使用我們構建的 alN.dict 字典文件。


清單 2. helloworld.config.xml 更改

                
original (line 114):
        <property name="dictionaryPath"
   value="resource:/edu.cmu.sphinx.model.acoustic.WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz.
Model!/edu/cmu/sphinx/model/acoustic/WSJ_8gau_13d
Cep_16k_40mel_130Hz_6800Hz/dict/cmudict.0.6d"/>

new:
        <property name="dictionaryPath"
   value="resource:/edu.cmu.sphinx.model.acoustic.WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz.
Model!/edu/cmu/sphinx/model/acoustic/WSJ_8gau_13d
Cep_16k_40mel_130Hz_6800Hz/dict/alN.dict"/>

還必須對同一個目錄中的 hello.gram 語法文件進行修改。清單 3 顯示的更改可以只提取字典文件中的字母和數字。


清單 3. hello.gram 更改

                

original:
public <greet> = (Good morning | Hello) 
( Bhiksha | Evandro | Paul | Philip | Rita | Will );

new:
public <greet> = ( zero | one | two | three | four | five | six |seven | eight | nine | 
a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | 
w | x | y | z) * ;

還需要對 HelloWorld.java 文件進行修飾性更改,如下所示:


清單 4. HelloWorld.java 更改

                
original (line 59):
    System.out.println
        ("Say: (Good morning | Hello) " +
                     "( Bhiksha | Evandro | Paul | Philip | Rita | Will )");

new:
    System.out.println
        ("Listening for letters and numbers");

完成以上更改後,可以構建並運行修改後的示例。更改 Sphinx-4 主目錄併發出命令 ant(“BUILD SUCCESSFUL” 消息將使您瞭解到更改是否正確)。對於 Linux,用 $JAVA_HOME/bin/java -mx312m -jar bin/HelloWorld.jar 命令運行更新後的示例。對於 Windows,命令爲:java -mx312m -jar bin/HelloWorld.jar。朗讀 “The phone number for IBM tech support is one eight zero zero four two six seven three seven eight”,然後應當看到類似如下所示的輸出:

f o nine r four i b m x a four t one eight zero zero four two six seven three seven eight

 

文本處理

可以看到,發出聲音的句子被處理爲字母和數字,但並不完全正確。字母 “IBM” 和電話號碼中的數字將被正確識別,但是句子的其餘部分將被錯誤地歸類爲最佳匹配特定聲音的各個字母和數字。

您可能想知道:爲什麼不簡單地使用包括幾千個單詞的字典來識別那些錯誤的最佳猜測?畢竟,Sphinx-4 提供了大型詞彙表字典和語言模型。爲什麼不將演示示例配置爲識別其餘部分:“The phone number for tech support is” 和可能說出的任何其他單詞?

答案是因爲 Sphinx-4 十分優秀,但並不完美。擴展字典文件來識別成百上千的單詞將大大降低簡單數字和字符匹配的效率。您可以通過檢驗 Sphinx-4 “demo” 目錄中的某些其他程序,或者通過把現有示例修改爲使用大型字典文件和擴展語法列表,親自測試這一點。要使用開源系統開發實用的註釋系統,對只有字母和數字組成的文本進行後處理以獲得更有條理的數據,這種方法更加簡便。

遵循兩個簡單規則,從輸出文本中提取縮略詞和電話號碼將變得相對簡單:任何三個連續字母都被視爲縮略詞,而任何五個或更多的連續數字都被視爲電話號碼。清單 5、6、7 將顯示執行這些提取和查找的 annotateAcrNum.pl 程序的組成部分:


清單 5. annotateAcrNum.pl 的第 1 部分 —— 主程序邏輯

                
#!/usr/bin/perl -w
# annotateAcrNum.pl - extract and lookup acronyms and numbers from speech 
#                     recognition text output
use strict;
use Yahoo::Search;
use Net::Dict;
$|=1;  # non buffered output for better user feedback

my %numHash =
("zero" => "0",
"one"   => "1",
"two"   => "2",
"three" => "3",
"four"  => "4",
"five"  => "5",
"six"   => "6",
"seven" => "7",
"eight" => "8",
"nine"  => "9" );

while( my $line = <STDIN> )
{
  print "$line" if( $line =~ /(Start|You said:)/ );

  next unless ( $line =~ /You said:/ );
  my @words = split " ", substr($line,9);  # ignore the "You said:" prefix

  my @numArr = ();
  my @letArr = ();

  foreach my $chunk ( @words )
  {
    if( length($chunk) == 1 )
    { 
      phoneNmSearch(@numArr) if( @numArr > 4 );
      @numArr = ();

      push @letArr, $chunk;

      if( @letArr > 2 )
      { 
        acronymSearch( @letArr );
        shift( @letArr );
      }

    }elsif( length($chunk) > 1 )
    { 
      push @numArr, $numHash{$chunk};
      @letArr = ();
    }#if length greater
  }#for each word

  phoneNmSearch( @numArr ) if( @numArr > 4 );
  acronymSearch( @letArr ) if( @letArr > 2 );

}#while stdin

上面的主程序邏輯將搜索匹配簡單標準的字母和數字字符串。對於修改後的 Hello World 代碼輸出的每行語音識別文本,構建只有字母和數字的獨立數組。使用如下所示的 acronymSearch 子例程搜索字母數組。注意,每執行完一次縮略詞查找後都輪換字母數組中字母的位置,以便從字符串 “i b m x” 中搜索 “ibm” 和 “bmx”。數字數組不執行這種位置輪換,而是獲取可以找到的最大數字並執行 Web 搜索。


清單 6. annotateAcrNum.pl 的第 2 部分 —— acronymSearch

                
sub acronymSearch
{
  my $dict = Net::Dict->new('dict.org');

  my $str = @_; $str =~ s/ //g;

  my $eref = $dict->define($str);
  next if ($eref eq "" );
  foreach my $entry (@$eref)
  {   
      my ($db, $definition) = @$entry;
      next if (   !(defined($definition)) || !(defined($db))  );
      if( $db =~ /(wn|vera|gazetteer|foldoc)/ ){ print "$db: $definition/n" }
  }#for each definition

}#acronymSearch

子例程 acronymSearch 將使用有用的 Net::Dict 模塊。只需指定字典服務器和查詢就可以在大量可用數據庫中進行查找。正則表達式 /(wn|vera|gazetteer|foldoc)/ 將把打印輸出限定到提供相關簡要描述的那些數據庫。您會發現使用在 dict.org 中獲得的其他數據庫可以更好地表示縮略詞空間,這需要刪除正則表達式限制程序。


清單 7. annotateAcrNum.pl 的第 3 部分 —— phoneNmSearch

                
sub phoneNmSearch
{
  my $str = @_; $str =~ s/ //g;
  if( length($str) == 11 )
  {
    $str =~ /(/d)(/d/d/d)(/d/d/d)(/d/d/d/d)/;
    $str = "$1-$2-$3-$4/n";
  }elsif( length($str) == 10 )
  {
    $str =~ /(/d/d/d)(/d/d/d)(/d/d/d/d)/;
    $str = "$1-$2-$3/n";
  }elsif( length($str) == 7 )
  {
    $str =~ /(/d/d/d)(/d/d/d/d)/;
    $str = "$1-$2/n";
  }
  print "Results for: $str/n";

  my @results = Yahoo::Search->Results(Doc => "$str", AppId => "PhNmLookup" );
  warn $@ if $@; # report any errors
  
  my $recCount = 0;
  for my $res (@results)
  {   
      print "Title: ", $res->Title, " /n";
      print $res->Summary, "/n";
      print $res->Url, "/n";
      print "/n";
      last if( $recCount > 1 ); # print first 3 results only
      $recCount++;
  }#for each result

}#phoneNmSearch

對於某些搜索引擎,可以通過向電話號碼數字添加格式來獲得更準確的搜索結果。例如,把 18004267378 改爲 1-800-426-7378 或者把 4152042 改爲 415-2042 將由 phoneNmSearch 子例程的第一部分來執行。這個稍微修改過的電話號碼隨後在 Yahoo! 搜索參數中用作查詢,使用便捷的 Jeffrey Friedl Yahoo::Search Perl 模塊。

使用自定義 Sphinx-4 語音識別和 annotateAcrNum Perl 程序,您現在可以開始對語音交談進行註釋。對於 Linux,用命令 $JAVA_HOME/bin/java -mx312m -jar bin/HelloWorld.jar | perl annotateAcrNum.pl 運行註釋程序。對於 Windows,命令爲 java -mx312m -jar bin/HelloWorld.jar | perl annotateAcrNum.pl

圖 1 顯示 “Terminal” 在 Vector Linux 中的註釋程序設置輸出。注意,帶下劃線的鏈接文本可用於根據 Web 搜索結果啓動頁面。


圖 1. Terminal 在 Vector Linux 中的交談註釋程序屏幕快照
Terminal 在 Vector Linux 中的交談註釋程序屏幕快照

結束語

本文中選擇的查詢和數據庫類型只是註釋的一般示例。您會發現使用 Google 進行 Web 搜索查找更加有效,或者可以把電話號碼查找與員工通訊錄聯繫起來。同樣,也可將這些方法用於從識別出的字母和數字中提取更有條理的數據。交談可能更多地集中在 IP 地址或者員工編號上。使用上述的一些技術,可以提取 IP 地址和惟一標識符,並把查找與您自己的數據庫聯繫起來。

Sphinx-4 還提供了多種方法增強語音識別效率。考慮爲您和團隊成員創建專門製作的聲音模型來提供更高的準確率。擴展字典文件來包括大量常用口語詞彙並測試 Sphinx-4 的實時轉錄質量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章