<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://www.vladsandulescu.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.vladsandulescu.com/" rel="alternate" type="text/html" /><updated>2026-02-02T16:30:20+00:00</updated><id>https://www.vladsandulescu.com/feed.xml</id><title type="html">Vlad Sandulescu</title><subtitle>mine</subtitle><author><name>Vlad Sandulescu</name></author><entry><title type="html">The winning solution to the KDD Cup 2016 competition - Predicting the future relevance of research institutions</title><link href="https://www.vladsandulescu.com/the-winning-solution-to-the-kdd-cup-2016/" rel="alternate" type="text/html" title="The winning solution to the KDD Cup 2016 competition - Predicting the future relevance of research institutions" /><published>2016-09-28T09:08:20+00:00</published><updated>2016-09-28T09:08:20+00:00</updated><id>https://www.vladsandulescu.com/the-winning-solution-to-the-kdd-cup-2016</id><content type="html" xml:base="https://www.vladsandulescu.com/the-winning-solution-to-the-kdd-cup-2016/"><![CDATA[<p>The ACM SIGKDD Conference on Knowledge Discovery and Data Mining, or short KDD is one of the largest premier academic conference on data science and large scale data mining and machine learning. Many well-known researchers choose to publish their research at <a href="http://www.kdd.org/kdd2016/">KDD</a> and the conference attracts most of the big names in the machine learning community. The <a href="https://kddcup2016.azurewebsites.net">KDD Cup</a> challenge is held in conjunction with the conference and every year it gathers many participants competing to win the award. This year the top three teams received $10,000, $6500 and $3500 respectively. More than 500 teams registered for the competition which comprised of three stages, each time-boxed to one month each.</p>

<p>To compete in the KDD Cup is something I have been meaning to do for a few years now. To win it on the first go was simply incredible! This year, the stars aligned just right and I actually got some time to focus on this 3 months long competition. My friend and former colleague Mihai Chiru joined me and we proved once again we make one hell of a good team. The competition progressed great for us and in each phase we improved our predictions and overall rank.</p>

<p><strong>The task?</strong>
The research task was to predict the ranking of affiliations (universities, research institutions or companies) based on the number of their accepted full research papers at 8 future academic conferences in 2016. Each research paper is written by a number of authors, each affiliated to an university or company. The authors of a paper receive equal scores (1/number of paper authors) for each accepted paper. Then the score for each of the affiliations is simply the sum of these author scores. The affiliations are ranked according to these scores (also called ‘relevance’ by the competition organizers) and this represents the predicted ranking in the competition.</p>

<p><strong>Ok, but how were the teams evaluated?</strong>
The evaluation metric used to rank the teams was NDCG@20, a typical ranking evaluation metric. Basically a team would get a lower score if its ranking was different compared to the true ranking once the accepted full research papers would be published at the chosen conference. You can find more details about how NDCG@20 is computed together with a straightforward example <a href="https://kddcup2016.azurewebsites.net/Rules">here</a>.</p>

<p><strong>What data did we use?</strong>
Microsoft, the competition organizer offered a free snapshot of the <a href="https://www.microsoft.com/en-us/research/project/microsoft-academic-graph/">Microsoft Academic Graph (MAG)</a>, a heterogeneous graph containing various historical information about many academic papers. From this giant graph we extracted information about all the papers ever published at the chosen conferences, about all their authors and the affiliations the authors belonged to.</p>

<p><strong>So how did we do it?</strong>
First things first we looked at our data. We checked for any obvious trends for the accepted papers made by top affiliations to each conference. We consider a top affiliation one which had a large number of accepted papers at a conference in the last five years. The assumption is that for large conferences at least, the top 20 places each year will belong to more prolific affiliations, likely to have participated in the past to the conference. We also choose to focus more on the first 20 places because the evaluation metric used in the competition is NDCG@20. We have explored the dataset in a lot of ways but will only mention the most important finding in this article.</p>

<p>In Figure 1 we plot the number of full research papers accepted at the KDD conference between 2011 and 2015 for the top 20 affiliations. The length of each line maps the range of the number of accepted papers for the affiliation and the mean number of papers is marked by the larger dot on each line. The plot shows the mean number of papers across all years could be a good predictor to how an affiliation will score in the future.</p>

<p><img src="/figs/2016-09-28-the-winning-solution-to-the-kdd-cup-2016/plot-yearly_papers_counts-1.pdf" alt="center" /></p>

<p><em>Figure 1: Full range and mean value of the number of accepted full research papers for top 20 affiliations at KDD between 2011 and 2015</em></p>

<p>Second, all good predictive models need their trustworthy baseline. In the first phase of the competition we aim to build a solid baseline model. For this, we compute the probabilities that full research papers belong to affiliations, based on their number of accepted papers across all past five years. We then rank the affiliations according to these probabilities and this becomes our baseline model against which we will compare all our other models.</p>

<p>In the second phase and also in the final phase of the competition, we experiment with two classes of models: <a href="https://en.wikipedia.org/wiki/Mixed_model">mixed models</a> and <a href="http://xgboost.readthedocs.io/en/latest/model.html">gradient boosted decision trees (GBDT)</a>. The former is more interpretable while the latter has more predictive power. We set the relevance of each affiliation as the target of our predictions in whatever models we try. The relevance is, if you remember, the sum of the fractional contributions by all the authors of an affiliation for a conference in a year. You can imagine now our dataset is a large matrix where the columns are our features (I’ll explain which features we use in just a bit) and the rows are the observations. Basically each row holds the features values for each conference and each affiliation and each year.</p>

<p>More data is <em>always</em> better, so the next thing we try is to increase the dataset size by using information from more years and conferences related to each of the conferences we are interested in making predictions for. What does ‘related’ mean? Most researchers publish their work at different conferences. However they specialize in a specific area and so the conferences they publish at have to be more or less similar at least in a few respects. We use authors and keywords from the papers in MAG to cluster similar conferences together. It is a straightforward way to grow the dataset even more. The intuition behind this is the information from related conferences will enforce the patterns discovered by the models, because prolific affiliations are prolific across all conferences they submit to, not just at one of them. We compute the Jaccard similarity for both authors and keywords for any pair of conferences in the MAG. From this, we can determine which conferences are for example most similar to KDD in terms of common authors and common papers’ keywords. We experimented with different numbers of related conferences allows us to expand our training dataset immensely and greatly improve our predictions.</p>

<p>Ok, with the dataset in place comes the fun part: <strong>feature engineering</strong>.
We have experimented with many other features, but will only mention here the ones which worked best for us. We created features meant to capture each affiliation’s long and short-term relevance trends:</p>
<ul>
  <li>Stats of all previous relevance scores (std, sum, mean, median, min, max)</li>
  <li>Previous relevance scores computed in windows from previous year up to 4 years ago</li>
  <li>Stats of previous relevance scores (std, sum, mean, median, min, max) computed in windows from previous year up to 4 years ago</li>
  <li>Drift trend of previous relevance scores</li>
  <li>Exponential weighted moving average of previous relevance scores with estimated smoothing parameter</li>
  <li>Exponential weighted moving average of previous relevance scores, computed with a fixed smoothing parameter</li>
</ul>

<p><strong>Dataset+Features+Baseline+Tuning=Profit</strong>
Final step in any competition is to polish your predictions through tuning. In the final phase of the competition the organizers chose 3 well-known conferences for validation: <a href="http://www.cs.ucdavis.edu/fse2016/">FSE</a>, <a href="http://www.acmmm.org/2016/">MM</a> and <a href="https://www.sigmobile.org/mobicom/2016/">MOBICOM</a>. We search for the features configuration for which the GBDT model gives the best predictions for each of the conferences. We perform a grid search on different combinations of features and numbers of related conferences. Thus the training dataset was of course different for each of the 3 conferences. Although the final feature sets was different overall between the conferences, some of the features do well across all conferences: the exponential smoothing features improved the final predictions for all of them.</p>

<p>Figure 2 shows the corresponding results of the best features configurations for each conference. We used the tuning process to chose the best feature sets for each of the conferences, such that all the scores of the GBDT model are above the probabilities model baseline.</p>

<p><img src="/figs/2016-09-28-the-winning-solution-to-the-kdd-cup-2016/plot-benchmark_simple_probabilities-1.pdf" alt="center" /></p>

<p><em>Figure 2: Results for the best configuration of the engineered features</em></p>

<p><strong>Conclusions and tips for ML competitions</strong>
This was my first shot at the KDD Cup competition and it couldn’t have ended better. I believe our systematic way to build the models coupled with some careful feature engineering was what in the end set us apart from the other teams. So here are some pointers I have for you to have in mind. You probably read all of them before but they cannot be stressed enough.</p>

<ul>
  <li>Tidy up your data and explore it! I mean really explore it, plot it like crazy. Spend a lot of time on doing this because you will get that extra intuition to create awesome features. You can squeeze some more performance by tuning your models or stacking them and the re-stacking them and then doing a final ensemble of it all, you know, the <a href="https://www.kaggle.com">Kaggle</a> way. But well thought out features will get you a much more elegant win. I don’t think a single company puts ensembles of 20 models into production.</li>
  <li>Set up your own validation procedure and baseline model. You will compare all your other models with the baseline and this how you will progress. Flooding the leaderboards in order to test your model is going to get you nowhere.</li>
  <li>Try simple models first and move on to more complicated ones gradually. Simple models are interpretable and can help you spot new features.</li>
  <li>Teamwork is very important because it acts as a natural ensemble. You will not get all the ideas yourself.</li>
  <li>Eyes on the prize! Don’t give up no matter how bad you do in the competition, because you will at least learn something new.</li>
