在 React Native 里实作 NSFW (Not suitable for work,工作场合不宜) 分类器

需求与场景

虽然我们的 App 为了怕麻烦,有要求 18+ 以上才能使用,但还是怕会有绕过这个限制的小孩
在一对一聊天的场景,可以传图片。虽然大部分都非常健全,但偶尔还是会出现色情图片。
为了怕发生什麽对我们平台麻烦的事,我们决定要自动侦测是不是裸照,在搭配他们自己说的年龄(不等於实际年龄),如果有可能有十八岁以下,我们会自动跳出一个警告说如果有发现任何不法事宜会配合警察。

第一步:寻找分类器模型

完成我们的需求的第一步,就是要有一个裸照分类器。这个应该是非常常见的需求,所有的用户产生内容平台应该都有。我们一定没必要自己做,而且自己做也不一定做得比别人好。所以我们就很自然的去 GitHub 上找已经训练好的模型。
Github 上只要搜 "NSFW" (Not suitable for work,工作场合不宜) 就有非常多适合各种语言的现成模型。比如说
infinitered/nsfwjs: NSFW detection on the client-side via TensorFlow.js (github.com)
或是
GantMan/nsfw_model: Keras model of NSFW detector (github.com)

评估模型

我们找了几个 javascript 可以用的,做了简单的评估。
评估用的资料集是 1200 张实际用户传的图片,一半 positive(有裸露),一半 negative(正常)。
然後就简单的测了一下 precision 跟 recall。
最後选了一个表现最佳的模型。

实作

取的模型後,下一步是要加进 code 做实时判断。
因为我们用是 tensorflow 的模型,我们就用了 tfjs 这个 library
https://www.npmjs.com/package/@tensorflow/tfjs

import '@tensorflow/tfjs';
import * as tfnode from '@tensorflow/tfjs-node';

核心部分的实作如下

tfnode.tidy(() => {
	const tensor = tfnode.node.decodeImage(file.buffer, 3, 'int32');
	const image = tfnode.image
	.resizeBilinear(tensor, [IMAGE_SIZE, IMAGE_SIZE])
	.mul(1.0 / 255.0)
	.reshape([1, IMAGE_SIZE, IMAGE_SIZE, 3]);
	const predictions = mobilenet.predict(image) as tfnode.Tensor;
	const predictedData = predictions.dataSync();
	const adultRatio = predictedData[3] + predictedData[4];
	resolve(adultRatio);
});

效能影响

因为传图片不是主要功能,频率也不高,加了这个判断,对效能的影响不大。
唯一一种情况我们有优化的是,我们发现有些人会一直传同一张图片,为了避免每次都重复判断,判断过的图过我们会转成 hash,把 hash 跟结果存在 DB 里。如果以前有判断过,就直接取用。

结论

在做这个功能之前,曾经被抱怨过一两次,但自从加了这个分类器跟警告之後,一年多来都没有出现任何问题,所以我觉得这个功能有达到我们预期的效果了!

最新文章会分享在脸书:https://www.facebook.com/gigi.wuwu/
欢迎留言讨论


<<:  GitHub Actions 基本介绍 - 开始自动化 workflow 的第一步

>>:  Day 10 - Web Storage API

Day 11: QwikLabs

前情提要 Day 1: 介绍这30天的计画 Day 2-8: 刷题 Day 9-10: 面试找工作分...

【Day01】楔子-关於永丰金融APIs

iT邦帮忙一直以来都是我查询技术问题的好夥伴;而铁人赛为IT界名闻遐迩的年度盛事。 在友人极力鼓吹报...

【程序】说是说不 转生成恶役菜鸟工程师避免 Bad End 的 30 件事 - 25

说是说不 坚守原则,安全第一 一诺千金 最大公约数 ...

# Day 14 Cache and TLB Flushing Under Linux (Q&A - II)

今天来复习 cache 相关的知识! 首先可以参考一下这篇:Day.8 Cache 的基本原理 ca...