使用自定义字典 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 的实时转录质量。

本文档介绍Sphinx4在Windows下的文训练过程及注意事项,与本文档配套的是我自己的训练实例bergtrain和用到的软件。 本文档编写日期 2013-04-23 1、为什么要训练? sphinx4目前的版本仅提供了英文等语音识别库。文的库是PTM或semi类型的,在java版sphinx无法使用。 2、Sphinx的训练指哪些内容? 在Sphinx有语言模型、声学模型等概念,如果你不想了解这些,请参考以下内容: a1、文每个字的标准发音已经有一个较为全面的文件进行了标注 这个文件就是zh_broadcastnews_utf8.dic(下称这类文件为发音字典),在sphinx网站上可以下载,我们也包含了它。 下面是该文件的片断,它用类似拼音的方式标注了每个字或词的发音。 昌 ch ang 昌北 ch ang b ei 昌必 ch ang b i 昌都 ch ang d u 昌赫 ch ang h e a2、需要告诉sphinx我们经常使用的字、词是哪些,它们出现的频率如何 由于开放式语音识别尚难实现,所以sphinx实际上只能较好的处理相对小的语言集合。 因此,针对特定的领域,告诉sphinx该领域的词汇和各词出现的频率将极大提高识别率。 a3、需要告诉sphinx每个字、词的真正读音 发音字典告诉sphinx每个字的标准读音,但面对的说话人往往不会以标准读音来朗读。 因此sphinx需要学习说话人的“口音”。 如果训练时的读者发音比较标准,则sphinx能“举一反三”,识别其他不那么标准的读者的语音。 推荐的做法是训练一些典型的口音:标准男、女声,童音,最后再考虑特定用户的口音。 3、如何准备训练内容所需的原料? 需要准备两大内容:1)文本语料文件,2)语料录音文件。 文本语料文件给出2.a2需要的内容,在bergtrain的etc文件下的berginput.txt文件就是一个预料文件。 它以行为单位,给出了150个文句子。 语料录音文件是根据文本语料文件,朗读它的每行/句话,保存到每一个语音文件即可。 语料文件的语句应该尽量选择领域相关的,在覆盖领域内名词的前提下,覆盖尽可能多的通用词汇。 4、训练环境及注意事项 本文的训练软硬件如下: 硬件:T60P笔记本,机器自带录音设备;操作系统为Win7 32位。 软件:Sphinx cmuclmtk-0.7-win32.zip pocketsphinx-0.8-win32.zip sphinxbase-0.8-win32.zip sphinxtrain-1.0.8-win32.zip sphinx4-1.0beta6-bin.zip,用于编写java版的识别软件所需的库 脚本执行软件 ActivePerl-5.16.3.1603-MSWin32-x86-296746.msi ActivePython-2.7.2.5-win32-x86.msi 录音和处理软件 audacity-win-2.0.3rc1.zip,可进行录音和声音文件处理(如降噪),免费软件 FairStars.zip,可进行批量录音(V3.5绿色版) 文本编辑软件UltraEdit,UltraEdit-32.rar绿色版 注意: 文件格式 语料文件必须使用UltraEdit进行编辑, 在编辑后,使用 文件-转换-ASCII转UTF-8(UNICODE编辑),指定文件使用utf8编码。 在保存前,设置格式如下: 换行符:UNIX终束符 - LF 指定文件的回车/换行符为编码0A的换行符 格式:UTF-8 - 无BOM 每个文件的末尾必须有一个回车! 这个回车将在保存时被替换为编码0A的换行符,训练脚本需要这个符号来确认文件的结束。 录音文件 如果你不希望去编辑训练的配置文件,则在使用FairStars录音时作如下设定: 进入菜单和对话框 选项-显示录音选项-编码-WMA, 设定:采样率(16000Hz)、通道(单声道)、比特率(16Kbps) 5、训练步骤 下面逐步从零开始进行训练 5.1 软件环境的安装 将本文档所在的文件夹解压或拷贝到d:\,即本文档路径是d:\sphinxtrain\Sphinx文训练教程.txt 1)点击安装ActivePerl-5.16.3.1603-MSWin32-x86-296746.msi和ActivePython-2.7.2.5-win32-x86.msi; 2)解压Sphinxsphinx4-1.0beta6-bin.zip外的压缩文件到d:\sphinxtrain下
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值