</ul>

<p>That’s it.</p>

<p>P.S.1. The approach is fully described in the paper <a href="https://arxiv.org/abs/1609.02728">Predicting the future relevance of research institutions - The winning solution of the KDD Cup 2016</a>. Parts of this article were shamelessly taken from the paper. Some things were only superficially mentioned in this article. So I encourage you to read the entire paper for a full overview of the solution.</p>

<p>P.S.2. This entire article was also published on the <a href="http://engineering.adform.com/blog/data-science/the-winning-solution-to-the-kdd-cup-2016-competition-predicting-the-future-relevance-of-research-institutions/">Adform Engineering Blog</a></p>]]></content><author><name>Vlad Sandulescu</name></author></entry><entry><title type="html">We won the KDD Cup 2016!</title><link href="https://www.vladsandulescu.com/predicting-the-future-relevance-of-research-institutions/" rel="alternate" type="text/html" title="We won the KDD Cup 2016!" /><published>2016-08-09T07:08:20+00:00</published><updated>2016-08-09T07:08:20+00:00</updated><id>https://www.vladsandulescu.com/predicting-the-future-relevance-of-research-institutions</id><content type="html" xml:base="https://www.vladsandulescu.com/predicting-the-future-relevance-of-research-institutions/"><![CDATA[<p><strong>Update:</strong></p>

<p>Check out the abstract and read the <a href="https://arxiv.org/abs/1609.02728">paper</a> which fully explains our approach.</p>

<p>You can read the papers from the top 12 teams which participated in the KDD Cup 2016 <a href="https://docs.com/alex-wade/1578/kdd-cup">here</a>.</p>

<p><strong>ABSTRACT</strong></p>

<p>The world’s collective knowledge is evolving through research and new scientific discoveries. It is becoming increasingly difficult to objectively rank the impact research institutes have on global advancements. However, since the funding, governmental support, staff and students quality all mirror the projected quality of the institution, it becomes essential to measure the affiliation’s rating in a transparent and widely accepted way. We propose and investigate several methods to rank affiliations based on the number of their accepted papers at future academic conferences. We carry out our investigation using publicly available datasets such as the Microsoft Academic Graph, a heterogeneous graph which contains various information about academic papers. We analyze several models, starting with a simple probabilities-based method and then gradually expand our training dataset, engineer many more features and use mixed models and gradient boosted decision trees models to improve our predictions.</p>

<hr />

<p>To compete in the KDD Cup is something I have been meaning to do for a few years now. To win it on the first go was simply incredible! This year, the stars aligned just right and I actually got some time to focus on this 3 months long competition. My friend and former colleague Mihai Chiru joined me and we proved once again we make one hell of a good team.</p>

<p>The research task was to predict the ranking of affiliations (universities, research institutions or companies) based on the number of their accepted full research papers at various academic conferences in 2016. Microsoft, the competition organizer offered a free snapshot of the Microsoft Academic Graph (MAG), a heterogenous graph containing various historical information about many academic papers.</p>

<p>The competition progressed great for us and in each phase we improved our predictions and overall rank. I believe our systematic way to build the models coupled with some careful feature engineering was what in the end set us apart from the other teams.</p>

<p>The approach is fully described in the paper <a href="https://arxiv.org/abs/1609.02728">Predicting the future relevance of research institutions - The winning solution of the KDD Cup 2016</a>. I will present the paper in August in San Francisco at the <a href="https://kddcup2016.azurewebsites.net">KDD Cup 2016: Towards measuring the impact of research institutions</a> workshop part of <a href="http://www.kdd.org/kdd2016/">KDD 2016</a>.</p>]]></content><author><name>Vlad Sandulescu</name></author></entry><entry><title type="html">Data Science and Machine Learning in Copenhagen Meetup - March 2016</title><link href="https://www.vladsandulescu.com/data-science-and-machine-learning-copenhagen-meetup/" rel="alternate" type="text/html" title="Data Science and Machine Learning in Copenhagen Meetup - March 2016" /><published>2016-03-05T21:08:26+00:00</published><updated>2016-03-05T21:08:26+00:00</updated><id>https://www.vladsandulescu.com/data-science-and-machine-learning-copenhagen-meetup</id><content type="html" xml:base="https://www.vladsandulescu.com/data-science-and-machine-learning-copenhagen-meetup/"><![CDATA[<p><strong>[Update]</strong>: I have moved the slides to my presentation <a href="https://drive.google.com/file/d/1Bk0U76Yd73LGSCz6DgD1447Ib1xWCiWv/view?usp=sharing">here</a>.</p>

<p>On March 1st, we decided to share with the data science community in Copenhagen some of the cool projects we work on at Adform. So I helped organize the second edition of the <a href="http://www.meetup.com/datacph/events/228706239/">Machine Learning and Beer</a> event at our office and welcomed around 60 machine learning enthusiasts . The meetup turned out great and the positive feedback we got from the participants made it all worthwhile. Nice to see the small Copenhagen DS community growing and becoming more sophisticated with more and more companies making machine learning part of their roadmaps.</p>

<p>You can check out the <a href="http://www.meetup.com/datacph/photos/">event photos</a>, but you need to be a group member in order to see them.</p>]]></content><author><name>Vlad Sandulescu</name></author></entry><entry><title type="html">Detecting Singleton Review Spammers Using Semantic Similarity</title><link href="https://www.vladsandulescu.com/detecting-singleton-review-spammers-using-semantic-similarity/" rel="alternate" type="text/html" title="Detecting Singleton Review Spammers Using Semantic Similarity" /><published>2015-03-26T21:08:26+00:00</published><updated>2015-03-26T21:08:26+00:00</updated><id>https://www.vladsandulescu.com/detecting-singleton-review-spammers-using-semantic-similarity</id><content type="html" xml:base="https://www.vladsandulescu.com/detecting-singleton-review-spammers-using-semantic-similarity/"><![CDATA[<p>My paper “Detecting Singleton Review Spammers Using Semantic Similarity” with <a href="http://www.cs.sfu.ca/~ester/">Martin Ester</a> was accepted at <a href="http://www.pheme.eu/events/rdsm2015/">Rumors and Deception in Social Media workshop</a> at <a href="http://www.www2015.it/">WWW 2015</a>. I will present the work at WWW this year in Florence.</p>

<p>Check out the abstract and view the <a href="https://arxiv.org/abs/1609.02727">paper</a>.</p>

<p><strong>ABSTRACT</strong></p>

<p>Online reviews have increasingly become a very important resource for consumers when making purchases. Though it is becoming more and more difficult for people to make well-informed buying decisions without being deceived by fake reviews. Prior works on the opinion spam problem mostly considered classifying fake reviews using behavioral user patterns. They focused on prolific users who write more than a couple of reviews, discarding one-time reviewers. The number of singleton reviewers however is expected to be high for many review websites. While behavioral patterns are effective when dealing with elite users, for one-time reviewers, the review text needs to be exploited. In this paper we tackle the problem of detecting fake reviews written by the same person using multiple names, posting each review under a different name. We propose two methods to detect similar reviews and show the results generally outperform the vectorial similarity measures used in prior works. The first method extends the semantic similarity between words to the reviews level. The second method is based on topic modeling and exploits the similarity of the reviews topic distributions using two models: bag-of-words and bag-of-opinion-phrases. The experiments were conducted on reviews from three different datasets: Yelp (57K reviews), Trustpilot (9K reviews) and Ott dataset (800 reviews).</p>]]></content><author><name>Vlad Sandulescu</name></author></entry><entry><title type="html">Predicting what user reviews are about with LDA and gensim</title><link href="https://www.vladsandulescu.com/topic-prediction-lda-user-reviews/" rel="alternate" type="text/html" title="Predicting what user reviews are about with LDA and gensim" /><published>2014-09-09T00:00:00+00:00</published><updated>2014-09-09T00:00:00+00:00</updated><id>https://www.vladsandulescu.com/topic-prediction-lda-user-reviews</id><content type="html" xml:base="https://www.vladsandulescu.com/topic-prediction-lda-user-reviews/"><![CDATA[<p>I was rather impressed with the impressions and feedback I received for my <a href="http://www.vladsandulescu.com/opinion-phrases/">Opinion phrases</a> prototype - code repository <a href="https://github.com/vladsandulescu/phrases">here</a>. So yesterday, I have decided to rewrite my previous post on topic prediction for short reviews using Latent Dirichlet Analysis and its implementation in <a href="http://radimrehurek.com/gensim/" title="Gensim">gensim</a>.</p>

<p>I have previously worked with topic modeling for my <a href="http://www.vladsandulescu.com/opinion-spam-detection-through-semantic-similarity/">MSc thesis</a> but there I used the <a href="http://www.semanticsimilarity.org/">Semilar toolkit</a> and a looot of C# code. Having read many articles about gensim, I was itchy to actually try it out.</p>

<p><strong>Why would we be interested in extracting topics from reviews?</strong></p>

<p>It is becoming increasingly difficult to handle the large number of opinions posted on review platforms and at the same time offer this information in a useful way to each user so he or she can make a decision fast whether to buy the product or not. Topic-based aggregations and short review summaries are used to group and condense what other users think about the product in order to personalize the content served to a new user and shorten the time he needs to make a buying decision.</p>

