Using ML to detect fake face images created by AI

Using ML to detect fake face images created by AI

Improving a classifier to hold up in production

In this blog post, I will walk you through the steps on how I built and improved a supervised Machine Learning classifier to become better at prediction for production. Which actually is not at all the same thing as being good and accurate when contained in your lab. Right? ;)

My choice of classifier is to predict whether or not a face image is generated by an AI.

The three part blog series, describing this project, consist of the following posts:

  1. Using ML to detect fake face images created by AI
  2. Using ML to understand the behavior of an AI
  3. How long and how much to train an ML-classifier.

To play with the end result of this classifier, head to this super simple web app. The ML-model will present you with its prediction of face images you upload for it to classify.



  1. Deep Learning is easy with the Fastai Library and an ML-model can easily be trained to predict if an image is AI-generated performing better than humans.
  2. Near 100% accuracy, and no overfitting, still doesn’t guarantee the ML-model will perform well in production though.
  3. Improving for production involves presenting the model with new information creatively. The end result for this particular classifier is an accuracy of 99,99% for the Test set (simulation of production environment), a performance better than the Validation set after training, where the accuracy is 99,21%.
  4. Training with heavily photoshopped images makes some obviously AI-generated images be predicted as real-world images.
  5. Though seemingly advanced in replicating and recognizing faces, ML-models do not have the same understanding as us humans of what a face actually is. It is still just algorithms no smarter than its ability for pattern recognition.

AI-generated images are blowing our minds

Nvidia released in December 2018 a StyleGAN that resulted in an AI-generator that can produce very realistic fake human faces. You can check out the Nvidia AI-generated images for yourself at or just have a look at this collage that is put together by Nvidia:

To put these generated faces in perspective, below is a collage of faces generated by the same StyleGAN technology from 2014. This is how fast it has been moving along for the unsuspectable general public. Think about the somewhat suspicious applications of use that’s been putting AI-generated images in the spotlight: fake news and dating service profile pictures. Historically, new technology and its boundaries are tested first with inadequate use cases before the good is catching up. Legit areas of usage are starting to emerge now such as: artwork, marketing departments saving on expensive photoshoots, and access to faces of underrepresented groups to balance the usage of media and marketing material.

Let’s start

Come along the ride with me when I built and incrementally improved an ML-classifier for production to predict between if an image is:

  • An AI-generated image
  • Not an AI-generated image

The classifier is trained using the Fastai Library which sits on top of the widely used PyTorch framework. The PyTorch API has been expanded and enhanced to enable easy accessibility to Neural Nets and Deep Learning for anybody with some coding experiences and not requiring a formal training in Data Science.

The training (and validation) data used was 30 000 face images from a dataset with images produced by Nvidia’s AI-generator and the UTKFace dataset containing 24 000 face images from the real wild world produced by a real camera with a real person as a subject in the age span of 0-116 years. This is a total of 54 000 images, where 80% is used for training and 20% as validation.

To speed things up, a pre-trained convolutional neural network known as ResNet34 was chosen for my starting point. ResNet is trained on ImageNet, a dataset of 14 million images, publicly available for anyone doing Machine Learning.

Below is a sample of the images that started the training of my ML-model:

The first run

Very early on in training, already at the second run of the deep learning layers (number of epochs), the classifier reached an accuracy of both near 100% and actually even 100%. Since there were no classical signs of overfitting* in the trained model, this is a marker that the Fastai library is providing state-of-the-art model training.

Definitions and what is a sign of overfitting varies within the Data Science community and they can also contradict each other. The tell sign I’m using for overfitting is taught in the Fastai course materials: as long as the training loss is higher than the validation loss, then the model is for sure not overfitting. Some training beyond might be possible too as long as the validation loss is decreasing.

Note! Accuracy is defined as: 1 – error rate.

