Comment configurer la détection de contenu NSFW avec Machine Learning

Apprendre à une machine à reconnaître un contenu indécent n'a pas été difficile rétrospectivement, mais c'était certainement difficile la première fois.

Voici quelques leçons apprises et quelques trucs et astuces que j'ai découverts lors de la construction d'un modèle NSFW.

Bien que cela ait pu être mis en œuvre de nombreuses façons, l'espoir de cet article est de fournir un récit amical afin que d'autres puissent comprendre à quoi ce processus peut ressembler.

Si vous êtes nouveau dans ML, cela vous incitera à former un modèle. Si vous le connaissez, j'aimerais savoir comment vous auriez pu créer ce modèle et vous demander de partager votre code.

Le plan:

  1. Obtenez beaucoup de données
  2. Étiquetez et nettoyez les données
  3. Utiliser Keras et transférer l'apprentissage
  4. Affinez votre modèle

Obtenez beaucoup de données

Heureusement, un ensemble vraiment cool de scripts de scraping a été publié pour un jeu de données NSFW. Le code est simple est déjà livré avec des catégories de données étiquetées. Cela signifie que le simple fait d'accepter les valeurs par défaut de ce grattoir de données nous donnera 5 catégories tirées de centaines de sous-redits.

Les instructions sont assez simples, vous pouvez simplement exécuter les 6 scripts conviviaux. Faites attention à eux car vous pourriez décider de changer les choses.

Si vous souhaitez ajouter d'autres sous-redits, vous devez modifier les URL sources avant d'exécuter l'étape 1.

Par exemple, si vous deviez ajouter une nouvelle source d'exemples neutres, vous l'ajouteriez à la liste des subreddits dans nsfw_data_scraper/scripts/source_urls/neutral.txt.

Reddit est une excellente ressource de contenu sur le Web, car la plupart des sous-reddit sont légèrement contrôlés par les humains pour être ciblés pour ce sous-reddit.

Étiquetez et nettoyez les données

Les données que nous avons obtenues du grattoir de données NSFW sont déjà étiquetées! Mais attendez-vous à des erreurs. D'autant que Reddit n'est pas parfaitement organisé.

La duplication est également assez courante, mais réparable sans comparaison humaine lente.

La première chose que j'aime exécuter duplicate-file-finderest la correspondance et la suppression de fichier exactes les plus rapides. Il est alimenté en Python.

Qarj / duplicate-file-finder

Trouvez les fichiers en double. Contribuez au développement de Qarj / duplicate-file-finder en créant un compte sur GitHub. github.com

Je peux généralement éliminer la majorité des doublons avec cette commande.

python dff.py --path train/path --delete

Maintenant, cela n'attrape pas les images qui sont «essentiellement» les mêmes. Pour cela, je préconise l'utilisation d'un outil Macpaw appelé «Gemini 2».

Bien que cela semble super simple, n'oubliez pas de fouiller dans les doublons automatiques et sélectionnez TOUS les doublons jusqu'à ce que votre écran Gemini déclare «Rien ne reste» comme ceci:

Il est prudent de dire que cela peut prendre un temps extrême si vous avez un énorme ensemble de données. Personnellement, je l'ai exécuté sur chaque classification avant de l'exécuter sur le dossier parent afin de conserver des durées d'exécution raisonnables.

Utiliser Keras et transférer l'apprentissage

J'ai examiné Tensorflow, Pytorch et Python brut comme moyens de créer un modèle d'apprentissage automatique à partir de zéro. Mais je ne cherche pas à découvrir quelque chose de nouveau, je veux effectivement faire quelque chose de préexistant. Alors je suis allé pragmatique.

J'ai trouvé que Keras était l'API la plus pratique pour écrire un modèle simple. Même Tensorflow est d'accord et travaille actuellement pour être plus semblable à Keras. De plus, avec une seule carte graphique, je vais prendre un modèle préexistant populaire + poids, et simplement m'entraîner dessus avec un apprentissage par transfert.

Après quelques recherches, j'ai choisi Inception v3 pondérée avec imagenet. Pour moi, c'est comme aller au magasin ML préexistant et acheter l'Aston Martin. Nous allons simplement raser la couche supérieure afin de pouvoir utiliser ce modèle selon nos besoins.

conv_base = InceptionV3( weights="imagenet", include_top=False, input_shape=(height, width, num_channels) )

Avec le modèle en place, j'ai ajouté 3 couches supplémentaires. Une couche de 256 neurones cachés, suivie d'une couche de 128 neurones cachés, suivie d'une couche finale de 5 neurones. Ce dernier étant le classement ultime dans les cinq classes finales modérées par softmax.