<p>A short example always works best. Suppose a review says:
<em>The mailing pack that was sent to me was very thorough and well explained,correspondence from the shop was prompt and accurate,I opted for the cheque payment method which was swift in getting to me. All in all, a fast efficient service that I had the upmost confidence in,very professionally executed and I will suggest you to my friends when there mobiles are due for recycling :-)</em></p>

<p>Some of the topics that could come out of this review could be <em>delivery</em>, <em>payment method</em> and <em>customer service</em>.</p>

<p>In short, knowing what the review talks helps automatically categorize and aggregate on individual keywords and aspects mentioned in the review, assign aggregated ratings for each aspect and personalize the content served to a user. Or simply calculate the efficiency of each of the departments in a company by what people write in their reviews - in this example, the guys in the customer service department as well as the delivery guys would be pretty happy.</p>

<p><strong>What do I need to run the code?</strong></p>

<p>You can clone the <a href="https://github.com/vladsandulescu/topics">repository</a> and play with the Yelp’s dataset which contains many reviews or use your own short document dataset and extract the LDA topics from it.</p>

<p>Get the <a href="http://www.yelp.com/dataset_challenge">Yelp academic dataset</a> and import the reviews from the json file into your local MongoDB by running the <strong>yelp/yelp-reviews.py</strong> file. Use <a href="http://www.mongodb.org/">MongoDB</a>, take my word for it, you’ll never write to a text file ever again! You will also need <a href="http://api.mongodb.org/python/current/">PyMongo</a>, <a href="http://www.nltk.org/">NLTK</a>, <a href="http://www.nltk.org/data.html">NLTK data</a> (in Python run <em>import nltk</em>, then <em>nltk.download()</em>). I personally have these Corpora modules installed: Brown Corpus, SentiWordNet, WordNet, as well as the following Models: Treebank Part of Speech Tagger (HMM), Treebank Part of Speech Tagger (Maximum Entropy), Punkt Tokenizer Models. 
Finally, don’t forget to install  <a href="http://radimrehurek.com/gensim/" title="Gensim">gensim</a>.</p>

<p>OK, enough foreplay, this is how the code works. Skip to the results if you are not interested in running the prototype.</p>

<p><strong>How does the prototype work?</strong></p>

<p>Well, the main goal of the prototype of to try to extract topics from a large reviews corpus and then predict the topic distribution for a new unseen review. Please read this<a href="http://www.yelp.com/html/pdf/YelpDatasetChallengeWinner_ImprovingRestaurants.pdf"> paper</a> first, before checking out the source code, as I have followed it rather closely and tried to reproduce their results. These guys won a prize in the Yelp dataset challenge and in order for me to check if I get similar results, I also experimented on the <a href="http://www.yelp.com/dataset_challenge">Yelp academic dataset</a>.</p>

<p>Future plans include trying out the prototype on <a href="http://www.trustpilot.com">Trustpilot</a> reviews, when we will open up the Consumer APIs to the world. I plan to do another blog post then, when I will explain how you can run the prototype on top of the <a href="https://github.com/trustpilot/developers">Trustpilot API</a> and get nice results from it.</p>

<p>If you clone the repository, you will see a few python files which make up the execution pipeline: yelp/yelp-reviews.py, reviews.py, corpus.py, train.py, display.py and predict.py. I have not yet made a main class to run the entire prototype, as I expect people might want to tweak this pipeline in a number of ways. For example, some may prefer a corpus containing more than just nouns, or avoid writing to Mongo, or keep more than 10000 words, or use more/less than 50 topics and so on.</p>

<p>You should just run these following files in order.</p>

<ul>
  <li>
    <p><strong>yelp/yelp-reviews.py</strong> - gets the reviews from the json file and imports them to MongoDB in a collection called <em>Reviews</em></p>
  </li>
  <li>
    <p><strong>reviews.py</strong>/ <strong>reviews_parallel.py</strong> - loops through all the reviews in the initial dataset and for each review it: splits the review into sentences, removes stopwords, extracts parts-of-speech tags for all the remaining tokens, stores each review, i.e. reviewId, business name, review text and (word,pos tag) pairs vector to a new MongoDB database called <em>Tags</em>, in a collection called <em>Reviews</em>. If you have many reviews, try running <strong>reviews_parallel.py</strong>, which uses the Python multiprocessing features to parallelize this task and use multiple processed to do the POS tagging.</p>
  </li>
  <li>
    <p><strong>corpus.py</strong> - loops through all the reviews from the new MongoDB collection in the previous step, filters out all words which are not nouns, uses WordNetLemmatizer to lookup the lemma of each noun, stores each review together with nouns’ lemmas to a new MongoDB collection called <em>Corpus</em>.</p>
  </li>
  <li>
    <p><strong>train.py</strong> - feeds the reviews corpus created in the previous step to the gensim LDA model, keeping only the 10000 most frequent tokens and using 50 topics.</p>
  </li>
  <li>
    <p><strong>display.py</strong> - loads the saved LDA model from the previous step and displays the extracted topics.</p>
  </li>
  <li>
    <p><strong>predict.py</strong> - given a short text, it outputs the topics distribution. Simply lookout for the highest weights on a couple of topics and that will basically give the “basket(s)” where to place the text.</p>
  </li>
  <li>
    <p><strong>stopwords.txt</strong> - <a href="http://www.lextek.com/manuals/onix/stopwords2.html">stopwords list</a> created by Gerard Salton and Chris Buckley for the experimental SMART information retrieval system at Cornell University</p>
  </li>
</ul>

<p><strong>The resulting topics</strong></p>

<p>POS tagging the entire review corpus and training the LDA model takes considerable time, so expect to leave your laptop running over night while you dream of phis and thetas. It took ~10h on my personal laptop (Lenovo T420s with Intel i5 inside and 8GB of RAM) to do POS tagging for all 1,125,458 Yelp reviews (used reviews_parallel.py for this). I ran the LDA model for 50 topics, but feel free to choose more.</p>

<p>Here were the resulting 50 topics, ignore the bold words written in parenthesis for now:</p>