Near 100% accuracy is also a marker of that the problem at hand is a fairly easy one for an ML-algorithm to solve. Far easier than for the general public. As a curiosa, when I played the game at choosing between one real face image and one produced by an AI-generator, out of 30 pairs of images, I’ve got 5 incorrect. That is a whooping 17% error rate. Which we most likely would not readily accept to be good enough if predicted by an ML-model. See the collage below for some of the pairings I was presented with.

And if you really want to nerd yourself into the game, there are some tell signs for distinguishing images created by an AI from the real ones. Spoiler alert: it’s not about looking at the actual face for signs but for weird artifacts surrounding the face.

Is 100% accuracy of the model good enough for production?

One of the metrics to tell how good a produced ML-model is, and is used broadly by any Data Scientist, is accuracy. This metric will tell how well the training of the model went, in relation to the data set aside, called the validation set. Many times, though not always, the data for training and validation comes from the same data set.

A problem with accuracy in production arises when the data, in reality, differs from the data we used to train and validate the model with. Which explains why an ML-model can have an accuracy of near 100% but still do poorly when released outside the contained lab into the wild world and in hands of the end-user.

I do believe that the near 100% accuracy at the first try is actually a tell sign that it will most likely do substantially worse in production. Probably not worse than any other technique or choice of model training out there. The problem may be addressed by looking at the training data. The information provided for the model to train with may not be enough, in quantity or quality, for the complexity of the problem domain. In this case, it just translates into: predicting what is an image generated by an AI is quite easy, but not as easy as it seemed at first glance.

Stress-testing the ML-model

I found out by some creative thinking and trial and error, that one way to stress-test the model, is to test how well it will recognize images that are Photoshopped.

But, is a Photoshopped face image real or fake?

Well, ok, it’s fake. Semantically. In your world view, as well as in mine, an image of a Photoshopped face is not real. But the definition for ‘fake’ for this classifier is if the image of the face is AI-generated. A more suitable definition of a Photoshopped face image, in this context, would be to say it’s from the real world but manipulated. It’s in any way, not AI-generated.

For the model to be able to pick up on real face images that use filters like the ones from Instagram, or images that has been through post-production which is standard at all newspapers and magazines nowadays, I used the Real and Fake Face Detection Dataset (see sample below) available at Kaggle (an ML competition site with lots of public datasets available), as a Test set to benchmark how well my model would do in production.

The first run was quite alarming. As you see below, my model was only detecting 4% of the Photoshopped images as a real face image. That is much worse than a monkey brain picking a choice between two outcomes which would result in 50% accuracy by chance. The realization was that there was a systematic error built into the model.

The label “ai-generated” on the axis “Actual” is swooped for the label “photoshopped”, a category that does not exist for my model though. So 100% of the images, both with label “real-world” and “ai-generated/photoshopped” should be classified and predicted as a real-world face in this Stress test.

The idea to fix the problem is now to add more datasets to the training with variations that the model might not have seen before. This is to give the model new information to be able to go deeper in its understanding. This is essentially what Learning is about. I think about it as myself being the Mentor, providing the right material for my Adept, the Deep-Learning Neural Net, to become better in the Learning process.

Adding another AI-generated dataset

The Test set is used as a benchmark to measure the improvement, so it’s used as a Stress test. The goal is now to add more images to the training with new information. And the benchmark is to improve from 4% accuracy when testing against this Photoshopped dataset.

First, I added a new dataset of 3 000 AI-generated images by Generated Photos who is distributing model face images for easy transfer into any marketing campaign (or dating service as they themselves think is an appropriate use case). These photos differed from the set generated by Nvidia since the faces would be simulated to be shoot with a background of a blue screen.

To my surprise, adding this dataset changed nothing in regard to the accuracy on the Stress test!

The conclusion I drew is that all StyleGAN generators out there may probably have the same underlying understanding of how to produce a human face. There was nothing new introduced to the model by adding this other AI-generated dataset of faces. This is contrary to what my human eye is perceiving. Also, when researching a bit, it seems likely that the Nvidia dataset is the most thoroughly trained out in the public so far, trained with eight of the giant Nvidia’s fastest GPUs for 9 days non-stop.

