モデル概要
モデル特徴
モデル能力
使用事例
license: mit base_model:
- timm/eva02_base_patch14_448.mim_in22k_ft_in22k_in1k pipeline_tag: image-classification tags:
- pytorch
- transformers
EVAベースの高速NSFW画像分類器
目次
モデル説明
このモデルはEVAアーキテクチャに基づくビジョントランスフォーマーで、NSFWコンテンツ分類用にファインチューニングされています。10万枚の合成ラベル付き画像を使用して、4つのカテゴリ(neutral, low, medium, high)の視覚コンテンツを検出するようにトレーニングされています。
このモデルは、必要に応じてバイナリ(true/false)分類器として使用したり、完全な出力確率を取得したりできます。Falconsai/nsfw_image_detectionやAdamCodd/vit-base-nsfw-detectorなどの他の優れた公開モデルよりも優れた性能を発揮し、ユースケースに適したNSFWレベルを選択できるという利点もあります。
オンラインで試す! 🚀
Hugging Face Spaceを通じて、ブラウザで直接このモデルを試すことができます。任意の画像をアップロードすると、インストールなしで即座にNSFW分類結果を得られます。
モデル性能比較
全体性能
カテゴリ | Freepik | Falconsai | Adamcodd |
---|---|---|---|
High | 99.54% | 97.92% | 98.62% |
Medium | 97.02% | 78.54% | 91.65% |
Low | 98.31% | 31.25% | 89.66% |
Neutral | 99.87% | 99.27% | 98.37% |
以下の表の結果は次のように得られました:
-
FalconsaiとAdamCoddモデルの場合:
- 画像が「low」、「medium」、「high」とラベル付けされ、モデルがtrueを返した場合、予測は正しいと見なされます。
- ラベルが「neutral」の場合、正しい出力はfalseです。
-
Freepikモデルの場合:
- 画像ラベルが「low」、「medium」、「high」の場合、モデルは少なくとも「low」を返す必要があります。
- ラベルが「neutral」の場合、正しい出力は「neutral」です。
結論:
- 私たちのモデルはAdamCoddとFalconsaiよりも精度が高いです。「high」と「neutral」ラベルでの比較は完全に公平です。
- 私たちのモデルはより細かい粒度を提供します。「high」と「neutral」コンテンツの検出に適しているだけでなく、「low」と「medium」のNSFWコンテンツの識別にも優れています。
- Falconsaiは一部の「medium」と「low」画像をNSFWとして分類せず、他のものを安全(SFW)としてマークする可能性があり、予期しない結果を招く可能性があります。
- AdamCoddは「low」と「medium」カテゴリの両方をNSFWとして分類しますが、ユースケースによっては望ましくない場合があります。さらに、「low」と「medium」の画像の10%がSFWと見なされます。
AIコンテンツ別精度
バイアス(性別、民族など)を避けるために注意を払いながら、手動でラベル付けされたデータセットを作成しました。サンプルサイズは比較的小さいですが、さまざまなシナリオでのモデル性能について有意義な洞察を提供し、トレーニングプロセスでバイアスを避けるのに非常に役立ちました。
以下の表は、さまざまなNSFWカテゴリとコンテンツタイプにわたる検出精度の割合を示しています:
AI生成コンテンツ
カテゴリ | Freepikモデル | Falconsaiモデル | Adamcoddモデル |
---|---|---|---|
High | 100.00% | 84.00% | 92.00% |
Medium | 96.15% | 69.23% | 96.00% |
Low | 100.00% | 35.71% | 92.86% |
Neutral | 100.00% | 100.00% | 66.67% |
結論:
- AI生成コンテンツにはFalconsaiを使用しないでください。予測エラーを防ぐためです。
- AI生成コンテンツのNSFWコンテンツを検出するには、私たちのモデルが最適です。
使用方法
pipによるクイックスタート
pip install nsfw-image-detector
from PIL import Image
from nsfw_image_detector import NSFWDetector
import torch
# 検出器を初期化
detector = NSFWDetector(dtype=torch.bfloat16, device="cuda")
# 画像を読み込んで分類
image = Image.open("your_image")
# 画像に「medium」以上のNSFWコンテンツが含まれているか確認
is_nsfw = detector.is_nsfw(image, "medium")
# すべてのカテゴリの確率スコアを取得
probabilities = detector.predict_proba(image)
print(f"Is NSFW: {is_nsfw}")
print(f"Probabilities: {probabilities}")
出力例:
Is NSFW: False
Probabilities:
[
{<NSFWLevel.HIGH: 'high'>: 0.00372314453125,
<NSFWLevel.MEDIUM: 'medium'>: 0.1884765625,
<NSFWLevel.LOW: 'low'>: 0.234375,
<NSFWLevel.NEUTRAL: 'neutral'>: 0.765625}
]
パイプラインでのクイックスタート
from transformers import pipeline
from PIL import Image
# 分類器パイプラインを作成
classifier = pipeline(
"image-classification",
model="Freepik/nsfw_image_detector",
device=0 # GPU(0)またはCPU(-1)を使用
)
# 画像を読み込んで分類
image = Image.open("path/to/your/image.jpg")
predictions = classifier(image)
print(predictions)
出力例:
[
{'label': 'neutral', 'score': 0.92},
{'label': 'low', 'score': 0.05},
{'label': 'medium', 'score': 0.02},
{'label': 'high', 'score': 0.01}
]
このモデルは、複数の画像の効率的なバッチ処理をサポートしています:
images = [Image.open(path) for path in ["image1.jpg", "image2.jpg", "image3.jpg"]]
predictions = classifier(images)
注: 本番環境でモデルを使用する場合は、このアプローチを使用する前に速度とメモリメトリクスセクションを確認してください。
pip依存関係のインストールを回避
以下の例は、NSFW検出ラベルをカスタマイズする方法を示しています。PyPyのコードと非常に似ています。このコードは、NSFWレベルが「medium」以上の場合にTrueを返します:
from transformers import AutoModelForImageClassification
import torch
from PIL import Image
from typing import List, Dict
import torch.nn.functional as F
from timm.data.transforms_factory import create_transform
from torchvision.transforms import Compose
from timm.data import resolve_data_config
from timm.models import get_pretrained_cfg
device = "cuda" if torch.cuda.is_available() else "cpu"
# モデルとプロセッサを読み込む
model = AutoModelForImageClassification.from_pretrained("Freepik/nsfw_image_detector", torch_dtype = torch.bfloat16).to(device)
# オリジナルプロセッサを読み込む(テンサーの場合より高速)
cfg = get_pretrained_cfg("eva02_base_patch14_448.mim_in22k_ft_in22k_in1k")
processor: Compose = create_transform(**resolve_data_config(cfg.__dict__))
def predict_batch_values(model, processor: Compose, img_batch: List[Image.Image] | torch.Tensor) -> List[Dict[str, float]]:
"""
画像のバッチを処理し、各NSFWカテゴリの予測スコアを返す
"""
idx_to_label = {0: 'neutral', 1: 'low', 2: 'medium', 3: 'high'}
# バッチを準備
inputs = torch.stack([processor(img) for img in img_batch])
output = []
with torch.inference_mode():
logits = model(inputs).logits
batch_probs = F.log_softmax(logits, dim=-1)
batch_probs = torch.exp(batch_probs).cpu()
for i in range(len(batch_probs)):
element_probs = batch_probs[i]
output_img = {}
danger_cum_sum = 0
for j in range(len(element_probs) - 1, -1, -1):
danger_cum_sum += element_probs[j]
if j == 0:
danger_cum_sum = element_probs[j]
output_img[idx_to_label[j]] = danger_cum_sum.item()
output.append(output_img)
return output
def prediction(model, processor, img_batch: List[Image.Image], class_to_predict: str, threshold: float=0.5) -> List[bool]:
"""
画像が特定のNSFW閾値を満たすか超えるかを予測
"""
if class_to_predict not in ["low", "medium", "high"]:
raise ValueError("class_to_predict must be one of: low, medium, high")
if not 0 <= threshold <= 1:
raise ValueError("threshold must be between 0 and 1")
output = predict_batch_values(model, processor, img_batch)
return [output[i][class_to_predict] >= threshold for i in range(len(output))]
# 使用例
image = Image.open("path/to/your/image.jpg")
print(predict_batch_values(model, processor, [image]))
print(prediction(model, processor, [image], "medium")) # オプション: low, medium, high
出力例:
[
{'label': 'neutral', 'score': 0.92},
{'label': 'low', 'score': 0.08},
{'label': 'medium', 'score': 0.03},
{'label': 'high', 'score': 0.01}
]
[False]
注: 合計が1を超えるのは、選択したラベル以上のすべてのラベルの累積和が予測されるためです(neutralを除く)。たとえば、「medium」を選択すると、「medium」と「high」の合計になります。私たちの意見では、このアプローチは最高確率ラベルのみを選択するよりも効果的です。
トレーニング
- トレーニング中に10万枚の画像が使用されました。
- モデルは3 NVIDIA GeForce RTX 3090で3エポックトレーニングされました。
- モデルはトレーニングと検証の2つのセットでトレーニングされました。
- トレーニングと検証の間で重複やバイアスを避けるため、コサイン類似度が0.92以上の画像はありません。重複排除に使用されたモデルは「openai/clip-vit-base-patch32」です。
- カスタムロスが作成され、真のクラスよりも低い予測を最小化します。たとえば、「high」とラベル付けされた画像が「neutral」と予測されることは非常に稀です(0.46%の確率でしか発生しません)。
速度とメモリメトリクス
バッチサイズ | バッチあたり平均(ms) | VRAM(MB) | 最適化 |
---|---|---|---|
1 | 28 | 540 | PIL画像を使用したBF16 |
4 | 110 | 640 | PIL画像を使用したBF16 |
16 | 412 | 1144 | PIL画像を使用したBF16 |
1 | 10 | 540 | テンサーを使用したBF16 |
4 | 33 | 640 | テンサーを使用したBF16 |
16 | 102 | 1144 | テンサーを使用したBF16 |
注:
- モデルはbf16でトレーニングされているため、bf16での使用が推奨されます。
- テンサーを使用: テンサーを使用した速度はパイプラインでは達成されません。本番環境ではパイプラインの使用を避けてください。
- 測定はNVIDIA RTX 3090で行われました。より強力なサーバーではより良いメトリクスが期待できます。
- スループットはバッチサイズが大きいほど向上します。バッチサイズを選択する際はユースケースを考慮してください。
- リストされた最適化は、パフォーマンスをさらに向上させる可能性のある提案です。
- テンサーの使用は特に推奨されます。たとえば、テキストから画像へのモデルや類似の用途にモデルを使用する場合、出力はすでにテンサー形式です。
ライセンス
このプロジェクトはMITライセンスの下でライセンスされています - 著作権 2025 Freepik Company S.L.
引用
このモデルを研究やプロジェクトで使用する場合は、次のように引用してください:
@software{freepik2025nsfw,
title={EVA-based Fast NSFW Image Classifier},
author={Freepik Company S.L.},
year={2025},
publisher={Hugging Face},
url = {https://huggingface.co/Freepik/nsfw_image_detector},
organization = {Freepik Company S.L.}
}
謝辞
このモデルは、以下の論文で説明されているEVAアーキテクチャ(timm/eva02_base_patch14_448.mim_in22k_ft_in22k_in1k)に基づいています:
EVA-02: A Visual Representation for Neon Genesis - https://arxiv.org/abs/2303.11331
@article{EVA02,
title={EVA-02: A Visual Representation for Neon Genesis},
author={Fang, Yuxin and Sun, Quan and Wang, Xinggang and Huang, Tiejun and Wang, Xinlong and Cao, Yue},
journal={arXiv preprint arXiv:2303.11331},
year={2023}
}