<p><strong>0: (food or sauces or sides)</strong> 0.028<em>sauce + 0.019</em>meal + 0.018<em>meat + 0.017</em>salad + 0.016<em>food + 0.015</em>menu + 0.015<em>side + 0.015</em>flavor + 0.013<em>dish + 0.012</em>pork
<strong>1: (breakfast)</strong> 0.122<em>egg + 0.096</em>breakfast + 0.065<em>bacon + 0.064</em>juice + 0.033<em>sausage + 0.032</em>fruit + 0.024<em>morning + 0.023</em>brown + 0.023<em>strawberry + 0.022</em>crepe
<strong>2: (restaurant owner)</strong> 0.074<em>owner + 0.073</em>year + 0.048<em>family + 0.032</em>business + 0.029<em>company + 0.028</em>day + 0.026<em>month + 0.025</em>time + 0.024<em>home + 0.021</em>daughter
<strong>3: (terrace or surroundings)</strong> 0.065<em>park + 0.030</em>air + 0.028<em>management + 0.027</em>dress + 0.027<em>child + 0.026</em>parent + 0.025<em>training + 0.024</em>fire + 0.020<em>security + 0.020</em>treatment
<strong>4: (seafood)</strong> 0.091<em>shrimp + 0.090</em>crab + 0.077<em>lobster + 0.060</em>seafood + 0.054<em>nail + 0.042</em>salon + 0.039<em>leg + 0.033</em>coconut + 0.032<em>oyster + 0.031</em>scallop
<strong>5: (thai food)</strong> 0.055<em>soup + 0.054</em>rice + 0.045<em>roll + 0.036</em>noodle + 0.032<em>thai + 0.032</em>spicy + 0.029<em>bowl + 0.028</em>chicken + 0.026<em>dish + 0.023</em>beef
<strong>6: (cafe)</strong> 0.086<em>sandwich + 0.063</em>coffee + 0.048<em>tea + 0.026</em>place + 0.018<em>cup + 0.016</em>market + 0.015<em>cafe + 0.015</em>bread + 0.013<em>lunch + 0.013</em>order
<strong>7: (service)</strong> 0.068<em>food + 0.049</em>order + 0.044<em>time + 0.042</em>minute + 0.038<em>service + 0.034</em>wait + 0.030<em>table + 0.029</em>server + 0.024<em>drink + 0.024</em>waitress
<strong>8: (dessert)</strong> 0.078<em>cream + 0.071</em>ice + 0.059<em>flavor + 0.056</em>dessert + 0.049<em>cake + 0.039</em>chocolate + 0.021<em>sweet + 0.015</em>butter + 0.014<em>taste + 0.013</em>apple
<strong>9: (greek food)</strong> 0.052<em>topping + 0.039</em>yogurt + 0.034<em>patty + 0.033</em>hubby + 0.026<em>flavor + 0.026</em>sample + 0.024<em>gyro + 0.022</em>sprinkle + 0.021<em>coke + 0.020</em>greek
<strong>10: (service)</strong> 0.055<em>time + 0.037</em>job + 0.032<em>work + 0.026</em>hair + 0.025<em>experience + 0.024</em>class + 0.020<em>staff + 0.020</em>massage + 0.018<em>day + 0.017</em>week
<strong>11: (mexican food)</strong> 0.131<em>chip + 0.081</em>chili + 0.071<em>margarita + 0.056</em>fast + 0.031<em>dip + 0.030</em>enchilada + 0.026<em>quesadilla + 0.026</em>gross + 0.024<em>bell + 0.020</em>pastor
<strong>12: (price)</strong> 0.082<em>money + 0.046</em>% + 0.042<em>tip + 0.040</em>buck + 0.040<em>ticket + 0.037</em>price + 0.033<em>pay + 0.029</em>worth + 0.027<em>cost + 0.024</em>ride
<strong>13: (location or not sure)</strong> 0.061<em>window + 0.058</em>soda + 0.056<em>lady + 0.037</em>register + 0.031<em>ta + 0.030</em>man + 0.028<em>haha + 0.026</em>slaw + 0.020<em>secret + 0.018</em>wet
<strong>14: (italian food)</strong> 0.144<em>pizza + 0.038</em>wing + 0.031<em>place + 0.029</em>sauce + 0.026<em>cheese + 0.023</em>salad + 0.021<em>pasta + 0.019</em>slice + 0.016<em>brisket + 0.015</em>order
<strong>15: (family place or drive-in)</strong> 0.157<em>car + 0.150</em>kid + 0.030<em>drunk + 0.028</em>oil + 0.026<em>truck + 0.024</em>fix + 0.021<em>college + 0.016</em>vehicle + 0.016<em>guy + 0.013</em>arm
<strong>16: (bar or sports bar)</strong> 0.196<em>beer + 0.069</em>game + 0.049<em>bar + 0.047</em>watch + 0.038<em>tv + 0.034</em>selection + 0.033<em>sport + 0.017</em>screen + 0.017<em>craft + 0.014</em>playing
<strong>17: (hotel or accommodation)</strong> 0.134<em>room + 0.061</em>hotel + 0.044<em>stay + 0.036</em>pool + 0.027<em>view + 0.024</em>nice + 0.020<em>gym + 0.018</em>bathroom + 0.016<em>area + 0.015</em>night
<strong>18: (restaurant or atmosphere)</strong> 0.073<em>wine + 0.050</em>restaurant + 0.032<em>menu + 0.029</em>food + 0.029<em>glass + 0.025</em>experience + 0.023<em>service + 0.023</em>dinner + 0.019<em>nice + 0.019</em>date
<strong>19: (not sure)</strong> 0.052<em>son + 0.027</em>trust + 0.025<em>god + 0.024</em>crap + 0.023<em>pain + 0.023</em>as + 0.021<em>life + 0.020</em>heart + 0.017<em>finish + 0.017</em>word
<strong>20: (location or not sure)</strong> 0.057<em>mile + 0.052</em>arizona + 0.041<em>theater + 0.037</em>desert + 0.034<em>middle + 0.029</em>island + 0.028<em>relax + 0.028</em>san + 0.026<em>restroom + 0.022</em>shape
<strong>21: (club or nightclub)</strong> 0.064<em>club + 0.063</em>night + 0.048<em>girl + 0.037</em>floor + 0.037<em>party + 0.035</em>group + 0.033<em>people + 0.032</em>drink + 0.027<em>guy + 0.025</em>crowd
<strong>22: (brunch or lunch)</strong> 0.171<em>wife + 0.071</em>station + 0.058<em>madison + 0.051</em>brunch + 0.038<em>pricing + 0.025</em>sun + 0.024<em>frequent + 0.022</em>pastrami + 0.021<em>doughnut + 0.016</em>gas
<strong>23: (casino)</strong> 0.212<em>vega + 0.103</em>la + 0.085<em>strip + 0.047</em>casino + 0.040<em>trip + 0.018</em>aria + 0.014<em>bay + 0.013</em>hotel + 0.013<em>fountain + 0.011</em>studio
<strong>24: (service)</strong> 0.200<em>service + 0.092</em>star + 0.090<em>food + 0.066</em>place + 0.051<em>customer + 0.039</em>excellent + 0.035<em>! + 0.030</em>time + 0.021<em>price + 0.020</em>experience
<strong>25: (pub or fast-food)</strong> 0.254<em>dog + 0.091</em>hot + 0.026<em>pub + 0.023</em>community + 0.022<em>cashier + 0.021</em>way + 0.021<em>eats + 0.020</em>york + 0.019<em>direction + 0.019</em>root
<strong>26: (not sure)</strong> 0.087<em>box + 0.040</em>adult + 0.028<em>dozen + 0.027</em>student + 0.026<em>sign + 0.025</em>gourmet + 0.018<em>decoration + 0.018</em>shopping + 0.017<em>alot + 0.016</em>eastern
<strong>27: (bar)</strong> 0.120<em>bar + 0.085</em>drink + 0.050<em>happy + 0.045</em>hour + 0.043<em>sushi + 0.037</em>place + 0.035<em>bartender + 0.023</em>night + 0.019<em>cocktail + 0.015</em>menu
<strong>28: (italian food)</strong> 0.029<em>chef + 0.027</em>tasting + 0.024<em>grand + 0.022</em>caesar + 0.021<em>amazing + 0.020</em>linq + 0.020<em>italian + 0.018</em>superb + 0.016<em>garden + 0.015</em>al
<strong>29: (not sure)</strong> 0.064<em>bag + 0.061</em>attention + 0.040<em>detail + 0.031</em>men + 0.027<em>school + 0.024</em>wonderful + 0.023<em>korean + 0.023</em>found + 0.022<em>mark + 0.022</em>def
<strong>30: (mexican food)</strong> 0.122<em>taco + 0.063</em>bean + 0.043<em>salsa + 0.043</em>mexican + 0.034<em>food + 0.032</em>burrito + 0.029<em>chip + 0.027</em>rice + 0.026<em>tortilla + 0.021</em>corn
<strong>31:</strong> 0.096<em>waffle + 0.057</em>honey + 0.034<em>cheddar + 0.032</em>biscuit + 0.030<em>haze + 0.025</em>chicken + 0.024<em>cozy + 0.022</em>let + 0.022<em>bring + 0.021</em>kink
<strong>32:</strong> 0.033<em>lot + 0.027</em>water + 0.027<em>area + 0.027</em>) + 0.025<em>door + 0.023</em>( + 0.021<em>space + 0.021</em>parking + 0.017<em>people + 0.013</em>thing
<strong>33:</strong> 0.216<em>line + 0.054</em>donut + 0.041<em>coupon + 0.030</em>wait + 0.029<em>cute + 0.027</em>cooky + 0.024<em>candy + 0.022</em>bottom + 0.019<em>smoothie + 0.018</em>clothes
<strong>34:</strong> 0.090<em>phoenix + 0.077</em>city + 0.042<em>downtown + 0.037</em>gem + 0.026<em>seating + 0.025</em>tourist + 0.022<em>convenient + 0.021</em>joke + 0.020<em>pound + 0.017</em>tom
<strong>35:</strong> 0.072<em>lol + 0.056</em>mall + 0.041<em>dont + 0.035</em>omg + 0.034<em>country + 0.030</em>im + 0.029<em>didnt + 0.028</em>strip + 0.026<em>real + 0.025</em>choose
<strong>36:</strong> 0.159<em>place + 0.036</em>time + 0.026<em>cool + 0.025</em>people + 0.025<em>nice + 0.021</em>thing + 0.021<em>music + 0.020</em>friend + 0.019<em>‘m + 0.018</em>super
<strong>37:</strong> 0.138<em>steak + 0.068</em>rib + 0.063<em>mac + 0.039</em>medium + 0.026<em>bf + 0.026</em>side + 0.025<em>rare + 0.021</em>filet + 0.020<em>cheese + 0.017</em>martini
<strong>38:</strong> 0.075<em>patio + 0.064</em>machine + 0.055<em>outdoor + 0.039</em>summer + 0.038<em>smell + 0.032</em>court + 0.032<em>california + 0.027</em>shake + 0.026<em>weather + 0.023</em>pretzel
<strong>39:</strong> 0.124<em>card + 0.080</em>book + 0.079<em>section + 0.049</em>credit + 0.042<em>gift + 0.040</em>dj + 0.022<em>pleasure + 0.019</em>charge + 0.018<em>fee + 0.017</em>send
<strong>40:</strong> 0.081<em>store + 0.073</em>location + 0.049<em>shop + 0.039</em>price + 0.031<em>item + 0.025</em>selection + 0.023<em>product + 0.023</em>employee + 0.023<em>buy + 0.020</em>staff
<strong>41:</strong> 0.048<em>az + 0.048</em>dirty + 0.034<em>forever + 0.033</em>pro + 0.032<em>con + 0.031</em>health + 0.027<em>state + 0.021</em>heck + 0.021<em>skill + 0.019</em>concern
<strong>42:</strong> 0.037<em>time + 0.028</em>customer + 0.025<em>call + 0.023</em>manager + 0.023<em>day + 0.020</em>service + 0.018<em>minute + 0.017</em>phone + 0.017<em>guy + 0.016</em>problem
<strong>43:</strong> 0.197<em>burger + 0.166</em>fry + 0.038<em>onion + 0.030</em>bun + 0.022<em>pink + 0.021</em>bacon + 0.021<em>cheese + 0.019</em>order + 0.018<em>ring + 0.015</em>pickle
<strong>44:</strong> 0.069<em>picture + 0.052</em>movie + 0.052<em>foot + 0.034</em>vip + 0.031<em>art + 0.030</em>step + 0.024<em>resort + 0.022</em>fashion + 0.021<em>repair + 0.020</em>square
<strong>45:</strong> 0.054<em>sum + 0.043</em>dim + 0.042<em>spring + 0.034</em>diner + 0.032<em>occasion + 0.029</em>starbucks + 0.025<em>bonus + 0.024</em>heat + 0.022<em>yesterday + 0.021</em>lola
<strong>46:</strong> 0.071<em>shot + 0.041</em>slider + 0.038<em>met + 0.038</em>tuesday + 0.032<em>doubt + 0.023</em>monday + 0.022<em>stone + 0.022</em>update + 0.017<em>oz + 0.017</em>run
<strong>47:</strong> 0.152<em>show + 0.050</em>event + 0.046<em>dance + 0.035</em>seat + 0.031<em>band + 0.029</em>stage + 0.019<em>fun + 0.018</em>time + 0.015<em>scene + 0.014</em>entertainment
<strong>48:</strong> 0.099<em>yelp + 0.094</em>review + 0.031<em>ball + 0.029</em>star + 0.028<em>sister + 0.022</em>yelpers + 0.017<em>serf + 0.016</em>dream + 0.015<em>challenge + 0.014</em>‘m
<strong>49:</strong> 0.137<em>food + 0.071</em>place + 0.038<em>price + 0.033</em>lunch + 0.027<em>service + 0.026</em>buffet + 0.024<em>time + 0.021</em>quality + 0.021<em>restaurant + 0.019</em>eat</p>

<p>All right, they look pretty cohesive, which is a good sign. Now comes the manual topic naming step where we can assign one representative keyword to each topic. This is useful when predicting the topics of new unseen reviews. 
I have suggested some keywords based on my instant inspiration, which you can see in the round parenthesis. I got bored after half of them, but I feel I made the point. You only need to set these keywords once and <em>summarize</em> each topic. I suggested some keywords while watching over the Kung Pao Chicken and having a beer…so my keywords may not match yours! Anyway, you get the idea.</p>

<p>It’s up to you how you choose the keywords: you can be broader or more precise about what you are interested in the topic, select the most frequent word in the topic and setting that as the keywords, etc..</p>

<p><strong>Predicting the topics of new unseen reviews</strong></p>

<p>OK, now that we have the topics, let’s see how the model predicts the topics distribution for a new review:</p>

<p><em>It’s like eating with a big Italian family. Great, authentic Italian food, good advice when asked, and terrific service. With a party of 9, last minute on a Saturday night, we were sat within 15 minutes. The owner chatted with our kids, and made us feel at home. They have meat-filled raviolis, which I can never find. The Fettuccine Alfredo was delicious. We had just about every dessert on the menu. The tiramisu had only a hint of coffee, the cannoli was not overly sweet and they had this custard with wine that was so strangely good. It was an overall great experience!</em></p>

<p>The output of the <strong>predict.py</strong> file given this review is: [(0, 0.063979336376367435), (2, 0.19344804518265865), (6, 0.049013217061090186), (7, 0.31535985308065378), (8, 0.074829314265223476), (14, 0.046977300077683241), (15, 0.044438343698184689), (18, 0.09128157138884592), (28, 0.085020844956249786)]</p>

<p>Thus, the review is characterized mostly by topics 7 (32%) and 2 (19%). The missing topics, such as 1, 3, 4, 5 and so on are all zero, that’s why they are missing.
Well, what do you know, those topics are about the <strong>service</strong> and <strong>restaurant owner</strong>.</p>

<p>Another one:
<em>Either the quality has gone down or my taste buds have higher expectations than the last time I was here (about 2 years ago). Now that SF has so many delicious Italian choices where the pasta is made in-house/homemade, it was tough for me to eat the store-bought pasta.  The pasta lacked texture and flavor, and even the best sauce couldn’t change my disappointment.  The gnocchi tasted better, but I just couldn’t get over how cheap the pasta tasted.  I discovered another spot in North Beach called X and I was really impressed with their pasta, so that’s my new go-to spot.</em></p>

<p>Distribution: [(2, 0.049949761363727557), (14, 0.67415587326751736), (28, 0.14795291772795682), (33, 0.044461283686581303), (44, 0.044349729171608801)]</p>

<p>Clearly, the review is about topic 14, which is <strong>italian food</strong>.</p>

<p>Third time’s the charm:
<em>Really superior service in general; their reputation precedes them and they deliver. It can indeed be tough to get seating, but I find them willingly accommodating when they can be, and seating at the bar can be really enjoyable, actually. So many wonderful items to choose from, but don’t forget to save room for the over-the-top chocolate souffle; elegant and wondrous. Oh and hello, roast Maine lobster, mini quail and risotto with dungeness crab. De-lish.</em></p>

<p>[(0, 0.12795812236631765), (4, 0.25125769311344842), (8, 0.097887323141830185), (17, 0.15090844416208612), (24, 0.12415345702622631), (27, 0.067834960190092219), (35, 0.06375000000000007), (41, 0.06375000000000007)]</p>

<p>The topics predicted are topic 4 - <strong>seafood</strong> and topic 24 - <strong>service</strong>. Right on the money again. I just picked the first couple of topics but these can be selected based on their distribution, i.e. taking all above a set threshold.</p>

<p>It isn’t generally this sunny in Denmark though… Take a closer look at the topics and you’ll notice some are hard to summarize and some are overlapping. This is where a bit of LDA tweaking can improve the results.</p>

<p>While this method is very simple and very effective, it still needs some polishing, but that is beyond the goal of the prototype. LDA is however one of the main techniques used in the industry to categorize text and for the most simple review tagging, it may very well be sufficient.</p>]]></content><author><name>Vlad Sandulescu</name></author><category term="topic modeling" /><category term="lda" /><category term="reviews" /><category term="gensim" /><category term="yelp" /></entry><entry><title type="html">Opinion spam detection - Literature review</title><link href="https://www.vladsandulescu.com/opinion-spam-detection-literature-review/" rel="alternate" type="text/html" title="Opinion spam detection - Literature review" /><published>2014-09-07T00:00:00+00:00</published><updated>2014-09-07T00:00:00+00:00</updated><id>https://www.vladsandulescu.com/opinion-spam-detection-literature-review</id><content type="html" xml:base="https://www.vladsandulescu.com/opinion-spam-detection-literature-review/"><![CDATA[<p>I have decided to make a sort of a series about several findings in my <a href="http://www.vladsandulescu.com/opinion-spam-detection-through-semantic-similarity/">thesis about opinion spam detection</a>. This is the pilot episode, a literature review of the most significant research papers on opinion spam until now.</p>

