使用 InfoSphere Streams 的自定义 Java 运算符和 ICU4J 实现实时音译

集成 Java 音译模块和 InfoSphere Streams 的自定义 Java 运算符

随着网络监控和情感分析的重要性与日俱增,人们迫切需要识别大数据中的模式(执行文本分析)。但是,在本次练习中,诸多挑战之一就是各个国家可以拥有多种语言,这为有效运行文本分析带来了挑战,因为规则并不适用于所有语言。例如,在印度,每个州的官方语言并不相同,而且既可以通过英语也可以通过本地语言来提供数据。本文介绍如何在音译过程中实现一致性,如何使用 IBM® InfoSphere® Streams® 来准备语言材料,以及如何应用文本分析或模式识别逻辑。

Bharath Kumar Devaraju, 软件工程师, IBM

作者照片Bharath Kumar Devaraju 从 2009 年起就职于 IBM,目前从事 InfoSphere Streams 工具包开发工作。他是一位通过了 QualityStage 和 DataStage 认证的解决方案开发人员。他拥有广泛的客户 POC 经验,并曾参与过成长市场方面的售前活动。



2013 年 9 月 03 日

简介

在成长型市场区域中,任何解决方案提供商面临的首要挑战是可用数据的方言和语言学的不一致性。由于成长型市场区域中拥有包括英语在内的多种官方语言,所以地区的语言符号逐渐嵌入到了英语符号中。因此,您首先需要执行音译来实现数据中的一致性,然后再继续执行处理/文本分析。

如果使用预定的语言,那么数据音译会为您提供更统一、更一致的结果。本文将介绍使用 InfoSphere Streams 的自定义 Java 运算符和 ICU4J 库执行实时音译时所涉及的步骤。IBM InfoSphere Streams 提供了执行实时分析流程的功能,提供了各种工具包和适配器,允许您实时连接到各种资源并从中交换数据,在数据上执行操作。实时音译的高级实现架构如图 1 所示。

图 1. 实时音译高级解决方案图
实时音译解决方案架构

先决条件

  • 业务先决条件:应当具有利用 InfoSphere Streams 设计和运行 Streams Processing Language (SPL) 应用程序作业的基本技能,并能利用 Java 编程的中级技能。源语言必须使用 UTF-8、UTF-16 格式进行编码。
  • 软件先决条件:InfoSphere Streams(2.0 或更高版本),以及 ICU4J 库。

创建音译自定义 Java 运算符