# Add 256 x = Dense(256, activation="relu", kernel_initializer=initializers.he_normal(seed=None), kernel_regularizer=regularizers.l2(.0005))(x) x = Dropout(0.5)(x) # Add 128 x = Dense(128,activation='relu', kernel_initializer=initializers.he_normal(seed=None))(x) x = Dropout(0.25)(x) # Add 5 predictions = Dense(5, kernel_initializer="glorot_uniform", activation="softmax")(x)

Visuellement, ce code se transforme en ceci:

Certains des éléments ci-dessus peuvent sembler étranges. Après tout, ce n'est pas tous les jours que vous dites «glorot_uniform». Mais à part les mots étranges, mes nouvelles couches cachées sont en cours de régularisation pour éviter le surajustement.

J'utilise l'abandon, qui supprimera aléatoirement les voies neuronales afin qu'aucune fonctionnalité ne domine le modèle.

De plus, j'ai également ajouté la régularisation L2 à la première couche.

Maintenant que le modèle est terminé, j'ai augmenté mon ensemble de données avec une certaine agitation générée. J'ai tourné, décalé, recadré, tranchant, zoomé, retourné et le canal décalé mes images d'entraînement. Cela permet de garantir que les images sont entraînées par le bruit commun.

Tous les systèmes ci-dessus sont destinés à éviter le surajustement du modèle sur les données d'entraînement. Même s'il s'agit d'une tonne de données, je souhaite que le modèle soit aussi généralisable que possible aux nouvelles données.

After running this for a long time, I got around 87% accuracy on the model! That’s a pretty good version one! Let’s make it great.

Refine your model

Basic fine-tuning

Once the new layers are trained up, you can unlock some deeper layers in your Inception model for retraining. The following code unlocks everything after as of the layer conv2d_56.

set_trainable = False for layer in conv_base.layers: if layer.name == 'conv2d_56': set_trainable = True if set_trainable: layer.trainable = True else: layer.trainable = False

I ran the model for a long time with these newly unlocked layers, and once I added exponential decay (via a scheduled learning rate), the model converged on a 91% accuracy on my test data!

With 300,000 images, finding mistakes in the training data was impossible. But with a model with only 9% error, I could break down the errors by category, and then I could look at only around 5,400 images! Essentially, I could use the model to help me find misclassifications and clean the dataset!

Technically, this would find false negatives only. Doing nothing for bias on the false positives, but with something that detects NSFW content, I imagine recall is more important than precision.

The most important part of refining

Even if you have a lot of test data, it’s usually pulled from the same well. The best test is to make it easy for others to use and check your model. This works best in open source and simple demos. I released //nsfwjs.com which helped the community identify bias, and the community did just that!

The community got two interesting indicators of bias fairly quickly. The fun one was that Jeffrey Goldblum kept getting miscategorized, and the not-so-fun one was that the model was overly sensitive to females.

Once you start getting into hundreds of thousands of images, it’s hard for one person (like moi) to identify where an issue might be. Even if I looked through a thousand images in detail for bias, I wouldn’t have even scratched the surface of the dataset as a whole.

That’s why it’s important to speak up. Misclassifying Jeff Goldblum is an entertaining data point, but identifying, documenting, and filing a ticket with examples does something powerful and good. I was able to get to work on fixing the bias.

With new images, improved training, and better validation I was able to retrain the model over a few weeks and attain a much better outcome. The resulting model was far more accurate in the wild. Well, unless you laughed as hard as I did about the Jeff Goldblum issue.

Si je pouvais fabriquer un défaut… je garderais Jeff. Mais hélas, nous avons atteint une précision de 93%!

En résumé

Cela a peut-être pris beaucoup de temps, mais ce n'était pas difficile et c'était amusant de construire un modèle. Je vous suggère de récupérer le code source et de l'essayer par vous-même! J'essaierai même probablement de recycler le modèle avec d'autres cadres de comparaison.

Montre-moi ce que tu as. Contribuer ou? Star / regardez le repo si vous souhaitez voir les progrès: https://github.com/GantMan/nsfw_model

Gant Laborde est stratège en chef de la technologie chez Infinite Red, auteur publié, professeur adjoint, orateur public mondial et scientifique fou en formation. Applaudissez / suivez / tweetez ou rendez-lui visite lors d'une conférence.

Avoir une minute? Découvrez-en quelques autres:

Évitez les cauchemars - NSFW JS

Client-side indecent content checking for the soulshift.infinite.red5 Things that Suck about Remote Work

The Pitfalls of Remote Work + Proposed Solutionsshift.infinite.red