<p>OK, here goes.
The opinion spam problem was first formulated by Jindal and Liu in the context of product reviews, <a href="#Jindal2008">(Jindal &amp; Liu, 2008)</a>. By analyzing several million reviews from the popular Amazon.com, they showed how widespread the problem of fake reviews was. The existing detection methods can be split in the context of machine learning into supervised and unsupervised approaches. Second, they can be split into three categories by their features: behavioral, linguistic or those using a combination of these two.
They categorized spam reviews into three categories: non-reviews, brand-only reviews and untruthful reviews. The authors ran a logistic regression classifier on a model trained on duplicate or near-duplicate reviews as positive training data, i.e. fake reviews, and the rest of the reviews they used as truthful reviews. They combined reviewer behavioral features with textual features and they aimed to demonstrate that the model could be generalized to detect non-duplicate review spam. This was the first documented research on the problem of opinion spam and thus did not benefit from existing training databases. The authors had to build their own dataset, and the simplest approach was to use near-duplicate reviews as examples of deceptive reviews. Although this initial model showed good results, it is still an early investigation into this problem.</p>

<p><a href="#Lim2010">(Lim, Nguyen, Jindal, Liu, &amp; Lauw, 2010)</a> is also an early work on detecting review spammers which proposed scoring techniques for the spamicity degree of each reviewer. The authors tested their model on Amazon reviews, which were initially taken through several data preprocessing steps. In this stage, they decided to only keep reviews from highly active users - users that had written at least 3 reviews. The detection methods are based on several predefined abnormalities indicators, such as general rating deviation, early deviation - i.e. how soon after a product appears on the website does a suspicious user post a review about it or very high/low ratings clusters. The features weights were linearly combined towards a spamicity formula and computed empirically in order to maximize the value of the normalized discounted cumulative gain measure. The measure showed how well a particular ranking improves on the overall goal. The training data was constructed as mentioned earlier from Amazon reviews, which were manually labeled by human evaluators. Although an agreement measure is used to compute the inter-evaluator agreement percentage, so that a review is considered fake if all of the human evaluators agree, this method of manually labeling deceptive reviews has been proven to lead to low accuracy when testing on real-life fake review data. 
First, <a href="#Ott2011">(Ott, Choi, Cardie, &amp; Hancock, 2011)</a> demonstrated that it is impossible for humans to detect fake reviews simply by reading the text. Second, <a href="#Mukherjee2012">(Mukherjee, Liu, &amp; Glance, 2012)</a> proved that not even fake reviews produced through crowdsourcing methods are valid training data because the models do not generalize well on real-life test data.</p>

