reddit.com/r/antisemitism

Joseph W Pope
8 min readSep 4, 2018

--

Unsupervised Learning Project using NLP; Sentiment Analysis and Topic Modeling

Warning: Explicit language contained below

This summer at Metis NYC we are studying natural language processing, topic modeling and sentiment analysis. Given a disturbing number of recent events, I decided to look into hate speech and anti-semitic remarks on reddit.

Data Extraction

After some time experimenting with and reviewing Reddit’s API and PRAW python wrapper, I became aware of pushshift.io. Founded by reddit user stuck_in_the_matrix, pushshift.io has billions of comments available for researchers to query. They also have their own API as well as tables of comments and submissions in the cloud at Google BigQuery. Eventually, I settled on a workflow where I created a query in BigQuery which output a table I could reference from my AWS EC2 instance for further analysis with python.

Instead of looking at some enormous swath of reddit data, I elected to narrow my scope and use regular expressions to filter for potentially anti-semitic comments. I used keywords like ‘jew’, ‘zion’ (as in Zionism), and other slurs and online jargon used by hate groups.

I ended up with 100K+ comments, 10MM words encompassing over 3774 subreddits from May to June 2018. The data included bots, so I excluded any user with ‘bot’ in their user name (aka AutoModeratorBot, WikiBot). This was a quick and flawed method, but probably decent enough for this first analysis.

The most common subreddits by comment count are shown here:

The first three are very popular subreddits, so it makes sense to see them there. I won’t link to any of these others, but milliondollarextreme is a ‘satire’ subreddit that seems to enjoy being anti-PC to an absurd degree. CringeAnarchy is a subreddit of alt-right redditors who lampoon notable people and issues on the liberal left. The_Donald is home to “The Donald’s” fiercest supporters.

This list of subreddits in no way suggests that these subreddits are full of anti-semites, but it does suggest that we should investigate further to see what is happening. In generalize further, Trump’s backers support Israel and milliondollarextreme users hurl slurs mostly in jest.

Quick tangent — I made an interesting discovery on the pushshift.io slack channel where I was able to run additional queries on more current reddit activity. I queried the Jewish slur ‘kike’, and saw that the LA Dodgers subreddit was the #1 site! How could this be? I’m not a baseball fan, so it was news to me that CF Enrique Hernandez also goes by the nickname “Kiké”!

Text Preprocessing

Once I had the data loaded into a pandas dataframe, I performed some basic text cleanup:

# set the body (text) of the dataframe to all lowercase
df[‘body’] = df[‘body’].apply(lambda x: x.lower());
# remove common stop words from the same field
from nltk.corpus import stopwords
stop = stopwords.words('english')
df['body'] = df['body'].apply(lambda x: " ".join(x for x in x.split() if x not in stop));
# remove punctuation from text
df['body'] = df['body'].str.replace('[^\w\s]','');

This allowed me to perform basic NLP analysis on the reddit comments. I tried stemming and lemmatizing the text, but my models did not perform very well after this step so I ended up leaving as is.

Sentiment Analysis

VADER, TextBlob and Word2Vec

For sentiment analysis I looked to VADER, TextBlob, and word2vec. VADER and TextBlob were relatively straightforward to implement. I decided to solely utilize ‘polarity’ for TextBlob and ‘compound’ for Vader. This approach ignores any subjectivity or relative usage for positive, negative or neutral tokens or phrases. Both scores are stored as floats and range from -1 (most negative) to +1 (most positive). Almost all comments are rated neutral, but since we want ‘hate speech’ we will focus on the negative comments from both libraries.

# TextBlob -- parse text for score and create new column in dffrom textblob import TextBlobdef sentiment_finder_partial(comment):
analysis = TextBlob(comment)
return analysis.sentiment.polarity
df['SA_p'] = np.array([ sentiment_finder_partial(comment) for comment in df['body']])# VADER -- same. Use 'compound' instead of 'polarity' though. from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzeranalyser = SentimentIntensityAnalyzer()def sentiment_finder_vader(comment):
analysis = analyser.polarity_scores(comment)
return analysis['compound']
df['Vader'] = np.array([ sentiment_finder_vader(comment) for comment in df['body'] ])

I did not utilize word2vec as much as I would have liked. It certainly feels like a powerful, intelligent library. When looking at ‘most similiar words’ using keyword ‘zionist’ word2vec returned:

w = 'zionist'
model.wv.most_similar (positive = w)
[('zionists', 0.6999108791351318),
('neocon', 0.5981375575065613),
('zionism', 0.555126965045929),
('zog', 0.5072057247161865),
('settler', 0.4846901595592499),
('isreali', 0.47860807180404663),
('stooge', 0.4716537594795227),
('zionistic', 0.4544820487499237),
('colonialist', 0.4532729685306549),
('antizionist', 0.4468907415866852)]