执行以下步骤,创建音译自定义 Java 运算符。

  1. 按照 Streams 信息中心 中的描述搭建用于 Java 运算符开发的 Streams Studio 环境。
  2. 搭建好环境之后,使用 Java 运算符中的 ICU4J 库编写音译逻辑。ICU4J 库的 jar 文件应导入到项目工作区中。SPL 中的原始 Java 运算符的结构如清单 1 所示。
    清单 1. InfoSphere Streams 中 Java 运算符的格式
    public synchronized void initialize(OperatorContext context);
                            
    public void process(StreamingInput<Tuple> inputStream, Tuple tuple);
                            
    public void processPunctuation(StreamingInput<Tuple> inputStream,
                StreamingData.Punctuation marker);
                            
    public void allPortsReady();
                            
    public void shutdown();
  3. 运算符的逻辑应位于流程函数内。清单 2 显示了一个样例代码。
    清单 2. 使用 Java 运算符执行音译的样例代码
    public String toBaseCharacters(final String sText) {
            if (sText == null || sText.length() == 0)
                    return sText;
                            
            final char[] chars = sText.toCharArray();
            final int iSize = chars.length;
            final StringBuilder sb = new StringBuilder(iSize);
            for (int i = 0; i < iSize; i++) {
                    String sLetter = new String(new char[] { chars[i] });
                    sLetter = Normalizer.normalize(sLetter, Normalizer.NFKD);
                            
                    try {
                    byte[] bLetter = sLetter.getBytes("UTF-8");
                    sb.append((char) bLetter[0]);
                    } catch (UnsupportedEncodingException e) {
                    }
            }
            return sb.toString();
    }
                            
    public final synchronized void process(final StreamingInput input,
                            final Tuple tuple) throws Exception  {
            try
            {
                    OperatorContext ctxt =getOperatorContext();
                            
                    Transliterator t=Transliterator.getInstance(
                ctxt.getParameterValues("sourceLanguage").get(0)+"-"+
                    ctxt.getParameterValues("destLanguage")
                    .get(0));				
                    StreamingOutput<OutputTuple> output = getOutput(0);
                    OutputTuple outputTuple = output.newTuple();
                    boolean  reject      = false;
                    //read the source tuple
                    String value =  tuple.getString("inp");
                            
                    if ((value == null)) {
                    throw(new Exception("Input is null"));
                    } else {
                    outputTuple.setString("TransliteratedText",
                    toBaseCharacters(t.transliterate(value.toString())));
                    }
                    output.submit(outputTuple);                        
                }
                catch(Exception e)
                {
                            
                }
                .....

    读取输入文本,进行音译,然后提交给输出端口,请注意,应将输入作为 ustring 来读取,这是 Java 运算符中的字符串。
  4. 创建并编译好运算符代码后,配置运算符模型,使之可供 SPL 应用程序使用。
  5. 对于每一个新运算符而言,根据需要指定的整体配置需求创建相应的运算符模型。运算符模型的一个片段如图 2 所示。
    图 2. 外部的库依赖关系
    该图显示了运算符模型,为每一个新模型创建了不同的运算符模型
  6. 运算符中需要为各个代码小节设置的值如表 1 所示。
表 1. 自定义 Java 运算符模型
代码小节属性描述
Context -> Execution SettingsClass Name表示包含执行音译的逻辑的 Java 运算符的类名称。com.ibm.streams.transliteration
Context -> Libraries-> LibraryLibPath表示 ICU4J 库的 jar 文件的绝对路径或相对路径。../../impl/lib/icu4j.jar
Context -> Libraries-> LibraryLibPath表示存放运算符类文件的绝对路径和相对路径。../../impl/java/bin
Parameters -> ParameterName以源语言读取的 rstring 类型的参数。sourceLanguage
Parameters -> ParameterName以将要音译的语言读取的 rstring 类型的参数。destLanguage

通过 SPL 在 InfoSphere Streams 应用程序中使用自定义的 Java 运算符

考虑这样一个场景,通过分析博客帖子和社交媒体社区帖子,您希望了解什么样的人群在讨论您的产品,该场景是专门针对您的产品而创建。您的产品的客户已经使用地方方言表达了他们的意见,但是分析工具很难理解这些客户的态度,因为文本分析规则并不适用于所有方言。

为了解决这一挑战,可在源语言上执行音译,然后进行分析。清单 3 向您展示了如何在执行文本分析之前执行音译。音译运算符具有两个参数:源语言和目标语言。如果源语言已知,则需要对其进行相应的设置。如果输入语言未知,或者具有多种语言符号,那么将其设置为 Any 会更安全一些。

清单 3. 使用自定义 Java 运算符执行音译的 SPL 样例应用程序
composite Main {
                
        graph
        stream <rstring LingualInput> SourceBlogs = InetSource ()
        {
                param
                URIList:
                        ["http://localblogs.com/fashionwear"];
                initDelay: 5u;
                incrementalFetch: true;
                fetchIntervalSeconds: 60u;
        }	
                
        stream <ustring TransliteratedText> TransliteratedOutput=
        Transliterate(LingualInput)
        {
                param
                        sourceLanguage:"Any";
                        destLanguage:"Latin";
        } 		
                
    stream <rstring text,rstring product,rstring sentiment,rstring sentiment_text> 
        as sentiment = TextExtractor(TransliteratedOutput)
        {
                param
                        AQLFile: "getsentiment.aql";
    }
        () as RssResults = FileSink(sentiment)
        {
            param
                    file: "output.txt";
                    format: csv;
                    hasDelayField: false;
                } 
                
}

考虑从 URL 中读取输入。在这里,客户对 xyz 公司的产品表达了负面的情绪。此时的挑战就是输入,这是一个多语言的文本。

मुझे xyz suit पसंद नहीं आया

进行音译之后,输入就转换为英语格式。

mujhe xyz suit pasanda nahin aya

音译输出为您提供了一个运行文本分析的通用平台。在文本中,pasandnahin 都包含负面情绪。因此,这个输入连同 AQL 文件中的规则一起传递给 Text Extractor 运算符,AQL 文件中的规则配置为处理音译后的地区方言关键词,比如 pasand、nahin 等。因此,Text Extractor 的输出将如下所示。

mujhe xyz suit pasanda nahin aya, negative, nahin aaya

因此,您可以从一个多语言输入中成功提取客户的情绪。


ICU4J 简介

ICU4J 提供一组支持区域化的类别。支持区域化功能的主要类别是 TransliteratorNormalizer

  • Transliterator 类提供了一个 transliterate() 函数,该函数将字符串从一种语言转换为另一种语言。音译函数没有状态,也就是说函数中不保留以前的调用信息。使用 transliterate() 函数之前,需要为 Transliterator 实例提供所需的源语言和目标语言来将其初始化,并用破折号 (-) 分隔它们。例如:Transliterator.getInstance("Hindi-Latin");
  • Normalizer 类提供将音译函数的输出标准化为组合格式或分解格式的函数。例如:拉丁字符 A-acute 等就可标准化为组合格式的单个 A,或者分解格式的两个 A (AA)。

ICU4J 支持的一些语言转换如下所示。

  • ASCII-Latin
  • Accents-Any
  • Amharic-Latin/BGN
  • Arabic-Latin
  • Bengali-Devanagari
  • Bengali-Latin
  • Kannada-Latin
  • Hindi-Latin
  • Telugu-Latin
  • Tamil-Latin

异常情况

InfoSphere Streams 提供了一个调试程序,可以支持实时应用程序 Streams Debugger。Streams Debugger 提供的命令和选项可轻松用于跟踪和验证输出。您可以在 参考资料 一节中找到 Streams Debugger 的有关调试的更多信息。


结束语

本文提出了如何使用 ICU4J 库执行音译的问题,以及人们在构建原始 Java 运算符时必须执行的各种配置设置。音译将充当解决多种语言挑战的关键组件,并为运行文本分析提供了一个共同基础。

参考资料

学习

获得产品和技术

  • 利用 IBM 试用版软件 构建您的下一个开发项目,该软件可直接从 developerWorks 下载。
  • 以最适合您的方式 评估 IBM 产品:下载产品试用版,在线试用产品,在云环境下使用产品,或者在 SOA 沙盒 中花费几小时来了解如何高效地实现面向服务的架构。
  • 您可以在 ICU 下载部分 中找到已经可供下载的新版本。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management
ArticleID=943264
ArticleTitle=使用 InfoSphere Streams 的自定义 Java 运算符和 ICU4J 实现实时音译
publish-date=09032013