Adding more datasets with faces from the real-world

I found several datasets that differed quite a lot from the first one used in regard to how my eyes perceive the images (scroll to the bottom for sources and credits). Adding them improved the model with small steps, so yes, it did add some new dimensions for my model to train on, but not as much as I thought when judging with my human eye.

But then I found one dataset that had celebrities represented both as a child and as an adult. This one was my bingo dataset. It was very useful to add images that had the quality of spanning up to more than half a century. It introduced many new features into the training of my model: blurriness, black-and-white, a picture taken of an image, distortion of various kinds produced by the camera or other poor lens qualities, etc.

A sample from the Large Age Gap Face Verification Dataset

The dataset only contained 3 800 images but gave the model an accuracy of 60% against the Test set of Photoshopped images (compared to the earlier 4%). Ok, 60% sounds like just a little bit better than this earlier mentioned monkey brain choosing between two alternatives. The hard indication is though that new information has been added to the training that adjusted for digital fake images that are not AI-generated, and the systematic error from before is reduced substantially.

Next step, I made the choice to throw in the dataset of Photoshopped face images into the training. Note that now I’ve already ditched the Stress test here and back to training my model, since it only had the purpose of experimentation, finding out what matters to my model. As few as 1000 images from the Photoshopped dataset, out of the now total of 76 000 images, now improved the model’s prediction in production!

This is a decision I would not have been making without experimentation and the realization that actually many of the images out there of real faces are enhanced in one way or another with the help of digital techniques. I now could make a non-expected, but a very helpful choice, to give relevant information to my model for training. Becoming good at any specific Machine Learning problem at hand comes down to this in the end: experimentations and iterations.

As can be seen below, the accuracy interestingly got slightly worse for the trained model, 0.992141 compared to the accuracy of 0.998983 (error rate 0.001017) in the first run, before any tweaks to the model. But remember, the accuracy when tested against the Stress test of the Photoshopped dataset is 60% instead of the previous 4%. One of the conclusions drawn here, is that it’s better to aim at less than 100% accuracy in training, but do well on a Stress test that simulates production.

The model has become production-ready

After training the model with several different image datasets that addressed such things as age-span, age of the images and manipulation in Photoshop, the classifier finally converged to near 100% accuracy for the trained model, and giving about the same degree of accuracy for new test data, which is the simulated production data.

You might be thinking that the Stress test now has vanished for further testing since it got thrown into the training. And yes, that is the situation now.

I figured that really heavily Photoshopped images should not be the end Test set, it’s not representative of the reality in production. These images were just very helpful in improving the model for production.

A proper Test set from the real world should be a large dataset of regular images that acts as a sample of what the end-user might throw at the model. For this, I choose the CelabFacees Attributes Dataset (CelabA, see sample below) with over 202 000 images of 10 000 public figures. This dataset contains these people in many varying situations; performing on stage, in private, on vacation, receiving a Grammy, with or without make-up, polished in a magazine, cut out from a youtube-video, taken by a paparazzi, shot with a mobile phone. It feels like it covers many of the different strikes and qualities of an image an end user could feed this model with in production.

The Test set compromises of 202 000, for the model unseen real-world images, and 30 000 unseen AI-generated images from the same earlier used Nvidia dataset The 1 million Fake Faces dataset. This decision is based on my earlier conclusion that nobody else has generated better quality fake face images, or actually trained longer with the available StyleGAN algorithm, than Nvidia has done.

And the verdict is in

The result for the Test set, my simulated production environment, reached an accuracy of 99,99%. An accuracy I feel proud of having reached in my first attempt to build an ML-classifier. Someting worth noting is that the prediction for the Test set gave us a better accuracy than the training accuracy of 99,21%!

Commonly, Data Scientists fear that the production accuracy is way off their validation accuracy from the model in the lab. This result is a very confident sign that I did not overfit, the biggest sin of all in Data Science hadn’t been committed.