<p><a href="#Wang2012">(Wang, Xie, Liu, &amp; Yu, 2012)</a> considered the triangular relationship among stores, reviewers and their reviews. This was the first study to capture such relationships between these concepts and study their implications. They introduced 3 measures meant to do this: the stores reliability, the trustworthiness of the reviewers and the honesty of the reviews. Each concept depends on the other two, in a circular way, i.e. a store is more reliable when it contains honest reviews written by trustworthy reviewers and so on for the other two concepts. They proposed a heterogeneous graph based model, called the review graph, with 3 types of nodes, each type of node being characterized by a spamicity score inferred using the other 2 types. In this way, they aimed to capture much more information about stores, reviews and reviewers than just focus on behavioral reviewer centric features. This is also the first study on store reviews, which are different than product reviews. The authors argue that when looking at product reviews, while it may be suspicious to have multiple reviews from the same person for similar products, it is ok for the same person to buy multiple similar products from the same store and write a review every time about the experience. In almost all fake product reviews, studies which use the cosine similarity as a measure of review content alikeness, a high value is considered as a clear signal of cheating, since the spammers do not spend much time writing new reviews all the time, but reuse the exact same words. However, when considering store reviews, it is possible for the same user to make valid purchases from similar stores, thus reusing the content of his older reviews and not writing completely different reviews all the time. <a href="#Wang2012">(Wang, Xie, Liu, &amp; Yu, 2012)</a> used an iterative algorithm to rank the stores, reviewers and reviews respectively, claiming that top rankers in each of the 3 categories are suspicious. They evaluated their top 10 top and bottom ranked spammer reviewers results using human evaluators and computed the inter-evaluator agreement. The evaluation of the resulted store reliability score, again for the top 10 top and bottom ranked stores was done by comparison with store data from Better Business Bureaus, a corporation that keeps track businesses reliability and possible consumer scams. </p>

<p><a href="#Xie2012">(Xie, Wang, Lin, &amp; Yu, 2012)</a> observed that the vast majority of reviewers (more than 90% in their study or resellerratings.com reviews up to 2010) only wrote one review, so they have focused their research on this type of reviewers. They also claim, similarly to <a href="#Feng2012">(Feng, Xing, Gogar, &amp; Choi, 2012)</a>, that a flow of fake reviews coming from a hired spammer distorts the usual distribution of ratings for the product, leaving distributional traces behind. Xie et al. observed the normal flow of reviews is not correlated with the given ratings over time. Fake reviews come in bursts of either very high ratings, i.e. 5-stars, or very low ratings, i.e. 1-star, so the authors aim to detect time windows in which these abnormally correlated patterns appear. They considered the number of reviews, average ratings and the ratio of singleton reviews which stick out when looking over different time windows. The paper makes important contributions to opinion spam detection by being the first study to date to formulate the singleton spam review problem. Previous works have disregarded this aspect completely by purging singleton reviews from their training datasets and focusing more on tracking the activity of reviewers as they make multiple reviews. It is of course reasonable to claim that the more information is saved about a user and the more data points about a user’s activity exist, the easier it is to profile that user and assert with greater accuracy whether he is a spammer or not. Still, it is simply not negligible that a large percentage of users on review platforms write only one review.  </p>

<p><a href="#Feng2012">(Feng, Xing, Gogar, &amp; Choi, 2012)</a> published the first study to tackle the opinion spam as a distributional anomaly problem, considering crawled data from Amazon and TripAdvisor. They claim product reviews are characterized by natural distributions which are distorted by hired spammers when writing fake reviews. Their contribution consists of first introducing the notion of natural distribution of opinions and second of conducting a range of experiments that finds a connection between distributional anomalies and the time windows when deceptive reviews were written. For the purpose of evaluation they used a gold standard dataset containing 400  known deceptive reviews written by hired people, created by <a href="#Ott2011">(Ott, Choi, Cardie, &amp; Hancock, 2011)</a>. Their proposed method achieves a maximum accuracy of only 72.5% on the test dataset and thus is suitable as a technique to pinpoint suspicious activity within a time window and draw attention on suspicious products or brands. This technique does not solely represent however a complete solution where individual reviews can be deemed as fake or truthful, but simply brings to the foreground delimited short time windows where methods from other studies can be applied to detect spammers.</p>

<p><a href="#Li2011">(Li, Huang, Yang, &amp; Zhu, 2011)</a> have used supervised learning and manually labeled reviews crawled from Epinions to detect product review spam. They also added to the model the helpfulness scores and comments the users associated with each review. Due to the dataset size of about 60K reviews and the fact that manual labeling was required, an important assumption was made - reviews that receive fewer helpful votes from people are more suspicious. Based on this assumption, they have filtered out review data accordingly, e.g. only considering reviews which have at least 5 helpfulness votes or comments.
They achieved a 0.58 F-Score result using their supervised method model, which outperformed the heuristic methods used at that time to detect review spam. However, this result is very low when compared with that of more recent review spam detection models. The main reason for this has been the training of the model on manually labeled fake reviews data, as well as the initial data pre-processing step where reviews were selected based on their helpfulness votes. <a href="#Mukherjee2013">(Mukherjee et al., 2013)</a> also makes the  assumption that deceptive reviews get less votes. But their model evaluation later showed that helpfulness votes not only perform poorly but they may also be abused - groups of spammers working together to promote certain products may give many votes to each others reviews. The same conclusion has been also expressed by <a href="#Lim2010">(Lim, Nguyen, Jindal, Liu, &amp; Lauw, 2010)</a>.</p>

<p><a href="#Ott2011">(Ott, Choi, Cardie, &amp; Hancock, 2011)</a> produced the first dataset of gold-standard deceptive opinion spam, employing crowdsourcing through the Amazon Mechanical Turk. They demonstrated that humans cannot distinguish fake reviews by simply reading the text, the results of these experiments showing an  at-chance probability. The authors found that although part-of-speech n-gram features give a fairly good prediction on whether an individual review is fake, the classifier actually performed slightly better when psycholinguistic features were added to the model. The expectation was also that truthful reviews resemble more of an informative writing style, while deceptive reviews are more similar in genre to imaginative writing. The authors coupled the part-of-speech tags in the review text which had the highest frequency distribution with the results obtained from a text analysis tool previously used to analyze deception. Testing their classifier against the gold-standard dataset, they revealed clue words deemed as signs of deceptive writing. However, this can be seen as overly simplistic, as some of these words, which according to the results have a higher probability to appear in a fake review, such as “vacation” or “family”, may as well appear in truthful reviews. The authors finally concluded that the domain context has an important role in the feature selection process. Simply put, the imagination of spammers is limited - e.g. in the case of hotel reviews, they tend to not be able to give spatial details regarding their stay. While the classifier scored good results on the gold-standard dataset, once the spammers learn about them, they could simply avoid using the particular clue words, thus lowering the classifier accuracy when applied to real-life data on the long term. </p>

<p><a href="#Mukherjee2012">(Mukherjee, Liu, &amp; Glance, 2012)</a> were the first to try to solve the problem of opinion spam resulted from a group collaboration between multiple spammers. The method they proposed first extracts candidate groups of users using a frequent itemset mining technique. For each group, several individual and group behavioral indicators are computed, e.g. the time differences between group members when posting, the rating deviation between group members compared with the rest of the product reviewers, the number of products the group members worked together on, or review content similarities. The authors also built a dataset of fake reviews, with the help of human judges which manually labeled a number of reviews. They experimented both with learning to rank methods, i.e. ranking of groups based on their spamicity score and with classification using SVM and logistic regression, using the labeled review data for training. The algorithm, called GSRank considerably outperformed existing methods by achieving an area under the curve result (AUC) of 95%. This score makes it a very strong candidate for production environments where the community of users is very active and each user writes more than one review. However, not many users write a lot of reviews, there exists a relatively small percentage of “elite” contributing users. So this method would best be coupled with a method for detecting singleton reviewers, such as the method from <a href="#Xie2012">(Xie, Wang, Lin, &amp; Yu, 2012)</a>. </p>

<p><a href="#Mukherjee2013b">(Mukherjee, Venkataraman, Liu, &amp; Glance, 2013)</a> have questioned the validity of previous research results based on supervised learning techniques trained on Amazon Mechanical Turk (AMT) generated fake reviews. They tested the method of <a href="#Ott2011">(Ott, Choi, Cardie, &amp; Hancock, 2011)</a> on known fake reviews from Yelp. The assumption was that the company had perfected its detection algorithm for the past decade and so its results should be trustworthy. Surprisingly, unlike <a href="#Ott2011">(Ott, Choi, Cardie, &amp; Hancock, 2011)</a> which reported a 90% accuracy using the fake reviews generated through the AMT tool, <a href="#Mukherjee2013b">(Mukherjee, Venkataraman, Liu, &amp; Glance, 2013)</a> experiments showed only a 68% accuracy when they tested Ott’s model on Yelp data. This led the authors to claim that any previous model trained using reviews collected through the AMT tool can only offer near chance accuracy and is useless when applied on real-life data. However, the authors do not rule out the effectiveness of using n-gram features in the model and they proved the largest accuracy obtained on Yelp data was achieved using a combination of behavioral and linguistic features. Their experiments show little improvement over accuracy when adding n-gram features. Probably the most interesting conclusion is that behavioral features considerably outperform n-gram features alone. </p>

