DFA 算法选型思路

1. 写在最前面

真的是心力交瘁的一个月,最近在做「敏感词过滤」的功能:

  • 需要识别敏感的英语单词
  • 需要识别敏感的英语词组

虽然笔者在需求评审会议上极力说明,这个需求的复杂程度比较高,自己实现有种种风险,但是无奈人家人多,被产品和负责人怼回来了。

行吧,做就做呗。不过这让我想起来一句话,「人有多大胆,地有多大产」。

2. 算法调研

2.1 google 大法好

本着不懂就查的思路,笔者从 google 处得到了一丝丝思路:

在这里插入图片描述

2.2 github 一下

接着这个思路,笔者从一众开源算法中,挑选到了

注:其实还尝试了 godlp,但这个更倾向于一个根据一系列规则对敏感数据的识别和处置方案,不大适用本场景。

3. 上手

3.1 不如试试

本着 「talk is cheap show me the code」的原则,笔者就这两个库,是否能够满足,产品的需求做了一个简单的 POC 尝试,代码如下:

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"

	filter "github.com/antlinker/go-dirtyfilter"
	"github.com/importcjj/sensitive"
)

func FilterDirtyFilter(path, content string, isReplace bool) ([]string, error) {
	fd, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	df := filter.NewNodeReaderFilter(bytes.NewReader(fd), '\n')
	var (
		result = make([]string, 0)
		rs     string
	)
	if isReplace {
		rs, err = df.Replace(content, '*')
		result = append(result, rs)

	} else {
		result, err = df.Filter(content)
	}

	if err != nil {
		return nil, err
	}
	return result, nil

}

func FilterSensitive(path, content string, isReplace bool) ([]string, error) {
	filter := sensitive.New()
	err := filter.LoadWordDict(path)
	if err != nil {
		return nil, err
	}
	if isReplace {
		s := filter.Replace(content, '*')
		return []string{s}, nil

	}

	s := filter.FindAll(content)
	return s, nil
}

func TestCNFilter() {
	c := "小明抓到了一只王八"
	fmt.Printf("原始词 %s - 脏词 %s\n", c, "王八")
	sr, err := FilterSensitive("./filter-cn.txt", c, true)
	if err != nil {
		panic(err)
	}
	dr, err := FilterDirtyFilter("./filter-cn.txt", c, true)
	if err != nil {
		panic(err)
	}
	fmt.Println("sensitive", sr)
	fmt.Println("dirty", dr)

}

func TestENFilter() {
	c := "fucked"
	fmt.Printf("原始词 %s - 脏词 %s\n", c, "fuck")
	sr, err := FilterSensitive("./filter-en.txt", c, true)
	if err != nil {
		panic(err)
	}
	dr, err := FilterDirtyFilter("./filter-en.txt", c, true)
	if err != nil {
		panic(err)
	}
	fmt.Println("sensitive", sr)
	fmt.Println("dirty", dr)

}

func main() {
	TestCNFilter()
	fmt.Println()
	TestENFilter()
}

注:./filter-en.txt 为与 mian.go 同级的一个文件,包含「fuck」 字符

​ ./filter-cn.txt 为与 main.go 同级的一个文件,包含 「王八」 字符

3.2 求甚解

上述两个库都是 DFA 算法的一种实现,实现的时候使用 Trie Tree 这种数据结构。这篇文章主要介绍选项的思路,后续有空会整理一篇 DFA 跟 Trie Tree 相关的文章。

注:先记在这里,求不打自己的脸。

4. 遇到的问题

「出来混,总是会遇到各种各样的问题」

4.1 英文词组可拆为字母

英文单词由单词组成,假设敏感词的词库里有 fuck 这个单词,所有带有 fuck 的词组,下图两个 golang 库测试例子:

在这里插入图片描述

4.2 误识别的问题

开源版本的算法,都是识别部分,不支持对上下文及情绪进行判断,会产生较高的误识别率,下图两个 golang 库测试例子:
在这里插入图片描述

注:做人啊,不能要求太高,连情绪啥的都开源了,人家做这个的公司不得黄了

5. 碎碎念

以上就是这个月糟心的开始,毕竟猜测没准产品他们后面就想着要不自己实现一个好了……,但是做人还是要乐观、坚持、努力吖:

  • 相逢的意义在于照亮彼此,不然的话 一个人喝茶也很浪漫,一个人吹风也能清醒。
  • 为什么要蜷缩在黑暗里,仅有一次的人生当然要活的炽热。
  • 在你的成长过程中,你会渐渐发现世界是以这样一种方式在运转着,人们会告诉你世事险恶,你要遵规守纪,不要做一些太出格的事。这是非常局限的生活。当你发现这样一个简单的事实,生命会无限扩展——你身边一切被你称之为生活的事物,都是一些不如你聪慧的人创造的。而你可以影响它们,你可以改变这一切,你可以建造出给别人带来福祉的事物,上面有着只属于你的印记。一旦你学会这一点,你将卓越不凡。

6. 参考资料

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值