Reddit Social Media Analytics Report
Reddit Social Media Analytics Report
Contents
1 Introduction 5
2 Statistical Analysis 5
2.1 Social Media Analytics for sub-Reddit Feeds . . . . . . . . . . . . . . . . . 5
2.1.1 Reddit REST-full API Wrapper . . . . . . . . . . . . . . . . . . . 6
2.1.2 Statistical Analysis of the r/technology Feed . . . . . . . . . . . . 7
2.2 Graph Analysis of Social Networks . . . . . . . . . . . . . . . . . . . . . . 16
2.2.1 Centrality Measures in Social Network Graphs . . . . . . . . . . . 17
2.2.2 Community Detection in Social Network Graphs . . . . . . . . . . 19
3 Text Mining 22
3.1 Data Mining for Topic Modelling . . . . . . . . . . . . . . . . . . . . . . . 22
3.1.1 LDA Parameter Tuning . . . . . . . . . . . . . . . . . . . . . . . . 22
3.1.2 LDA vs LSI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.1.3 Topic Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.2 Machine Learning for Sentiment Analysis . . . . . . . . . . . . . . . . . . 38
3.2.1 Random Forest Multi-Label Classification . . . . . . . . . . . . . . 38
3.2.2 Random Forest Binary Classification . . . . . . . . . . . . . . . . . 45
3.2.3 Recurrent Neural Network Classification . . . . . . . . . . . . . . . 49
3.2.4 Application of Trained Models for Sentiment Analysis . . . . . . . 53
3.3 Extractive Summarisation . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4 Appendix 60
4.1 Reddit API Wrapper Class . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.2 Radial Plot Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
4.3 Facebook Social Network Graph Analysis Reports . . . . . . . . . . . . . 65
4.3.1 Degree Report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.3.2 Weighted Degree Report . . . . . . . . . . . . . . . . . . . . . . . . 66
4.3.3 Graph Distance Report . . . . . . . . . . . . . . . . . . . . . . . . 67
4.3.4 Modularity Report . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
4.3.5 Statistical Inference Report . . . . . . . . . . . . . . . . . . . . . . 68
4.4 Text Pre-Processing Utility Class . . . . . . . . . . . . . . . . . . . . . . . 68
4.5 Extractive Summarization Utility Functions . . . . . . . . . . . . . . . . . 71
List of Tables
1 Feature description for the extracted Reddit. . . . . . . . . . . . . . . . . 8
2 K-Fold validation scores for multi-label classification. . . . . . . . . . . . . 43
3 Validation run for the multi-class classifier. . . . . . . . . . . . . . . . . . 44
4 K-Fold validation scores for binary-label classification. . . . . . . . . . . . 47
5 Validation run for the bi-class model. . . . . . . . . . . . . . . . . . . . . . 48
Page 1
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
List of Figures
1 Connecting to the Reddit API via the wrapper class. . . . . . . . . . . . . 6
2 Extracting data for Reddit posts via the API wrapper class. . . . . . . . . 7
3 Reddit data-set cleaning. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
4 Most popular source domains for the ”r/Technology” feed (at 26th March
2023). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
5 Distribution listings per domain for the ”r/Technology” feed (at 26th
March 2023). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6 Data extraction and normalization for comparing the top post on a sub-
reddit feed. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
7 Comparing the top posts on a subreddit feed. . . . . . . . . . . . . . . . . 13
8 Comparing methods for deciding the ”top” listing for a subreddit against
Reddits algorithm. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
9 Comparing topic occurrences for the ”r/Technology” feed (at 26th March
2023). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
10 Visualising number of posts tagged with the ”Business” topic in the
”r/Technology” subreddit per day. . . . . . . . . . . . . . . . . . . . . . . 16
11 Overview of the ego-Facebook graph. . . . . . . . . . . . . . . . . . . . . . 17
12 Graph properties calculations using the Gephi tools. . . . . . . . . . . . . 18
13 Graph visualisation - node size by betweenes centrality. . . . . . . . . . . 19
14 Community detection by modularity class. . . . . . . . . . . . . . . . . . . 20
15 Community detection by modularity class - Force Atlas adjusted by node
size. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
16 Community detection by modularity class - Force Atlas adjusted by node
size and filtered for a higher degree centrality range. . . . . . . . . . . . . 21
17 Word cloud resulting from the aggregated news headlines in the r technology new [Link]
data-set. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
18 Top coherence results for LDA parameters combinations. . . . . . . . . . . 24
19 Resulting data-frame for results comparison, per data-set, per pass. . . . . 26
20 Sample one CV coherence scores. . . . . . . . . . . . . . . . . . . . . . . . 27
21 Sample one UMass coherence scores. . . . . . . . . . . . . . . . . . . . . . 28
22 Sample two CV coherence scores. . . . . . . . . . . . . . . . . . . . . . . . 29
23 Sample two UMass coherence scores. . . . . . . . . . . . . . . . . . . . . . 30
24 Sample three CV coherence scores. . . . . . . . . . . . . . . . . . . . . . . 31
25 Sample three UMass coherence scores. . . . . . . . . . . . . . . . . . . . . 32
26 Sample four CV coherence scores. . . . . . . . . . . . . . . . . . . . . . . . 33
27 Sample four UMass coherence scores. . . . . . . . . . . . . . . . . . . . . . 34
28 Frequency distribution for the aggregated news headlines in the r technology new [Link]
data-set. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
29 Most important words per topic via LDA model. . . . . . . . . . . . . . . 36
30 Most important words per topic via LSI model. . . . . . . . . . . . . . . . 37
31 Comparing per topic coherence scores between the LDA and LSI modes
for the r technology new [Link] data-set. . . . . . . . . . . . . . . . . . . 37
32 Visualising topic data for the trained LDA model with the pyLDAvis library. 38
33 Loading the multi-class data-set. . . . . . . . . . . . . . . . . . . . . . . . 39
Page 2
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 3
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Glossary
API Application Programming Interface
LDA Latent Dirichlet Allocation
LSI Latent Semantic Indexing
NLP Natural Language Processing
NN Neural Network
RFC Random Forest Classifier
RNN Recurrent Neural Network
SNA Social Network Analysis
TFIDF Term Frequency — Inverse Document Frequency
Page 4
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
1 Introduction
Given the rapid expansion of the Internet, social media has become an indispensable
part of our lives. Daily, billions of users around the world are sharing their experiences,
thoughts and opinions on various online platforms, creating digital content. The vast
amount of data generated by these interactions presents a vital opportunity for businesses
to gain insights into their customers preferences, behavior, and sentiment towards their
brand. As the potential of this information became apparent, a new field of study
specialised in extracting valuable insights from large social networks has emerged. This
sub-field is commonly known as social media analytics.
One of the key challenges in analyzing social media content is dealing with the vast
amount of unstructured data that is generated on these platforms. Natural Language
Processing (NLP), a sub-field of artificial intelligence that deals with the interaction
between computers and human language, has become an essential tool for analyzing
social media data.
This report explores the intersection of social media analytics and natural language
processing. The following sections discuss the various techniques and tools used in social
media analytics, followed by NLP methods such as topic modeling, sentiment analysis
and text summarisation.
2 Statistical Analysis
Social media analytics is the process of gathering and analyzing data from social networks
such as Facebook, Instagram, LinkedIn, or Twitter. It a specialised sub-field of analytics
focused on extracting valuable hidden insights from vast amounts of semi-structured
and unstructured social media data to enable informed and insightful decision making
(Sponder and Khan, 2017).
There are three main steps in analyzing social media:
1. Data Identification
2. Data Analysis
3. Information Interpretation
To maintain focus and thus maximizing the value derived at every point during the
process, analysts may define questions to be answered through the insight gained within
the data. These questions help in determining the proper data sources to evaluate, which
can affect the type of analysis that can be performed (Ganis and Kohirkar, 2015).
Page 5
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Extracting data for Reddit posts is done through the wrapper object by calling
its ”PullSubredditFeedRaw” and ”PullSubredditFeed” methods (Appendix 4.1). The
”PullSubredditFeed” is the primary method of fetching Reddit posts, since it has the
added utility of transforming the incoming data from a semi-structured JSON format
into a Pandas data-frame object (Figure 2). The parameters of these functions dictate
(in order as per Figure 2) the subreddit where the posts originate, the filtering method
(”top” or ”all”) and the limit of records to return.
Page 6
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 2: Extracting data for Reddit posts via the API wrapper class.
Page 7
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
nology” subreddit at the date of 26th of March, 2023, ordered chronologically from
the newest to the oldest post.
• r technology top [Link] - Contains the top2 listing from the ”r/Technology”
subreddit at the date of 26th of March, 2023, ordered chronologically from the
newest to the oldest post.
All datasets extracted via the API wrapper hold the same features structure, available
in Table 2.1.2.
Table 1: Feature description for the extracted Reddit.
Page 8
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Question Q1 aims to identify which is the most influential online news outlet for
the ”r/Technology” subreddit. For this analysis we consider the degree of influence to
be directly correlated to the number of redistributed news within the feed in the recent
period of time at the time of data extraction. Meaning that we sum up individual domain
occurrences for the extracted feed and compare the results.
The following code is used to compute the total occurrences per each domain in the
data-set entries, then displays the bar plot in Figure 4:
Page 9
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
9 [Link](font_scale=2)
10 [Link](data=filtered_df,
,→ y='domain').set(title='Most popular domain occurences', xlabel="Count",
,→ ylabel="News source domain" );
Figure 4: Most popular source domains for the ”r/Technology” feed (at 26th March
2023).
The r technology new [Link] sample presents a total of 176 individual domains as
sources for the listed tech news headlines. For a more focused visualisation, we choose
to display only the domains that occur in more than 5 listing, as per the previously
presented code snippet. From Figure 4 we can see that the two most popular news
sources in this subreddit are ”[Link]” and ”[Link]”, with the former
taking the first spot.
To obtain a better perspective on how the most popular news sources compare to the
ones that are used less, we aggregate all domains that occur less that 10 times within the
extracted feed. In Figure 5 we use a pie plot to visualise in which percentage of posts in
the entire feed does a domain occur. The data and plot for Figure 5 is generated using
the following Python code:
1 value_counts = reddit_data_cleaned['domain'].value_counts()
2 # Group values with less than 10 occurrences into an "Other" category
3 other_count = value_counts[value_counts < 10].sum()
4 other_values = list(value_counts[value_counts < 10].index)
5 value_counts = value_counts[value_counts >= 10]
6 value_counts['Other (Less than 10 occurences per domain)'] = other_count
7
8 # Create a pie chart using MatPlotLib
Page 10
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 5: Distribution listings per domain for the ”r/Technology” feed (at 26th March
2023).
Question #2 (Q2): What is the most popular post within the gathered
subreddit feed?
The second question which this analytical pipeline covers is used to identify the
most popular (or ”top”) post within the extracted feed. Reddits ranking algorithms
for different categories (”best”, ”top”, ”rising”, and ”controversial”) are closed-source,
allowing the user-base of the platform to only speculate how these calculations are made.
This analysis attempts to classify the top post within a collection of listings without
relying on the ordering provided by the Reddit API endpoints. We do so by comparing
the most relevant post parameters that would dictate its popularity, namely the up-vote
ratio, number of up-votes, number of comments and number of cross-posts (Table 2.1.2).
The experiments for Q2 sees the analysis performed on the r technology top [Link]
data-set, which contains listings with higher degrees of interaction from the platform
users, giving us bigger data dimensions for the selected features so that we can visualise
differences more easily. The data-set is loaded from local storage and the numerical
features are then normalised in order to match the numerical dimension of the up-vote
Page 11
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
ratio (Figure 6), so that the plot visualisation will be more coherent. With the normalised
data, we use the following Python script to generate the plot in Figure 7:
1 # Plotting the figure
2 fig, ax = [Link](figsize=(10, 5))
3 pivot_data = reddit_data_top_subset.sample(5).melt(id_vars = 'title_truncated',
,→ value_vars=['upvote_ratio', 'ups', 'num_comments', 'num_crossposts'])
4 ax.tick_params(axis='x', rotation=45)
5 [Link](x='title_truncated', y='value', hue='variable', data=pivot_data,
,→ ax=ax);
6 sbn.move_legend(ax, "upper left", bbox_to_anchor=(1, 1))
7 [Link](fig)
Figure 6: Data extraction and normalization for comparing the top post on a subreddit
feed.
Looking at Figure 7, five random listing from the r technology top [Link] are being
compared. Based on the number of up-votes and the up-vote ratio, we could consider the
fifth post (left to right) to be more popular. Yet, given the social aspect of the platform,
it could be considered that stronger user interactions and outreach (user commenting on
the post and number of cross-posts respectively) would serve as more weighted metrics
for this comparison. Therefore, making the third listing the most popular one within the
subreddit feed. This proves that nominating a top post could be subjective to the party
that is performing the analysis, thus this experiments serves rather as demonstration,
more than directly answering question Q2.
Page 12
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Question #3 (Q3): How does the top post on a subreddit (extracted via
the corresponding API end- point) compares to one manually selected from
the historical feed?
To complement the findings for Q2 and offer further insight for those tasked with
decision making duties, from the extracted feed, we compare top posts by different met-
rics with the true top post by Reddits standards. To do so, we generate a series of
radial plots (Figure 8), overlapping the parameters of the top Reddit post with those
of the per-metric top post, in different categories. To produce the plots in Figure 8
we use a function whose code is available in the Appendix section 4.2. Before we ap-
ply the function and produce the plots, we select the top posts per category from the
r technology top [Link] data-set using the following code:
1 # Getting the top entries from each daset and per category, respectively
2 top_post_subreddit = reddit_data_top.loc[:0]
3 top_post_ups = reddit_data_cleaned.sort_values(by=['ups'], ascending=False,
,→ ignore_index=True).loc[:0]
4 top_post_comments = reddit_data_cleaned.sort_values(by=['num_comments'],
,→ ascending=False, ignore_index=True).loc[:0]
5 top_post_crossposts = reddit_data_cleaned.sort_values(by=['num_crossposts'],
,→ ascending=False, ignore_index=True).loc[:0]
6 top_post_ratio = reddit_data_cleaned.sort_values(by=['upvote_ratio'],
,→ ascending=False, ignore_index=True).loc[:0]
The resulting radial plots in Figure 8 reveal that up-votes and cross-posts metrics com-
bined (Sub-figure 8a) offer the best overlap in parameters with the top post by Red-
dit algorithms. Therefore, it can be considered that up-votes and cross-posts numbers
weight more in interpreting which post is more popular within a subreddit feed, at least
by comparing to the coveted Reddit standards.
Page 13
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
(a) Top listing by up-votes and cross-posts. (b) Top listing by number of comments.
Figure 8: Comparing methods for deciding the ”top” listing for a subreddit against
Reddits algorithm.
Page 14
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 9: Comparing topic occurrences for the ”r/Technology” feed (at 26th March
2023).
1 # The we group the data and plot a line chart for the 'Business' topic
2 data = reddit_data_cleaned[['link_flair_text', 'created_utc']]
3 data = [Link](['link_flair_text', 'created_utc']).size()
4 data = [Link]([Link]["Business"], columns=['count']).reset_index()
5
The resulting line plot can be seen in Figure 10. Based on the this visualisation
we can discern that, within the 15-25th March 2023 period, business content on the
”r/Technology” subreddit peaked on the 16th with 23 total post, decreasing over the
course of the next 3 days, then rising in frequency over the next 4 days, and then again
loosing popularity towards the last day in the interval.
Page 15
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 10: Visualising number of posts tagged with the ”Business” topic in the
”r/Technology” subreddit per day.
Page 16
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
The network graph contains 4039 nodes with 88234 directed edges. To obtain an overview
of the whole graph network, we first use the Yifan Hu layout to distance the sub-graphs,
then apply the Force Atlas layout algorithm to further expand individual nodes per
cluster (Figure 11).
Page 17
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
as seen in Figure 12. A complete series of visual reports for the graphs properties can
be found in the Appendix, Section 4.3.
For visualising the most important nodes in the target network, betweenes centrality
is used. Figure 13 displays the nodes with varying sized, depending on their degree of
betweenes centrality.
Page 18
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 19
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 15: Community detection by modularity class - Force Atlas adjusted by node
size.
Page 20
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 16: Community detection by modularity class - Force Atlas adjusted by node
size and filtered for a higher degree centrality range.
Page 21
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
3 Text Mining
This section of the report records the application of different NLP techniques on posts
extracted from the feeds of multiple subreddits. The techniques detailed in the following
sections are:
• Topic Modelling - Topic modelling is a technique used in the field of text mining
to automatically identify topics present in a text object and to derive hidden
patterns. It is a type of statistical modelling for discovering the abstract ”topics”
that occur in a collection of documents, making it an effective tool for discovery
of hidden semantic structures.
Page 22
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
3 documents = [Link]().values
4 print(f"{len(documents)} kept from a total of {len([Link])}")
5
6 # Pre-processing title data into tokens - stop-word removal; punctuation
,→ removal; lemmatization.
7 from [Link] import TextPreprocess
8 textPreprocess = TextPreprocess()
9 tokens_data = []
10 for document in documents:
11 tokens = textPreprocess.process_corpus(document,
,→ word_reduce_strategy='lemma')
12 tokens_data.append(tokens)
13
14 # Generating dictionary and corpus for LDA and LSI processing
15 dictionary = [Link](tokens_data)
16 corpus = [dictionary.doc2bow(token) for token in tokens_data]
17
18 # Flattening tokens list for word cloud
19 tokens_list = [token for sublist in tokens_data for token in sublist]
20 frequency_distribution = [Link](tokens_list)
21 # Showing word cloud
22 wordcloud = WordCloud(max_font_size=50, max_words=100,
,→ background_color="black").generate_from_frequencies(frequency_distribution)
23 [Link](figsize=(10,6))
24 [Link](wordcloud, interpolation="bilinear");
Figure 17: Word cloud resulting from the aggregated news headlines in the
r technology new [Link] data-set.
Page 23
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
coherence score. Based on the resulting scores (Figure 18), on average, an ”iterations”
value of 40 would result in more optimal coherence for the targeted data-set. The
following Python is used to carry out the optimisation process:
1 iteration_options = [10,20,30,40,50,60,70,80,90,100]
2 num_topics_options = [2,4,6,8,10]
3
4 iter_coherence_scores = []
5 for num_topics_option in num_topics_options:
6 iteration_scores = []
7 for iteration_option in iteration_options:
8 lda_model = [Link](corpus, id2word=dictionary,
,→ iterations=iteration_option, num_topics=num_topics_option)
9 coherence_model_lda_cv = CoherenceModel(model=lda_model,
,→ texts=tokens_data, dictionary=dictionary, coherence='c_v')
10 coherence_score = coherence_model_lda_cv.get_coherence()
11 iteration_scores.append([iteration_option, coherence_score])
12
,→ print(f"For num_topics={num_topics_option} and iterations={iteration_option}
13 coherence score is => {coherence_score}")
14 best_iteration = sorted(iteration_scores, key=itemgetter(1),
,→ reverse=True)[0]
15 print(f" | => Best iterations number for {num_topics_option} topics is
16 {best_iteration[0]} with coherence of {best_iteration[1]}.")
17 iter_coherence_scores.append([num_topics_option, best_iteration[0],
,→ best_iteration[1]])
Page 24
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
The data-sets correspond with the top listings from four different subreddits, namely
”r/News”, ”r/WordlNews”, ”r/Science” and ”r/Technology”. These additional subred-
dits show similar attributes to ”r/Technology”3 , utilised as a case study in the previous
sections of the report. All data was extracted within the same time-frame on the 1st of
May, 2023. For each testing sample, we test for both UMass and CV coherence scores,
comparing side-by-side the performance of the algorithms.
First, we load and pre-process all the title data while keeping track of its origin
data-set:
1 from [Link] import TextPreprocess
2 textPreprocess = TextPreprocess()
3
Page 25
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
3 for i in range(10):
4 print(f"Begining test iteration for num_topics={i+1}")
5 lda_model = [Link](iteration_sample_corpus,
,→ id2word=iteration_sample_dictionary, iterations=40, num_topics=i+1)
6 lsi_model = [Link](iteration_sample_corpus,
,→ id2word=iteration_sample_dictionary, num_topics=i+1)
7
8 coherence_model_lda_umass = CoherenceModel(model=lda_model,
,→ corpus=iteration_sample_corpus, dictionary=iteration_sample_dictionary,
,→ coherence='u_mass')
9 coherence_model_lsi_umass = CoherenceModel(model=lsi_model,
,→ corpus=iteration_sample_corpus, dictionary=iteration_sample_dictionary,
,→ coherence='u_mass')
10 coherence_model_lda_cv = CoherenceModel(model=lda_model,
,→ texts=iteration_sample_tokens, dictionary=iteration_sample_dictionary,
,→ coherence='c_v')
11 coherence_model_lsi_cv = CoherenceModel(model=lsi_model,
,→ texts=iteration_sample_tokens, dictionary=iteration_sample_dictionary,
,→ coherence='c_v')
12
13 scores_data.append(
14 [i+1,
15 # lda_model.log_perplexity(corpus),
16 # lsi_model.log_perplexity(corpus),
17 coherence_model_lda_umass.get_coherence(),
18 coherence_model_lsi_umass.get_coherence(),
19 coherence_model_lda_cv.get_coherence(),
20 coherence_model_lsi_cv.get_coherence()]
21 )
22
23 coherence_scores = [Link](data=scores_data,
,→ columns=["num_topics","lda_umass","lsi_umass","lda_cv","lsi_cv"])
Figure 19: Resulting data-frame for results comparison, per data-set, per pass.
Finally, the coherence scores calculation is done 16 times, four times for each testing
set. The resulting visualisations can be seen in Figures 20 through 27. Based on the
Page 26
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
experiment results, both algorithms performed similarly, with LDA being slightly more
coherent given the data used and domain off application. While LSI seems to have,
on average, a better CV coherence score, the LDA model maintained more consistent
CV trend lihes, and consistently better UMass. UMass score better reflects per-topic
coherence, which is more desirable given our type of targeted text format. In addition,
based on the optimisation process presented in Section 3.1.1 and the performance results
of both LDA and LSI models, the optimal number of topics which would offer best topic
coherence on Reddit news titles is four.
Page 27
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 28
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 29
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 30
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 31
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 32
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 33
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 34
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 28: Frequency distribution for the aggregated news headlines in the
r technology new [Link] data-set.
Two helper functions are used to format the extracted topics from the trained models:
1 # Helper functions
2 def format_topic(topic):
3 t = {}
4 t["id"] = topic[0]
5 a = topic[1].split(" + ")
6 t["words"] = {}
7 for i,m in enumerate(a):
8 k = [Link]("*")
9 if i == 0:
10 max_weight = float(k[0])
11 t["words"][k[1].replace('"','')]=float(k[0])/max_weight
12
13 return t
14
15 def get_topic_words(topic):
16 words = []
17 weights = topic[1].split(" + ")
18 t["words"] = {}
19 for i,m in enumerate(weights):
Page 35
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
20 k = [Link]("*")
21 [Link](k[1].replace('"',''))
22
23 return words
From Figures 29 and 30 we can see that the LDA model outperforms the LSI model
in the given scenario. The LDA topic output is more coherent and distinctive between
the four topic choices. Meanwhile, the LSI topic output tends to loose coherence between
the second and fourth topic, while also presenting similar topics.
The resulting topics and CV coherence scores in Figure 31 further reinforce the
previous affirmation about the performance of the two models. While the coherence
scores for the two models are fairly similar (approximately 0.015 difference), the per-
topic coherence of the LSI model is highly inconsistent, with higher highs and lower lows
for the presented topics.
Figure 29: Most important words per topic via LDA model.
Page 36
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 30: Most important words per topic via LSI model.
Figure 31: Comparing per topic coherence scores between the LDA and LSI modes for
the r technology new [Link] data-set.
Page 37
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 32: Visualising topic data for the trained LDA model with the pyLDAvis library.
Page 38
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
1 - somewhat negative
2 – neutral
3 - somewhat positive
4 – positive
The structure of the data-set can be observed in Figure 33, where we can see that the re-
views corpus has been split into n-grams, organised by the ”PhraseId” and ”SentenceId”
columns. Sub-Figure 34a reveals a heavy imbalance between the classes. To adjust for
this imbalance and maximise the amount of usable data, we first merge the ”somewhat
positive” and ”somewhat negative” classes with ”positive” and ”negative” respectively
(Sub-Figure 34b). Then we further balance the labels by dropping 50% of the ”neutral”
data (Sub-Figure 34c). The final data-set now contains 116269 records across three
classes: 1 - negative; 2 – neutral; 3 - positive.
Page 39
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Text analysis is performed on the original (pre-merge) data-set, selecting only the
text data that is not an n-gram. This results in 8529 records kept from a total of 156060.
The data is pre-processed into tokens and visually analysed using frequency distributions
and word clouds:
Page 40
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
8 frequency_distribution = [Link](tokens_list)
9 # Plotting frequency distribution and showing word cloud
10 [Link](figsize=(12,8))
11 [Link]("Frequency Distribution of words", fontsize=20)
12 frequency_distribution.plot(30,cumulative=False)
13 TextPreprocess.generate_wordcloud_from_frequencies(frequency_distribution,"Word Cloud")
(a) Positive words word cloud. (b) Negative words word cloud.
For machine learning applications it was preferred to use the ”clean corpus” method
form the TextPreprocess utility class (Appendix 4.4). This approach results in much
faster processing times4 for tokenizing, cleaning and lemmatizing text data.
After pre-processing, the analysis data is used to generate the plots in Figure 35.
The ”film” and ”movie” words are removed during pre-processing both for the analysis
and training data. Due to the nature of the training data-sets, these words appear with
4
The light-weight approach uses nltk processing methods, consuming on average one second per 100
records. The ”process corpus” method relies on the gensim processing pipeline, and while it is more
thorough, it averages at two minutes per 100 records.
Page 41
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
a frequency far above the top margin seen in Sub-Figure 42c, so they have been removed
in order to minimise noise in the trained models.
The text review data is is split, with 70% of the data-set being reserved for training
and 15% each for validation and testing. The split is performed with the stratify strategy,
ensuring the same distribution of target labels per split (Figure 36).
Figure 36: Testing balance in label distribution in the train-test split for the
multi-class model.
In order to be fitted on the RFC model, the feature sub-sets of the training, validation
and testing splits are vectorized using Term Frequency - Inverse Document Frequency
(TFIDF) algorithm:
1 # Vectorizer function for convenience
2 def vectorize(data,tfidf_vect_fit):
3 X_tfidf = tfidf_vect_fit.transform(data)
4 words = tfidf_vect_fit.get_feature_names_out()
5 X_tfidf_df = [Link](X_tfidf.toarray())
6 X_tfidf_df.columns = words
7 return(X_tfidf_df)
8
9 tfidf_vect = TfidfVectorizer(max_features=1000, analyzer=lambda x:
,→ TextPreprocess.clean_corpus(x, extra_stop_words=['film', 'movie']))
10 #tfidf_vect = TfidfVectorizer()
11 tfidf_vect_fit = tfidf_vect.fit(X_train['Phrase'])
12 X_train_vect = vectorize(X_train['Phrase'],tfidf_vect_fit)
13 X_val_vect = vectorize(X_val['Phrase'], tfidf_vect_fit)
14 X_test_vect=vectorize(X_test['Phrase'],tfidf_vect_fit)
The RFC model is then tested using K-Fold validation, default parameters and 5
folds. The resulting accuracy scores are recorded in Table 2. Then we perform hyper-
parameter tuning by using GridSearchCV with the following parameters: ”n estimators”:
[5,50,100]; ”max depth”: [2,10,20,None]. Based on the results (Figure 37) the opti-
mal parameters for the multi-class RFC model is a ”max depth” of ”None” and a
”n estimators” of 100. Based on the top three parameters combinations, three mod-
Page 42
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
els are then trained and tested on the validation set, measuring accuracy, recall and
precision.
Fold # R2 Score
1 0.62906991
2 0.63767048
3 0.62513822
4 0.63476071
5 0.63334767
Average 0.632
Figure 37: Hyper-parameter tuning with GridSearchCV for the multi-class classifier.
Page 43
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
The resulting measurements, recorded in Table 3, show that the top model from
the GridSearchCV run is indeed the most optimal. We encode and store the model via
pickling, then we proceed with the final testing run for the multi-class RFC. On the test
data-set we obtain a final measurement of 88% accuracy, 80% precision and 88% recall.
Figures 39 and 38 present the most important features for the sentiment analysis model
and the confusion matrix during classification.
Figure 38: Confusion matrix on the testing set for the final multi-class RFC model.
Page 44
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 39: Most important features for the final multi-class RFC model.
0 – negative
1 - positive
Page 45
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Unlike the multi-label data-set (Section 3.2.1), the binary classification training data
contains only complete review phrases and no n-gram deconstructions (Figure 40). In
addition, the binary classification data-set is perfectly balanced in terms of class distri-
bution, as seen in Figure 41.
Page 46
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
We apply the same pre-processing on the complete review phrases in the bi-class
data-set and produced the analytical visualisations in Figure 42.
(a) Positive words word cloud. (b) Negative words word cloud.
The text data within the bi-class data-set is pre-processed and vectorized in the
same manner as for the multi-label RFC model. Initial performance analysis on the
binary RFC model is carried out via cross-fold validation, with default parameters in
five folds. The resulting accuracy scores (Table 4) are much higher when compared to
the multi-label RFC model.
Fold # R2 Score
1 0.829
2 0.82571429
3 0.83314286
4 0.83071429
5 0.82628571
Average 0.829
Page 47
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
The binary-classification data-set has fewer records and dimension than the multi-
label sample, allowing us to execute a wider GridSearchCV search with less compu-
tational resources. The following parameters are tested during the GridSearchCV op-
timisation: ”n estimators”: [5,10,25,50,75,100]; ”max depth”: [2,5,10,20,30,50,None].
Following the hyper-parameter tuning, the parameters that resulted in the most op-
timal model are ”None” for ”max depth” and 100 for ”n estimators”, similar to the
multi-label RFC model.
We compile results on the validation data-set (Table 5) to confirm that the afore-
mentioned parameters are most optimal and then store the produced model. Lastly,
we predict on the training set and obtain a final measurement of 92% accuracy, 93%
precision and 92% recall. Figures 43 and 44 present the most important features for
the binary sentiment analysis model and the confusion matrix after classifying on the
training set.
Figure 43: Confusion matrix on the testing set for the final bi-class RFC model.
Page 48
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 44: Most important features for the final bi-class RFC model.
Page 49
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
The training data is pre-processed in the same manner as for the other two models, with
the exception of excluding TFIDF vectorization, so that it would be compatible with
the input layer of our RNN model. The RNN model is trained for 6 epochs, with a 100
units batch size. Despite the very high accuracy scores reached during the training cycle
(Figure 46), the finished RNN model perform very poorly on testing data, as denoted in
the classification report in Figure 47.
The poor performance can be attributed to the pre-processing techniques usedand to
the interpretation of the predicted results. The RNN model returns a probability score
instead of the outright class, indicating which class is most likely to be. The current
interpretation strategy is to group all predictions with a probability higher than 0.5 as
”positive” sentiments and the opposite as ”negative” sentiments.
Proposed improvements for future iterations include:
Page 50
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 51
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 52
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 53
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
17 # Vectorizing target text based on the same schema used for training the
,→ given RFC model
18 vectorized_text = tfidf_vect_fit.transform(target_text)
19 words = tfidf_vect_fit.get_feature_names_out()
20 vectorized_text_df = [Link](vectorized_text.toarray())
21 vectorized_text_df.columns = words
22
23 predictions = binary_rfc.predict(vectorized_text_df)
24 return [labels[label_index] for label_index in predictions]
We load the optimised and trained RFC models from storage, and prime the TFIDF
vectorizers that will be used to individually fit test data to each classifier (Figure 49).
We first asses the sentiment analysis capacity of the two models on actual movie
reviews, extracted from multiple sources. This test aims to prove that the models are
viable for text data that matches the same domain as their training data. The reviews
used of analysis are in order of prediction:
Review #1 - Positive:
”Great review. As a former mechanic and sales person for 12 years. I am a total need
when it comes to wrong audio being dubbed over cars and inaccuracies. Big budget
films must just get the directors cousin to be the automotive expert sometimes I swear.
So many inaccuracies of models, years or tech spec.”
Review #2 - Negative:
Page 54
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
”A negative rating for Negative. I’m not sure what accomplished director/producer/cin-
ematographer Joshua Caldwell was thinking taking on this project. This film has got to
be the epitome of terrible writing and should be a classroom example of ’what not to do’
when writing a screenplay. Why would Joshua take on (clearly) amateur writer Adam
Gaines script is beyond me. Even his good directing and excellent cinematography could
not save this disaster.”
Review #3 - Negative:
”No action there. Woman and dude take a car and drive away. Still nothing happens.
Half the movie, they finally met an old friend of the woman because of... convenient
script. A few stupid and useless speaking about food or dogs starts there. What’s the
point ? Guess it’s because amateurish script.”
Review #4 - Positive:
”But the clear highlight of an already-stellar cast (which also includes Noah Taylor and
Andy Nyman as fellow Annex residents) is Schreiber, whose Otto is the pillar upon
which the show truly rests. It’s a turn of noble resolve and determination, a quiet man
whose bravery spurs Miep to demonstrate some of her own. (Their scenes together, often
the quietest in the show, are some of the show’s best.) Schreiber’s always been a king
of speaking volumes through the quietest rumblings of his deep baritone, and this is a
stellar showcase for those qualities.”
The resulting sentiment classifications are visible in Figures 50 and 51. From the re-
sults, we can see that the binary model performs adequately, correctly identifying the
sentiment for each review. As for the multi-class model, the results hint that it may be
under-performing when discerning between positive and neutral sentiments.
Finally, the models are tested for their intended purpose, performing sentiment anal-
ysis on Reddit comments. From Figures 52 and 53 we can observe similar behaviours
as with the movie reviews. The multi-class RFC models correctly interprets negative
sentiments, but shows some bias towards the neutral status. The analysis is considered
to be fairly accurate, given that most of the comments analysed in the test sample are
either negative or neutral towards the topic of the post.
Looking at the sentiment analysis for the binary classifier, we can see good per-
formance in terms of predicting negative sentiments. We can also notice a tendency
of interpreting sarcastic or passive-aggressive comments as positive sentiments, which
could be considered correct given the tone of the discussion and that some of the tar-
geted comments are interpretable as jokes..
Figure 50: Sentiment analysis on sample movie reviews with the multi-class RFC
model.
Page 55
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 51: Sentiment analysis on sample movie reviews with the bi-class RFC model.
Figure 52: Sentiment analysis on Reddit comments with the multi-class RFC model.
Page 56
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 53: Sentiment analysis on Reddit comments with the bi-class RFC model.
Page 57
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Figure 54: Fetching the top post on ”r/WorldNes” then extracting the news body via
the BeautifulSoup library.
Page 58
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Finally, we select the sentences that have an importance score greater than 1.5 times
over the average. The resulting summary can be seen in Figure 55.
Page 59
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
4 Appendix
4.1 Reddit API Wrapper Class
1 import requests
2 from pprint import pprint
3 import pandas as pd
4 import os
5 import configparser
6 from datetime import datetime
7
8 class RedditAPIHandler:
9 """
10 Wrapper for the Reddit API to simplify some of the calls, turning incoming
11 json to dataframes, and hiding authentication secrets for the Reddit app.
12 """
13 def __init__(self, path = '[Link]'):
14 """
15 Args:
16 path (String): Path to the .ini file to read the API authentication secrets.
17 Defaults to './[Link]'.
18 """
19 self._path = path # for debug purposes
20 self.__config = [Link]()
21 self.__config.read(self._path)
22
23 self.config_status = {
24 'date_modified': self.__config['DEFAULT']['datemodified'],
25 'grant_type': self.__config['DEFAULT']['granttype'],
26 'app_name': self.__config['[Link]']['app'],
27 'client_name': self.__config['[Link]']['username']
28 }
29
30 self.__headers = {'User-Agent': self.__config['[Link]']['app']}
31
32 [Link]()
33
34
35 def GenerateAuthToken(self, path = None):
36 """
37 Generate new authentication token for the API. The token expires every ~2 hours.
38
39 Args:
40 path (str, optional): Provide a new path for a .ini file containing the API
41 authentication secrets. Defaults to the .ini path provided on class
42 instantiation.
43 """
44 if(path):
45 self._path = path
46 self.__config.read(self._path)
47 auth = self.__app_auth()
48
49 # Setup login data
Page 60
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 61
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
99 'upvote_ratio': post['data'].get('upvote_ratio'),
100 'ups': post['data'].get('ups'),
101 'downs': post['data'].get('downs'),
102 'score': post['data'].get('score'),
103 'link_flair_text': post['data'].get('link_flair_text'),
104 'is_original_content': post['data'].get('is_original_content'),
105 'is_video': post['data'].get('is_video'),
106 'post_hint': post['data'].get('post_hint'),
107 'url': post['data'].get('url'),
108 'created_utc': post['data'].get('created_utc')),
109 'id': post['data'].get('id'),
110 'kind': post['kind'],
111 'total_awards_received':
,→ post['data'].get('total_awards_received'),
112 'num_comments': post['data'].get('num_comments'),
113 'num_crossposts': post['data'].get('num_crossposts'),
114 'num_reports': post['data'].get('num_reports'),
115 'domain': post['data'].get('domain'),
116 }, index=[0])
117 df = [Link]([df, append_df], ignore_index=True)
118
119 return df
120
121 def PullSubredditFeed(self, subreddit, sort_by = 'new', limit = 20):
122 """Fetch post data from a specified subreddit feed. Search for new
123 or popular threads.
124
125 Args:
126 subreddit (String): r/woosh The subreddit name, without the 'r/'.
127 sort_by (String): Enum, of 'new', 'hot', 'best', 'top', 'controversial'.
128 Defaults to 'new'.
129 sort_order (Boolean): True for ascending
130 limit (Integer): How many posts to return. Applies only when sorting posts
131 by 'new'. Defaults to 20.
132
133 Returns:
134 [Link]: DataFrame containing multiple reddit posts
135 belonging to a subreddit feed.
136 """
137
142 if(limit<=100):
143 params = {'limit': limit}
144 res = [Link](requests_string,
145 headers = self.__headers,
146 params = params)
147 # get dataframe from response
Page 62
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 63
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 64
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
23 values = [Link][0].[Link]().tolist()
24 values += values[:1]
25 [Link](angles, values, linewidth=1, linestyle='solid', label=first_label)
26 [Link](angles, values, 'b', alpha=0.1)
27
Page 65
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 66
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Results:
Diameter: 17
Radius: 0
Average Path length: 4.33774423847196
Results:
Modularity: 0.835
Modularity with resolution: 0.835
Number of Communities: 16
Page 67
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 68
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
Page 69
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
53 in Reddit data
54 tokens = [word for word in words if not word.orth_.isspace()]
55
56 # Removing punctuation
57 if(not keep_punctuation):
58 tokens = [token for token in tokens if not token.is_punct]
59
60 match word_reduce_strategy:
61 case 'lemma':
62 # Lemmatize the words
63 tokens = [token.lemma_ for token in tokens]
64 tokens = [[Link]() for token in tokens]
65 case 'stem':
66 # Stem the words
67 stemmer = SnowballStemmer('english')
68 tokens = [token.lower_ for token in tokens]
69 tokens = [[Link](token) for token in tokens]
70 case other:
71 tokens = [token.lower_ for token in tokens]
72
73 # # Removing stop words
74 if(not keep_stop_words):
75 tokens = [token for token in tokens if token not in
,→ self.stop_words_en and token not in extra_stop_words and
,→ len(token) >= min_token_length]
76
77 if(join_tokens):
78 return ' '.join(tokens)
79 else:
80 return tokens
81
82
83 # Optimized for single use
84 @staticmethod
85 def clean_corpus(corpus, min_word_length=2, extra_stop_words=[]):
86 wn = [Link]()
87 stopwords = [Link]('english')
88 tokens = nltk.word_tokenize(corpus)
89 lower = [[Link]() for word in tokens]
90 no_stopwords = [word for word in lower if word not in stopwords and
,→ word not in extra_stop_words and len(word)>min_word_length]
91 no_alpha = [word for word in no_stopwords if [Link]()]
92 lemm_text = [[Link](word) for word in no_alpha]
93 return lemm_text
94
95
Page 70
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
129 @staticmethod
130 def generate_wordcloud_from_frequencies(frequency_distribution, label,
,→ background_color="black", max_words=100, max_font_size=50):
131 [Link](figsize=(12,8))
132 wc = WordCloud(background_color=background_color, max_words=max_words,
,→ max_font_size=max_font_size)
133 wc.generate_from_frequencies(frequency_distribution)
134 [Link](label, fontsize=20)
135 [Link]([Link](colormap='Pastel2', random_state=17), alpha=0.98)
136 [Link]('off')
Page 71
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
10 def GenerateWordFrequencyDistribution(text):
11 stops = set([Link]("english"))
12 words = word_tokenize(text) #tokenize text by words
13 freqTable = dict()
14
24
25 def CalculateSentenceImportance (text, freqTable):
26 sents = sent_tokenize(text)
27 sentScores = dict()
28
29 for sent in sents:
30 for word, freq in [Link]():
31 if word in [Link]():
32 if sent in sentScores:
33 sentScores[sent] += freq #Add the frequency of a word
,→ occuring to the sentence score if it has been added to
,→ before
34 else:
35 sentScores[sent] = freq #Set score of a sentence to the
,→ score of the first word occuring in the sentence
36 return sentScores, sents
37
38
39 def CalculateAverageSentenceImportance (sentScores):
40 sumValues = 0
41 for sentence in sentScores:
42 sumValues += sentScores[sentence] #Calculate total sentence values
43
Page 72
BIRMINGHAM CITY UNIVERSITY
SCHOOL OF COMPUTING AND DIGITAL TECHNOLOGY
References
Sponder, M. and G. Khan (2017). Digital analytics for marketing. Routledge.
Ganis, M. and A. Kohirkar (2015). Social media analytics: Techniques and insights for
extracting business value out of social media. IBM Press.
Bastian, M., S. Heymann, and M. Jacomy (2009). “Gephi: an open source software for
exploring and manipulating networks”. In: Proceedings of the international AAAI
conference on web and social media. Vol. 3. 1, pp. 361–362.
Leskovec, J. and J. Mcauley (2012). “Learning to discover social circles in ego networks”.
In: Advances in neural information processing systems 25.
Blondel, V. D., J.-L. Guillaume, R. Lambiotte, and E. Lefebvre (2008). “Fast unfolding
of communities in large networks”. In: Journal of statistical mechanics: theory and
experiment 2008.10, P10008.
Blei, D. M., A. Y. Ng, and M. I. Jordan (2003). “Latent dirichlet allocation”. In: Journal
of machine Learning research [Link], pp. 993–1022.
Hofmann, T. (1999). “Probabilistic latent semantic indexing”. In: Proceedings of the
22nd annual international ACM SIGIR conference on Research and development in
information retrieval, pp. 50–57.
Xiao, J. and Z. Zhou (2020). “Research progress of RNN language model”. In: 2020
IEEE International Conference on Artificial Intelligence and Computer Applications
(ICAICA). IEEE, pp. 1285–1288.
Tarwani, K. M. and S. Edem (2017). “Survey on recurrent neural network in natural
language processing”. In: Int. J. Eng. Trends Technol 48.6, pp. 301–304.
Jelodar, H., Y. Wang, R. Orji, and S. Huang (2020). “Deep sentiment classification and
topic discovery on novel coronavirus or COVID-19 online discussions: NLP using
LSTM recurrent neural network approach”. In: IEEE Journal of Biomedical and
Health Informatics 24.10, pp. 2733–2742.
Page 73