I had no idea what ‘zog’ meant. I looked this up and it is used to refer to the ‘Zionist Occupation Government’. In other words, ‘jew agents’ have infiltrated Western states and are running the world, much like in the widely debunked and often-cited ‘Protocols of the Elders of Zion’. This term is not used causally in the pro/anti-Israel discussions held by reasonable people who disagree, this is a term used by people who want to spread hate and misinformation.

This leads me to the conclusion that Word2vec is an excellent tool in finding new terms, codes and slang used to disparage and malign others. I would likely use this in future queries to cast a wider net for potential hate-speech.

Topic Modeling

Next I looked at topic modeling. I tried a number of methods and parameters here. In the end, the default settings using sklearn CountVectorizer and NMF decomposition produced the most interesting results. These three topics seem to break down observed words in logical conceptual groupings.

hate speech:['people', 'said', 'kike', 'white', 'black', 'like', 'think', 'want', 'racist', 'jewish']religion:['god', 'jesus', 'christ', 'one', 'believe', 'life', 'lord', 'bible', 'man', 'gods']israel:['jews', 'israel', 'jewish', 'palestinians', 'land', 'state', 'israeli', 'palestine', 'arab', 'arabs']

When reviewing these topics over time, we see that the most comments relate to the ‘Israel’ topic, which is likely to be the case in reality. Israel is an incredibly controversial topic across a number of subreddits.

As a final step, I combine the ‘hate speech’ topic with the negative VADER and TextBlog sentiment scores to produce a subset of comments that are likely to be hate speech at worst, controversial at best. The orange quadrant does not show all the anti-semitic comments, but it does show a good place to start looking for them.

Tableau Viz (orange indicates hate-speech comments)

Scattertext!

Scattertext!

Scattertext is an incredibly cool library to visualize term frequency differences between two documents. In the graphic above, I use the tool to compare r/worldnews against r/worldpolitics. You can see that in the bottom right of the graph, we see frequent worldpolitics terms like ‘kike’, ‘goyim’ and ‘zionazis’. r/worldpolitics is effectively a completely unmoderated and uncensored version of r/worldnews, so this is not so surprising to see. It feels quite likely that people who post comments I have flagged as potential hate-speech AND post regularly in r/worldpolitics, are legitimate anti-semites. At least from the comfort of their digital safe space.

Scattertext allows further analysis of the comments themselves. If you search all comments for the term ‘kike’, it appears 0 (rounded down) times in 25,000 documents on the mainstream r/worldnews subreddit. One of the post-processed texts is here:

well religion teaches word god kill people leave faith probably lot seems like mind made eith passive aggressive comment is want open discussion im ears going try make got ya dumb comments kike need respond

It’s a bit hard to read without the stopwords and punctuation. However, it seems as though this poster is using ‘kike’ as a slur. This is hate speech and should be flagged by the moderators at r/worldnews.

Conversely, the uncensored r/worldpolitics has 13 incidents per 25,000 [I censored the f-word].

w or kike answer question

ever met george soros know kike jew

shut f*** up kike

ignorant buffoon thats hardly surprising zionists jew stooges are

I think we may be zeroing on the hate speech now. The term ‘jew’ is used 50 times per 25,000 words in r/worldnews versus 87 times versus 25,000 words. in r/worldpolitics. Again, this seems to indicate an increased preoccupation with discussing Jews in r/worldpolitics. It is important to note that r/worldpolitics has a much lower subscriber count and comment volume than r/worldnews.

THE MAIN TAKEAWAY

Classifying anti-semitic posts on a case-by-case basis is possible, but very problematic because of context, satire, slang and a dynamic jargon of codewords used by hate groups. Given the large volume of comments every hour on reddit, it can also be like finding a neo-Nazi needle in a haystack.

What if we classify posters, instead of posts?

In other words, instead of hunting for ‘hate speech’ let’s find ‘hate speakers’.

We can review multiple posts for one user within a subreddit, then back out and look at what other subreddits they frequent, and what other comments they made. If a number of known toxic subreddits appear in their comment history, it should be a strong indicator of the user’s toxicity.

Like many unsupervised learning projects, this project can pivot into a supervised classification project with labeled data. # of toxic subreddits, # of flagged comments, # of slurs used, # of CAPS used, word count and many other features can help guide us towards more accurate predictions as unseen data streams into our monitoring model.

We should narrow our scope of analysis to the relevant subreddit. r/politics, r/worldnews, and r/The_Donald each have their own unique dialects and inside jokes and should be treated as their own corpus. A longer date range can be used, perhaps weighting recent comments. Word2vec can be utilized to increase our ‘hitlist’ of potentially anti-semitic terms.

I would love to hear other thoughts on any aspect of this project. I want to emphasize that I am not advocating for any type of censoring or shadow banning device here. However, a tool to monitor redditors and increase transparency into potentially hurtful, if not outright physically dangerous behaviour feels prudent and reasonable.

--

--