text:
% !TeX encoding = utf8
% !TeX spellcheck = en_US
% !BIB program = biber
% !TeX program = lualatex

\documentclass[aspectratio=169,14pt,usepdftitle=false]{beamer}
\nonstopmode % never stop to ask to fix things.

% Configure beamer
\usetheme{Dresden}
\usecolortheme{dove}
\usefonttheme[stillsansserifsmall]{serif}
\setbeamerfont{title}{size=\LARGE,family=\titlefont}
\setbeamerfont{subtitle}{parent={title},size=\Large}
\setbeamerfont{author}{parent={title},size=\Large}
\setbeamerfont{date}{parent={author}}
\setbeamerfont{frametitle}{size=\Large}
\usefonttheme{professionalfonts}
\setbeamertemplate{navigation symbols}{}
\setbeamersize{text margin right=0.13\paperwidth,%
    text margin right=0.13\paperwidth}
\setbeamertemplate{frametitle continuation}{}  % no indication that this is the second frame in an allowframebreaks group
% Make the background, including the section header, lightgray
% NOTE: If you use a different theme, you might have to tweak this a bit
\definecolor{lightgray}{RGB}{245,245,245}
\setbeamercolor{background canvas}{bg=lightgray}
\setbeamercolor{section in head/foot}{bg=lightgray}
\setbeamercolor{subsection in head/foot}{bg=lightgray}

\setbeamercolor{alerted text}{fg=red!70!black}

% Configure fonts and languages
\usepackage{fontspec}
\usepackage{unicode-math}
\defaultfontfeatures{Ligatures=TeX}
% These fonts are not installed by default.
% Download them and install them in your $HOME/.fonts/ folder
% https://github.com/libertinus-fonts/libertinus
% http://overpassfont.org/
% FontAwesome might not be installed by default on Mac, but is available online for free.
\setmainfont[Numbers={OldStyle, Proportional}]{Libertinus Serif}
\setmathfont{Libertinus Math}
\setsansfont{Overpass}
\setmonofont{Overpass Mono}
\newfontfamily\titlefont{Libertinus Serif Display}[Numbers={OldStyle, Proportional}]
\usepackage{fontawesome}
\usepackage{amsmath}
\usepackage{polyglossia}
\setmainlanguage[variant=american]{english}
\usepackage{csquotes}
\usepackage{microtype}
\frenchspacing
\microtypecontext{spacing=nonfrench}

% Add a page with the section title at the beginning of each section.
% (The less-custom way to do this would be \AtBeginSection{\frame{\sectionpage}})
\AtBeginSection[]{
  \begin{frame}
  \vfill
  \centering
  \begin{beamercolorbox}[sep=8pt,center,shadow=true,rounded=true]{title}
    \usebeamerfont{title}\insertsection\par%
  \end{beamercolorbox}
  \vfill
  \end{frame}
  % After putting in this section, increment the subsection counter.
  % I'm not using subsections, but the beamer theme looks at the subsection counter to see whether it should put dots representing the number of slides used.
  % If you are using subsections and have trouble trouble with subsection numbering, comment this line out.
  \stepcounter{subsection}
}
\usepackage{changepage}
\usepackage[absolute,overlay]{textpos}
\usepackage{xifthen}  % provide \isempty
\makeatletter
\newcommand{\customframenumber}{%
\ifnumequal{\c@framenumber}{0}{}{% Only do the following for slides that aren't #0
% Line up the numbers with the progress dots
\begin{textblock*}{2ex}[1,1](0.989\paperwidth,0.98\paperheight)%
\raggedleft%
\insertframenumber%
\end{textblock*}%
}%
}
\makeatother
\setbeamertemplate{footline}{\customframenumber}

