Skip to content
Chris Prinz
Share
Explore
Writing

icon picker
How I Taught an AI to Play Cards Against Humanity

In 1997, IBM’s Deep Blue beat Gary Kasparov at chess. In 2011, it was Jeopardy. Just recently, Google’s AlphaGo beat Ke Jie in an undefeated series of Go, a game so complex that the number of possible board combinations outnumbers the number of grains of sand on the beach. As Go is the epitome of strategic thinking, Cards Against Humanity is arguably much simpler game. You just have to be as crude, vulgar, and dark humored as possible. Though easy for humans, this is a complex task for AI. Currently, understanding natural language is one of the most researched fields in artificial intelligence.
For those unfamiliar with Cards Against Humanity, here are the rules:
One player (the judge) draws a prompt card, containing blanks for one or more responses. For example: “And the Academy Award goes to? _______”. The other players each have a hand of seven white cards, where they can pick a response to the prompt. For example: “Grandma”. This example was intentionally tame, and it is doubtful that the judge would’ve picked it as a winner. In a typical round, the response with the darkest/crudest humor wins.
But how do you train a machine learning model to pick distasteful, yet hilarious responses? To answer this, let’s get into the basics of machine learning.

How machine learning works

Machine learning is the process of a mathematical model adjusting itself based on the data that it’s trained on. Linear regression is one of the simplest applications of machine learning: A model can fit a line to a set of data points by minimizing the squared error of the line. As you include more data points, the line will generalize more accurately and become a better predictor.
Back to Cards Against Humanity. The main challenge with teaching a machine what “funny” is, as the model sees words as quantitative embeddings. Depending on how the model learned the weights of certain words, the presence of a word like “Grandma” could lead to that card getting picked disproportionately over cards, regardless of the prompt card context.

Quantifying funniness

The first issue we had to solve was creating a vector representation of each card so that the bot could understand relationships between words and their semantic meanings. To do this, we used Word2Vec, an algorithm which creates 50 dimensional vectors for words based on their relationship to other words. Using this, we created a vector representation for each word, and took the average of all vectors in the phrase. To ensure the meaning did not get diluted by miscellaneous words (and, a, it, etc.), we took out these stopwords and multiplied verb and noun vectors by 1.5 to get a weighted average. Now we can quantitatively look at the contextual difference between a prompt card and a response card.
However, just picking the response vector that’s in the nearest proximity to the prompt vector would be like responding to “What’s your favorite food?” with “Food”. To account for this, we used cosine similarity, or the difference in the vector angles, as a substitute for distance. The algorithm picks the response vector closest to the prompt’s perpendicular line, or a cosine similarity of zero. The rational behind this is that the response won’t be too literal, but will retain the context of the prompt. As seen by the responses chosen by the bot, this approach worked surprisingly well.
image.png
At this point, you’re probably thinking “Wait a minute… where’s the labeled dataset? This isn’t machine learning, this is just math!”. You wouldn’t be wrong. This biggest issue with this approach is that the model doesn’t learn whats funny, it simply chooses the closest vector to 90 degrees. As different people play the game, all with their own sense of humor, this bot will never be able to deviate from this process. This is because we simply did not have the data to support creating a machine learning model. It takes thousands, if not millions of data points to create an accurate model. Neural nets are in fashion, but we have to remember that without data, these powerful models are literally no better than guessing at random.
Once we deploy this AI Cards Against Humanity player into the wild, we’ll be able to collect data on which responses users think are funny. Using this data, we can take our current algorithm and adjust it so that it learns what similarity between vectors results in the funniest pick.
A node.js implementation of the AI CAH bot can be found on my . For the python notebook used to create word vectors, please reach out to me directly as the Word2Vec files are too large to host.
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.