my "emotapal" library
Click for link to EmotaPal on Github
Concept
An EmotaPal is a palette of words and colors. Just as a 'color palette' describes the colors of some visual object, an 'emotion palette' describes the emotions felt from a visual object. An EmotaPal combines both pieces (visual and psychological) of information.
Motivation
The idea for this project came to me through two very different avenues.
art
I like to make generative art. And I often think about which color palettes to use. I thought there has to be some data-driven way to select colors that would elicit certain emotions.
business
Working in the marketing space, a lot of weight (and money) is put on brand positioning. You want consumers to view you as XYZ. Okay, so how do you make that happen? So much of that process depends on visual information. Imagine if the goofy colors of Google and austere monochrome of Uber were switched. It would just be weird. Colors say a lot.
business Case 1
If brands already have a positioning strategy, EmotaPal can help create a color scheme that is aligned with that strategy.
business Case 2
And if marketers already have a proposed color palette, EmotaPal can verify that the palette elicits emotional reactions consistent with the brand's positioning.
Data
Problem
The goal is to match emotions with colors. To make this a supervised learning project, I had to find a dataset with features (color, emotion). To my knowledge, no robust dataset really existed. So I made it.
Solution
First, I found a list of emotion words. I got these from the Center for Nonviolent Communication. Now I had to assign each emotion a color.
Thankfully, Google images exists. For each emotion, I tried to download the top 100 images on Google Images (some threw errors when downloading). My logic for using Google Images is that Google Image placement reflects the "voting" (or clicking) behavior of large swaths of people. If an image was truly irrelevant, it would probably not make the top 100 images.
After downloading these images, I extracted their dominant color. This step gave me the dataset I wanted: emotions and colors.
Model
Now that I had this dataset with features (color, emotion), I could predict an emotion from a color.
To do that, I used a K Nearest Neighbors (KNN) classifier. A KNN classifier takes a candidate color, looks at neighboring colors of the candidate, and then calls a vote. Whichever emotion gets the most votes is the prediction.
Optimization
The main parameter here is "K". How many neighbors do we survey? Normally, people optimize "K" with respect to some objective, like accuracy. There are 250+ emotions. If my classifier does not pick the correct one, this is not such a big deal, as long as we are "in the ballpark". So for example, if the ground truth is "sadness" and the classifier says "despair", that's okay.
To operationalize this, I optimized K w/r/t a custom error function. That function calculated the semantic distance between the actual emotion and the predicted emotion. The specific metric is called "path similarity". Path similarity looks at words A and B in a giant graph and finds the shortest number of edges to get from word A to word B.
Program
The program pivots on this classifier. The EmotaPal library provides several ways to construct an EmotaPal object. An EmotaPal object is simply a palette of colors and assoaciated emotions.
Thinking back to the use cases above, I reasoned constructors had to be able to do two things. First, you should be able to take an existing color palette and get emotions from it. This is the use case of an artist deciding between which palette to use, or a brand verifying their visual identity matches their desired positioning. We use the KNN classifier, here. Second, you should be able to start with some desired emotions and then get a color palette. Imagine a startup with a clear ideas of what their product should do, but little direction on how the logo should look. This constructor method relies on scraping the colors of Google Image results for desired emotions.
So out of those considerations came 4 construction options. You can build an EmotaPal from a google images query, a url pointing to an image, an image file, or a a set of colors.
Once constructed, you can do a couple of things with an EmotaPal. First, you can look at its attributes. What are the colors? What are the emotions? Second, you can perform several functions. You can calculate the sentiment of an EmotaPal by calculating the sentiment of its words. And you can display an EmotaPal as a palette by showing its colors.
To Dos
I want to get more and better data. This was basically a proof of concept, but I think the concept proved itself. With more emotion words and more images, EmotaPal would be an even better library.
Something I am still trying to figure out is: What happens if the same color matches with multiple emotions? This did occur in my dataset, and I just left these observations in because some colors do mean very different things. Black can be bold, artsy, or depressing.
There should be metrics to evaluate an EmotaPal. One metric, for instance, could be internal consistency. Are the emotions relatively similar or are they very different? Path similarity would be a good metric here.
It would be cool if you could generate multiple palettes from an EmotaPal. As of now, each EmotaPal has as attributes words and colors. But I think it would be interesting if an EmotaPal could take its colors, and then generate variations of this base palette.
Anyway...