如何将不使用空格的泰语句子拆分成单词?

16

如何从泰语句子中分割单词? 英语中,我们可以通过空格来分割单词。

示例:I go to school,分割 = ['I', 'go', 'to' ,'school'] 只用空格分割。

但是泰语没有空格,所以我不知道该如何做。例如:将“ฉันจะไปโรงเรียน”从txt文件中拆分为['ฉัน' 'จะ' 'ไป' 'โรง' 'เรียน'],并输出到另一个txt文件。

是否有任何程序或库可识别泰语单词边界并进行分割?


1
这是一个人的解决方案:https://issues.apache.org/jira/browse/LUCENE-503 - mpontillo
如果没有令牌,那么你不能像那样分割字符串。 - Mike
这不会是一个简单的工具,内置于像C或Python这样的语言中 - 需要使用对泰语有详细了解的库(我想这种库已经存在)。 - djechlin
@Mike - 我认为应该将库链接发布为答案。 - djechlin
@djechlin 好的,你成功地说服了我。;-) - mpontillo
5个回答

8
在2006年,有人为Apache Lucene项目贡献了代码来实现这一功能。
他们的方法(用Java编写)是使用BreakIterator类,调用getWordInstance()来获得基于字典的泰语单词迭代器。请注意,还有一个声明依赖于ICU4J项目。下面是他们代码的相关部分:
  private BreakIterator breaker = null;
  private Token thaiToken = null;

  public ThaiWordFilter(TokenStream input) {
    super(input);
    breaker = BreakIterator.getWordInstance(new Locale("th"));
  }

  public Token next() throws IOException {
    if (thaiToken != null) {
      String text = thaiToken.termText();
      int start = breaker.current();
      int end = breaker.next();
      if (end != BreakIterator.DONE) {
        return new Token(text.substring(start, end), 
            thaiToken.startOffset()+start,
            thaiToken.startOffset()+end, thaiToken.type());
      }
      thaiToken = null;
    }
    Token tk = input.next();
    if (tk == null) {
      return null;
    }
    String text = tk.termText();
    if (UnicodeBlock.of(text.charAt(0)) != UnicodeBlock.THAI) {
      return new Token(text.toLowerCase(), 
                       tk.startOffset(), 
                       tk.endOffset(), 
                       tk.type());
    }
    thaiToken = tk;
    breaker.setText(text);
    int end = breaker.next();
    if (end != BreakIterator.DONE) {
      return new Token(text.substring(0, end), 
          thaiToken.startOffset(), 
          thaiToken.startOffset()+end,
          thaiToken.type());
    }
    return null;
  }

鉴于,如果你在Lucene跟踪器上阅读历史记录,就会发现对ICU4J的依赖已从最终代码中移除。它只使用了标准的Java库。然而,如果你打算在非Java平台上进行这个操作,可以使用ICU项目。 - mpontillo

4

有多种方法可以进行“泰语单词分词”。一种方法是使用基于字典或模式的方法。在这种情况下,算法将通过字符,并且如果它出现在字典中,我们将计算为一个单词。

此外,还有最近的库可用于对泰文进行分词,其中使用深度学习对BEST corpus上的泰语单词进行了训练,包括rkcosmos/deepcutpucktada/cutkum等。

deepcut的示例用法:

import deepcut
deepcut.tokenize('ฉันจะไปโรงเรียน')
# output as ['ฉัน', 'จะ', 'ไป', 'โรง', 'เรียน']

1

对于中文和日文来说,最简单的分词器是使用基于贪心字典的方案。这种方法同样适用于泰语——获取一个泰语单词的字典,在当前字符处,匹配存在于字典中的最长字符串。这将为您提供一个相当不错的分词器,至少在中文和日文中如此。


在中文和日文中,音节的分界非常清晰。泰语在这方面稍微复杂一些。 - Mark Wilbur

1
在某种程度上,泰语单词之间不需要空格,因为约70%的单词都有自己内置的“分隔符”。
这就是我教外国人如何阅读泰语的方法。
虽然这涉及到一些启发式算法,但并不像其他语言中简单的空格那样直截了当。
首先,所有的“左手元音”(如 เ แ โ ไใ)都表示一个单词的开始。
字母 ห 几乎总是用来开头一个单词。
还有几个字母总是用来结束一个单词(如 ะ)。
还有一些字母组合表示下一个字母就是单词的结尾,例如 เบิx เxา เxย บัx บืx vบ็x/บ็อx(其中 บ 是任何辅音字母或“簇”,x 是任何辅音,v 是一个元音)。
不幸的是,当你用完所有内置的分隔符后,你必须进行字典搜索并调用启发式算法——因为一些字母组合可能有多种读法——你必须从上下文中知道哪个是正确的单词。如果你有一个不错的词汇量,通常很容易判断。

1
这里介绍如何使用 Kotlin 和 ICU4J 将泰语文本分成单词。与 Lucene 版本(最后更新于 2011 年)相比,ICU4J 是更好的选择,因为它不断更新并具有其他相关工具。在 mvnrepository.com 搜索 icu4j 可以查看所有工具。
 fun splitIntoWords(s: String): List<String> {
    val wordBreaker = BreakIterator.getWordInstance(Locale("th"));
    wordBreaker.setText(s)
    var startPos = wordBreaker.first()
    var endPos = wordBreaker.next()

    val words = mutableListOf<String>()

    while(endPos != BreakIterator.DONE) {
        words.add(s.substring(startPos,endPos))
        startPos = endPos
        endPos = wordBreaker.next()
    }

    return words.toMutableList()
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接