内容


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

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

Comments

简介

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

如果使用预定的语言,那么数据音译会为您提供更统一、更一致的结果。本文将介绍使用 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 运算符时必须执行的各种配置设置。音译将充当解决多种语言挑战的关键组件,并为运行文本分析提供了一个共同基础。


相关主题


评论

添加或订阅评论,请先登录注册

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