% Define a fullscreenback command, to be called like:
% \fullscreenback{my-label}{back-button-label}{image-filename}
% All arguments are required, but may be empty.
\newcommand{\fullscreenback}[3]{%
{%
\usebackgroundtemplate{%
% parbox borrowed from https://tex.stackexchange.com/a/26459
\parbox[c][\paperheight][c]{\paperwidth}{%
\centering\includegraphics[height=\paperheight, width=\paperwidth, keepaspectratio]{#3}
}%
}%
\begin{frame}[plain]
% Optional arguments borrowed from https://tex.stackexchange.com/a/58629
\ifthenelse{\isempty{#1}}{}{\label{#1}}
\ifthenelse{\isempty{#2}}{}{\backbutton{#2}}
\usebeamerfont{footline}{\customframenumber}
\end{frame}
}%
}
\newcommand{\fullscreen}[2][]{%
% Call the fullscreenback command with no back argument, so no back button
% Label is optional first argument
\fullscreenback{#1}{}{#2}
}

\newcommand{\fullscreencredit}[3][bottom right]{%
% Like \fullscreen, but with a photo credit
{%
\usebackgroundtemplate{%
% parbox borrowed from https://tex.stackexchange.com/a/26459
\parbox[c][\paperheight][c]{\paperwidth}{%
\centering\includegraphics[height=\paperheight, width=\paperwidth, keepaspectratio]{#2}
}%
}%
\begin{frame}[plain]
% Pick alignment. Only bottom right, top right, and bottom left are implemented so far.
\ifthenelse{\equal{#1}{bottom right}}{%
  % If optional is "bottom right", the default
  \begin{textblock*}{\widthof{\usebeamerfont{footline}{#3}}}[1,0](0.98\paperwidth, 0.96\paperheight)
  \hfill \usebeamerfont{footline}{#3}%
}{%
\ifthenelse{\equal{#1}{top right}}{% if optional is not "bottom right", check if it's "top right"
  % If optional is "top right"
  \begin{textblock*}{\widthof{\usebeamerfont{footline}{#3}}}[1,0](0.98\paperwidth, 0.03\paperheight)
  \hfill \usebeamerfont{footline}{#3}%
}{%
\ifthenelse{\equal{#1}{bottom left}}{%
  % If optional is "bottom left"
  \begin{textblock*}{\widthof{\usebeamerfont{footline}{#3}}}[0,0](0.02\paperwidth, 0.96\paperheight)
  \raggedright \usebeamerfont{footline}{#3}%
}{%  if optional is not "bottom right", "top right", or "bottom left"
  \begin{textblock*}{\textwidth}[1,0](0.98\paperwidth, 0.03\paperheight)
  \large WARNING: alignment #1 is not implemented.
}}}
% Remaining lines are outside the if-else because we run it in any case
\usebeamerfont{footline}{\customframenumber}
\end{textblock*}
\end{frame}
}%
}

\newcommand{\navbutton}[2]{%
\hyperlink{#1}{\beamerbutton{#2}}%
}

% Use the textpos package to make it easy to put the beamer "back" button in the bottom right
% the new command is called \backbutton. It takes one argument, the label you're linking back to.
\newcommand{\backbutton}[1]{%
% these text positions are measured from the upper left corner, so 0.9, 0.9 is lower right
\begin{textblock*}{2cm}(0.93\paperwidth,0.92\paperheight)%
\navbutton{#1}{Back}
\end{textblock*}%
}
\setbeamercolor{button}{bg=white, fg=black}
\setbeamercolor{button border}{fg = black!60!gray}
\setbeamerfont{button}{family=\sffamily}

% Improve math spacing around \left and \right
\usepackage{mleftright}
\mleftright{}

\DeclareMathOperator{\blackboardE}{\mathbb{E}}
% Define \expected and \indicator commands
\newcommand{\expected}[2][]{%
% If no optional argument, no subscript:
\ifthenelse{\isempty{#1}}{
\blackboardE\left[#2\right]
}{
% If optional argument is provided, use it as the subscript
\blackboardE_{#1}\left[#2\right]
}}
\newcommand{\indicator}[1]{\symbf{1}\left[#1\right]}

\usepackage[biblatex]{embrac}
% Define a postparen command to fix spacing after ")", "]", or "}" because of embrac.
\newlength{\postparenlength}
\setlength{\postparenlength}{0.14em}
\newcommand{\postparen}{\hspace{\postparenlength}}

\usepackage[version=4]{mhchem}  % use the \ce{} command for chemistry expressions
\usepackage{booktabs}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{sparklines}

% If you want to use siunitx, here are some setting suggestions:
% \usepackage{siunitx}
% \sisetup{
%   group-separator={,},
%   group-digits = integer,
%   input-ignore = {,},
%   input-symbols = {()},  % make siunitx not flip out about () for standard errors
%   input-open-uncertainty  = ,
%   input-close-uncertainty  = ,
%   input-decimal-markers = {.},
%   table-space-text-post = ***,
%   table-align-text-post = false,
%   round-mode = figures,
%   round-precision = 2,
% tight-spacing = true,
% table-alignment = right
% }
\usepackage[authordate,isbn=false,backend=biber,autopunct=true]{biblatex-chicago}
\usepackage{biblatex-certrand} % provided in the same folder -- biblatex-certrand.sty
\renewcommand*{\bibfont}{\small}

% Use mdframed to make a semi-transparent title box
% Borrowed from http://danielfalster.com/blog/2013/06/18/a-nice-title-page-for-beamer-presentations/
\usepackage[framemethod=tikz]{mdframed}

\usepackage{hyperref}
\hypersetup{colorlinks,
  linkcolor=black,
  filecolor=black,
  urlcolor=blue!40!black,  % 40% blue, 60% black
  citecolor=black,
  pdfpagemode=UseNone,
  pdftoolbar=false,
  pdftitle={a},
  pdfauthor={},
  pdfsubject={},
  pdfcreator={},
  pdfproducer={},
  pdflang=en,
  unicode=true
}

\usepackage{dcolumn}

% Define two column types, d, a basic numeric column, and A, the same for alerted text.
% Changes are in sync with the 'alerted text' beamer color.
\newcolumntype{d}[0]{D{.}{.}{4}}
\makeatletter
% Borrowed from https://tex.stackexchange.com/a/152313
\newcolumntype{A}[0]{>{\begin{alertenv}\DC@{.}{.}{4}}c<{\DC@end\end{alertenv}}}
\makeatother
\newcommand{\alertcol}[1]{\multicolumn{1}{A}{#1}}

% Things to customize:
\addbibresource{refs.bib}
\graphicspath{{../graphics/}}
% If you only want to print your \note{}s
% \setbeameroption{show only notes}
\title{Punny title: evidence from\\Punnsylvania}
\subtitle{}
\author[]{Author}
\institute{}
\date{January 19, 2038}

\begin{document}
{
\usebackgroundtemplate{%
% parbox borrowed from https://tex.stackexchange.com/a/26459
\parbox[c][\paperheight][c]{\paperwidth}{%
\centering
\includegraphics[height=\paperheight, width=\paperwidth, keepaspectratio]{sample_image}
% Sample photo by Peter Oslanec on Unsplash
}}
\begin{frame}[plain]
\begin{mdframed}[tikzsetting={draw=black, fill=white, fill opacity=0.7, line width=4pt},
    backgroundcolor=none,
    leftmargin=0.1\paperwidth,
    rightmargin=-0.1\paperwidth,
    skipabove=0.15\paperwidth,
    skipbelow=0.05\paperwidth,
    innertopmargin=1em,
    innerbottommargin=1em]

    {\usebeamerfont{title}{\inserttitle}}

\begin{columns}[T] % align columns
\begin{column}{.45\textwidth}
    \vspace{\baselineskip}

    {\usebeamerfont{author}{\insertauthor}}

    {\usebeamerfont{institute}{\insertinstitute}}

    {\usebeamerfont{date}{\insertdate}}

\end{column}
\begin{column}{.55\textwidth}

    \faicon{paper-plane} \href{mailto:email@example.com}{email@example.com}

    \faicon{laptop} \href{https://example.org}{https://example.org}

    \faicon{map-signs} Some place
\end{column}%
\end{columns}
\end{mdframed}
\end{frame}
}

\section{Section 1}

\begin{frame}{Isn't this a great deck?}

\end{frame}

\appendix
\section{References}

\begin{frame}[t,allowframebreaks] % References
  \frametitle{References}
  \printbibliography
\end{frame}
\end{document}

%%%%%%%%%%%%%%%%
% Useful template material:
\begin{frame}{}
  \begin{itemize}
    \item
    \item
    \item
  \end{itemize}
\end{frame}

% A fullscreen figure:
\fullscreen{my_fav_photo}
% A fullscreen figure with \label:
\fullscreen[fig:my-fav]{my_fav_photo}

% Table:
\makebox[\linewidth][c]{
\begin{tabular}{l S S S}
A & \multicolumn{1}{c}{B} & \multicolumn{1}{c}{C} &  \multicolumn{1}{c}{D}
\end{tabular}
}

% Fancy table:
\begin{frame}{Results!}
\makebox[\linewidth][c]{
\begin{tabular}{l dddd}
  \toprule
 &  \multicolumn{1}{c}{Means} & \multicolumn{3}{c}{Diff-in-Diff Estimates} \\
  Outcome 1 & 2.58 & 0.11 & 0.08 & 0.12\\
            & (2.55) & (0.04) & (0.04) & (0.04)\\
 Outcome 2 & 60.90 & -0.73^{**} & -0.113^{***} & -1.58\\
            & (17.02) & (0.10) & (0.11) & (0.12) \\
  Outcome 3 & \alertcol{18.98} & 0.77 &1.28 & 1.62 \\
            & \alertcol{(6.74)} & (0.13) & (0.13) & (0.12)\\
  \bottomrule
  \addlinespace
  % NOTE: Adjust this multicolumn number to be the number of columns you have, and adjust the fraction of \linewidth to make the column spacing look good.
  \multicolumn{5}{p{0.7\linewidth}}{
  \small
  \textsc{Note:}
  The standard errors are clustered by exactly the right variables.
  \par
  ** and *** indicate significance at the 5\% and 1\% levels.
  }
\end{tabular}
}
\end{frame}

% Two-column frame
\begin{frame}{Two Column Frame}
    \begin{columns}[T] % align columns
        \begin{column}{.58\textwidth}
        \color{red}\rule{\linewidth}{4pt}
        Column 1
        \end{column}%
    \hfill%
        \begin{column}{.38\textwidth}
        \color{blue}\rule{\linewidth}{4pt}
        Column 2
        \end{column}%
    \end{columns}
\end{frame}


text:
\section{Telekinesis}\label{spell:telekinesis}
\textbf{Cost:} 100 CP\\
\textbf{Requirements:}~\nameref{rune:air} I,~\nameref{rune:arcana} I\\
\textbf{Spell, Active, Source, Memory(50 Gold), Repeatable}\\
You spend 6 AP and 5 Mana to slightly lift a remote object or creature that is the equivalent of one small or smaller object.
You can move the lifted item around freely in the air, taking 1 Mana and 1 AP per \passus{1} moved.
You can also just keep it in the air, which doesn't cost you AP or Mana.\\
The effect ends when you decide to, or when you lose sight of the object.
Another person can try to also control the same object.
If they are doing so manually, they make a Strength check against your Intellect check.
If they also try to manipulate the object with a Telekinesis spell, you make opposing Intellect checks similar to the effect of a "Dispel Magic" spell.
If you lose, the spell also ends and the other person gains control of the item.\\
\\
Level Progression:\\
II: 500 CP, 10 initial Mana a medium object.\\

III: 1,000 CP, 20 initial Mana for a large object.
Also, moving lifted items that are small or smaller doesn't cost additional Mana anymore.\\

IV: 2,500 CP, 30 initial Mana for an extra-large object.
Also, moving lifted items that are medium or smaller doesn't cost additional Mana anymore.

ext: tex

max_stars_repo_name: NTrixner/RaggedLandsPenAndPaper

max_issues_repo_name: NTrixner/RaggedLandsPenAndPaper

max_forks_repo_name: NTrixner/RaggedLandsPenAndPaper


text:
\chapter{Background}

Feature and classifier selection are both crucial for classification using machine learning; analyzing the key properties of a dataset with the model best suited for that domain tends to lead to better results.  Classical machine learning classifiers require numerical values to represent observations of each class.  Since the datasets in natural language processing (NLP) tasks are usually raw text, as is the case for this research study, there must be a conscientious choice on how to accurately portray the text numerically.  Two NLP techniques to produce vectorized representations of text documents are presented in this chapter: term frequency-inverse document frequency score weighting, and word embeddings.  This chapter also includes a section on preprocessing techniques to refine the textual data, as well as a brief synopsis on the field of sentiment analysis to motivate the idea that sentiment scores can be important features for this study since they provide insight about the motivation and purpose of a piece of text.  Lastly, this chapter formally introduces the classifier models used in this research: k-nearest neighbors, support vector machines, and recurrent neural networks.

\section{Preprocessing} \label{preprocessingSection}
Real-world data is usually messy.  One of the first steps before performing any data analysis is to clean or refine the data by making the data structured and correct, and removing any discernible noise.  The preprocessing steps performed in this study fall into the category Jurafsky and Martin call "text normalization" because the text is being converted into a convenient and standard form \cite{preprocessing}.  The very first step in text processing is to tokenize the data, or separate the words.  Though common practice is to simply use whitespace and punctuation to delimit words, compound words such as proper nouns (e.g., "White House") can lose their meaning when broken up.  To overcome this information loss, named entity recognizers can be used to prevent splitting up these tokens.

To standardize the data, the tokens may then be converted to their roots so different tenses of words can be linked together.  However, this task, called lemmatization, requires that the words in each sentence are first tagged with their part-of-speech to determine the root word.  Since part-of-speech tagging is sometimes too computationally intensive for large documents, a simpler approach called stemming is often used in its place.  Stemming aims to remove the suffixes of each word to get the root.  However, the effectiveness of the stemmer is implementation dependent.  For example, the Porter stemmer aims to remove suffixes using pattern matching, potentially producing incoherent words or semantically incorrect words (e.g., the stem of "ties" is "ti", and the stem of "operator" is "operate") \cite{porterStemmer}.  Finally, to refine the text of the document, articles, pronouns, prepositions, and other uninformative words are sometimes filtered out before the core analysis is performed.  These uninformative words, called stop words, usually help in information retrieval and document similarity tasks \cite{stopWord}.

\section{Term Frequency-Inverse Document Frequency} \label{tfidfSection}

Once preprocessing is complete, the remaining text must be transformed into real-valued vectors so that the text can be used by a model.  One technique to produce numerical values for words in a document is to represent each word by its term frequency-inverse document frequency score.  The term frequency-inverse document frequency (tf-idf) of a word is used to quantify the importance of a word in a corpus based on how frequently the word shows up in a document and how many other documents also contain the word \cite{tfidf}.

\begin{equation}
\label{eq:tfidf}
\mbox{tf-idf}_{w,d_{i},D} = ( \frac{c_{w}}{|d_{i}|} ) \cdot \log ( \frac{|D|}{1 + |d  \in  D : w  \in  d|} )
\end{equation}

A basic tf-idf scoring function is available in Eq. \ref{eq:tfidf}.  The first term represents the term frequency (tf) of the word $w$, which is the ratio of the number of occurrences of the word ($c_{w}$) to the total number of words in the document ($|d_{i}|$).  The second term is the inverse document frequency (idf) which serves to boost rarer, more informative words, and diminish the impact of frequently used non-informative words, like articles and pronouns.  Since the idf is computed by taking the logarithm of the total number of documents in the corpus ($|D|$) divided by the number of documents with the word offset by 1 to avoid 0 denominators ($1 + |d  \in  D : w  \in  d|$), words that appear in almost all the documents will have a idf close to 0.  On the other hand, words that appear in only select documents will have larger idf values, thereby increasing their tf-idf weights.

\section{Word Embeddings}

\begin{figure}[h]
\centering
\captionsetup{justification=centering,width=0.95\textwidth}
\centerline{\includegraphics[width=0.95\textwidth]{similarWordVectors.png}}
\caption[t-SNE Visual of Numbers and Occupations]{
    t-SNE visualization of word embeddings \cite{wordEmbeddingImg}\\
    Left: the number region in a word embedding model\\
    Right: the occupations region
}
\label{fig:similarWordVectors}
\end{figure}

Another way to numerically represent a text is to use a word embedding model to transform each word into a real-valued vector.  The word embedding of a word is the high-dimensional vector that is the result of mapping the word with a parameterized function that was developed using a large corpus that is representative of the source language.  One of the primary benefits of using word embeddings is that similar words will tend to map to the same region.  t-distributed stochastic neighbor embedding (t-SNE) is a probabilistic technique designed for dimensionality reduction, and can be used to visualize high-dimensional datasets like word embeddings \cite{tsneAbout}.  The t-SNE algorithm converts similarities between data points into joint probabilities and tries to minimize the divergence between these joint probabilities and the high-dimensional data \cite{tsneVisual, tsnePython}.  Due to the reduction in dimensionality, mainly for the purposes of visualization, the axes and its units on t-SNE plots do not have any real meaning; however, the t-SNE still meaningfully shows which of the points are closer together in the original feature space \cite{tsneAxes}.  An example of the benefit is shown in Fig. \ref{fig:similarWordVectors} which shows zoomed-in views on the number and jobs regions of a t-SNE visual constructed using word embeddings.

\begin{figure}[h]
\centering
\captionsetup{justification=centering,width=0.95\textwidth}
\centerline{\includegraphics[width=0.65\textwidth]{comparativeVsSuperlative.png}}
\caption[t-SNE Visual of Comparative and Superlative Words]{
    t-SNE visual of GloVe word embeddings for select comparative and superlative words \cite{comparativeVsSuperlative}
}
\label{fig:comparativeVsSuperlative}
\end{figure}

The word embedding model used in this study is the GloVe model that was trained by a team of Stanford researchers using global word-to-word co-occurrence statistics.  This vector representation model proves to be highly effective at grouping together similar or related words in higher dimensions.  Furthermore, the model was designed in way such that vector differences between two words' word embeddings capture "the meaning specified by the juxtaposition of two words" \cite{glove}.  For example, the conceptual difference between "short", "shorter", and "shortest" is similar to the difference between "slow", "slower", and "slowest".  Using the underlying words' GloVe word embedding vectors, this conceptual difference is mirrored by vector differences in the t-SNE plot in Fig. \ref{fig:comparativeVsSuperlative}.

\section{Sentiment Analysis} \label{sentimentAnalysisSection}

One common text categorization task is sentiment analysis, which is the identification of sentiment-related features such as the author's positive or negative orientation towards the subject of the text.  Closely related is opinion mining which relates to the extraction and analysis of opinion about entities.  In most literature, and in this paper, the two terms are used interchangeably since the two tasks have become synonymous with each other \cite{sentimentApp}.  Texts such as movie, book, or product reviews, are clear examples of authors expressing their opinions, and sentiments, towards the product.  Similarly, editorials and political texts express the author's sentiment toward the political candidate or the political action that is the subject of the text \cite{nbSentiment}.

Sentiment analysis can be performed at varying granularities: document-level, sentence-level, and aspect-level.  As the terminology hints, document- and sentence-level sentiment analysis aim to classify the sentiment of the text using the whole document as a singular unit.  By classifying constituent sentences, a heuristic can be applied using these lower-level results.  On the other hand, aspect-level sentiment analysis aims to classify sentiment with respect to particular entities, such as parts of a products or distinct characteristics of a person \cite{sentimentApp}.

The potential, and observed, applications of sentiment analysis include product opinion gathering and monitoring, bias detection, automated recommendation engines, and even question answering and automated summarization \cite{sentimentAnalysis}.  Tasks such as product reception, review analysis, and suggesting other products to users based on their reviews are textbook examples of document- and sentence-level sentiment analysis.  Effective question answering systems need to be able to discern the aspect with which questions are asked; that is, whether not the question is purely fact-oriented, or is inherently opinionated and, thus, seeks an opinion-oriented response.  Similarly, summarization benefits from understanding the viewpoints of the text to provide a more cohesive output.

\section{$K$-Nearest Neighbors} \label{knnSection}

The $k$-nearest neighbors (KNN) algorithm is a decision-boundary based classification algorithm that classifies an input to the majority class of its $k$ nearest neighbors in space \cite{knnIR}.  The tunable hyperparameters for this algorithm include $k$, the number of neighbors used for classifying any given input, and the distance metric used for determining the closest neighbors.  The least robust KNN is thought to be $k$ = 1 because this model runs the risk of becoming heavily reliant on noise or outliers.  Variants of KNN may weigh the votes of training set observations with their cosine similarity relative to their input, as shown in Eq. \ref{eq:knnClassScore}.

\begin{equation}
\label{eq:knnClassScore}
score(c, d) = \sum_{d' \in S_{k}(d)} (I_{c}(d') \cdot cos(v(d'), v(d))
\end{equation}

In this scoring weighting scheme, $S_{k}(d)$ is the set of $d$'s $k$ nearest neighbors and $I_{c}(d')$ is the indicator function which equals 1 if and only if the observation $d'$ is part of class $c$, otherwise 0 \cite{knnIR}.

The advantages of KNN as a classification algorithm for practical applications are numerous.  As a non-parametric learning algorithm, KNN requires no assumption on the underlying distribution of the input data.  For applications in natural language processing, specifically classification of news articles as genuine or maliciously authored for political gain, there is not enough substantial evidence to map the articles' text to a closed form probabilistic distribution.  Furthermore, since KNN is an instance-based algorithm, the only "learning" required is to load the observations into memory, which significantly reduces training time \cite{knnGuide}.

As with any machine learning algorithm, KNN also has some drawbacks.  Testing inputs with KNN requires all of the training set to be in memory, or available through some highly performant data store, like a database, so vectorized inputs can be compared with every training point to determine the $k$ nearest neighbors.   However, because our dataset is not too large, this limitation is not a burden for our task.  Another downside to KNN is the time cost for testing: for each individual input, every training point must be checked to see if it is one of the $k$ nearest neighbors, and if so, use its label for classification.  As it turns out, even this limitation does not severely impact testing performance due to the size of the dataset; thus, a trained KNN model is highly performant and can be used for real-time classification \cite{knnGuide}.

\section{Support Vector Machines} \label{svmSection}

The support vector machine (SVM) classifier is a high performing machine learning algorithm that relies on the relatively simple concept of dividing the data into distinct regions.  For example, in binary classification, SVMs seek to maximize the distance between the data points of opposing classes and the dividing decision boundary.   The decision boundary, also known as the hyperplane, is formulated as a linear combination of weights on each dimension of the input, as shown in Eq. \ref{eq:hyperplane}.  $w$ is the vector of weights applied to input $x$, a support vector, whose length corresponds to the dimensionality of $x$, and $b$ is the bias, a constant offset.

\begin{equation}
\label{eq:hyperplane}
w^{T}x + b = 0
\end{equation}

The data points closest to the hyperplane are called the support vectors, and the shortest distance between these points and the boundary is called the margin.  By maximizing the margin, the probability for misclassification due to noise is reduced, assuming that the testing data points come from the same distribution as the training data.  One clear advantage of using SVMs is the low memory cost: only these support vectors need to be held in memory; the other data points, which are farther away from the hyperplane, no longer need to be considered (recall that the KNN algorithm requires every input be compared with every training observation to determine the most likely class) \cite{svmIR}.

However, in most practical applications, the data cannot directly be separated into 2 well-defined regions, especially for complex datasets with a lot of overlap in the original feature space.  In these instances, it may be possible to map the feature space into a higher dimension where the classes are more easily separable.  However, this mapping may be too complex and computationally intensive to apply to large training sets \cite{svmTutorial}.  This computational complexity can be avoided altogether by using symmetric kernel functions on the pair of vectors, which results in a similarity score that is exactly equivalent to the dot product of its inputs when mapped into a higher dimensional space without having to explicitly map the vectors and computing their dot product, as shown in Eq. \ref{eq:kernelSubstitution} \cite{bishop}.

\begin{equation}
\label{eq:kernelSubstitution}
K(x, x') = \phi(x)^{T}*\phi(x') = \phi(x')^{T}*\phi(x) = K(x', x)
\end{equation}

One example use-case for this higher-order mapping is when the classes' data points are radially dependent.  As shown in Fig. \ref{fig:radialSeparation}, the data can be mapped to $R^{3}$ using the mapping function in Eq. \ref{eq:r3Mapping}.

\begin{equation}
\label{eq:r3Mapping}
z^{2} = x^{2} + y^{2}
\end{equation}

\begin{figure}[h]
\centering
\captionsetup{justification=centering,width=0.95\textwidth}
\centerline{\includegraphics[width=0.95\textwidth]{radialSeparation.png}}
\caption[Mapping Observations from Radially Dependent Classes]{
    Visualizing 2-dimensional observations from two radially dependent distributions \cite{radialSeparation}\\
    Left: 2-D plot of the dataset where $x$ is the X-Label and $y$ is the Y-Label\\
    Right: Dataset is mapped into $R^{3}$ where $z$ is the radius from the origin
}
\label{fig:radialSeparation}
\end{figure}

The analogous radial basis function (RBF) kernel, also known as the Gaussian kernel, is show in Eq. \ref{eq:rbfEq} \cite{rbfKernel}:

\begin{equation} \label{eq:rbfEq}
K(x, x') = exp(-\gamma \cdot ||x-x'||^{2})
\end{equation}

\section{Neural Networks} \label{nnSection}

One of the most popular models that can be found in a modern-day machine learning engineer's toolkit is a neural network.  Though they are at the forefront of many modern  advances and innovations in artificial intelligence, they are far from new.  The idea of an artificial neuron dates as far back to 1943 when McCulloch and Pitts used their knowledge of neurology to devise their mathematical neuron that emulated simple neurons that acted in a binary fashion by firing when the sum of their inputs surpassed some internal threshold \cite{mccullochPitts}.  This simple neuron from 1943 is the foundation for the basic unit now known as a perceptron: a node with various inputs that are summed together to produce a binary result.  A perceptron (shown in Fig. \ref{fig:perceptron}) on its own is the simplest, single-layer neural network, and the weighted sum of its inputs models a linear classifier that can be used for binary classification.  In fact, the optimal values for each weight is learned during training just as the weights and bias are learned for a linear classifier.

\begin{figure}[h]
\centering
\captionsetup{justification=centering,width=0.95\textwidth}
\centerline{\includegraphics[width=0.65\textwidth]{perceptron.png}}
\caption[Perceptron Model] {
    A perceptron with three inputs: $x_{1}, x_{2}, x_{3}$ \cite{perceptron}
}
\label{fig:perceptron}
\end{figure}

Another key parameter when training a perceptron is its activation function, the input dependent function that decides whether or not the perceptron fires, that is, whether its output is 0 or 1.  In fact, if the simple perceptron emulates a linear classifier with the form in Eq. \ref{eq:hyperplane}, the perceptron's activation function is the Heaviside function (aka step function) since it classifies input vectors as class 0 on negative values and class 1 on positive values.  This classifier is also known as the simplest artificial neural network (ANN or NN) because it is a single layer of perceptrons: the weighted inputs are fed directly to the outputs.  To build more a complex model capable of making more complex decisions, layers of perceptrons are combined to create a network of nodes.  Such networks have historically been called multi-layer perceptrons (MLPs), even though modern networks are usually composed of neurons with other activation functions like the sigmoid, tanh, and rectified linear unit (ReLU) functions, which are shown in Fig. \ref{fig:activationFn} \cite{neuralNetsNLP}.

\begin{figure}[h]
\centering
\captionsetup{justification=centering,width=0.95\textwidth}
\centerline{\includegraphics[width=0.95\textwidth]{activationFn.png}}
\caption[Activation Functions]{
    Common activation functions for artificial neurons \cite{activationFn}
}
\label{fig:activationFn}
\end{figure}

The layers that provide the interface between the input and output nodes are called hidden layers.  In typical feedforward networks, the layers of the network are fully connected, and unidirectional.  Thus, the information is strictly moving forward from the input towards the output and there are no cycles or loops.  Typical training of neural networks involves choosing the optimal architecture for the application, which in turn implies choosing the number of hidden layers, and number of nodes in each hidden layer.  The weights of the links between nodes are usually initialized to random values, and then trained with a technique called backpropagation.  Using the chosen loss function that penalizes misclassifications, the delta, or the difference between the model output and true value, of each training iteration is propagated backwards through the network to incrementally update the weights in order to minimize the loss function.  The learning rate of the model dictates at what pace the weights will follow the direction of the delta.  High learning rates will cause the model to take large steps in the direction of the delta, possibly overshooting the minimum and requiring extra iterations; on the other hand, smaller learning rates may lead to slower or incomplete training since many more iterations may be required to reach the minimum loss \cite{neuralNetsNLP}.

\section{Recurrent Neural Networks} \label{rnnSection}

Another class of neural networks showing great promise in the NLP domain is the recurrent network.  In contrast to feedforward networks, recurrent neural networks (RNNs) have directed cycles.  The primary advantage that cycles provide to RNNs is the ability to "[remember] information about what has been calculated so far" since each internal state is dependent on all of the previous computations and states leading up that state \cite{introRNN}.

The cycle in the RNN also allows the RNN to continuously transition between internal states for the entire length of the input sequence.  Thus, while basic feedforward neural networks have strict dimensional requirements for their input and output vectors, RNNs are able to dynamically operate on sequences of vectors \cite{rnn}.  For example, if the input sequence is a sentence with 5 words, the unrolled network would have 5 layers.  Fig. \ref{fig:rnnUnrolled} shows an RNN that unfolds into t+1 layers, where each layer (\textbf{A}) represents an internal state that was computed using the previous state and the next available piece of the input sequence (\textbf{x\textsubscript{t}}).  Note that an activation function can also be applied at each internal state to produce an output (\textbf{h\textsubscript{t}}).

\begin{figure}[h]
\centering
\captionsetup{justification=centering,width=0.95\textwidth}
\centerline{\includegraphics[width=0.95\textwidth]{rnnUnrolled.png}}
\caption[Unrolled RNN]{
    An RNN unrolled into a neural network with t+1 layers \cite{rnnUnrolled}
}
\label{fig:rnnUnrolled}
\end{figure}

Some applications for which RNNs have proven useful include speech transcription, machine translation (translating one language to another), video frame classification, and image captioning \cite{rnn}.  These applications all require the RNNs' stateful transitioning while processing the sequence of input; for example, producing a valid translation greatly depends on the part of sentence previously translated.  Furthermore, RNNs have also proven themselves to be highly performant in the absence of sequential input, as was the case in DeepMind's RNN that transcribed house numbers from Google Street View \cite{deepMindHouseNumber}.

\begin{figure}[h]
\centering
\captionsetup{justification=centering,width=0.95\textwidth}
\centerline{\includegraphics[width=0.95\textwidth]{rnnTransformations.png}}
\caption[Various RNN Setups]{
    The various use-cases for RNNs (green blocks) using input vectors (red) to produce output (blue) \cite{rnnTransformations}
}
\label{fig:rnnTransformations}
\end{figure}

As shown by Fig. \ref{fig:rnnTransformations}, RNNs can be used in a variety of settings.  The left-most setup ("one to one") demonstrates the transformation that occurs in typical neural networks: the input vector is processed completely by all of the hidden layers and then mapped to an output vector.  The "one to many" setup shows a transformation that may occur in settings like image captioning where a fix-sized image is transformed into a sequence of words.  The next setup, "many to one", illustrates how a sequential input is processed to produce a single label, which could be applied towards applications like sentiment classification.  The first "many to many" setup exemplifies the transformation that sentences could undergo in machine translation applications: input sequences are mapped to the target language using local context as opposed directly mapping each word independently.  Lastly, the second "many to many" configuration depicts a scenario in which an output is required for each constituent of the input sequence, e.g., a video classification task that requires labelling each frame \cite{rnnTransformations}.

However, there is a flaw with conventional RNNs.  The current state of an RNN, though dependent on previous parts of the input sequence, may be too far removed from the state at which a relevant piece of information was introduced.  For example, in the input sentence "I grew up in France... I speak fluent [language]", the RNN may not be able to predict "French" as the language since the word "France" occurred a lot earlier than where that information was actually necessary.  This gap between the necessary information and the point at which that information is actually needed may ultimately become too large for the RNN to be effective \cite{lstm}.  However, there is a special variant of the RNN, the long short-term memory (LSTM) network, that can overcome this limitation.

LSTMs are RNNs with special memory units (also known as cells) that can selectively keep information for an extended period of time \cite{lstmClassification}.  Instead of only consisting of a single repeating layer, as is the case with an RNN, the vanilla LSTM has one memory unit composed of four special layers: three sigmoid layers, and one tanh layer \cite{lstm}.  All sigmoid layers output values between 0 and 1, and the tanh layer outputs values between -1 and 1.  Together, these layers help the cell forget, remember, update, and produce information.

\begin{figure}[h]
\centering
\captionsetup{justification=centering,width=0.95\textwidth}
\centerline{\includegraphics[width=0.95\textwidth]{rnnChainlstmChain.png}}
\caption[RNN Layer vs LSTM Layer]{
    Unrolled RNN and LSTM chains\\
    Top: RNN with a single layer in each state \cite{rnnChain}\\
    Bottom: LSTM with one memory unit in each state \cite{lstmChain}
}
\label{fig:lstmChain}
\end{figure}

As shown in the LSTM in Fig. \ref{fig:lstmChain}, the first layer is a sigmoid layer whose input is the concatenation of the output from the previous state (\textbf{h\textsubscript{t-1}}) and the current input (\textbf{x\textsubscript{t}}).  In LSTMs, sigmoid layers that are joined with pointwise multiplication operators act as gates that let information through whenever their outputs are non-zero values.  The first sigmoid layer uses \textbf{h\textsubscript{t-1}} and \textbf{x\textsubscript{t}} and forms a gate on the incoming stream of values from the previous cell state (the top left corner of each cell in Fig. \ref{fig:lstmChain}).  This gate, often called the "forget gate", outputs a number between 0 and 1 for each value in the previous state.  Thus, if the gate outputs 0 for a particular value, that value is completely forgotten.

The next stage of the cell decides how much of the new information (\textbf{h\textsubscript{t-1}} and \textbf{x\textsubscript{t}}) will be retained in the state.  First, a tanh layer is used to compute an updated value for each bit of new information.  Afterwards, these updated values are filtered by another gate in order to extract whatever is deemed pertinent by the LSTM.  Finally, the filtered information is added with whatever information from the previous state that was not forgotten to form the new cell state.

The last stage of the cell computes the output for the current state (\textbf{h\textsubscript{t}}).  The first step in this stage is to map the cell state into the acceptable output space.  In Fig. \ref{fig:lstmChain}, the tanh activation function is applied to the cell state to push each value between -1 and 1.  The transformed state is then passed through the final sigmoid gate; thus, the output consists of only the parts of the cell state the LSTM deems appropriate.  For example, in a machine translation setting, the LSTM may output whether or not the subject is singular or plural, so the LSTM knows how to conjugate the following verb if that is in fact the following input \cite{lstm}.

There are other LSTM configurations, and each has its own advantages in certain settings.  However, a recent study shows that most of these variations do not perform significantly better than the vanilla LSTM \cite{variousLSTMs}.  The LSTM model used in this thesis is a variant of the vanilla LSTM model that has a configurable number of memory units \cite{kerasLSTM}.  Note that the LSTM presented in this section only had a single memory unit, and, thus, produced a single output.  Adding extra memory units increases the dimensionality of the output at each state.  Thus, if the LSTM contains 50 memory units in each layer, the LSTM will ultimately produce a 50-dimensional output vector after processing the entire input sequence.  Since the challenge presented in this thesis is a binary classification task, the outputs of each LSTM are passed through another sigmoid activation layer to produce a prediction.

max_stars_repo_name: mirajp/malicious-news-classification

max_issues_repo_name: mirajp/malicious-news-classification

max_forks_repo_name: mirajp/malicious-news-classification


text:
\section{Examples and Properties of Groups}
\begin{definition}
    A group $G$ is called abelian if $ab=ba$ for any $a,b\in G$.
\end{definition}
\begin{definition}
    A group is finite if the underlying set $G$ has finitely many element.
    In which case, we write $|G|$ to denote the number of elements in $G$.
    We call it the \textit{order} of $G$.
\end{definition}
\begin{example}
    1. Consider the set that contains a single element.
    There is an unique binary operation that can be defined on it which makes it a group.\\
    2. The set of integers under addition $(\mathbb Z, +, 0)$ is a group.\\
    3. We can replace the set $\mathbb Z$ by $\mathbb R, \mathbb C$ or $\mathbb Q$ and we still get a group.
    These groups are all abelian.\\
    4. (non-example) $(\mathbb N, +, 0)$ is not a group since it does not have inverses.\\
    5. (non-example) $(\mathbb Z, -, 0)$ is not a group since it does not have the law of associativity.
    $1-(1-1)\neq (1-1)-1$.\\
    6. (non-example) $(\mathbb Q, \times, 1)$ is not a group since $0$ does not have an inverse.\\
    7. $(\mathbb Q\setminus \{0\},\times, 1)$ is a group.
    Similarly, $(\mathbb C\setminus \{0\},\times, 1)$, $(\mathbb R\setminus \{0\},\times, 1)$ are also groups.
    And they are all abelian.\\
    8. If $X\subset\mathbb R^3$ is a solid, then the set of rotational symmetries of it gives a group under composition.
    The identity element is ``doing nothing''.
    Note that it may or may not be abelian.
    It can also be infinite (e.g. sphere).\\
    9. $(\mathbb Q_{>0}, \times, 1)$ is a group.\\
    10. $(\{z\in\mathbb C: |z|=1\}, \times, 1)$ is a group.\\
    11. For any natural number $n$,
    $$C_n=\{z\in\mathbb C: z^n=1\}$$
    is a group under multiplication.
    It is abelian and finite as well, and it has exactly $n$ elements.\\
    12. For any $n\in\mathbb N$, the set $\mathbb Z_n=\{0,1,2,\ldots n-1\}$ is a group under $+_n$, the addition modulo $n$.
    It is also abelian and finite (order $n$).
    The groups $C_n$ and $\mathbb Z_n$ are actually the same (why?).\\
    13. Consider the set $\operatorname{Isom}(\mathbb R)$ be the set of isometries (i.e. distance-preserving maps) within the real numbers.
    They constitute a group under composition, where $e$ is the identity function.
    Examples of elements in this group are: the function $r:x\mapsto -x$, the function $t:x\mapsto x+1$.
    So $r\circ t=-(x+1)=-x-1$, but $t\circ r=(-x+1)=1-x\neq r\circ t$.
    Therefore this group is non-abelian.
    It is not finite as well.\\
    14. Let $\operatorname{GL}_2(\mathbb R)$ be the set of invertible $2\times 2$ matrices in $\mathbb R$.
    It gives a group if we take the multiplication to be composition (matrix multiplication) and identity to be the identity matrix.
\end{example}
\begin{definition}
    Let $(G,\cdot_G,e_G)$ and $(H,\cdot_H, e_H)$.
    We say the latter is a subgroup of the former if $H\subseteq G$, $e_H=e_G$ and
    $$\forall a,b\in H, a\cdot_Hb=a\cdot_Gb$$
    In this case, we say $H\le G$.
\end{definition}
\begin{proposition}
    Let $(G,\cdot_G,e_G)$ be a group and $H\subseteq G$ be nonempty.
    If for all $a,b\in H$, $a\cdot_Gb^{-1}\in\mathbb H$, then there is a unique $\cdot_H$ on $H$ and a unique $e_H\in\mathbb H$ such that $(H,\cdot_H, e_H)$ is a group and $H\le G$.
\end{proposition}
\begin{proof}
    As $H$ is nonempty, it contains some element $x$, so by hypothesis we have $e_G=x\cdot_Gx^{-1}\in H$.
    Now for any $a\in H$, we write $a^{-1}=e_G\cdot_Ga^{-1}\in\mathbb H$.
    For any $a,b\in H$, we have $ab=a\cdot_G(b^{-1})^{-1}\in H$.\\
    Define $e_H=e_G$ and $a\cdot_Hb=a\cdot_Gb$, which makes $H$ a subgroup of $G$.
    Trivial to check.
    The uniqueness follows from the definition of a subgroup.
\end{proof}
\begin{example}
    1. $(\mathbb Z,+,0)\le(\mathbb Q,+,0)\le(\mathbb R,+,0)\le(\mathbb C,+,0)$.\\
    2. Any group is a subgroup of itself.\\
    3. For any group $(G,\cdot,e)$, $\{e\}\le G$. This is called the trivial subgroup.\\
    4. $(\{1,-1\},\times,1)\le(\mathbb Q\setminus\{0\},\times,1)$.\\
    5. If $m|n$, $C_m\le C_n$.\\
    6. In the rotational symmetry group of the tetrahedron, the rotations by $0,\pi$ through an axis joining the midpoint of two opposite edges is a subgroup.\\
    7. The group $\operatorname{SL}_2(\mathbb R)$ consisting of all matrices of determinant $1$ is a subgroup of $\operatorname{GL}_n(\mathbb R)$.
\end{example}
In general, we cannot find the all subgroups of a group, but we can do it sometimes.
\begin{proposition}
    The subgroups of $\mathbb Z$ under addition are of the form $k\mathbb Z$ where $k\in\mathbb Z$.
\end{proposition}
\begin{proof}
    It is obvious that $k\mathbb Z$ is always a subgroup for any $k\in\mathbb Z$.
    Indeed, suppose we have $kn,km\in k\mathbb Z$, we have $kn-km=k(n-m)\in k\mathbb Z$.
    And $0\in k\mathbb Z$, so it is not empty.\\
    For any subgroup of $S\le\mathbb Z$, either $S=\{0\}=0\mathbb Z$ or we can consider the smallest positive integer $k$ in that subgroup.
    Then $k\mathbb Z\subseteq S$.
    Also, if there is any element that is not a multiple of $k$, that is $S\ni x=kn+r$ for soem $n\in\mathbb Z$ and $0<r<k$.
    But then $r=x-kn\in S$ contradicts the minimality of $k$, which is a contradiction.
\end{proof}
\begin{definition}[Direct Product of Groups]
    Consider two group $(G,\cdot_G,e_G)$ and $(H,\cdot_H,e_H)$.
    Define the binary operation $\cdot$ on $G\times H$ by
    $$(g_1,h_1)\cdot (g_2,h_2)=(g_1\cdot_Gg_2,h_1\cdot_Hh_2)$$
    This makes $G\times H$ a group by taking the identity to be $(e_G,e_H)$.
\end{definition}
From now on, we omit the explicit statement of the binary operation and the identity element.
\subsection{Symmetries of Regular Polygons}
let $D_{2n}$ be the set of isometries of the regular $n$-gon.
We can think of the $n$-gon as the group generated by the $n^{th}$ root of unity.
Then $D_{2n}$ consists of isometries of the complex numbers which send the $n$-gon to itself.
\begin{theorem}
    If we take the set of such isometries, and composition as multiplication and the identity to be the identity function, then it is a group of order $2n$.
\end{theorem}
\begin{proof}
    The first two axioms are trivial.\\
    We now exhaust the elements in this group.
    Let $r:\mathbb C\to\mathbb C$ be the map $z\mapsto ze^{2\pi i/n}$.
    One can show that it is an isometry.
    Also, $r(e^{2\pi ik/n})=e^{2\pi i(k+1)/n}$, so it does send the $n$-gon to itself.
    Note as well that $r^n=e$ where $e$ is the identity function, which we have defined as the identity.
    So $r$ has an inverse, so have all $r^k$.\\
    Consider the map $s:\mathbb C\to\mathbb C$ by the map $z\mapsto\bar z$.
    One can also check that it is an isometry satisfying our conditions.
    Note this time that $s^2=1$, so $s$ has an inverse which is itself.\\
    Let $f$ be an element of $D_{2n}$.
    $f(1)=e^{2\pi ik/n}=r^k(1)$ for some $k$ as $f$ preserves that $n$-gon.
    So let $g(x)=r^{-k}\circ f$, then $g(1)=1$.\\
    Now consider $g(e^{2\pi i/n})$, this is either $e^{2\pi i/n}$ or $e^{2\pi i(n-1)/n}$ as $g$ is an isometry.\\
    If it is the former case, then $g$ fixes $0,1$ and $e^{2\pi i/n}$.
    One can show that an isometry that fixes three points actually fixes any point.
    So $f=r^{k}$.\\
    If it is the latter case, then $s\circ g$ would fix $0,1$ and $e^{2\pi i/n}$, so it is the identity again.
    Therefore $f=r^{k}g=r^{k}s$.\\
    So $D_{2n}=\{r^ks^\delta:k\in\{0,1,\ldots,n-1\}, \delta\in\{0,1\}\}$, one can show that none of which equals to any other and all of them have inverses.
    This set has $2n$ elements.
\end{proof}
Note that in $D_{2n}$, $sr$ maps $1$ to $e^{2\pi i(n-1)/n}$, and $rsr$ fixes $1$ and $rsr(e^{2\pi i/n})=e^{2\pi i(n-1)/n}$, so $srsr=e\implies rsr=s\implies sr=r^{-1}s$.
\footnote{The group $D_{2n}$ can be written otherwise as $D_{2n}=\langle s,r|srsr, r^n, s^2\rangle$.}
\subsection{Symmetries of Sets}
For a set $X$, the permutation of $X$ is a bijective function $f:X\to X$.\\
Let $\operatorname{Sym}(X)$ be the set of all permutations of $X$.
\begin{theorem}
    For any set $X$, the set of permutations of $X$ under composition, where the identity is the identity function, is a group called the symmetric group on $X$.
\end{theorem}
\begin{proof}
    Obvious.
\end{proof}
When $X=\{1,2,\ldots n\}$, then we denote $\operatorname{Sym}(X)$ by $S_n$.
Immediately $|S_n|=n!$.

max_stars_repo_name: david-bai-notes/IA-Groups

max_issues_repo_name: david-bai-notes/IA-Groups

max_forks_repo_name: david-bai-notes/IA-Groups