首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >贝叶斯垃圾邮件过滤接口

贝叶斯垃圾邮件过滤接口
EN

Code Review用户
提问于 2015-07-14 08:38:08
回答 1查看 84关注 0票数 6

本质上,我想要做的是把一个字符串分割成一个单词和两个单词片段,然后针对它们训练分类器。首先,它降低字符串,然后剥离所有非字母数字字符。

然后,它将字符串拆分为一个单字条目列表。之后,它创建了一个新的*[]string,它填充了所有连续的双单词条目。

特别是,我关心的是我创建两个单词的*[]string切片的方式,以及我使用指针的方式。第一个是效率问题,第二个是内存效率问题。

代码语言:javascript
复制
const (
    Spam     bayesian.Class = "Spam"
    Spamlike bayesian.Class = "Spamlike"
    NotSpam  bayesian.Class = "NotSpam"
)

type SpamFilter struct {
    singleWordClassifier *bayesian.Classifier
    doubleWordClassifier *bayesian.Classifier
}

func CreateNewSpamFilter() *SpamFilter {
    v1 := bayesian.NewClassifier(Spam, Spamlike, NotSpam)
    v2 := bayesian.NewClassifier(Spam, Spamlike, NotSpam)
    tmp := SpamFilter{v1, v2}
    return &tmp
}

func LoadSpamFilterFromFile(fileName1 string, fileName2 string) *SpamFilter {
    tmp1, err1 := bayesian.NewClassifierFromFile(fileName1)
    tmp2, err2 := bayesian.NewClassifierFromFile(fileName2)
    switch {
    case err1 != nil:
        panic(err1)
    case err2 != nil:
        panic(err2)
    }
    return &SpamFilter{tmp1, tmp2}
}

func splitStringToSingleWords(input string) *[]string {
    reg, err := regexp.Compile("[^A-Za-z0-9 ]+")
    if err != nil {
        panic(err)
    }

    tmp := reg.ReplaceAllString(input, "")
    split := strings.Fields(tmp)
    return &split
}

func SplitStringToWords(input string) (*[]string, *[]string) {
    splitSingle := splitStringToSingleWords(strings.ToLower(input))
    var splitDouble = make([]string, len(*splitSingle)-1)

    for i := 0; i < len(*splitSingle)-1; i++ {
        splitDouble[i] = (*splitSingle)[i] + " " + (*splitSingle)[i+1]
    }

    return splitSingle, &splitDouble
}

func (filter *SpamFilter) TrainStringsInSpamFilter(trainType bayesian.Class, singleWords *[]string, doubleWords *[]string) *SpamFilter {
    (*filter).singleWordClassifier.Learn(*singleWords, trainType)
    (*filter).doubleWordClassifier.Learn(*doubleWords, trainType)
    return filter
}

func (filter *SpamFilter) TestStringThroughSpamFilter(testString string) (*[]float64, *[]float64) {
    splitSingle, splitDouble := SplitStringToWords(testString)
    p1, _, _ := (*filter).singleWordClassifier.ProbScores(*splitSingle)
    p2, _, _ := (*filter).doubleWordClassifier.ProbScores(*splitDouble)
    return &p1, &p2
}

一般说来,这看上去怎么样?我该怎么做才好呢?

此外,在这里复制:

  • 我如何使用指针(嗯,对吗)?
  • 我是否以最有效的方式分割字符串?我打算在一个相当大的数据集上使用这一点。
  • 对于大型数据集来说,这是对线程安全/戈鲁丁友好的吗?
EN

回答 1

Code Review用户

发布于 2018-08-13 16:53:20

您错过了import块,所以我假设您在提供的代码段中使用github.com/jbrukh/bayesian作为bayesian

通过值

传递片

嗯。我知道你是如何在切片中使用指针的。让我告诉你一些关于切片内部的事情。

在Go片值中,C中有一个小的结构模拟来支持这个结构:

代码语言:javascript
复制
struct Slice {
    Elem *ptr;
    int cap;
    int len;
};

caplen字段代表片的容量和长度。ptr保存一个指针,用于片元素的连续内存。

因此,当您按值复制一个片段时,您实际上复制了它的标题,而不是它的内容:

代码语言:javascript
复制
a := []string{"Hello,", "World!"}

// Copying slice by value and changing it
b := a
b[1] = "Code Review!"

fmt.Println(a[0], a[1])

提供的代码片段将输出Hello,代码评审!因为a's和b's都指向相同的记忆。

按价值传递一片是完全可以的。大多数标准库代码都是这样做的。

接下来,我在Golang博客上发布了一篇关于切片和数组内部的Go切片:使用和内部文章,我建议您来看看。它解释了很多关于它们是如何制造的,以及为什么通过价值来传递它们是可以的。

提示:如果您确实需要一份切片的副本,请使用copy

另外,不要取消引用结构值,比如在(*filter).singleWordClassifier中。

直接使用filter.singleWordClassifier

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/96883

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档