0

此脚本在 play.golang.org 中编译时没有错误:http ://play.golang.org/p/Hlr-IAc_1f

但是当我在我的机器上运行时,比我预期的要长得多,终端没有发生任何事情。

我正在尝试构建的是 PartOfSpeech 标注器。

我认为最长的部分是将 lexicon.txt 加载到地图中,然后将每个单词与那里的每个单词进行比较,看看它是否已经在词典中被标记。词典只包含动词。但是不是每个单词都需要检查它是否是动词。

更大的问题是我不知道如何确定一个单词是否是具有简单启发式的动词,如副词、形容词等。

4

2 回答 2

7

(引用):

我不知道如何确定一个单词是否是具有简单启发式的动词,如副词、形容词等。

我无法谈论您的 Go 实现中的任何问题,但我将解决一般 POS 标记的更大问题。听起来您正在尝试构建基于规则的一元标记器。详细说明这些术语:

  • “unigram”表示您正在分别考虑句子中的每个单词。请注意,unigram 标记器本质上是有限的,因为它不能消除可以采用多个 POS 标记的单词的歧义。例如,您应该将“鱼”标记为名词还是动词?“last”是动词还是副词?
  • “基于规则”的意思正是它听起来的样子:一组规则来确定每个单词的标签。基于规则的标记以不同的方式受到限制 - 它需要大量的开发工作来组装一个规则集,该规则集将处理通用语言中合理部分的歧义。如果您正在使用我们没有良好培训资源的语言工作,这种努力可能是合适的,但在大多数常用语言中,我们现在有足够的标记文本来训练高精度标记模型。

最先进的 POS 标记在格式良好的新闻专线文本上的准确率超过 97%(在不太正式的类型上的准确率自然较低)。基于规则的标注器的性能可能会差很多(您必须确定满足您的要求所需的准确度级别)。如果您想继续使用基于规则的路径,我建议您阅读本教程。该代码基于 Haskell,但它将帮助您了解基于规则的标记中的概念和问题。

也就是说,我强烈建议您查看其他标记方法。我提到了 unigram 标记的弱点。相关的方法是'bigram',这意味着我们在标记单词n时考虑前一个单词,'trigram'(通常是前两个单词,或者前一个单词,当前单词和下一个单词);更一般地说,“n-gram”是指考虑 n 个单词的序列(通常是我们当前标记的单词周围的滑动窗口)。该上下文可以帮助我们消除“鱼”、“最后”、“苍蝇”等的歧义。

例如,在

我们钓鱼

我们可能想将fish标记为动词,而在

吃了鱼

这当然是一个名词。

NLTK 教程在这里可能是一个很好的参考。一个可靠的 n-gram 标注器应该让你的准确率超过 90%;可能高于 95%(再次在新闻专线文本上)。

更复杂的方法(称为“结构化推理”)将整个标签序列视为一个整体。也就是说,他们不是尝试分别预测每个单词的最可能标签,而是尝试预测整个输入序列的最可能标签序列。结构化推理当然更难实现和训练,但通常会比 n-gram 方法提高准确性。如果您想阅读该领域的内容,我建议您阅读Sutton 和 McCallum 的精彩介绍

于 2014-04-29T19:14:25.693 回答
0

您在此函数中有一个大数组参数:

func stringInArray(a string, list [214]string) bool{
    for _, b := range list{
        if b == a{
            return true;
        }
    }
    return false
}

每次调用此函数时都会复制停用词数组。

大多数情况下,在 Go 中,您应该在大多数情况下使用切片而不是数组。将 this 的定义更改为list []string并定义stopWords为切片而不是数组:

stopWords := []string{
    "and", "or", ...
}

可能更好的方法是构建一个停止词的地图:

isStopWord := map[string]bool{}
for _, sw := range stopWords {
    isStopWord[sw] = true
}

然后您可以快速检查一个单词是否为停用词:

if isStopWord[word] { ... }
于 2014-04-27T07:24:48.647 回答