Below, you can also have a look at the Top Losses of the model, meaning, the images that the model was most confused about. As you can easily spot, there are some really obvious images for humans to know that they absolutely belong to the category of fake images (either made by AI or extremely heavily Photoshopped). Speculation for why my model is not picking up on that is that after all, some heavily Photoshopped images were part of the training labeled as being from the real-world.

To improve this, I should train again from the beginning with a third label/category: from the real world but Photoshopped. On the other hand, I’m content at this point of experimentation for my learning purposes.

ML-models are here to aid people in things that are hard for humans. In this case, I have a really great accuracy from throwing in the Photoshopped dataset in the training, and the overall very few (less than 17 out of 30 000 images, and by the look of it, actually maybe half of the 17), but very obvious images my model is not picking up on, a human can do; an harmony in knowledge and skills distribution.

Future possible improvements

These are the things that pop up in my head when I think of how this ML-model could be improved further. Or if I would have done it from scratch and start over.

  1. Create a new label/category for training: Real-world but Photoshopped. This might help the model to reduce the number of really obvious AI-generated images getting predicted as coming from the real-world.
  2. Add another dataset of more Photoshopped images to the training (1000 images was used here) and it would most likely bump up the accuracy of 60% substantially differentiating out if an image is Photoshopped.
  3. With Machine Learning or any other cutting edge tech, you are never really done. New tech is deployed constantly, the previously released versions get outdated. In this case, not done means to keep an eye on future improvements of the StyleGAN technique. Currently, the AI-generators are using the StyleGAN2. When the next generation is out, this trained model will need to be re-trained with new images produced by the “StyleGAN3”, or any other tech improving technique, to stay accurate in its prediction.

Dig deeper and broader into more exploration details

An insight that hit me, from this exploration about what a classifier in Machine Learning is about, made me draw this conclusion:

Though seemingly advanced in replicating and recognizing faces, ML-models do not have the same understanding as us humans of what a face actually is. It is still just algorithms no smarter than its ability for pattern recognition pixel for pixel..

It’s obvious that the algorithm does not “understand” that the pixels are representing a human face, or rather, that specific strange pixel areas are not representative of a human face.

There is much more stuff I learned while building and improving this ML-classifier. If interested, head over to the companion blog post where I described how I dug deeper and used this ML-classifier to draw conclusions about the behavior of the AI that creates the generated images.

About the author discovering Fastai

My background is many years with iOS Development and just as recent as in 2019, I decided to switch focus into Data Science, and Machine Learning in particular. I believe that’s where our future lays, in tech terms, but also where our species and society is heading.

Discovering Fastai, and it’s a library built on top of PyTorch, made my switch of field easier than I ever imagined. I discovered that quickly being able to do cool stuff with Neural Nets and Deep Learning is no longer rocket science, not at all. The hurdle, which I’m slowly but steadily is overcoming, has rather been that Data Science includes some Back-end and Cloud Development, that is something quite different from my experiences working with front-end with a deep interest in UX.

Anyways, I highly recommend to anyone interested in Machine Learning, no matter your current expertise on your journey into the AI tech world, to go through some of the Fastai video courses and learn from the brilliant and absolutely practical Jeremy Howard teachings. He is promising to take you through the steps and the practices that enable you to create state-of-the-art ML-models. With my very first ever implemented ML classifier, I would say that for me, he kept his promise.

The classifier I’ve built is a variation of the Lab talked about in the course Deep Learning for Coders in Lesson 2 which I expanded quite a bit beyond the scope into the experimentation talked about in this blog post.

Here I’m signing off,
for the Jayway Blog,

Silvia Man,
Senior software engineer


Face datasets for training (and validation)

AI-generated – a total of 33 000 images

  1. The 1 million Fake Faces dataset – used 30 000 images
  2. The Generated Data Dataset – used 3 000 images