<p><a href="#Mukherjee2013">(Mukherjee et al., 2013)</a> built an unsupervised model called the Author Spamicity Model that aims to split the users into two clusters - truthful users and spammers. The intuition is that the two types of users are naturally separable due to the behavioral footprints left behind when writing reviews. The authors studied the distributional divergence between the two types and tested their model on real-life Amazon reviews. Most of the behavioral features in the model have been previously used in two previous studies by <a href="#Mukherjee2012">(Mukherjee, Liu, &amp; Glance, 2012)</a> and <a href="#Mukherjee2013b">(Mukherjee, Venkataraman, Liu, &amp; Glance, 2013)</a>. In these studies though, the model was trained using supervised learning. The novelty about the proposed method in this paper is a posterior density analysis of each of the features used. This analysis is meant to validate the relevance of each model feature and also increase the knowledge on their expected values for truthful and fake reviews respectively.</p>

<p><a href="#Fei2013">(Fei et al., 2013)</a> focused on detecting spammers that write reviews in short bursts. They represented the reviewers and the relationships between them in a graph and used a graph propagation method to classify reviewers as spammers. Classification was done using supervised learning, by employing human evaluation of the identified honest/deceptive reviewers. The authors relied on behavioral features to detect periods in time when review bursts per product coincided with reviewer burst, i.e. a reviewer is very prolific just as when a number of reviews which is higher than the usual average of reviews for a particular product is recorded. The authors discarded singleton reviewers from the initial dataset, since these provide little behavior information - all the model features used in the burst detection model require extensive reviewing history for each user. By discarding singleton reviewers, this method is similar to the one proposed by <a href="#Mukherjee2012">(Mukherjee, Liu, &amp; Glance, 2012)</a>. These methods can thus only detect fake reviews written by elite users on a review platform. Exploiting review posting bursts is an intuitive way to obtain smaller time windows where suspicious activity occurs. This can be seen as a way to break the fake review detection method into smaller chunks and employ other methods which have to work with considerably less data points. This would decrease the computational and time complexity of the detection algorithm. </p>

<p><a href="#Mukherjee2013a">(Mukherjee, Venkataraman, Liu, &amp; Glance, 2013)</a> made an interesting observation in their study: the spammers caught by Yelp’s filter seem to have “overdone faking” in their try to sound more genuine. In their deceptive reviews, they tried to use words that appear in genuine reviews almost equally frequently, thus avoiding to reuse the exact same words in their reviews. This is exactly the reason why a cosine similarity measure is not enough to catch subtle spammers in real life scenarios, such as Yelp’s. </p>

<h1 id="references">References</h1>
<ol class="bibliography"><li><span id="Jindal2008">Jindal, N., &amp; Liu, B. (2008). Opinion Spam and Analysis. In <i>Proceedings of the 2008 International Conference on Web Search and
	Data Mining</i> (pp. 219–230). New York, NY, USA: ACM. doi:10.1145/1341531.1341560</span></li>
<li><span id="Lim2010">Lim, E.-P., Nguyen, V.-A., Jindal, N., Liu, B., &amp; Lauw, H. W. (2010). Detecting Product Review Spammers Using Rating Behaviors. In <i>Proceedings of the 19<sup>th</sup> ACM International Conference
	on Information and Knowledge Management</i> (pp. 939–948). New York, NY, USA: ACM. doi:10.1145/1871437.1871557</span></li>
<li><span id="Ott2011">Ott, M., Choi, Y., Cardie, C., &amp; Hancock, J. T. (2011). Finding Deceptive Opinion Spam by Any Stretch of the Imagination. In <i>Proceedings of the 49<sup>th</sup> Annual Meeting of the Association
	for Computational Linguistics: Human Language Technologies - Volume
	1</i> (pp. 309–319). Stroudsburg, PA, USA: Association for Computational Linguistics. Retrieved from http://dl.acm.org/citation.cfm?id=2002472.2002512</span></li>
<li><span id="Mukherjee2013">Mukherjee, A., Kumar, A., Liu, B., Wang, J., Hsu, M., Castellanos, M., &amp; Ghosh, R. (2013). Spotting Opinion Spammers Using Behavioral Footprints. In <i>Proceedings of the 19<sup>th</sup> ACM SIGKDD International
	Conference on Knowledge Discovery and Data Mining</i> (pp. 632–640). New York, NY, USA: ACM. doi:10.1145/2487575.2487580</span></li>
<li><span id="Mukherjee2012">Mukherjee, A., Liu, B., &amp; Glance, N. (2012). Spotting Fake Reviewer Groups in Consumer Reviews. In <i>Proceedings of the 21<sup>st</sup> International Conference
	on World Wide Web</i> (pp. 191–200). New York, NY, USA: ACM. doi:10.1145/2187836.2187863</span></li>
<li><span id="Mukherjee2013a">Mukherjee, A., Venkataraman, V., Liu, B., &amp; Glance, N. (2013). What yelp fake review filter might be doing. In <i>Proceedings of the International Conference on Weblogs and Social
	Media</i>.</span></li>
<li><span id="Mukherjee2013b">Mukherjee, A., Venkataraman, V., Liu, B., &amp; Glance, N. (2013). <i>Fake Review Detection: Classification and Analysis of Real and Pseudo
	Reviews</i>. UIC-CS-03-2013. Technical Report.</span></li>
<li><span id="Wang2012">Wang, G., Xie, S., Liu, B., &amp; Yu, P. S. (2012). Identify Online Store Review Spammers via Social Review Graph. <i>ACM Trans. Intell. Syst. Technol.</i>, <i>3</i>(4), 61:1–61:21. doi:10.1145/2337542.2337546</span></li>
<li><span id="Xie2012">Xie, S., Wang, G., Lin, S., &amp; Yu, P. S. (2012). Review Spam Detection via Time Series Pattern Discovery. In <i>Proceedings of the 21<sup>st</sup> International Conference
	Companion on World Wide Web</i> (pp. 635–636). New York, NY, USA: ACM. doi:10.1145/2187980.2188164</span></li>
<li><span id="Feng2012">Feng, S., Xing, L., Gogar, A., &amp; Choi, Y. (2012). Distributional Footprints of Deceptive Product Reviews. In J. G. Breslin, N. B. Ellison, J. G. Shanahan, &amp; Z. Tufekci (Eds.), <i>ICWSM</i>. The AAAI Press. Retrieved from http://dblp.uni-trier.de/db/conf/icwsm/icwsm2012.html#FengXGC12</span></li>
<li><span id="Li2011">Li, F., Huang, M., Yang, Y., &amp; Zhu, X. (2011). Learning to Identify Review Spam. In <i>Proceedings of the Twenty-Second International Joint Conference on
	Artificial Intelligence - Volume Volume Three</i> (pp. 2488–2493). AAAI Press. doi:10.5591/978-1-57735-516-8/IJCAI11-414</span></li>
<li><span id="Fei2013">Fei, G., Mukherjee, A., Liu, B., Hsu, M., Castellanos, M., &amp; Ghosh, R. (2013). Exploiting Burstiness in Reviews for Review Spammer Detection. In <i>Seventh International AAAI Conference on Weblogs and Social Media</i>.</span></li></ol>]]></content><author><name>Vlad Sandulescu</name></author><category term="opinion spam" /><category term="fake reviews" /></entry><entry><title type="html">Opinion phrases</title><link href="https://www.vladsandulescu.com/opinion-phrases/" rel="alternate" type="text/html" title="Opinion phrases" /><published>2014-09-02T00:00:00+00:00</published><updated>2014-09-02T00:00:00+00:00</updated><id>https://www.vladsandulescu.com/opinion-phrases</id><content type="html" xml:base="https://www.vladsandulescu.com/opinion-phrases/"><![CDATA[<p>In <a href="http://www.vladsandulescu.com/topic-prediction-lda-user-reviews/">Predicting what user reviews are about with LDA and gensim</a> I played with extracting topics from short reviews and given a new review, tried to predict the most probable topic(s) it can be associated with. LDA relies on a bag-of-words model, which is a very popular document representation approach. The model disregards any syntactic dependencies between the words, i.e. any grammar, as well as word order in the documents. For a deeper read about the assumptions made by the LDA model, try to digest <a href="http://machinelearning.wustl.edu/mlpapers/paper_files/BleiNJ03.pdf">Blei’s paper</a>…if you dare!</p>

<p>Anyway, much of the research on opinion mining used the bag-of-words model, but as <a href="http://www.sfu.ca/~sam39/">Samaneh Abbasi Moghaddam</a> also suggests in her PhD thesis <a href="http://summit.sfu.ca/item/12790">Aspect-based opinion mining in online reviews</a>, it is not clear whether this approach is actually the most effective. Instead, she experimented with a LDA model based on opinion phrases. The full details are found in her paper, but I will make a short summary of the method.
In a nutshell, she concluded that bag-of-opinion phrases outperform the bag-of-words topic models and using the grammar relationships outperforms the existing preprocessing techniques in extracting aspects from user reviews.</p>

<p><strong>What is an opinion phrase, anyway?</strong>
An opinion phrase is defined as a pair (aspect, sentiment) like <em>camera nice</em> or <em>room clean</em>. This is the stuff that people are generally interested in when reading a review, these key points that sum up a user’s experience with the product. A very simple way to extract these pairs is to look for nouns and then pick the nearest adjective around it. This approch has obvious shortcomings.</p>

<p>Luckily, we are contemporary with some clever Stanford guys who made the <a href="http://nlp.stanford.edu/software/corenlp.shtml">Stanford CoreNLP</a> tool. Given a sentence, it can extract syntactic dependencies between words, output the words’ base forms and even predict the overall sentiment of a text.</p>

