Cómo configurar la detección de contenido NSFW con Machine Learning

Enseñar a una máquina a reconocer contenido indecente no fue difícil en retrospectiva, pero seguro que fue difícil la primera vez.

Aquí hay algunas lecciones aprendidas y algunos consejos y trucos que descubrí mientras construía un modelo NSFW.

Aunque hay muchas formas en que esto podría haberse implementado, la esperanza de esta publicación es proporcionar una narrativa amigable para que otros puedan entender cómo puede ser este proceso.

Si eres nuevo en ML, esto te inspirará a entrenar un modelo. Si está familiarizado con él, me encantaría saber cómo le habría ido con la construcción de este modelo y pedirle que comparta su código.

El plan:

  1. Obtenga una gran cantidad de datos
  2. Etiquetar y limpiar los datos
  3. Utilice Keras y transfiera el aprendizaje
  4. Refina tu modelo

Obtenga una gran cantidad de datos

Afortunadamente, se lanzó un conjunto realmente genial de scripts de scraping para un conjunto de datos NSFW. El código es simple y ya viene con categorías de datos etiquetadas. Esto significa que simplemente aceptar los valores predeterminados de este raspador de datos nos dará 5 categorías extraídas de cientos de subreddits.

Las instrucciones son bastante simples, simplemente puede ejecutar los 6 scripts amigables. Présteles atención, ya que puede decidir cambiar las cosas.

Si tiene más subreddits que le gustaría agregar, debe editar las URL de origen antes de ejecutar el paso 1.

Por ejemplo, si tuviera que agregar una nueva fuente de ejemplos neutrales, lo agregaría a la lista de subreddit en nsfw_data_scraper/scripts/source_urls/neutral.txt.

Reddit es un gran recurso de contenido en la web, ya que la mayoría de los subreddits están levemente controlados por humanos para estar en el objetivo de ese subreddit.

Etiquetar y limpiar los datos

¡Los datos que obtuvimos del raspador de datos NSFW ya están etiquetados! Pero espere algunos errores. Especialmente porque Reddit no está perfectamente curado.

La duplicación también es bastante común, pero se puede corregir sin una lenta comparación humana.

Lo primero que me gusta ejecutar es duplicate-file-findercuál es la coincidencia y eliminación exacta de archivos más rápida. Está potenciado en Python.

Qarj / buscador-de-archivos-duplicados

Encuentra archivos duplicados. Contribuya al desarrollo de Qarj / duplicate-file-finder creando una cuenta en GitHub. github.com

Por lo general, puedo eliminar la mayoría de los duplicados con este comando.

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

Ahora, esto no capta imágenes que son "esencialmente" iguales. Para eso, recomiendo usar una herramienta Macpaw llamada "Gemini 2".

Si bien esto parece súper simple, no olvide indagar en los duplicados automáticos y seleccione TODOS los duplicados hasta que su pantalla de Gemini declare "Nada restante" así:

Es seguro decir que esto puede llevar mucho tiempo si tiene un gran conjunto de datos. Personalmente, lo ejecuté en cada clasificación antes de ejecutarlo en la carpeta principal para mantener tiempos de ejecución razonables.

Utilice Keras y transfiera el aprendizaje

He analizado Tensorflow, Pytorch y Python sin procesar como formas de crear un modelo de aprendizaje automático desde cero. Pero no busco descubrir algo nuevo, quiero hacer efectivamente algo preexistente. Así que fui pragmático.

Encontré que Keras es la API más práctica para escribir un modelo simple. Incluso Tensorflow está de acuerdo y actualmente está trabajando para parecerse más a Keras. Además, con solo una tarjeta gráfica, tomaré un modelo preexistente popular + pesos y simplemente entrenaré sobre él con algo de aprendizaje de transferencia.

Después de investigar un poco, elegí Inception v3 ponderado con imagenet. Para mí, eso es como ir a la tienda ML preexistente y comprar el Aston Martin. Simplemente afeitaremos la capa superior para poder usar ese modelo según nuestras necesidades.

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

Con el modelo en su lugar, agregué 3 capas más. Una capa de 256 neuronas ocultas, seguida de una capa de 128 neuronas oculta, seguida de una capa final de 5 neuronas. Esta última es la clasificación final en las cinco clases finales moderadas por 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)

Visualmente, este código se convierte en esto:

Algunas de las anteriores pueden parecer extrañas. Después de todo, no todos los días dices "glorot_uniform". Pero aparte de las palabras extrañas, mis nuevas capas ocultas se están regularizando para evitar el sobreajuste.

Estoy usando abandono, que eliminará al azar las vías neuronales para que ninguna característica domine el modelo.

Además, también agregué la regularización L2 a la primera capa.

Ahora que el modelo está terminado, aumenté mi conjunto de datos con cierta agitación generada. Roté, cambié, recorté, corté, amplié, volteé y cambié de canal mis imágenes de entrenamiento. Esto ayuda a garantizar que las imágenes se entrenan a través del ruido común.

Todos los sistemas anteriores están destinados a evitar sobreajustar el modelo en los datos de entrenamiento. Incluso si se trata de una tonelada de datos, quiero mantener el modelo lo más generalizable posible a los nuevos datos.

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 pudiera fabricar un defecto ... me quedaría con Jeff. Pero, por desgracia, ¡hemos alcanzado el 93% de precisión!

En resumen

Puede que me haya llevado mucho tiempo, pero no fue difícil y fue divertido construir un modelo. ¡Le sugiero que tome el código fuente y lo pruebe usted mismo! Probablemente incluso intentaré reentrenar el modelo con otros marcos para comparar.

Muéstrame lo que tienes. Contribuir o? Destaque / mire el repositorio si desea ver el progreso: https://github.com/GantMan/nsfw_model

Gant Laborde es estratega en jefe de tecnología en Infinite Red, autor publicado, profesor adjunto, orador público mundial y científico loco en formación. Aplaude / sigue / tuitea o visítalo en una conferencia.

¿Tienes un minuto? Mira algunos más:

Evite las pesadillas - 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