Real-world in the wild – total 43 000 images / 54 000 images

  1. The UTKFace dataset – used 24 000 images
  2. The LFW dataset – used 13 000 images
  3. The Large Age Gap Face Verification Dataset – used 3 800 images
  4. The Real and Fake Face Detection Dataset – used 2 x 1000 images, both sets with real-world faces in the wild but one of the sets were Photoshopped
  5. Flickr-Faces-HQ Dataset – used 11 000 images. Was used by Nvidia when training a GAN network to produce the AI-generator that generated the face images for The 1 million Fake Faces dataset

Face dataset for test (indication of production quality)

AI-generated – a total of 30 000 images

  1. The 1 million Fake Faces dataset – used (another set of) 30 000 images

Real-world in the wild – a total of 202 000 images

  1. The CelabFaces Attributes dataset – used 202 000 images


  1. The 1 million Fake Faces dataset
    StyleGAN algorithm and model by NVIDIA under CC BY-NC 4.0
  2. The Generated Data Dataset
    Photo by Generated Photos
  3. The UTKFace dataset
    The UTKFace dataset is available for non-commercial research purposes only. The copyright belongs to the original owners.
  4. The LFW dataset
    Labeled Faces in the Wild is a public benchmark for face verification.
  5. The Large Age Gap Face Verification Dataset
    author = {Bianco, Simone},
    year = {2017},
    pages = {36-42},
    title = {Large Age-Gap Face Verification by Feature Injection in Deep Networks},
    volume = {90},
    journal = {Pattern Recognition Letters},
    doi = {10.1016/j.patrec.2017.03.006}}
  6. The Real and Fake Face Detection Dataset
    Available at Kaggle, License unknown, Visibility public
  7. Flickr-Faces-HQ Dataset
    The individual images were published in Flickr by their respective authors under either Creative Commons BY 2.0, Creative Commons BY-NC 2.0, Public Domain Mark 1.0, Public Domain CC0 1.0, or U.S. Government Works license. All of these licenses allow free use, redistribution, and adaptation for non-commercial purposes. However, some of them require giving appropriate credit to the original author, as well as indicating any changes that were made to the images. The license and original author of each image are indicated in the metadata.
  8. The CelabFaces Attributes dataset
    title = {Deep Learning Face Attributes in the Wild},
    author = {Liu, Ziwei and Luo, Ping and Wang, Xiaogang and Tang, Xiaoou},
    booktitle = {Proceedings of International Conference on Computer Vision (ICCV)},
    month = {December},
    year = {2015}}

This Post Has 9 Comments

  1. Fox

    So, I could really use this right now with all the social media and staying at home. How do I read this?


    1. Fox

      never mind, I’m stupid and blind. I see the e-06 a the end now. so this means the image is almost 100% random. thanks for an awesome resource!

      1. Silvia Man

        Yes, the prediction for the profile picture you uploaded is that it’s almost 100% certain NOT an image of a real person. Glad you found my AI useful!

  2. stepan

    Is there some service like ? :)

    1. Silvia Man

      Yes, I created a simple web app to try out this ML-classifier in action. The ML-model will classify if the image you upload is predicted to be AI-generated or from the real world.

      If you try it out, would be interested in your thoughts!

  3. Mattia

    Hi Silvia, congratulations on the great work you have done!
    I was wondering if you are going to publish the code you used or introduce an API for your web application that other projects can use.
    Thanks, ciao!

    1. Silvia Man

      Thanks Mattia for your kind acknowledgment :)
      The code is experimental and not cleaned out, but you can have a look at the Jupyter Notebook on Github here:
      The respective datasets of face images you would need to fetch yourself (see sources).

  4. Marc

    Hi Silvia,

    Amazing work. I’m currently looking at an investment website which contains “odd” looking pictures from their board members and your tool just reported all of them AI-Generated with 99% probability (which matches the other evidence I found that these persons do not exist).

    Thanks again for sharing and best of luck!

    1. Silvia Man

      That is so awesome Marc! Thank you for sharing back to me, this just made my day, knowing I could help to point at probable financial fraud.

Leave a Reply