<p><strong>What syntactical relations should be exploited?</strong>
The following grammatical dependencies are used to extract and construct the opinion phrases inside a short sentence. They are all present and explained in her PhD thesis. 
The <a href="http://nlp.stanford.edu/software/dependencies_manual.pdf">Stanford typed dependencies manual</a> explains very well the grammatical representations used below.</p>

<p>In order to end-up with opinion phrases, first, basic patterns are extracted:</p>
<ol>
  <li>Adjectival complement (acomp): <em>The camera looks nice</em>, parsed to <em>acomp(nice, looks)</em>.</li>
  <li>Adjectival modifier (amod): <em>This camera has great zoom</em> parsed to <em>amod(zoom, great)</em>;</li>
  <li>“And” conjunct (conj and): <em>This camera has great zoom and resolution</em> parsed to <em>conj and(zoom, resolution)</em>.</li>
  <li>Copula (cop): <em>The screen is wide</em> parsed to <em>cop(wide, is)</em>.</li>
  <li>Direct object (dobj):  <em>I love the quality</em> parsed to <em>dobj(love, quality)</em>.</li>
  <li>Negation modifier (neg): <em>The battery life is not long</em> parsed to <em>neg(long, not)</em>.</li>
  <li>Noun compound modifier (nn): <em>The battery life is not long</em> parsed to <em>nn(life, battery)</em>.</li>
  <li>Nominal subject (nsubj): <em>The screen is wide</em> parsed to <em>nsubj(wide, screen)</em>.</li>
</ol>

<p>The simple patterns are then combined in a tree-like manner to obtain more valuable opinion phrases. (N indicates a noun, A an adjective, V a verb, h a head term, m a modifier, and &lt; h, m &gt; an opinion phrase)<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>.</p>

<p>1.amod(N, A) →&lt; N, A &gt; 
<em>This camera has great zoom and resolution → (zoom, great)</em>
2.acomp(V, A) + nsubj(V, N) →&lt; N, A &gt;
<em>The camera case looks nice –&gt; (case, nice)</em></p>
<ol>
  <li>cop(A, V ) + nsubj(A, N) →&lt; N, A &gt;
<em>The screen is wide and clear –&gt; (screen, wide)</em></li>
  <li>dobj(V, N) + nsubj(V, N0) →&lt; N, V &gt;
<em>I love the picture quality –&gt; (picture, love)</em></li>
  <li>&lt; h1, m &gt; +conj and(h1, h2) →&lt; h2, m &gt;
<em>This camera has great zoom and resolution –&gt; (zoom, great), (resolution, great)</em></li>
  <li>&lt; h, m1 &gt; +conj and(m1, m2) →&lt; h, m2 &gt;
<em>The screen is wide and clear –&gt; (screen, wide), (screen, clear)</em></li>
  <li>&lt; h, m &gt; +neg(m, not) →&lt; h, not + m &gt;
<em>The battery life is not long –&gt; (battery life, not long)</em></li>
  <li>&lt; h, m &gt; +nn(h, N) →&lt; N + h, m &gt;
<em>The camera case looks nice –&gt; (camera case, nice)</em></li>
  <li>&lt; h, m &gt; +nn(N, h) →&lt; h + N, m &gt;
<em>I love the picture quality –&gt; (picture quality, love)</em></li>
</ol>

<p>Of course, these syntactical relations can be improved further on by looking up more combined patterns - did not think about this too much, but I have a gut feeling there are more combined patterns out there.</p>

<p><strong>Pruning the extracted patterns</strong>
As you can see in the code if you look in the <a href="https://github.com/vladsandulescu/phrases">GitHub repository</a>, the pruning step is quite important, as the “tree leafs” are the most significant patterns to keep, the final ones. 
I wanted opinion phrases like <em>fish had</em> and <em>bill paid</em> to go away, so I added the usual <a href="http://www.lextek.com/manuals/onix/stopwords2.html">stopwords</a> removal to the pruning step. This basically means eliminating the patterns which contain any stopword.</p>

<p><strong>Some results</strong>
Given a real-life user review:
<em>Great food and atmosphere.  Plenty of TVs to watch the games. The chef and his partners just opened this great location. Pumpkin Soup with pumpkin oil and croutons is such a great start to the Fall season. Wood fired oven pumping out flatbreads. Sweet Potato gnocchi made in house with roasted corn and gorgonzola crema is unbelievable. Very impressive selection of beer handles and delicious cocktails. Amazing view of the sunset as well. Can’t wait to return.</em></p>

<p>the extracted opinion phrases were:
[“atmosphere Great”, “food Great”, “location great”, “start great”, “corn roasted”, “gorgonzola crema roasted”, “selection impressive”, “view Amazing”]</p>

<p>Pretty good right?</p>

<p>Here’s another one:
<em>This place is amazing. I come here at least once a month &amp; am never disappointed. Food &amp; service is always great. The buffalo burger it TDF as well as the bruschetta. Outside seating is so cute with a lights (great for date nights) live music inside is a wonderful touch. This place is great to meet with friends, family or date night.</em></p>

<p>opinion phrases:
[“place amazing”, “service great”, “burger buffalo”, “seating cute”, “touch wonderful”, “seating Outside”, “place great”]</p>

<p>By now, it should be pretty obvious to see how easier aggregating after specific aspects such as <em>place</em> and <em>service</em> is.</p>

<p>Another one:
<em>The mailing pack that was sent to me was very thorough and well explained,correspondence from the shop was prompt and accurate,I opted for the cheque payment method which was swift in getting to me. All in all, a fast efficient service that I had the upmost confidence in,very professionally executed and I will suggest you to my friends when there mobiles are due for recycling :-)</em></p>

<p>opinion phrases:
[“correspondence, prompt”, “correspondence, accurate”, “service, efficient”]</p>

<p>OK, one more and that’s it:
<em>Aside from the wait to order and the other wait to get your food!  I was there for a late lunch on Friday and I opted to forgo my usual salad choice and go for the eggplant parm sandwich - yum!  Each bite of perfectly crusted eggplant had the most amazing tangy tomato sauce and melted cheese and it was oh so dlvine!  I had it on wheat bread and finished my entire sandwich (and yes, I ordered a full size!)  What a treat! Don’t try to special order at the restaurant - my boyfriend attempted to create his own sandwich and what he ended up with was nothing close to what he ordered. I can’t wait to go back to ‘make my own pizza’ - i know about that thanks to him! I have a feeling that I’ll be visiting this place quite a bit since I’m now living in the area after a recent move.  It’s a good thing - well, it’s a tasty thing, maybe not so good for the waistline!</em></p>

<p>opinion phrases:
[“salad choice usual”, “lunch late”, “salad choice forgo”, “tomato sauce amazing”, “eggplant crusted”, “tomato sauce tangy”, “sandwich finished”, “sandwich entire”, “size ordered”, “size full”, “sandwich create”, “order special”, “pizza make”, “move recent”, “bit visiting”, “thing good”, “thing tasty”]</p>

<p>In this last one, you may notice phrases like <em>thing good</em>, <em>sandwich entire</em>, <em>sandwich finished</em> and <em>sandwich create</em>, which don’t really help much in any aggregation, so it would be nice to eliminate them.
This could easily be done by cleverly and time-consumingly shove words like <em>thing</em>, <em>entire</em> and <em>create</em> into the stopwords list. Otherwise, the LDA model should filter these out, assuming a lot of people don’t mention the exact phrases.</p>

<p>Check out the <a href="https://github.com/vladsandulescu/phrases">code repository</a>, try extracting opinion phrases by running the code yourself and don’t forget to tweet to me if you have any comments.</p>

<p>The code is written in Java and it requires Stanford CoreNLP 3.4, Stanford Parser, JUnit and Mongo Java driver (if you plan to run it over many reviews stored in Mongo, because why wouldn’t you already keep the reviews in Mongo right?). 
If you do not want to use Mongo, just call the <em>run</em> method in <em>Extract</em> class giving it the text to extract opinion phrases from.</p>

<p>That is basically it.</p>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p><a href="http://summit.sfu.ca/item/12790">Abbasi Moghaddam, Samaneh. Aspect-based opinion mining in online reviews. Diss. Applied Sciences: School of Computing Science, 2013.</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Vlad Sandulescu</name></author><category term="opinion mining" /><category term="aspect mining" /></entry><entry><title type="html">Opinion spam detection through semantic similarity</title><link href="https://www.vladsandulescu.com/opinion-spam-detection-through-semantic-similarity/" rel="alternate" type="text/html" title="Opinion spam detection through semantic similarity" /><published>2014-07-12T00:00:00+00:00</published><updated>2014-07-12T00:00:00+00:00</updated><id>https://www.vladsandulescu.com/opinion-spam-detection-through-semantic-similarity</id><content type="html" xml:base="https://www.vladsandulescu.com/opinion-spam-detection-through-semantic-similarity/"><![CDATA[<p>Check out my <a href="https://drive.google.com/file/d/1Wl2Im9eOGTD1fYGGrOTb2JCz5hZChTuB/view?usp=sharing">thesis</a> on <em>Opinion spam detection through semantic similarity</em> and the <a href="https://drive.google.com/file/d/10qPb46yrIU0V2p9oS5LRTNKYOsoJk--L/view?usp=sharing">presentation slides</a>.   <br />
You can also take a look at the <a href="https://github.com/vladsandulescu/thesis">repository</a> if you need some LaTeX inspiration.</p>]]></content><author><name>Vlad Sandulescu</name></author><category term="opinion spam" /><category term="semantic similarity" /></entry></feed>