1

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

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

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

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

这是我正在处理的一个简单示例:http ://play.golang.org/p/2bnAjZX3r0

我只发布了表格生成逻辑,因为一切都已经很好了。

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

有人可以发布更有效的解决方案,或者至少可以指导我完成修复吗?我几乎可以肯定我已经过度分析了这个问题。

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

一如既往,谢谢!

4

2 回答 2

1

通过保持 rune 的循环缓冲区,您可以最大限度地减少分配。另请注意,从映射中读取新键返回零值(对于 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
}
于 2013-12-26T14:04:41.737 回答
1

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

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

于 2013-12-26T06:43:50.277 回答