构建ngram频率表并处理多字节符文

时间:2013-12-26 03:55:08

标签: unicode go rune

我目前正在学习Go并且正在取得很大进展。我这样做的一种方法是将项目和原型从先前语言移植到新语言。

现在我正忙着用语言检测器"我不久前在Python中做了原型。在这个模块中,我生成一个ngram频率表,然后我计算给定文本和已知语料库之间的差异。

这允许通过返回给定ngram表的两个向量表示的余弦来有效地确定哪个语料库是最佳匹配。好极了。数学式

我有一个用Go编写的原型,它与普通的ascii字符完美配合,但我非常希望能够使用unicode多字节支持。这就是我正在努力的地方。

以下是我正在处理的问题的简短示例:http://play.golang.org/p/2bnAjZX3r0

我只发布了生成逻辑的表,因为一切都已经正常工作了。

正如您通过运行代码段所看到的那样,第一个文本可以很好地工作并构建一个准确的表格。第二个文本是德语,里面有几个双字节字符。由于我构建ngram序列的方式,并且由于这些特定符文由两个字节组成,因此出现了2个ngram,其中第一个字节被截断。

有人可能会发布更有效的解决方案,或者至少引导我解决问题吗?我几乎肯定我正在分析这个问题。

我计划开源这个软件包并使用Martini将其作为服务实现,从而提供一个简单的API,人们可以用它来进行简单的语言计算。

一如既往,谢谢!

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您希望chars函数中的Parse保留字符串中的最后n个字符。由于您对Unicode字符而不是UTF-8表示感兴趣,因此您可能会发现将其作为[]rune切片进行管理更容易,并且只有在准备好将ngram添加到字符串时才转换回字符串。表。这样,您的逻辑就不需要特殊情况下的非ASCII字符。

以下是对您执行上述操作的示例程序的简单修改:http://play.golang.org/p/QMYoSlaGSv

答案 1 :(得分:1)

通过保持符文的循环缓冲区,您可以最小化分配。另请注意,从映射中读取新键会返回零值(对于int为0),这意味着代码中的未知键检查是多余的。

func Parse(text string, n int) map[string]int {
    chars := make([]rune, 2 * n)
    table := make(map[string]int)
    k := 0
    for _, chars[k] = range strings.Join(strings.Fields(text), " ") + " " {
        chars[n + k] = chars[k]
        k = (k + 1) % n
        table[string(chars[k:k+n])]++
    }
    return table
}