<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://turbolab.in/">
  <title>Turbolab Technologies</title>
  <subtitle>Turbolab is home to various technologies and products that aggregate, transform, analyze, and visualize extensive web data, enabling enterprises to make smarter data-driven decisions.</subtitle>
  <link href="https://turbolab.in/feed.xml" rel="self"/>
  <link href="https://turbolab.in/"/>
  <updated>2022-07-12T07:02:27.000Z</updated>
  <id>https://turbolab.in/</id>
  <entry>
    <title>Entity Linking &amp; Disambiguation using REL</title>
    <link href="https://turbolab.in/entity-linking-disambiguation-using-rel/"/>
    <updated>2022-08-05T14:34:41.000Z</updated>
    <published>2022-07-12T07:02:27.000Z</published>
    <id>https://turbolab.in/entity-linking-disambiguation-using-rel/</id>
    <content type="html">&lt;p&gt;Entity extraction, also known as &lt;em&gt;&lt;strong&gt;Named Entity Recognition(NER)&lt;/strong&gt;&lt;/em&gt;, is an information extraction process that extracts entities from unstructured text and then classifies them into predefined categories such as people, organizations, places, products, date, time, money, phone numbers and so on. The several terabytes of unstructured text data, that comes from documents, web pages, and social media, will be transformed into structured entities that help analysts query the data and generate insightful reports.&lt;/p&gt;
&lt;p&gt;spaCy provides different models in various languages to perform NER and NLP-related tasks. Building a custom NER model using spaCy has been explained in one of our blogs. You can check out the link &lt;strong&gt;&lt;a href=&quot;https://turbolab.in/build-a-custom-ner-model-using-spacy-3-0/&quot;&gt;here&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now, let’s look into the entity extraction from a random news article using spaCy and Flair:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Defending champion Novak Djokovic battled back from two sets to love down to defeat Jannik Sinner and reach his 11th Wimbledon semi-final on Tuesday. Djokovic triumphed 5-7, 2-6, 6-3, 6-2, 6-2 and will face Britain&#39;s Cameron Norrie of Belgium for a place in Sunday&#39;s final. It was the seventh time in the Serb&#39;s career that he had recovered from two sets to love at the Slams. &amp;quot;Huge congrats to Jannik for a big fight, he&#39;s so mature for his age, he has plenty of time ahead of him,&amp;quot; said Djokovic.
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Entity Extraction using spaCy:&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;import spacy
nlp = spacy.load(&#39;en_core_web_lg&#39;) # spacy load the model
ner_ent = {&#39;person&#39;: [], &#39;norp&#39;: [], &#39;fac&#39;: [], &#39;org&#39;: [], &#39;gpe&#39;: [], &#39;loc&#39;: [], &#39;product&#39;: [], &#39;event&#39;: [], &#39;work_of_art&#39;: [], &#39;law&#39;: [], &#39;language&#39;: [], &#39;date&#39;: [], &#39;time&#39;: [], &#39;percent&#39;: [], &#39;money&#39;: [], &#39;quantity&#39;: [], &#39;ordinal&#39;: [], &#39;cardinal&#39;: []}
doc = nlp(content)
for entity in doc.ents:
    if entity.label_.lower() in ner_ent:
        ner_ent[entity.label_.lower()].append(entity.text)
print(ner_ent)
# output
{&#39;person&#39;: [&#39;Novak Djokovic&#39;, &#39;Jannik Sinner&#39;, &#39;Cameron Norrie&#39;, &#39;Jannik&#39;, &#39;Djokovic&#39;, &#39;Novak Djokovic&#39;, &#39;Jannik Sinner&#39;, &#39;Cameron Norrie&#39;, &#39;Jannik&#39;, &#39;Djokovic&#39;], &#39;norp&#39;: [&#39;Serb&#39;, &#39;Serb&#39;], &#39;fac&#39;: [], &#39;org&#39;: [], &#39;gpe&#39;: [&#39;Britain&#39;, &#39;Belgium&#39;, &#39;Britain&#39;, &#39;Belgium&#39;], &#39;loc&#39;: [], &#39;product&#39;: [], &#39;event&#39;: [&#39;Wimbledon&#39;, &#39;Wimbledon&#39;], &#39;work_of_art&#39;: [], &#39;law&#39;: [], &#39;language&#39;: [], &#39;date&#39;: [&#39;Tuesday&#39;, &#39;Sunday&#39;, &#39;Tuesday&#39;, &#39;Sunday&#39;], &#39;time&#39;: [], &#39;percent&#39;: [], &#39;money&#39;: [], &#39;quantity&#39;: [], &#39;ordinal&#39;: [&#39;11th&#39;, &#39;seventh&#39;, &#39;11th&#39;, &#39;seventh&#39;], &#39;cardinal&#39;: [&#39;two&#39;, &#39;5&#39;, &#39;2-6&#39;, &#39;6-3&#39;, &#39;6&#39;, &#39;6-2&#39;, &#39;two&#39;, &#39;two&#39;, &#39;5&#39;, &#39;2-6&#39;, &#39;6-3&#39;, &#39;6&#39;, &#39;6-2&#39;, &#39;two&#39;]}
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Entity Extraction using Flair:&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;from flair.data import Sentence
from flair.models import SequenceTagger
ner_ent = {&#39;per&#39;: [], &#39;org&#39;: [], &#39;loc&#39;: [], &#39;misc&#39;: []}
# make a sentence
sentence = Sentence(content)
# load the NER tagger
tagger = SequenceTagger.load(&#39;ner&#39;)
# run NER over sentence
tagger.predict(sentence)
print(&#39;The following NER tags are found:&#39;)
# iterate over each entity
for entity in sentence.get_spans(&#39;ner&#39;):
    if str(entity.labels[0]).split()[0].lower() in ner_ent:
        ner_ent[str(entity.labels[0]).split()[0].lower()].append(entity.text)
# output
The following NER tags are found:
{&#39;per&#39;: [&#39;George Washington&#39;, &#39;Novak Djokovic&#39;, &#39;Jannik Sinner&#39;, &#39;Djokovic&#39;, &#39;Cameron Norrie&#39;, &#39;Jannik&#39;, &#39;Djokovic&#39;], &#39;org&#39;: [], &#39;loc&#39;: [&#39;Washington&#39;, &#39;Britain&#39;, &#39;Belgium&#39;], &#39;misc&#39;: [&#39;Wimbledon&#39;, &#39;Serb&#39;, &#39;Slams&#39;]}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Flair NER models give us only 4 entity types whereas spaCy gives 18 entity types.&lt;/p&gt;
&lt;h2 id=&quot;entity-linking-disambiguation&quot; tabindex=&quot;-1&quot;&gt;Entity Linking &amp;amp; Disambiguation&lt;/h2&gt;
&lt;p&gt;Entity Linking is the process of linking entities with the target knowledge base. Here, we map the entities to the wiki links or the wiki page titles. Hence the process is called Wikification. We can say entity linking is also referred to as entity validation. The entities extracted from the models of Spacy or Flair will get validated from the third-party knowledge base.&lt;/p&gt;
&lt;p&gt;However, this job is entity linking is intricate due to entity ambiguity and name variants. For example, the word &lt;strong&gt;Amazon&lt;/strong&gt; refers to an organization and a rainforest.&lt;/p&gt;
&lt;p&gt;Let’s have a detailed discussion on Entity Linking &amp;amp; Entity Disambiguation&lt;/p&gt;
&lt;h5&gt;News Article Clip:&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;Deforestation in Brazil&#39;s Amazon rainforest reached a record high for the first six months of the year, as an area five times the size of New York City was destroyed, preliminary government data showed on Friday.
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Spacy Output:&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;&#39;org&#39;: [&#39;Amazon&#39;], &#39;gpe&#39;: [&#39;Brazil&#39;, &#39;New York City&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;strong&gt;Amazon&lt;/strong&gt; is detected as the organization.&lt;/p&gt;
&lt;h5&gt;Flair Output:&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;&#39;loc&#39;: [&#39;Brazil&#39;, &#39;Amazon&#39;, &#39;New York City&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;strong&gt;Amazon&lt;/strong&gt; is detected as the location/GPE. The ambiguity problem is clearly visible here and can be solved by Radboud Entity Linker (REL).&lt;/p&gt;
&lt;h5&gt;REL Output:&lt;/h5&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/xCjHE8aHnH-480.webp 480w, https://turbolab.in/img/xCjHE8aHnH-960.webp 960w, https://turbolab.in/img/xCjHE8aHnH-1430.webp 1430w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/xCjHE8aHnH-480.png&quot; alt=&quot;&quot; width=&quot;1430&quot; height=&quot;266&quot; srcset=&quot;https://turbolab.in/img/xCjHE8aHnH-480.png 480w, https://turbolab.in/img/xCjHE8aHnH-960.png 960w, https://turbolab.in/img/xCjHE8aHnH-1430.png 1430w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/informagi/REL&quot;&gt;&lt;strong&gt;Radboud Entity Linker (REL)&lt;/strong&gt;&lt;/a&gt; deals with the tasks of Entity Linking and Entity Disambiguation. One can use the public API provided by REL or install it using Docker/Source code with the instructions mentioned in the documentation. By default, &lt;strong&gt;REL&lt;/strong&gt; uses Flair to extract entities; you can replace Flair with spaCy. REL also provides pre-trained models with case-sensitive and insensitive models with an f1 score of almost 93%.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://pypi.org/project/wikimapper/&quot;&gt;&lt;strong&gt;Wikimapper&lt;/strong&gt;&lt;/a&gt; python library is used to fetch the wikidata_id from the Wikipedia titles. You can have a look at the project which helps you to map Wikipedia page titles to WikiData IDs and vice-versa.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/facebookresearch/BLINK&quot;&gt;&lt;strong&gt;BLINK&lt;/strong&gt;&lt;/a&gt;, the Facebook research entity linking python library,  uses Wikipedia as the target knowledge base, similar to &lt;strong&gt;REL&lt;/strong&gt;. But, the BLINK documentation hasn’t revealed any information regarding entity disambiguation.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/wetneb/opentapioca&quot;&gt;&lt;strong&gt;OpenTapioca&lt;/strong&gt;&lt;/a&gt; is a simple and fast Named Entity Linking system for Wikidata. A spaCy wrapper of OpenTapioca called &lt;a href=&quot;https://spacy.io/universe/project/spacyopentapioca&quot;&gt;&lt;strong&gt;spaCyOpenTapioca&lt;/strong&gt;&lt;/a&gt; is also available for the entity linking process. But the results are not as great when compared to REL.&lt;/p&gt;
&lt;p&gt;spaCy includes a pipeline component called &lt;a href=&quot;https://spacy.io/api/entitylinker&quot;&gt;&lt;strong&gt;entitylinker&lt;/strong&gt;&lt;/a&gt; for Named Entity Linking and Disambiguation.&lt;/p&gt;
&lt;h2 id=&quot;dealing-with-disambiguation&quot; tabindex=&quot;-1&quot;&gt;Dealing with Disambiguation&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Japan began the defence of their title with a lucky 2-1 win against Syria in a championship match on Friday.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using the above statement, we will discuss the different approaches to choosing the appropriate entity in the case of Entity Disambiguation.&lt;/p&gt;
&lt;h5&gt;Let’s see how &lt;a href=&quot;https://wikifier.org/&quot;&gt;wikifier&lt;/a&gt; deals with the disambiguation:&lt;/h5&gt;
&lt;p&gt;&lt;a href=&quot;https://wikifier.org/&quot;&gt;&lt;strong&gt;Wikifier&lt;/strong&gt;&lt;/a&gt; doesn’t use any entity extraction method for extracting entities; it goes with Parts of Speech (POS).&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/7Yv6qFAVMw-480.webp 480w, https://turbolab.in/img/7Yv6qFAVMw-960.webp 960w, https://turbolab.in/img/7Yv6qFAVMw-1600.webp 1600w, https://turbolab.in/img/7Yv6qFAVMw-1891.webp 1891w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/7Yv6qFAVMw-480.png&quot; alt=&quot;&quot; width=&quot;1891&quot; height=&quot;381&quot; srcset=&quot;https://turbolab.in/img/7Yv6qFAVMw-480.png 480w, https://turbolab.in/img/7Yv6qFAVMw-960.png 960w, https://turbolab.in/img/7Yv6qFAVMw-1600.png 1600w, https://turbolab.in/img/7Yv6qFAVMw-1891.png 1891w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;The entities Syria and Japan are linked to their respective countries’ Wikipedia pages, &lt;a href=&quot;https://en.wikipedia.org/wiki/Syria&quot;&gt;&lt;strong&gt;Syria&lt;/strong&gt;&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Japan&quot;&gt;&lt;strong&gt;Japan&lt;/strong&gt;&lt;/a&gt;. In the context of the above statement, Japan and Syria actually refer to their football teams. Wikifier fetches all the Wikipedia page entities related to the entity and maps the entity with the most link targets.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/gc0qdqjLli-480.webp 480w, https://turbolab.in/img/gc0qdqjLli-483.webp 483w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/gc0qdqjLli-480.png&quot; alt=&quot;&quot; width=&quot;483&quot; height=&quot;671&quot; srcset=&quot;https://turbolab.in/img/gc0qdqjLli-480.png 480w, https://turbolab.in/img/gc0qdqjLli-483.png 483w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Wikifier considers the minLinkFrequency parameter to evaluate the score.&lt;/p&gt;
&lt;h5&gt;Let’s see how REL deals with the disambiguation:&lt;/h5&gt;
&lt;p&gt;In REL, entity linking decisions depend on the contextual similarity and coherence with the other entity linking decisions in the document. One entity mapping is dependent on the other entities found in the document. You can read the paper &lt;a href=&quot;https://arxiv.org/pdf/2006.01969.pdf&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/xfz5xqWGZr-480.webp 480w, https://turbolab.in/img/xfz5xqWGZr-960.webp 960w, https://turbolab.in/img/xfz5xqWGZr-1435.webp 1435w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/xfz5xqWGZr-480.png&quot; alt=&quot;&quot; width=&quot;1435&quot; height=&quot;215&quot; srcset=&quot;https://turbolab.in/img/xfz5xqWGZr-480.png 480w, https://turbolab.in/img/xfz5xqWGZr-960.png 960w, https://turbolab.in/img/xfz5xqWGZr-1435.png 1435w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;This example doesn’t have any impact since only two entities are found and the content is a one-liner. Instead of the entity detection method, if we had passed the POS output, the result might have been different.&lt;/p&gt;
&lt;p&gt;With passing the entire &lt;a href=&quot;https://www.firstpost.com/sports/fifa-world-cup-qualifiers-2022-syria-japan-secure-victories-to-make-it-to-next-round-9694971.html&quot;&gt;&lt;strong&gt;article&lt;/strong&gt;&lt;/a&gt; to the REL, the results are quite better. The REL model can now understand the context and relate more entities from the entire article.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/T1BXOVsXmi-480.webp 480w, https://turbolab.in/img/T1BXOVsXmi-960.webp 960w, https://turbolab.in/img/T1BXOVsXmi-1135.webp 1135w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/T1BXOVsXmi-480.png&quot; alt=&quot;&quot; width=&quot;1135&quot; height=&quot;300&quot; srcset=&quot;https://turbolab.in/img/T1BXOVsXmi-480.png 480w, https://turbolab.in/img/T1BXOVsXmi-960.png 960w, https://turbolab.in/img/T1BXOVsXmi-1135.png 1135w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Brazil&lt;/strong&gt; and &lt;strong&gt;Dutch&lt;/strong&gt; mapped to their respective football team wiki pages. Mapping &lt;strong&gt;Japan&lt;/strong&gt; to its respective football team is still a mystery though. LOL.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Instead of going with the score of the most link targets, REL considers the context and the relationship between the entities detected from the document. By improving the mentioned detection, REL can be used as a perfect Entity Disambiguation tool.&lt;/p&gt;
&lt;p&gt;Last but not least, there is a tool called &lt;a href=&quot;https://github.com/SapienzaNLP/extend&quot;&gt;&lt;strong&gt;ExtEnD&lt;/strong&gt;&lt;/a&gt;(Extractive Entity Disambiguation) which needs to explore. We can add this tool to the spaCy NLP pipeline.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/9MoAJb5M8B-480.webp 480w, https://turbolab.in/img/9MoAJb5M8B-665.webp 665w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/9MoAJb5M8B-480.png&quot; alt=&quot;&quot; width=&quot;665&quot; height=&quot;178&quot; srcset=&quot;https://turbolab.in/img/9MoAJb5M8B-480.png 480w, https://turbolab.in/img/9MoAJb5M8B-665.png 665w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;The output documented by &lt;strong&gt;ExtEnD&lt;/strong&gt; is much better compared to the REL-generated output. Before coming to conclusion, as mentioned above this tool needs to explore.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Incremental/Online/Continuous Model Training using Creme</title>
    <link href="https://turbolab.in/machine-learning-model-retraining-approach-incremental-online-continuous-model-training-using-creme/"/>
    <updated>2022-08-29T04:37:50.000Z</updated>
    <published>2022-02-25T09:01:02.000Z</published>
    <id>https://turbolab.in/machine-learning-model-retraining-approach-incremental-online-continuous-model-training-using-creme/</id>
    <content type="html">&lt;p&gt;Have you noticed the trained ML model performance degrades over time? Why will the model performance degrade? Let’s say we have a model which takes the person’s data as an input and detects the face. Now with the Covid situation, almost 90% of people wear masks and the model will not be able to detect faces which results in low performance and low accuracy of the model. What is the phenomenon called? This is called Model Drift and it is categorized into Concept Drift and Data Drift.&lt;/p&gt;
&lt;p&gt;Concept Drift is where the properties of the dependent variable change i.e., output/prediction of the model.&lt;/p&gt;
&lt;p&gt;Data Drift is where the properties of the independent variable change i.e., input to the model.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;y = a + bx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The change in the dependent variable &lt;strong&gt;y&lt;/strong&gt; leads to Concept Drift and the change in the independent variable &lt;strong&gt;x&lt;/strong&gt; leads to Data Drift.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Change is inevitable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The world and the parameters with which we train the model are going to change over time. Let’s discuss another example of a travel agency with a model considering a person’s average salary, season, weather as the input to predict the number of people traveling to some X country. With the covid regulations of border closures, flying restrictions, job losses, inflation, and with the change in people’s mindset the model would go for a toss.&lt;/p&gt;
&lt;h2 id=&quot;how-to-detect-the-model-drift&quot; tabindex=&quot;-1&quot;&gt;How to detect the model drift?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Monitoring&lt;/strong&gt; the model in production is the only way to detect the model drift. With the alert triggering by keeping the threshold of precision, recall, and f1score metrics through the monitoring tools. &lt;a href=&quot;https://evidentlyai.com/&quot;&gt;&lt;strong&gt;Evidently AI&lt;/strong&gt;&lt;/a&gt; is one such monitoring tool.&lt;/p&gt;
&lt;h2 id=&quot;how-to-avoid-the-model-drift&quot; tabindex=&quot;-1&quot;&gt;How to avoid the model drift?&lt;/h2&gt;
&lt;p&gt;Either we train the model with the streaming data coming in for the continuous learning of the model or retrain the model with the interval of a week, month, etc., in a scheduled manner with the updated data. Retraining the model with the latest data is not an efficient way to handle the models which are already deployed in production. Online/Incremental model training is the efficient way.&lt;/p&gt;
&lt;h2 id=&quot;model-retraining-approach&quot; tabindex=&quot;-1&quot;&gt;Model Retraining Approach&lt;/h2&gt;
&lt;p&gt;Let us explore the python tool &lt;strong&gt;&lt;a href=&quot;https://pypi.org/project/creme/&quot;&gt;creme&lt;/a&gt;&lt;/strong&gt; to train the incremental ML model with the streaming data one record at a time.&lt;/p&gt;
&lt;p&gt;With creme, we encourage a different approach, which is to continuously learn a stream of data. This means that the model process one observation at a time, and can therefore be updated on the fly. This allows learning from massive datasets that don’t fit in the main memory. Online machine learning also integrates nicely in cases where new data is constantly arriving. It shines in many use cases, such as time series forecasting, spam filtering, recommender systems, CTR prediction, and IoT applications. If you’re bored with retraining models and want to instead build dynamic models, then online machine learning (and therefore creme!) might be what you’re looking for.&lt;/p&gt;
&lt;h3 id=&quot;install-from-pypi&quot; tabindex=&quot;-1&quot;&gt;Install from PyPI&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;pip install creme
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;dataset-to-train-the-model&quot; tabindex=&quot;-1&quot;&gt;Dataset to train the model&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;docs = [
(&amp;quot;Cricket news: England James Anderson determined to revive international career despite West Indies axing&amp;quot;, &amp;quot;Cricket&amp;quot;),
(&amp;quot;Well Have Just One Head Coach For All Cricket Formats: CA Chairman&amp;quot;, &amp;quot;Cricket&amp;quot;),
(&amp;quot;Rod Marsh: Australian cricket legend in critical condition after suffering heart attack&amp;quot;, &amp;quot;Cricket&amp;quot;),
(&amp;quot;Facebook, Twitter highlight security steps for users in Ukraine&amp;quot;, &amp;quot;Technology&amp;quot;),
(&amp;quot;Apple launching new series of iphone&amp;quot;, &amp;quot;Technology&amp;quot;),
(&amp;quot;Galaxy S22 preorder sales indicate the phone is already a huge success&amp;quot;, &amp;quot;Technology&amp;quot;),
]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;setting-up-the-model-pipeline&quot; tabindex=&quot;-1&quot;&gt;Setting up the model pipeline&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;from creme import compose
from creme import feature_extraction
model = compose.Pipeline(
              (&#39;tokenize&#39;, feature_extraction.TFIDF(lowercase=True)),
              (&#39;nb&#39;, naive_bayes.MultinomialNB(alpha=1))
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, we are using TFIDF as the feature extraction method and Naive Bayes as the ML algorithm&lt;/p&gt;
&lt;p&gt;These are the other feature extraction methods we can try&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/Sw6h4a6tGq-480.webp 480w, https://turbolab.in/img/Sw6h4a6tGq-591.webp 591w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/Sw6h4a6tGq-480.png&quot; alt=&quot;&quot; width=&quot;591&quot; height=&quot;207&quot; srcset=&quot;https://turbolab.in/img/Sw6h4a6tGq-480.png 480w, https://turbolab.in/img/Sw6h4a6tGq-591.png 591w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h3 id=&quot;fitting-the-data-to-the-model-one-record-at-a-time&quot; tabindex=&quot;-1&quot;&gt;Fitting the data to the model, one record at a time&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;%%time
for sentence, label in docs:
    model = model.fit_one(sentence, label)
Wall time: 998 µs
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;predictions-testing-the-model&quot; tabindex=&quot;-1&quot;&gt;Predictions – Testing the model&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;model.predict_one(&amp;quot;Traffic arrangements for Australian cricket team&#39;s visit, Pakistan Day events reviewed&amp;quot;)
Out: &#39;Cricket&#39;
model.predict_one(&amp;quot;Launching Facebook Reels Globally and New Ways for Creators to Make Money&amp;quot;)
Out: &#39;Technology&#39;
test = &amp;quot;Footballer Koo Ja-cheol to Return to K-League After More Than Decade Abroad&amp;quot;
model.predict_one(test)
Out: &#39;Cricket&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we can see in the above model testing, the last record of football news is predicted as cricket. Both are related to the sports category, we can anyway train our model with the new category as football.&lt;/p&gt;
&lt;h3 id=&quot;training-on-a-new-data-and-new-category&quot; tabindex=&quot;-1&quot;&gt;Training on a new data and new category&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;newDocs = [&amp;quot;Footballer took out insurance policy on BMW minutes after smashing into parked cars&amp;quot;, &amp;quot;Russian footballer Fedor Smolov, a 32-year-old striker currently playing for his country, became one of the first Russian sportsmen to express his heartbreak at the invasion of Ukraine by his country.&amp;quot;, &amp;quot;Ukraine&#39;s international footballer Roman Yaremchuk scored the equalizer for Benfica in a Champions League match&amp;quot;]
for doc_ in newDocs:
    model.fit_one(doc_, &amp;quot;Football&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;retesting-the-model&quot; tabindex=&quot;-1&quot;&gt;Retesting the model&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;test = &amp;quot;Footballer Koo Ja-cheol to Return to K-League After More Than Decade Abroad&amp;quot;
model.predict_one(test)
Out: &#39;Football&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can update the model with the new data for the existing category or the new data with the new category.&lt;/p&gt;
&lt;p&gt;Some benefits of using creme (and online machine learning in general):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Incremental: models can update themselves in real-time.&lt;/li&gt;
&lt;li&gt;Adaptive: models can adapt to concept drift.&lt;/li&gt;
&lt;li&gt;Production-ready: working with data streams makes it simple to replicate production scenarios during model development.&lt;/li&gt;
&lt;li&gt;Efficient: models don’t have to be retrained and require little compute power, which lowers their carbon footprint&lt;/li&gt;
&lt;li&gt;Fast: when the goal is to learn and predict with a single instance at a time, then creme is an order of magnitude faster than PyTorch, Tensorflow, and scikit-learn.&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>Lazy Predict – Find the best suitable ML model</title>
    <link href="https://turbolab.in/lazy-predict-find-the-best-suitable-ml-model/"/>
    <updated>2022-01-18T13:39:52.000Z</updated>
    <published>2022-01-18T06:38:11.000Z</published>
    <id>https://turbolab.in/lazy-predict-find-the-best-suitable-ml-model/</id>
    <content type="html">&lt;p&gt;As in the earlier blog “&lt;a href=&quot;https://turbolab.in/text-classification-using-machine-learning/&quot;&gt;text classification using machine learning&lt;/a&gt;”, we saw a few drawbacks on how difficult it is to select the best ML models and time-consuming for tuning different model parameters to achieve better accuracy.  To overcome this problem we will discuss here an awesome python library “&lt;a href=&quot;https://lazypredict.readthedocs.io/en/latest/&quot;&gt;Lazy Predict&lt;/a&gt;”. This module helps us find the best model for classification and regression based on our data.&lt;/p&gt;
&lt;p&gt;It provides a Lazy Classifier for classification problems and Lazy Regression for regression problems.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;****Note:****Lazy Predict takes high computational power and it was a little time-consuming for me to run high dimensional data with multiple features.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Let us see how it works:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First, install this library in your local system&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pip  install lazypredict
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;dataset&quot; tabindex=&quot;-1&quot;&gt;Dataset&lt;/h3&gt;
&lt;p&gt;Here we are not concentrating more on the dataset or its feature extraction and transformation steps, as it has been shown in the previous blog on “&lt;a href=&quot;https://turbolab.in/text-classification-using-machine-learning/&quot;&gt;text classification using machine learning&lt;/a&gt;”.&lt;/p&gt;
&lt;p&gt;To demonstrate lazy predict classification and regression problems we are using “Drug type” and “Wine quality” data both taken from kaggle.com&lt;/p&gt;
&lt;h3 id=&quot;code&quot; tabindex=&quot;-1&quot;&gt;Code&lt;/h3&gt;
&lt;h4&gt;Importing required libraries&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;import lazypredict
import pandas as pd 
from sklearn.model_selection import train_test_split 
from lazypredict.Supervised import LazyClassifier, LazyRegressor
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Importing data and LazyClassifier model fitting&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;classificationData = pd.read_csv(&amp;quot;drugType.csv&amp;quot;)
classificationData.head()
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/4PZAQOW0oJ-406.webp 406w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/4PZAQOW0oJ-406.png&quot; alt=&quot;&quot; width=&quot;406&quot; height=&quot;185&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;X = classificationData..drop(columns=&amp;quot;Drug&amp;quot;)
y = classificationData.[&amp;quot;Drug&amp;quot;]
# Splitting our data into a train and test set
X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                    test_size=0.2,
                                                    random_state=42)

classifiers = LazyClassifier(ignore_warnings=True, custom_metric=None)
models,predictions = classifiers.fit(X_train, X_test, y_train, y_test)

print(models)
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/Flq3i4ZqRh-480.webp 480w, https://turbolab.in/img/Flq3i4ZqRh-767.webp 767w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/Flq3i4ZqRh-480.png&quot; alt=&quot;&quot; width=&quot;767&quot; height=&quot;568&quot; srcset=&quot;https://turbolab.in/img/Flq3i4ZqRh-480.png 480w, https://turbolab.in/img/Flq3i4ZqRh-767.png 767w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Here the model returns two values, different model names with its prediction accuracy.&lt;/p&gt;
&lt;h4&gt;Importing data and LazyRegressor model fitting&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;regressionData = pd.read_csv(&amp;quot;winequality.csv&amp;quot;)
regressionData.head()
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/ajR76tcCI0-480.webp 480w, https://turbolab.in/img/ajR76tcCI0-960.webp 960w, https://turbolab.in/img/ajR76tcCI0-1063.webp 1063w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/ajR76tcCI0-480.png&quot; alt=&quot;&quot; width=&quot;1063&quot; height=&quot;188&quot; srcset=&quot;https://turbolab.in/img/ajR76tcCI0-480.png 480w, https://turbolab.in/img/ajR76tcCI0-960.png 960w, https://turbolab.in/img/ajR76tcCI0-1063.png 1063w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;X = regressionData.drop(columns=&amp;quot;quality&amp;quot;)
y = regressionData[&amp;quot;quality&amp;quot;]
# Splitting our data into a train and test set
X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                    test_size=0.2, random_state = 42)
regressors = LazyRegressor(ignore_warnings=True, custom_metric=None)
models, predictions = regressors.fit(X_train, X_test, y_train, y_test)
print(models)
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/RdTd0UqaWm-480.webp 480w, https://turbolab.in/img/RdTd0UqaWm-629.webp 629w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/RdTd0UqaWm-480.png&quot; alt=&quot;&quot; width=&quot;629&quot; height=&quot;696&quot; srcset=&quot;https://turbolab.in/img/RdTd0UqaWm-480.png 480w, https://turbolab.in/img/RdTd0UqaWm-629.png 629w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h3 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Here, when we use the “Lazy Predict” library, different models are fitted on our data, and model results provide us with accuracy metrics for the given data. Observing the result we can then select the top 5 base models based on the best accuracy.&lt;/p&gt;
&lt;p&gt;Later we can tune the parameters of those top models and get better accuracy.&lt;/p&gt;
&lt;p&gt;As this library runs many different models at once it takes a lot of computational power. If you have low computational power I would suggest you use Google Colab.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Text Classification with Keras and GloVe Word Embeddings</title>
    <link href="https://turbolab.in/text-classification-with-keras-and-glove-word-embeddings/"/>
    <updated>2021-12-31T13:25:16.000Z</updated>
    <published>2021-12-31T13:25:16.000Z</published>
    <id>https://turbolab.in/text-classification-with-keras-and-glove-word-embeddings/</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;Deep Learning(DL)&lt;/strong&gt; is the subset of &lt;strong&gt;Machine Learning&lt;/strong&gt;. It is a method of statistical learning that extracts features or attributes from raw data. &lt;strong&gt;DL&lt;/strong&gt; uses a network of algorithms called artificial neural networks which imitates the function of the human neural networks present in the brain. &lt;strong&gt;DL&lt;/strong&gt; takes the data into a network of layers(Input, Hidden &amp;amp; Output) to extract the features and to learn from the data.&lt;/p&gt;
&lt;p&gt;In this blog, we will learn how to train a supervised text classification model using the DL python module called &lt;em&gt;&lt;strong&gt;Keras&lt;/strong&gt;&lt;/em&gt; and pre-trained &lt;em&gt;&lt;strong&gt;GloVe&lt;/strong&gt;&lt;/em&gt; word embeddings to transform the text data into a machine-understandable numerical representation. We will be using &lt;strong&gt;Convolutional Neural Networks&lt;/strong&gt;(CNN) architecture to train the classification model.&lt;/p&gt;
&lt;p&gt;The dataset and the category labels of the data are discussed in &lt;a href=&quot;https://turbolab.in/text-classification-using-machine-learning/&quot;&gt;&lt;strong&gt;Text Classification using Machine Learning&lt;/strong&gt;&lt;/a&gt; blog. Please refer to the blog and we will be using the same dataset here to train our CNN model to predict the classification of the given text.&lt;/p&gt;
&lt;p&gt;Assume the dataset is referred to as the pandas dataframe called &lt;strong&gt;df&lt;/strong&gt;in the code snippet.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/xdNAoFIiEr-480.webp 480w, https://turbolab.in/img/xdNAoFIiEr-512.webp 512w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/xdNAoFIiEr-480.jpeg&quot; alt=&quot;dataset&quot; width=&quot;512&quot; height=&quot;442&quot; srcset=&quot;https://turbolab.in/img/xdNAoFIiEr-480.jpeg 480w, https://turbolab.in/img/xdNAoFIiEr-512.jpeg 512w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;dataset&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;cleaning-the-dataset&quot; tabindex=&quot;-1&quot;&gt;Cleaning the dataset&lt;/h2&gt;
&lt;p&gt;The data cleaning part is also discussed in the &lt;a href=&quot;https://turbolab.in/text-classification-using-machine-learning/&quot;&gt;&lt;strong&gt;blog&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/AmFuTa2_BE-480.webp 480w, https://turbolab.in/img/AmFuTa2_BE-752.webp 752w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/AmFuTa2_BE-480.jpeg&quot; alt=&quot;&quot; width=&quot;752&quot; height=&quot;332&quot; srcset=&quot;https://turbolab.in/img/AmFuTa2_BE-480.jpeg 480w, https://turbolab.in/img/AmFuTa2_BE-752.jpeg 752w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Cleaned Dataset&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;We have used stemming and stopwords removal on the dataset content. We can replace stemming with lemmatization and check out this blog about &lt;a href=&quot;https://turbolab.in/stemming-vs-lemmatization-with-python-nltk/&quot;&gt;&lt;strong&gt;stemming vs lemmatization&lt;/strong&gt;&lt;/a&gt; to know the differences. Skipping the cleaning part on the dataset for this DL blog, because stemming can give us meaningless words which don’t have the embedding glove vector.&lt;/p&gt;
&lt;p&gt;As a part of data preparation, we are going to perform these operations on the dataset &lt;strong&gt;df&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lowering the content because the glove embedding vectors are generated for the lower case words.&lt;/li&gt;
&lt;li&gt;Stripping and making sure the word starts with alphanumerics ie., removing special characters.&lt;/li&gt;
&lt;li&gt;Dropping the null and empty columns from the df.&lt;/li&gt;
&lt;li&gt;Dropping the duplicates from the df.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;df = df[[&#39;content&#39;, &#39;label&#39;]]
df = df.astype(&#39;str&#39;).applymap(str.lower)
df = df.applymap(str.strip).replace(r&amp;quot;[^a-z0-9 ]+&amp;quot;, &amp;quot;)
df = df.dropna()
df = df.drop_duplicates()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;loading-the-glove-embeddings&quot; tabindex=&quot;-1&quot;&gt;Loading the Glove Embeddings&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://nlp.stanford.edu/projects/glove/&quot;&gt;&lt;strong&gt;GloVe&lt;/strong&gt;&lt;/a&gt; is an unsupervised learning algorithm for obtaining vector representations for words. Trained the models on Wiki, Twitter and common crawled data to have pre-trained word vectors with differences in size, tokens, and vocab size. For this blog, we will use the &lt;strong&gt;glove.6b.100d.txt&lt;/strong&gt; pretrained glove word vector.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/dY5cbg-TRl-480.webp 480w, https://turbolab.in/img/dY5cbg-TRl-960.webp 960w, https://turbolab.in/img/dY5cbg-TRl-1315.webp 1315w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/dY5cbg-TRl-480.jpeg&quot; alt=&quot;&quot; width=&quot;1315&quot; height=&quot;942&quot; srcset=&quot;https://turbolab.in/img/dY5cbg-TRl-480.jpeg 480w, https://turbolab.in/img/dY5cbg-TRl-960.jpeg 960w, https://turbolab.in/img/dY5cbg-TRl-1315.jpeg 1315w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Glove Embeddings&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;In the above image, we can see the words &lt;strong&gt;that&lt;/strong&gt;, &lt;strong&gt;on&lt;/strong&gt;, &lt;strong&gt;is&lt;/strong&gt;, &lt;strong&gt;was&lt;/strong&gt; is represented by vector coefficients.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def loading_embeddings():
    &amp;quot;&amp;quot;&amp;quot; loading glove embeddings &amp;quot;&amp;quot;&amp;quot;
    embeddings_index = {}
    f = open(glove_path + &#39;glove.6B.100d.txt&#39;, encoding=&amp;quot;utf8&amp;quot;) # loading the file
    for line in f:
        values = line.split()
        word = values[0]
        coefs = np.asarray(values[1:], dtype=&#39;float32&#39;)
        embeddings_index[word] = coefs
    f.close()
    return embeddings_index
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;preparing-the-embedding-matrix&quot; tabindex=&quot;-1&quot;&gt;Preparing the Embedding Matrix&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;MAX_NB_WORDS = 100000

def prepare_embedding_matrix(word_index):
    &amp;quot;&amp;quot;&amp;quot; preparing embedding matrix with our data set &amp;quot;&amp;quot;&amp;quot;

    embeddings_index = loading_embeddings()
    num_words = min(MAX_NB_WORDS, len(word_index))
    embedding_matrix = np.zeros((num_words + 1, EMBEDDING_DIM))

    for word, i in word_index.items():
        if i &amp;gt;= MAX_NB_WORDS:
            continue
        embedding_vector = embeddings_index.get(word)
        if embedding_vector is not None:
            # words not found in embedding index will be all-zeros.
            embedding_matrix[i] = embedding_vector
    return embedding_matrix, num_words
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;MAX_NB_WORDS&lt;/strong&gt;&lt;/em&gt;is the maximum number of words to consider as features for tokenizer&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;word_index&lt;/strong&gt;&lt;/em&gt;is the tokenizer unique words list which extracted by fitting on our dataset content&lt;/p&gt;
&lt;p&gt;The minimum of these two parameters is the &lt;em&gt;&lt;strong&gt;num_words&lt;/strong&gt;&lt;/em&gt;, which we keep as &lt;em&gt;&lt;strong&gt;input_dim&lt;/strong&gt;&lt;/em&gt; for the Keras Embedding layer.&lt;/p&gt;
&lt;h2 id=&quot;preparing-the-dataset-for-the-model-to-train&quot; tabindex=&quot;-1&quot;&gt;Preparing the dataset for the model to train&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;MAX_SEQUENCE_LENGTH = 1000
VALIDATION_SPLIT = 0.1

def vectorizing_data(df):
    &amp;quot;&amp;quot;&amp;quot; vectorizing and splitting the data for training, testing, validating &amp;quot;&amp;quot;&amp;quot;
    label_s = df[&#39;label&#39;].tolist()
    l = list(set(label_s))
    l.sort()
    labels_index = dict([(j,i) for i, j in enumerate(l)])
    labels = [labels_index[i] for i in label_s]
    print(&#39;Found %s texts.&#39; % len(df[&#39;content&#39;]))
    print(&#39;labels_index — &#39;, labels_index)

    tokenizer = Tokenizer(num_words=MAX_NB_WORDS)
    tokenizer.fit_on_texts(df[&#39;content&#39;])
    sequences = tokenizer.texts_to_sequences(df[&#39;content&#39;])
    word_index = tokenizer.word_index
    print(&#39;Found %s unique tokens.&#39; % len(word_index))

    df = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)
    labels = to_categorical(np.asarray(labels))

    # randomizing and splitting the df into a training set, test set and a validation set
    indices = np.arange(df.shape[0])
    np.random.shuffle(indices)
    df = df[indices]
    labels = labels[indices]
    num_validation_samples = int(VALIDATION_SPLIT * df.shape[0])
    x_train = df[:-num_validation_samples]
    y_train = labels[:-num_validation_samples]
    x_val = df[-num_validation_samples:]
    y_val = labels[-num_validation_samples:]
    x_test = x_train[-num_validation_samples:]
    y_test = y_train[-num_validation_samples:]
    return x_train, y_train, x_test, y_test, x_val, y_val, word_index
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Split the dataset for train, test, and validation purposes. Created a tokenizer and generated the word_index on the dataset content. Padded the sequences with the max length of &lt;em&gt;&lt;strong&gt;MAX_SEQUENCE_LENGTH.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;model-construction&quot; tabindex=&quot;-1&quot;&gt;Model construction&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;EMBEDDING_DIM = 100

def model_generation(embedding_matrix, num_words):
    &amp;quot;&amp;quot;&amp;quot; model generation &amp;quot;&amp;quot;&amp;quot;
    embedding_layer = Embedding(num_words + 1,
                                EMBEDDING_DIM,
                                weights=[embedding_matrix],
                                input_length=MAX_SEQUENCE_LENGTH,
                                trainable=False)
    convs = []
    filter_sizes = [3,4,5]
    sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype=&#39;int32&#39;)
    embedded_sequences = embedding_layer(sequence_input)
    for fsz in filter_sizes:
        l_conv = Conv1D(filters=128, kernel_size=fsz, activation=&#39;relu&#39;)(embedded_sequences)
        l_pool = MaxPooling1D(5)(l_conv)
        convs.append(l_pool)
    l_merge = Concatenate(axis=1)(convs)
    l_cov1= Conv1D(filters=128, kernel_size=5, activation=&#39;relu&#39;)(l_merge)
    l_cov1 = Dropout(0.2)(l_cov1)
    l_pool1 = MaxPooling1D(5)(l_cov1)
    l_cov2 = Conv1D(filters=128, kernel_size=5, activation=&#39;relu&#39;)(l_pool1)
    l_cov2 = Dropout(0.2)(l_cov2)
    l_pool2 = MaxPooling1D(30)(l_cov2)
    l_flat = Flatten()(l_pool2)
    l_dense = Dense(128, activation=&#39;relu&#39;)(l_flat)
    preds = Dense(label_count, activation=&#39;softmax&#39;)(l_dense)
    model = Model(sequence_input, preds)
    return model
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The model summary looks like this&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/mGJBbszUsl-480.webp 480w, https://turbolab.in/img/mGJBbszUsl-819.webp 819w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/mGJBbszUsl-480.jpeg&quot; alt=&quot;&quot; width=&quot;819&quot; height=&quot;815&quot; srcset=&quot;https://turbolab.in/img/mGJBbszUsl-480.jpeg 480w, https://turbolab.in/img/mGJBbszUsl-819.jpeg 819w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Model Summary&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The model is represented by the embedding layer followed by convolutional layers, pooling layers, and dropout layers. The final layer is the dense layer with the output size of labels/category count.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dropout&lt;/strong&gt; is dropping off the neurons to prevent an over-fitting problem in neural networks. It is an approach to regularization in neural networks which helps to reduce interdependent learning amongst the neurons. In Machine Learning we use regularization to prevent an over-fitting problem by adding a penalty to the loss function.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Batch normalization&lt;/strong&gt; is another method to regularize a convolutional network.&lt;/p&gt;
&lt;h2 id=&quot;f1-score-precision-and-recall&quot; tabindex=&quot;-1&quot;&gt;f1-score, precision, and recall&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;def recall_m(y_true, y_pred):
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    recall = true_positives / (possible_positives + K.epsilon())
    return recall
def precision_m(y_true, y_pred):
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
    precision = true_positives / (predicted_positives + K.epsilon())
    return precision
def f1_m(y_true, y_pred):
    precision = precision_m(y_true, y_pred)
    recall = recall_m(y_true, y_pred)
    return 2*((precision*recall)/(precision+recall+K.epsilon()))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These parameters evaluate the trained model. f1-score is the harmonic mean of precision and recall.&lt;/p&gt;
&lt;p&gt;Precision is calculated as the number of true positives divided by the total number of true positives and false positives.&lt;/p&gt;
&lt;p&gt;Recall is calculated as the number of true positives divided by the total number of true positives and false negatives.&lt;/p&gt;
&lt;h2 id=&quot;model-training-and-evaluation&quot; tabindex=&quot;-1&quot;&gt;Model training and evaluation&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;def training_evaluating_model(model, x_train, y_train, x_test, y_test, x_val, y_val):
    &amp;quot;&amp;quot;&amp;quot; training the model with the train and validation data
    and evaluating the model with the test data &amp;quot;&amp;quot;&amp;quot;
    model.compile(loss=&#39;categorical_crossentropy&#39;,
                  optimizer=&#39;rmsprop&#39;,
                  metrics=[&#39;acc&#39;, f1_m, precision_m, recall_m])
    # Displays the network structure
    model.summary()
    # fitting the model
    model.fit(x_train, y_train, validation_data=(x_val, y_val), epochs=epochs, batch_size=batch_size)
    &amp;quot;&amp;quot;&amp;quot;
    model.save_weights(home_path + &#39;model_trained&#39;) # Saving the model
    &amp;quot;&amp;quot;&amp;quot;
    # evaluating the model
    loss, accuracy, f1_score, precision, recall = model.evaluate(x_test, y_test, verbose=0)
    return loss, accuracy, f1_score, precision, recall
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/CfBoLwbUlj-480.webp 480w, https://turbolab.in/img/CfBoLwbUlj-960.webp 960w, https://turbolab.in/img/CfBoLwbUlj-1598.webp 1598w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/CfBoLwbUlj-480.jpeg&quot; alt=&quot;&quot; width=&quot;1598&quot; height=&quot;607&quot; srcset=&quot;https://turbolab.in/img/CfBoLwbUlj-480.jpeg 480w, https://turbolab.in/img/CfBoLwbUlj-960.jpeg 960w, https://turbolab.in/img/CfBoLwbUlj-1598.jpeg 1598w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Model Evaluation&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The model training accuracy is around 99.33% and validation accuracy is around 90.8%. Validation loss is more compared to training loss which resulted in the reduction of validation accuracy.  We have trained on dataset sample of 10000 rows only, if we have trained on complete dataset and increase in the number of epochs, results would have been much better.&lt;/p&gt;
&lt;p&gt;The complete code discussed above can be found &lt;em&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/Vasistareddy/text_classification_DL_vs_ML/blob/master/model_training_tutorial_dl.py&quot;&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How to monitor work-flow of scraping project with Apache-Airflow</title>
    <link href="https://turbolab.in/how-to-monitor-work-flow-of-scraping-project-with-apache-airflow/"/>
    <updated>2024-07-26T10:00:38.000Z</updated>
    <published>2021-12-22T08:16:05.000Z</published>
    <id>https://turbolab.in/how-to-monitor-work-flow-of-scraping-project-with-apache-airflow/</id>
    <content type="html">&lt;p&gt;Apache Airflow is a platform to programmatically monitor workflows, schedule, and authorize projects.&lt;/p&gt;
&lt;p&gt;In this blog, we will discuss handling the workflow of scraping &lt;strong&gt;&lt;a href=&quot;https://www.yelp.com/&quot;&gt;yelp.com&lt;/a&gt;&lt;/strong&gt; with Apache Airflow.&lt;/p&gt;
&lt;h2 id=&quot;quick-setup-of-airflow-on-ubuntu-2004-lts&quot; tabindex=&quot;-1&quot;&gt;Quick setup of Airflow on ubuntu 20.04 LTS&lt;/h2&gt;
&lt;h1&gt;make sure your system is up-to-date&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;sudo apt update
sudo apt upgrade
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;# install airflow dependencies&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install libmysqlclient-dev
sudo apt-get install libssl-dev
sudo apt-get install libkrb5-dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;# create the virtual env and install the airflow using pip&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt install python3-virtualenv
virtualenv airflow_test
cd airflow_test/
source bin/activate
export AIRFLOW_HOME=~/airflow # set Airflow home
pip3 install apache-airflow
pip3 install typing_extensions
airflow db init # initialize the db
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;db, unittests, logs, configuration(cfg)&lt;/strong&gt; files will be generated inside &lt;strong&gt;Airflow_Home&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;&lt;em&gt;Start a WebServer &amp;amp; Scheduler&lt;/em&gt;&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;airflow webserver -p 8080 # start the webserver
airflow scheduler # start the scheduler
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By default it is localhost. If you wish to change, you can give the command like this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;airflow webserver -H xxx.xxx.xxx.xxx -p 9005
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check the quick installation guide &lt;a href=&quot;https://airflow.apache.org/docs/apache-airflow/1.10.12/start.html&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If everything goes well, we can see the apache airflow web interface&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://localhost:8080/admin/ # web-server
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/EcPhzm_NGJ-480.webp 480w, https://turbolab.in/img/EcPhzm_NGJ-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/EcPhzm_NGJ-480.png&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;411&quot; srcset=&quot;https://turbolab.in/img/EcPhzm_NGJ-480.png 480w, https://turbolab.in/img/EcPhzm_NGJ-800.png 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Airflow WebServer&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Everything in Airflow works as &lt;strong&gt;DAGs&lt;/strong&gt;(Directed acyclic Graphs). We need to create a DAG with a unique dag_id and nest the tasks to that dag_id created. Simply put, DAG is the collection of tasks we want to run. Parameters like &lt;strong&gt;schedule_time&lt;/strong&gt;, &lt;strong&gt;start_time&lt;/strong&gt;, &lt;strong&gt;author&lt;/strong&gt;, and other parameters can also be passed to the DAG object.&lt;/p&gt;
&lt;p&gt;Create a folder named &lt;code&gt;dags&lt;/code&gt; inside the &lt;code&gt;Airflow_Home,&lt;/code&gt;the Scheduler will be checking for new DAGs for every 300’s, if any new dags are found — you can see them at web-server.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/je1EyTfSP1-480.webp 480w, https://turbolab.in/img/je1EyTfSP1-960.webp 960w, https://turbolab.in/img/je1EyTfSP1-1077.webp 1077w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/je1EyTfSP1-480.png&quot; alt=&quot;&quot; width=&quot;1077&quot; height=&quot;194&quot; srcset=&quot;https://turbolab.in/img/je1EyTfSP1-480.png 480w, https://turbolab.in/img/je1EyTfSP1-960.png 960w, https://turbolab.in/img/je1EyTfSP1-1077.png 1077w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Airflow Scheduler&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;We are going to create a workflow to scrape &lt;strong&gt;yelp.com&lt;/strong&gt; for business listings &amp;amp; save the data to MongoDB.&lt;/p&gt;
&lt;p&gt;The code to be used in this tutorial to scrape the &lt;strong&gt;yelp.com&lt;/strong&gt; can check &lt;a href=&quot;https://gist.githubusercontent.com/Vasistareddy/26a37b841e93756ab3256022e6daa09d/raw/a75b6b277ed64c953e09094e60e5f18d1789573a/yelp_search.py&quot;&gt;&lt;em&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;creation-of-dag&quot; tabindex=&quot;-1&quot;&gt;Creation of DAG&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;from airflow import DAG
from datetime import datetime
# dag creation
default_args = {&#39;owner&#39;: &#39;turbolab&#39;, &#39;start_date&#39;: datetime(2019, 1, 1), &#39;depends_on_past&#39;: False}
_yelp_workflow = DAG(&#39;_yelp_workflow&#39;, catchup=False, schedule_interval=None, default_args=default_args) # creating a DAG
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/az5UOKboSo-480.webp 480w, https://turbolab.in/img/az5UOKboSo-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/az5UOKboSo-480.png&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;218&quot; srcset=&quot;https://turbolab.in/img/az5UOKboSo-480.png 480w, https://turbolab.in/img/az5UOKboSo-800.png 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;DAG Created&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;_yelp_workflow&lt;/code&gt; DAG is created. &lt;code&gt;schedule_interval=None&lt;/code&gt; is for manual triggering the DAG. Other options are &lt;code&gt;@daily, @weekly,&lt;/code&gt; &lt;code&gt;“* * * */2 1”&lt;/code&gt;(cron schedule). Know about &lt;code&gt;catchup, depends_on_past&lt;/code&gt; the airflow documentation &lt;a href=&quot;https://airflow.apache.org/scheduler.html&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;task-creation&quot; tabindex=&quot;-1&quot;&gt;Task Creation&lt;/h2&gt;
&lt;p&gt;With the airflow set of &lt;a href=&quot;https://airflow.apache.org/concepts.html#operators&quot;&gt;&lt;strong&gt;operators&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; we can define tasks of the DAG workflow. An operator describes a single task in a workflow. While DAGs describes how to run a workflow, &lt;code&gt;Operators&lt;/code&gt; determine what actually gets done. To call a python function — &lt;code&gt;PythonOperator&lt;/code&gt;, for an Email — &lt;code&gt;EmailOperator&lt;/code&gt;, for a Bash command —&lt;code&gt;BashOperator&lt;/code&gt;, for a SQL instruction — &lt;code&gt;MySqlOperator&lt;/code&gt; etc.,&lt;/p&gt;
&lt;p&gt;Generally, operators run independently with no sharing of information in the order specified. If it absolutely can’t be avoided, Airflow does have a feature for operator cross-communication called &lt;em&gt;&lt;strong&gt;XCom.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def url_generator(**kwargs):
    &amp;quot;&amp;quot;&amp;quot; 
    generating the yelp url to find the business listings with place and search_query 
    {&#39;place&#39;: &#39;Location | Address | zip code&#39;}
    {&#39;search_query&#39;: &amp;quot;Restaurants | Breakfast &amp;amp; Brunch | Coffee &amp;amp; Tea | Delivery | Reservations&amp;quot;}
    &amp;quot;&amp;quot;&amp;quot;
    place = Variable.get(&amp;quot;place&amp;quot;)
    search_query = Variable.get(&amp;quot;search_query&amp;quot;)
    yelp_url = &amp;quot;https://www.yelp.com/search?find_desc={0}&amp;amp;find_loc={1}&amp;quot;.format(search_query,place)
    return yelp_url
&amp;quot;&amp;quot;&amp;quot;defining a task&amp;quot;&amp;quot;&amp;quot;
yelp_url_generator = PythonOperator(
    task_id=&#39;url_generator&#39;,
    python_callable=url_generator,
    provide_context=True,
    dag=_yelp_workflow)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Likewise, 6 tasks were created and the concepts like &lt;code&gt;variables&lt;/code&gt; and &lt;code&gt;xcom&lt;/code&gt; are used among the tasks.&lt;/p&gt;
&lt;h2 id=&quot;concept-of-xcom&quot; tabindex=&quot;-1&quot;&gt;Concept of xcom&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;def get_response(**kwargs):
    &amp;quot;&amp;quot;&amp;quot;
    validating the url and forwarding the response
    &amp;quot;&amp;quot;&amp;quot;
    ti = kwargs[&#39;ti&#39;]
    url = ti.xcom_pull(task_ids=&#39;url_generator&#39;)
    print(&#39;url generated: &#39;, url)
    headers = {&#39;user-agent&#39;: &#39;Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chrome/70.0.3538.77 Safari/537.36&#39;}
    success = False
    
    for retry in range(10):
        response = requests.get(url, verify=False, headers=headers)
        if response.status_code == 200:
            success = True
            break
        else:
            print(&amp;quot;Response received: %s. Retrying : %s&amp;quot;%(response.status_code, url))
            success = False
    
    if success == False:
        print(&amp;quot;Failed to process the URL: &amp;quot;, url)
        raise ValueError(&amp;quot;Failed to process the URL: &amp;quot;, url)
    return response
response_generator = PythonOperator(
    task_id=&#39;response_generator&#39;,
    python_callable=get_response,
    provide_context=True,
    dag=_yelp_workflow)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;url_generator&lt;/code&gt; task returning the &lt;code&gt;yelp_url&lt;/code&gt; has to pass to &lt;code&gt;response_generator&lt;/code&gt; task, where we will be checking the response of the URL. If the status_code of the response is &lt;code&gt;200&lt;/code&gt;, we are returning — otherwise raising a &lt;code&gt;ValueError&lt;/code&gt; to stop the pipeline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;xcom&lt;/strong&gt;’s can be viewed at the admin page after the successful task runs.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/VrjcWzILL7-480.webp 480w, https://turbolab.in/img/VrjcWzILL7-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/VrjcWzILL7-480.gif&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;382&quot; srcset=&quot;https://turbolab.in/img/VrjcWzILL7-480.gif 480w, https://turbolab.in/img/VrjcWzILL7-800.gif 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h2 id=&quot;concept-of-variable&quot; tabindex=&quot;-1&quot;&gt;Concept of variable&lt;/h2&gt;
&lt;p&gt;This concept is used when the user has to input the values(like command-line arguments in python) to the tasks created.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;place = Variable.get(&amp;quot;place&amp;quot;)
search_query = Variable.get(&amp;quot;search_query&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These variables &lt;code&gt;place&lt;/code&gt; and &lt;code&gt;search_query&lt;/code&gt; are used in the &lt;code&gt;url_generator&lt;/code&gt; python function of &lt;code&gt;yelp_url_generator&lt;/code&gt; task.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/Zx-mRiaOZL-480.webp 480w, https://turbolab.in/img/Zx-mRiaOZL-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/Zx-mRiaOZL-480.gif&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;535&quot; srcset=&quot;https://turbolab.in/img/Zx-mRiaOZL-480.gif 480w, https://turbolab.in/img/Zx-mRiaOZL-800.gif 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Variables Creation&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;tasks-relationshiparrangement&quot; tabindex=&quot;-1&quot;&gt;Tasks Relationship/Arrangement&lt;/h2&gt;
&lt;p&gt;The DAG will make sure that operators run in the correct certain order. Check &lt;a href=&quot;https://airflow.apache.org/concepts.html#dag-assignment&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/CZeanfLDOE-480.webp 480w, https://turbolab.in/img/CZeanfLDOE-799.webp 799w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/CZeanfLDOE-480.gif&quot; alt=&quot;&quot; width=&quot;799&quot; height=&quot;306&quot; srcset=&quot;https://turbolab.in/img/CZeanfLDOE-480.gif 480w, https://turbolab.in/img/CZeanfLDOE-799.gif 799w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;end_task &amp;lt;&amp;lt; validate_db &amp;lt;&amp;lt; writing_to_db &amp;lt;&amp;lt; validate_data &amp;lt;&amp;lt; get_data &amp;lt;&amp;lt; response_generator &amp;lt;&amp;lt; yelp_url_generator &amp;lt;&amp;lt; start_task
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;airflow upstream arrangement of tasks with &lt;code&gt;start_task and end_task&lt;/code&gt; is dummy tasks(&lt;em&gt;&lt;strong&gt;optional&lt;/strong&gt;&lt;/em&gt;). Others &lt;code&gt;yelp_url_generator →response_generator →get_data →validate_data →writing_to_db →validate_db&lt;/code&gt; are python tasks.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.githubusercontent.com/Vasistareddy/f0b5f7d73efc900f269e0aa81d04e81b/raw/8cc88cd5bd31fe219368b522b3dea3945e21caf4/yelp_business_listings.py&quot;&gt;&lt;strong&gt;Check the complete code here&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;triggering-the-dag&quot; tabindex=&quot;-1&quot;&gt;Triggering the DAG&lt;/h2&gt;
&lt;p&gt;Since we kept &lt;code&gt;schedule_interval=None,&lt;/code&gt; we have to manually trigger the DAG. Let’s see how to do that →&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/ls3Fi385Mq-480.webp 480w, https://turbolab.in/img/ls3Fi385Mq-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/ls3Fi385Mq-480.gif&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;344&quot; srcset=&quot;https://turbolab.in/img/ls3Fi385Mq-480.gif 480w, https://turbolab.in/img/ls3Fi385Mq-800.gif 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/5VvRAAOZMo-480.webp 480w, https://turbolab.in/img/5VvRAAOZMo-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/5VvRAAOZMo-480.png&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;219&quot; srcset=&quot;https://turbolab.in/img/5VvRAAOZMo-480.png 480w, https://turbolab.in/img/5VvRAAOZMo-800.png 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;MongoDB data&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;tree-view-of-each-dag-run&quot; tabindex=&quot;-1&quot;&gt;Tree View of each DAG run&lt;/h2&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/aeD_drUHNQ-480.webp 480w, https://turbolab.in/img/aeD_drUHNQ-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/aeD_drUHNQ-480.png&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;257&quot; srcset=&quot;https://turbolab.in/img/aeD_drUHNQ-480.png 480w, https://turbolab.in/img/aeD_drUHNQ-800.png 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Tree View of each DAG run&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;handling-cases&quot; tabindex=&quot;-1&quot;&gt;Handling Cases&lt;/h2&gt;
&lt;p&gt;You must be wondering why to use this setup of airflow for simple scraping. The reason is,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We can break down the whole single task into multiple tasks and have control over each task at any point.&lt;/li&gt;
&lt;li&gt;Will have clear logs at every level.&lt;/li&gt;
&lt;li&gt;Can easily connect to other servers with airflow operators to execute the script.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;here-are-the-few-cases-handled-in-the-work-flow&quot; tabindex=&quot;-1&quot;&gt;Here are the few cases handled in the work-flow&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;When we are trying to write the same set of data into the Database with multiple DAG runs.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/cZuBgLTLWk-480.webp 480w, https://turbolab.in/img/cZuBgLTLWk-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/cZuBgLTLWk-480.png&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;209&quot; srcset=&quot;https://turbolab.in/img/cZuBgLTLWk-480.png 480w, https://turbolab.in/img/cZuBgLTLWk-800.png 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Duplicate Key Error&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;task_id=writing_to_db&lt;/code&gt; will be handling this case.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When the data scraped and pushed to the database doesn’t match.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/tmhvk26lid-480.webp 480w, https://turbolab.in/img/tmhvk26lid-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/tmhvk26lid-480.png&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;220&quot; srcset=&quot;https://turbolab.in/img/tmhvk26lid-480.png 480w, https://turbolab.in/img/tmhvk26lid-800.png 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;task_id=validate_db&lt;/code&gt; will be handling this case. In case the anomaly is detected, we will be raising the &lt;code&gt;Value Error&lt;/code&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Text Similarity using fastText Word Embeddings in Python</title>
    <link href="https://turbolab.in/text-similarity-using-fasttext-word-embeddings-in-python/"/>
    <updated>2022-01-05T07:04:19.000Z</updated>
    <published>2021-12-09T09:41:31.000Z</published>
    <id>https://turbolab.in/text-similarity-using-fasttext-word-embeddings-in-python/</id>
    <content type="html">&lt;p&gt;Text Similarity is one of the essential techniques of NLP which is used to find similarities between two chunks of text. In order to perform text similarity, word embedding techniques are used to convert chunks of text to certain dimension vectors. We also perform some mathematical operations on these vectors to find the similarity between the text chunks. Recommendation System, Text Summarization, Information Retrieval, and Text Categorization are some of the main applications of text similarity.&lt;/p&gt;
&lt;p&gt;In this tutorial, we will discuss how sentence similarity can be achieved with the fastText module and also the use-case of generating related news articles.&lt;/p&gt;
&lt;h3 id=&quot;dataset&quot; tabindex=&quot;-1&quot;&gt;Dataset&lt;/h3&gt;
&lt;p&gt;Here, we have a science and technology news dataset with a sample of 6188 titles.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/hnJgSJCun0-478.webp 478w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/hnJgSJCun0-478.jpeg&quot; alt=&quot;&quot; width=&quot;478&quot; height=&quot;449&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h3 id=&quot;problem-statement&quot; tabindex=&quot;-1&quot;&gt;Problem Statement&lt;/h3&gt;
&lt;p&gt;From the above dataset, we are going to pick one article title i.e.,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
ROI = &amp;quot;Samsung to spend whopping $22B on artificial intelligence, cars&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Henceforth, we are going to call it &lt;strong&gt;ROI&lt;/strong&gt;in the tutorial. We will be fetching related articles of &lt;strong&gt;ROI&lt;/strong&gt; from the dataset using a fastText sentence vector.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Out:
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;generate-sentence-vectors&quot; tabindex=&quot;-1&quot;&gt;Generate sentence vectors&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Import the fastText module and load the model(300 dimension vector).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import fasttext
modelPath = &amp;quot;D://&amp;quot; # user defined path
ft = fasttext.load_model(modelPath+&#39;cc.en.300.bin&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate sentence vector to the &lt;em&gt;&lt;strong&gt;ROI&lt;/strong&gt; and call it as &lt;strong&gt;vector1&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def generateVector(sentence):
    return ft.get_sentence_vector(sentence)
vector1 = generateVector(&#39;Samsung to spend whopping $22B on artificial intelligence, cars&#39;)
Out:
array([-6.36741472e-03,  1.08614033e-02,  9.33997519e-03, -2.33159624e-02,
       -9.58340534e-04,  1.86185073e-02,  2.20048483e-02, -2.02285256e-02,
       -1.13004427e-02, -1.38842128e-02, -6.33053621e-03,  1.18326535e-02,
       -2.36112420e-02,  9.13483184e-03,  5.59101533e-03,  1.09400013e-02,
        4.77387244e-03, -1.54347951e-02, -1.35055669e-02, -2.90185958e-02,
        1.35819204e-02,  2.80883280e-03,  3.43523137e-02, -2.22271457e-02,
        …………..
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate sentence vector for the entire dataset.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;df[&amp;quot;vector&amp;quot;] = df[&amp;quot;title&amp;quot;].apply(generateVector)
Out:
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;calculate-spatial-distance&quot; tabindex=&quot;-1&quot;&gt;Calculate Spatial Distance&lt;/h3&gt;
&lt;p&gt;Calculate the spatial distance between the &lt;em&gt;&lt;strong&gt;ROI&lt;/strong&gt;&lt;/em&gt; and the rest of the dataframe titles to determine the related articles of &lt;em&gt;&lt;strong&gt;ROI&lt;/strong&gt;&lt;/em&gt;. The lesser the distance value, the more the related content.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from scipy import spatial
def spatialDistance(vector1, vector2):
    return spatial.distance.euclidean(vector1, vector2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;vector1&lt;/strong&gt; is the vector of &lt;em&gt;&lt;strong&gt;ROI&lt;/strong&gt;&lt;/em&gt; generated above. &lt;strong&gt;vector2&lt;/strong&gt; is the vector column of each title of the dataframe.&lt;/p&gt;
&lt;p&gt;Generating distance as a &lt;strong&gt;score&lt;/strong&gt; between the static &lt;em&gt;&lt;strong&gt;ROI&lt;/strong&gt;&lt;/em&gt; and the rest of the dataframe titles.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;df[&amp;quot;score&amp;quot;] = df.apply(lambda x: spatialDistance(vector1, x[&#39;vector&#39;]), axis=1)
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/pPJgYJPsgU-480.webp 480w, https://turbolab.in/img/pPJgYJPsgU-907.webp 907w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/pPJgYJPsgU-480.jpeg&quot; alt=&quot;&quot; width=&quot;907&quot; height=&quot;207&quot; srcset=&quot;https://turbolab.in/img/pPJgYJPsgU-480.jpeg 480w, https://turbolab.in/img/pPJgYJPsgU-907.jpeg 907w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Sorting the &lt;strong&gt;score&lt;/strong&gt; column of the dataframe to determine the closest related titles.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;df.drop_duplicates(subset=[&amp;quot;score&amp;quot;]).sort_values(by=[&#39;score&#39;])
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/T60Ow39u3L-480.webp 480w, https://turbolab.in/img/T60Ow39u3L-889.webp 889w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/T60Ow39u3L-480.jpeg&quot; alt=&quot;&quot; width=&quot;889&quot; height=&quot;199&quot; srcset=&quot;https://turbolab.in/img/T60Ow39u3L-480.jpeg 480w, https://turbolab.in/img/T60Ow39u3L-889.jpeg 889w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;From the dataset, the top 10 article titles related to the &lt;em&gt;&lt;strong&gt;ROI&lt;/strong&gt;&lt;/em&gt; are:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
outputs = df.drop_duplicates(subset=[&amp;quot;score&amp;quot;]).sort_values(by=[&#39;score&#39;])[0:10][&amp;quot;title&amp;quot;].tolist()

Out:
[&#39;OnePlus phones go cheaper on Amazon up to Rs 10,000, lots of EMI and exchange offers on latest models&#39;,
&#39;Samsung to invest nearly $500 mn to set up display factory in India&#39;,
&#39;Samsung Galaxy S20+ gets listed on Geekbench, revealed to bring 120Hz display, 8K video and more&#39;,
&#39;Worldwide spend on robotics systems, drones to hit $128.7 billion in 2020&#39;,
&#39;This is the pitch deck that the CEO of AI startup Directly used to convince its top customers Microsoft and Samsung to invest in a $20 million round&#39;,
&#39;Dell is working on a software to let users control iPhones from their laptops&#39;,
&amp;quot;Here&#39;s an exclusive look at the pitch deck AI privacy startup Mine used to raise $3 million to help people ask companies to delete their data&amp;quot;,
&#39;Samsung offering instant cashback of up to Rs 20,000 on Galaxy S10 series&#39;,
&#39;Google exec reveals how its cloud is helping retailers to keep their sites from crashing on their biggest shopping days of the year&#39;,
&amp;quot;Here&#39;s the pitch deck that email startup Front used to get get top tech execs like Zoom CEO Eric Yuan to invest in its $59 million Series C round&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;another-example&quot; tabindex=&quot;-1&quot;&gt;Another Example:&lt;/h3&gt;
&lt;p&gt;If the &lt;em&gt;&lt;strong&gt;ROI&lt;/strong&gt;&lt;/em&gt; is **“**&lt;em&gt;&lt;strong&gt;SpaceX launches third batch of 60 Starlink mini satellites”,&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
SpaceX launches third batch of 60 Starlink mini satellites
Out:
[&#39;SpaceX launches third batch of Starlink satellites&#39;,
&amp;quot;ISRO&#39;s GSAT 30 satellite successfully rides the Ariane 5 rocket into orbit abroad the first launch of 2020&amp;quot;,
&#39;SpaceX launch LIVE stream: Watch Elon Musk blast next Starlink satellites into orbit today&#39;,
&#39;ISRO targets to launch 19 satellites within a period of 7 months&#39;,
&#39;Asteroid alert: NASA tracks four large space rocks racing towards Earth in next 48 hours&#39;,
&#39;Huawei launches Mate 30 Pro 5G outside of China for first time, enters UAE&#39;,
&#39;ISRO&#39;s first mission of the decade on this date! Ariane rocket to launch GSAT-30 satellite&#39;,
&#39;Samsung teases launch of new Galaxy phone in 11 Feb event announcement&#39;,
&#39;SpaceX launch LIVE stream: Watch Elon Musk&#39;s first launch of 2020 online HERE&#39;,
&#39;NASA news: Space agency outlines goals for 2020 including a launch to Mars&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In this tutorial, we have discussed generating related content using fastText sentence embeddings and a mathematical operation called Spatial Distance. We can also try replacing the spatial distance with the cosine similarity between the vectors to find the related content. Pre-processing techniques like &lt;a href=&quot;https://turbolab.in/stemming-vs-lemmatization-with-python-nltk/&quot;&gt;lemmatization&lt;/a&gt;, stemming and removal of stopwords can also be performed on the dataset before the vector generation to improve the accuracy of the result. This specific use-case of generating related content can be enhanced to the recommendation system application considering the user’s interests.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Data Cleaning using Regular Expression</title>
    <link href="https://turbolab.in/data-cleaning-using-regular-expression/"/>
    <updated>2022-01-18T10:11:50.000Z</updated>
    <published>2021-11-30T12:06:01.000Z</published>
    <id>https://turbolab.in/data-cleaning-using-regular-expression/</id>
    <content type="html">&lt;p&gt;Data cleaning is the process of fixing or removing incorrect, corrupted, incorrectly formatted, duplicate, or incomplete data within a dataset.&lt;/p&gt;
&lt;p&gt;The data format is not always tabular. As we are entering the era of big data, the data comes in an extensively diverse format, including images, texts, graphs, and many more. Because the format is pretty diverse, ranging from one data to another, it’s essential to preprocess the data into a readable format for computers.&lt;/p&gt;
&lt;p&gt;In this blog, we will go over some Regex (Regular Expression) techniques that you can use in your data cleaning process.&lt;/p&gt;
&lt;p&gt;Regular Expression is a sequence of characters used to match strings of text such as particular characters, words, or patterns of characters.&lt;/p&gt;
&lt;p&gt;In Python, a Regular Expression (REs, regexes, or regex pattern) is imported through a ‘re’ module which is in-built in Python so you don’t need to install it separately.&lt;/p&gt;
&lt;p&gt;The re module offers a set of functions that allows us to search a string for a match.&lt;/p&gt;
&lt;p&gt;The most commonly used methods provided by ‘re’ package are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;re.match()&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;re.search()&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;re.findall()&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;re.split()&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;re.sub()&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;re.compile()&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3 id=&quot;replacing-multi-spaces&quot; tabindex=&quot;-1&quot;&gt;Replacing Multi-Spaces&lt;/h3&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Removing extra white spaces from data is an important step as it makes your data look well structured.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re
tweet = &amp;quot;if       you hold an empty gatorade bottle up to your ear   you can hear      the sports&amp;quot;
x = re.sub(&#39;&#92;s+&#39;, &amp;quot; &amp;quot;, tweet)
Input: x
Output: &#39;if you hold an empty gatorade bottle up to your ear you can hear the sports
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3 id=&quot;dealing-with-special-characters&quot; tabindex=&quot;-1&quot;&gt;Dealing with Special Characters&lt;/h3&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;In case you are working on an NLP project, you will need to get your text very clean and get rid of special characters that will not alter the meaning of the text for instance&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;1.   Removing special characters and keeping only alphabets and numbers&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;import re
tweet = &amp;quot;if you hold an empty # gatorade # bottle up to your ear @@ you can hear the sports 100 %%&amp;quot;
x = re.sub(&amp;quot;[^a-zA-Z0-9 ]+&amp;quot;, &amp;quot; &amp;quot;, tweet)
Output: &#39;if you hold an empty gatorade bottle up to your ear you can hear the sports 100&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;2. Keeping either of alphabets or numbers&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;import re
tweet = &amp;quot;if you hold an empty # gatorade # bottle up to your ear @@ you can hear the sports 100 %%&amp;quot;
x = re.sub(&amp;quot;[^a-zA-Z ]+&amp;quot;,&amp;quot; &amp;quot;, tweet)
Output: &#39;if you hold an empty gatorade bottle up to your ear you can hear the sports&#39;

tweet = &amp;quot;if you hold an empty # gatorade # bottle up to your ear @@ you can hear the sports 100 %%&amp;quot;
x = re.sub(&amp;quot; +&amp;quot;, &amp;quot;&amp;quot;,re.sub(&amp;quot;[^0-9 ]+&amp;quot;,&amp;quot;, tweet))
Output: &#39;100&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3 id=&quot;detect-and-remove-urls&quot; tabindex=&quot;-1&quot;&gt;Detect and Remove URLs&lt;/h3&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Here we are using “re.compile” to generate a regex pattern and use that saved pattern later for substitution, if needed.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re
tweet = &#39;follow this website for more details www.knowmore.com and login to http://login.com&#39;
pattern = re.compile(r&amp;quot;https?://&#92;S+|www&#92;.&#92;S+&amp;quot;)
x = re.findall(pattern, tweet)
Input: x
Output: [&#39;www.knowmore.com&#39;, &#39;http://login.com&#39;]

# remove urls 
z = re.sub(pattern, &amp;quot;&amp;quot;, tweet)
Input: z
Output: follow this website for more details and login to
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3 id=&quot;detect-and-remove-html-tags&quot; tabindex=&quot;-1&quot;&gt;Detect and Remove HTML Tags&lt;/h3&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;Import re
tweet = &#39;&amp;lt;p&amp;gt;follow this &amp;lt;b&amp;gt;website&amp;lt;/b&amp;gt; for more details. &amp;lt;/p&amp;gt;&#39;
x = re.findall(&#39;&amp;lt;.*?&amp;gt;&#39;, tweet)
Input : x
Output: [&#39;&amp;lt;p&amp;gt;&#39;, &#39;&amp;lt;b&amp;gt;&#39;, &#39;&amp;lt;/b&amp;gt;&#39;, &#39;&amp;lt;/p&amp;gt;&#39;]
# remove html tags
z = re.sub(&#39;&amp;lt;.*?&amp;gt;&#39;, &amp;quot;&amp;quot;, tweet)
Input: z
Output: &#39;follow this website for more details.&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3 id=&quot;detect-and-remove-email-ids&quot; tabindex=&quot;-1&quot;&gt;Detect and Remove Email IDs&lt;/h3&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Here we’ll use “re.search” to find e-mail ID.  re.search() only returns the first occurrence that matches the specified pattern. In contrast, re.findall() will iterate over all the lines and will return all non-overlapping matches of pattern in a single step.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re
tweet = &amp;quot;please send your feedback to myemail@gmail.com &amp;quot;
x = re.search(&amp;quot;[&#92;w&#92;.-]+@[&#92;w&#92;.-]+&#92;.&#92;w+&amp;quot;, tweet)
Input: x
Output: &amp;lt;re.Match object; span=(29, 40), match=&#39;myemail@gmail.com&#39;&amp;gt;

tweet = &amp;quot;please send your feedback to myemail@gmail.com &amp;quot;
z = re.sub(&amp;quot;[&#92;w&#92;.-]+@[&#92;w&#92;.-]+&#92;.&#92;w+&amp;quot;, &amp;quot;&amp;quot;, tweet)
Output: please send your feedback to
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3 id=&quot;detect-and-remove-the-hashtag&quot; tabindex=&quot;-1&quot;&gt;Detect and Remove the Hashtag&lt;/h3&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;import re
tweet = &amp;quot;love to explore. #nature #traveller&amp;quot;
x = re.findall(&#39;#[_]*[a-z]+&#39;,tweet)
Input: x
Output: [&#39;#nature&#39;, &#39;#traveller&#39;]
# remove html tags
z = re.sub(&#39;#[_]*[a-z]+&#39;, &#39; &#39;, tweet)
Input: z
Output: &amp;quot;love to explore.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3 id=&quot;detect-mentions-using-rematch-and-refindall&quot; tabindex=&quot;-1&quot;&gt;Detect Mentions using re.match() and re.findall()&lt;/h3&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Here we’ll use re.match and re.findall to detect mentions.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;re.match matches the pattern from the start of the string whereas re.findall searches for occurrences of the pattern anywhere in the string.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re
tweet = &amp;quot;@Bryan appointed as the new team captain&amp;quot;
x = re.match(&amp;quot;(@&#92;w+)&amp;quot;, tweet)
Output: &amp;lt;re.Match object; span=(0, 6), match=&#39;@Bryan&#39;&amp;gt;

tweet = &amp;quot;@Bryan appointed as the new team captain announced in @SportsLive&amp;quot;
x = re.findall(&amp;quot;@&#92;S+&amp;quot;, tweet)
Input: x
Output: [ &#39;@Bryan&#39;, &#39;@SportsLive&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Regular Expression is very useful for text manipulation in the text cleaning phase of Natural Language Processing (NLP). In this post, we have used “re.findall”, “re.sub”, “re.search”, “re.match”, and “re.compile” functions, but there are many other functions in the regex library that can help data processing and manipulation. If you don’t have sufficient understanding regarding Regular Expression, we recommend you to go through python’s official page on &lt;a href=&quot;https://docs.python.org/3/library/re.html&quot;&gt;regex&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Build a Custom NER model using spaCy 3.0</title>
    <link href="https://turbolab.in/build-a-custom-ner-model-using-spacy-3-0/"/>
    <updated>2021-12-03T05:33:50.000Z</updated>
    <published>2021-11-11T12:45:37.000Z</published>
    <id>https://turbolab.in/build-a-custom-ner-model-using-spacy-3-0/</id>
    <content type="html">&lt;p&gt;SpaCy is an open-source python library used for &lt;em&gt;Natural Language Processing(NLP).&lt;/em&gt; Unlike &lt;em&gt;NLTK&lt;/em&gt;, which is widely used in research, spaCy focuses on production usage. Industrial-strength &lt;em&gt;NLP&lt;/em&gt; &lt;em&gt;&lt;strong&gt;spaCy&lt;/strong&gt;&lt;/em&gt; is a library for advanced &lt;em&gt;NLP&lt;/em&gt; in Python and Cython. As of now, this is the best NLP tool available in the market.&lt;/p&gt;
&lt;p&gt;SpaCy provides ready-to-use language-specific pre-trained models to perform &lt;em&gt;parsing&lt;/em&gt;, &lt;em&gt;tagging&lt;/em&gt;, &lt;em&gt;NER&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://turbolab.in/stemming-vs-lemmatization-with-python-nltk/&quot;&gt;lemmatizer&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;tok2vec&lt;/em&gt;, &lt;em&gt;attribute_ruler&lt;/em&gt;, and other NLP tasks. It supports 18 languages and 1 multi-language pipeline. Check the supported language list &lt;strong&gt;&lt;a href=&quot;https://spacy.io/usage/models#languages&quot;&gt;here&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;SpaCy provides the following four &lt;a href=&quot;https://spacy.io/models/en&quot;&gt;&lt;strong&gt;pre-trained models&lt;/strong&gt;&lt;/a&gt; with MIT license for the English language:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;en_core_web_sm&lt;/strong&gt;&lt;/em&gt;(12 mb)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;en_core_web_md&lt;/strong&gt;&lt;/em&gt;(43 mb)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;en_core_web_lg&lt;/strong&gt;&lt;/em&gt;(741 mb)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;en_core_web_trf&lt;/strong&gt;&lt;/em&gt;(438 mb)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Support for transformers and the pretrained pipeline(&lt;strong&gt;en_core_web_trf)&lt;/strong&gt; has been introduced in spaCy 3.0.&lt;/p&gt;
&lt;p&gt;Named Entity Recognition(NER) is the NLP task that recognizes entities in a given text. NER is a model which performs two tasks: &lt;strong&gt;Detect&lt;/strong&gt; and &lt;strong&gt;Categorize&lt;/strong&gt;. It has to detect the entities(&lt;strong&gt;India&lt;/strong&gt;, &lt;strong&gt;America&lt;/strong&gt;, &lt;strong&gt;Abdul Kalam&lt;/strong&gt;) in the text and categorize(&lt;strong&gt;LOCATION&lt;/strong&gt;, &lt;strong&gt;LOCATION&lt;/strong&gt;, &lt;strong&gt;PERSON&lt;/strong&gt;) the entities detected. This tool helps in information retrieval from bulk uncategorized texts.&lt;/p&gt;
&lt;h2 id=&quot;load-a-spacy-model-and-check-if-it-has-ner-pipeline&quot; tabindex=&quot;-1&quot;&gt;Load a spaCy model and check if it has ner pipeline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;In:
!python -m spacy download en_core_web_sm
import spacy 
nlp = spacy.load(&amp;quot;en_core_web_sm&amp;quot;)
nlp.pipe_names

Out:
[&#39;tok2vec&#39;, &#39;tagger&#39;, &#39;parser&#39;, &#39;attribute_ruler&#39;, &#39;lemmatizer&#39;, &#39;ner&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;ner&lt;/strong&gt; is in the pipeline, let’s test how the entity detection will work on a sentence.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
sentence = &amp;quot;Daniil Medvedev and Novak Djokovic have built an intriguing rivalry since the Australian Open decider, which the Serb won comprehensively.&amp;quot;
doc = nlp(sentence)
from spacy import displacy
displacy.render(doc, style=&amp;quot;ent&amp;quot;, jupyter=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/qq_l7PWvpH-480.webp 480w, https://turbolab.in/img/qq_l7PWvpH-960.webp 960w, https://turbolab.in/img/qq_l7PWvpH-1252.webp 1252w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/qq_l7PWvpH-480.jpeg&quot; alt=&quot;&quot; width=&quot;1252&quot; height=&quot;99&quot; srcset=&quot;https://turbolab.in/img/qq_l7PWvpH-480.jpeg 480w, https://turbolab.in/img/qq_l7PWvpH-960.jpeg 960w, https://turbolab.in/img/qq_l7PWvpH-1252.jpeg 1252w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Let’s observe the doc to see how entities are being identified/tagged by the model.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
[(X, X.ent_iob_, X.ent_type_) for X in doc if X.ent_type_]
Out:
[(Daniil, &#39;B&#39;, &#39;PERSON&#39;),
(Medvedev, &#39;I&#39;, &#39;PERSON&#39;),
(Novak, &#39;B&#39;, &#39;PERSON&#39;),
(Djokovic, &#39;I&#39;, &#39;PERSON&#39;),
(Australian, &#39;B&#39;, &#39;NORP&#39;), # LOCATION
(Serb, &#39;B&#39;, &#39;NORP&#39;)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Novak&lt;/strong&gt; and &lt;strong&gt;Djokovic&lt;/strong&gt; are correctly identified as &lt;strong&gt;PERSON&lt;/strong&gt; but they are separate entities. But these are displayed as a single entity through &lt;strong&gt;Displacy&lt;/strong&gt;. &lt;strong&gt;IOB Tagging&lt;/strong&gt; plays a key role to combine the entities which are inclusive of one another.&lt;/p&gt;
&lt;h2 id=&quot;inside-outside-beginningiob-tagging&quot; tabindex=&quot;-1&quot;&gt;Inside-Outside-Beginning(IOB) Tagging&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;IOB&lt;/strong&gt; is the common tagging format for tagging the entities/chunks in the text.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;I&lt;/strong&gt;&lt;/em&gt; stands for Inside and it indicates that the token is an insider of a chunk.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;B&lt;/strong&gt;&lt;/em&gt; stands for Beginning and it indicates that the token is the beginning of a chunk.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;O&lt;/strong&gt;&lt;/em&gt; stands for Outside and it indicates that the token doesn’t belong to any chunk.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the above output, &lt;strong&gt;Daniil&lt;/strong&gt; is tagged as B which is the beginning of the entity chunk, and &lt;strong&gt;Medvedev&lt;/strong&gt; is tagged as &lt;em&gt;&lt;strong&gt;I&lt;/strong&gt;&lt;/em&gt; which is the insider token of the previous token &lt;strong&gt;Daniil.&lt;/strong&gt; These two tokens combine to form a &lt;strong&gt;PERSON&lt;/strong&gt; entity. Same is the scenario with &lt;strong&gt;Novak&lt;/strong&gt; and &lt;strong&gt;Djokovic.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The tokens tagged as &lt;strong&gt;O&lt;/strong&gt; are not classified as an entity type and we can see that no label has been assigned by the model.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[(and, &#39;O&#39;, &amp;quot;),
(have, &#39;O&#39;, &amp;quot;),
(built, &#39;O&#39;, &amp;quot;),
(an, &#39;O&#39;, &amp;quot;),
(intriguing, &#39;O&#39;, &amp;quot;),
(rivalry, &#39;O&#39;, &amp;quot;),
(since, &#39;O&#39;, &amp;quot;),
(the, &#39;O&#39;, &amp;quot;),
(Open, &#39;O&#39;, &amp;quot;),
(decider, &#39;O&#39;, &amp;quot;)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;CARDINAL&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;DATE&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;EVENT&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;FAC&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;GPE&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;LANGUAGE&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;LAW&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;LOC&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;MONEY&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;NORP&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;ORDINAL&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;ORG&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;PERCENT&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;PERSON&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;PRODUCT&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;QUANTITY&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;TIME&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;WORK_OF_ART&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;These are the entity labels provided by the NER pre-trained model. We can execute the command given below to understand each label.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
spacy.explain(&amp;quot;NORP&amp;quot;)
Out:
Nationalities or religious or political groups
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;why-do-we-need-a-custom-ner&quot; tabindex=&quot;-1&quot;&gt;Why do we need a Custom NER?&lt;/h2&gt;
&lt;p&gt;SpaCy pre-trained models detect and categorize the text chunks into 18 types of entities. If the user requirement is to extract information from job postings, the above pre-trained model will not provide any support. Let’s see an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
sentence = &amp;quot;&amp;quot;&amp;quot;As a Full Stack Developer, you will develop applications in a very passionate environment being responsible for Front-end and Back-end development. You will perform development and day-to-day maintenance on large applications. You have multiple opportunities to work on cross-system single-page applications.&amp;quot;&amp;quot;&amp;quot;
doc = nlp(sentence)
from spacy import displacy
displacy.render(doc, style=&amp;quot;ent&amp;quot;, jupyter=True)
Out:
UserWarning: [W006] No entities to visualize found in Doc object. If this is surprising to you, make sure the Doc was processed using a model that supports named entity recognition, and check the `doc.ents` property manually if necessary.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The warning says that no entities were found in the Doc object.&lt;/p&gt;
&lt;p&gt;This is where the custom NER model comes into the picture for our custom problem statement i.e., detecting the &lt;strong&gt;job_role&lt;/strong&gt; from the job posts.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/YIttXpTnx7-480.webp 480w, https://turbolab.in/img/YIttXpTnx7-960.webp 960w, https://turbolab.in/img/YIttXpTnx7-1401.webp 1401w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/YIttXpTnx7-480.jpeg&quot; alt=&quot;&quot; width=&quot;1401&quot; height=&quot;266&quot; srcset=&quot;https://turbolab.in/img/YIttXpTnx7-480.jpeg 480w, https://turbolab.in/img/YIttXpTnx7-960.jpeg 960w, https://turbolab.in/img/YIttXpTnx7-1401.jpeg 1401w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;Steps to build the custom NER model for detecting the job role in job postings in spaCy 3.0:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Annotate the data to train the model.&lt;/li&gt;
&lt;li&gt;Convert the annotated data into the spaCy bin object.&lt;/li&gt;
&lt;li&gt;Generate the config file from the spaCy website.&lt;/li&gt;
&lt;li&gt;Train the model in the command line.&lt;/li&gt;
&lt;li&gt;Load and test the saved model.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We will discuss the above steps in detail.&lt;/p&gt;
&lt;h3 id=&quot;spacy-ner-annotation-tool-by-agateteam&quot; tabindex=&quot;-1&quot;&gt;SpaCy NER annotation tool by agateteam&lt;/h3&gt;
&lt;p&gt;The agateteam provides a lightweight &lt;a href=&quot;http://agateteam.org/spacynerannotate/&quot;&gt;&lt;em&gt;&lt;strong&gt;annotation tool&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; to generate the spaCy-supported annotated data format.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/IdH2sIMIn--480.webp 480w, https://turbolab.in/img/IdH2sIMIn--960.webp 960w, https://turbolab.in/img/IdH2sIMIn--1600.webp 1600w, https://turbolab.in/img/IdH2sIMIn--1905.webp 1905w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/IdH2sIMIn--480.gif&quot; alt=&quot;&quot; width=&quot;1905&quot; height=&quot;975&quot; srcset=&quot;https://turbolab.in/img/IdH2sIMIn--480.gif 480w, https://turbolab.in/img/IdH2sIMIn--960.gif 960w, https://turbolab.in/img/IdH2sIMIn--1600.gif 1600w, https://turbolab.in/img/IdH2sIMIn--1905.gif 1905w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Annotation of a sentence is shown in the above gif. We have shown the &lt;strong&gt;job_role&lt;/strong&gt; tagging; you can add &lt;strong&gt;work_experience&lt;/strong&gt;, &lt;strong&gt;work_location&lt;/strong&gt;, &lt;strong&gt;experience&lt;/strong&gt; to the entity list. Here is the sample annotated data:&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/DHE8oS4vlS-480.webp 480w, https://turbolab.in/img/DHE8oS4vlS-960.webp 960w, https://turbolab.in/img/DHE8oS4vlS-1333.webp 1333w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/DHE8oS4vlS-480.jpeg&quot; alt=&quot;&quot; width=&quot;1333&quot; height=&quot;502&quot; srcset=&quot;https://turbolab.in/img/DHE8oS4vlS-480.jpeg 480w, https://turbolab.in/img/DHE8oS4vlS-960.jpeg 960w, https://turbolab.in/img/DHE8oS4vlS-1333.jpeg 1333w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h3 id=&quot;convert-the-annotated-data-into-the-spacy-bin-object&quot; tabindex=&quot;-1&quot;&gt;Convert the annotated data into the spaCy bin object&lt;/h3&gt;
&lt;p&gt;In spaCy 2.x, we can use this raw data to train a model. But, in spaCy 3.x, we need to convert it to a doc bin object. Consider this: we assign the above-annotated data to the variable called &lt;strong&gt;trainData&lt;/strong&gt;. We can convert it using the function below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import spacy
from spacy.tokens import DocBin
from tqdm import tqdm
nlp = spacy.blank(&amp;quot;en&amp;quot;) # load a new spacy model
db = DocBin() # create a DocBin object
for text, annot in tqdm(trainData): # data in previous format
    doc = nlp.make_doc(text) # create doc object from text
    ents = []
    for start, end, label in annot[&amp;quot;entities&amp;quot;]: # add character indexes
        span = doc.char_span(start, end, label=label, alignment_mode=&amp;quot;contract&amp;quot;)
        if span is None:
            print(&amp;quot;Skipping entity&amp;quot;)
        else:
            ents.append(span)
    try:
        doc.ents = ents # label the text with the ents
        db.add(doc)
    except:
        print(text, annot)
db.to_disk(&amp;quot;./train.spacy&amp;quot;) # save the docbin object
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we have the trainData saved as &lt;strong&gt;train.spacy&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;generate-the-config-file-to-train-via-command-line&quot; tabindex=&quot;-1&quot;&gt;Generate the config file to train via Command line&lt;/h3&gt;
&lt;p&gt;spaCy train from the command line is the recommended way to train our spaCy pipelines. &lt;em&gt;&lt;strong&gt;config.cfg&lt;/strong&gt;&lt;/em&gt; includes all settings and hyperparameters. If necessary, we can overwrite it.&lt;/p&gt;
&lt;p&gt;Go to the spaCy training &lt;strong&gt;&lt;a href=&quot;https://spacy.io/usage/training&quot;&gt;&lt;em&gt;link&lt;/em&gt;&lt;/a&gt;&lt;/strong&gt; and follow the steps below:&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/n8tnlA5yzW-480.webp 480w, https://turbolab.in/img/n8tnlA5yzW-960.webp 960w, https://turbolab.in/img/n8tnlA5yzW-1288.webp 1288w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/n8tnlA5yzW-480.gif&quot; alt=&quot;&quot; width=&quot;1288&quot; height=&quot;868&quot; srcset=&quot;https://turbolab.in/img/n8tnlA5yzW-480.gif 480w, https://turbolab.in/img/n8tnlA5yzW-960.gif 960w, https://turbolab.in/img/n8tnlA5yzW-1288.gif 1288w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Select the preferred language and component as &lt;strong&gt;ner&lt;/strong&gt;. As per your system requirement, you can choose CPU/GPU. You can save this configuration as &lt;strong&gt;base_config.cfg&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To fill the remaining system defaults, run this command on the command line to generate the &lt;em&gt;&lt;strong&gt;config.cfg&lt;/strong&gt;&lt;/em&gt; file*.*&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python -m spacy init fill-config base_config.cfg config.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;training-the-model-using-the-command-line&quot; tabindex=&quot;-1&quot;&gt;Training the model using the command line&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;[paths]
train = ./train.spacy
dev = ./dev.spacy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can specify the train, dev, and output file paths in the config file. The batch size, max steps, epochs, patience, etc can also be specified in the config file.&lt;/p&gt;
&lt;p&gt;Now that we have the config file and train data, let’s train the model using the command line.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/ePmj1jB6jV-480.webp 480w, https://turbolab.in/img/ePmj1jB6jV-960.webp 960w, https://turbolab.in/img/ePmj1jB6jV-1299.webp 1299w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/ePmj1jB6jV-480.gif&quot; alt=&quot;&quot; width=&quot;1299&quot; height=&quot;866&quot; srcset=&quot;https://turbolab.in/img/ePmj1jB6jV-480.gif 480w, https://turbolab.in/img/ePmj1jB6jV-960.gif 960w, https://turbolab.in/img/ePmj1jB6jV-1299.gif 1299w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;The model output will be saved in the specified folder as an argument at the command line.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/sVePOjc0TN-480.webp 480w, https://turbolab.in/img/sVePOjc0TN-948.webp 948w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/sVePOjc0TN-480.jpeg&quot; alt=&quot;&quot; width=&quot;948&quot; height=&quot;464&quot; srcset=&quot;https://turbolab.in/img/sVePOjc0TN-480.jpeg 480w, https://turbolab.in/img/sVePOjc0TN-948.jpeg 948w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h3 id=&quot;load-test-the-model&quot; tabindex=&quot;-1&quot;&gt;Load &amp;amp; Test the model&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Load the model.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;import spacy
nlp = spacy.load(&amp;quot;output/model-last/&amp;quot;) #load the model
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Take the unseen data to test the model prediction.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;sentence = &amp;quot;&amp;quot;&amp;quot;We are looking for a Backend Developer who has 4-6 years of experience in designing, developing and implementing backend services using Python and Django.&amp;quot;&amp;quot;&amp;quot;
doc = nlp(sentence)
from spacy import displacy
displacy.render(doc, style=&amp;quot;ent&amp;quot;, jupyter=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Out:&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/2tvxhg-d-r-480.webp 480w, https://turbolab.in/img/2tvxhg-d-r-960.webp 960w, https://turbolab.in/img/2tvxhg-d-r-1239.webp 1239w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/2tvxhg-d-r-480.jpeg&quot; alt=&quot;&quot; width=&quot;1239&quot; height=&quot;96&quot; srcset=&quot;https://turbolab.in/img/2tvxhg-d-r-480.jpeg 480w, https://turbolab.in/img/2tvxhg-d-r-960.jpeg 960w, https://turbolab.in/img/2tvxhg-d-r-1239.jpeg 1239w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Backend Developer&lt;/strong&gt; is predicted as a &lt;strong&gt;job_role&lt;/strong&gt; by the model.&lt;/p&gt;
&lt;h2 id=&quot;applications-of-ner&quot; tabindex=&quot;-1&quot;&gt;Applications of NER:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Enables Recommendation Systems.&lt;/li&gt;
&lt;li&gt;Simplify Customer Support.&lt;/li&gt;
&lt;li&gt;Classify the data of News Sources.&lt;/li&gt;
&lt;li&gt;Optimizing the Search Engine Algorithms.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;endnote&quot; tabindex=&quot;-1&quot;&gt;EndNote:&lt;/h2&gt;
&lt;p&gt;We have taken just 10 records to train the model. For better accuracy and precision, we need to have a huge amount of annotated data to train a model.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Stemming Vs. Lemmatization with Python NLTK</title>
    <link href="https://turbolab.in/stemming-vs-lemmatization-with-python-nltk/"/>
    <updated>2021-11-16T05:58:09.000Z</updated>
    <published>2021-10-29T17:00:31.000Z</published>
    <id>https://turbolab.in/stemming-vs-lemmatization-with-python-nltk/</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;Stemming&lt;/strong&gt; and &lt;strong&gt;Lemmatization&lt;/strong&gt; are text/word normalization techniques widely used in text pre-processing. They basically reduce the words to their root form. Here is an example:&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/7XxFL_M7fY-408.webp 408w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/7XxFL_M7fY-408.jpeg&quot; alt=&quot;&quot; width=&quot;408&quot; height=&quot;244&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Let’s say you have to train the data for classification and you are choosing any vectorizer to transform your data. These vectorizers create a vocabulary(set of unique words) from our data corpus. By applying stemming/lemmatization techniques, we can reduce the vocabulary size by converting the words to their base forms. This will make the vocabulary more distinct and will reduce the ambiguity for the model to train and yield better results.&lt;/p&gt;
&lt;p&gt;In this post, we will discuss the practical examples of how stemming and lemmatization can be done on words and sentences using the python &lt;strong&gt;nltk&lt;/strong&gt; package.&lt;/p&gt;
&lt;h2 id=&quot;stemming&quot; tabindex=&quot;-1&quot;&gt;Stemming&lt;/h2&gt;
&lt;p&gt;Stemming is a rule-based normalization approach as it slices the word’s prefix and suffix to reduce them to its root form. Stemming is faster compared to lemmatization as it cuts the prefixes(pre-, extra-, in-, im-, ir-, etc.)  and suffixes(ed-, ing-, es-, -ity, -ty, -ship, -ness, etc.) without considering the context of the words. &lt;strong&gt;Due to its aggressiveness, there is a possibility that the outcome from the stemming algorithm may not be a valid word&lt;/strong&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/z46WpHTGmF-480.webp 480w, https://turbolab.in/img/z46WpHTGmF-487.webp 487w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/z46WpHTGmF-480.jpeg&quot; alt=&quot;&quot; width=&quot;487&quot; height=&quot;295&quot; srcset=&quot;https://turbolab.in/img/z46WpHTGmF-480.jpeg 480w, https://turbolab.in/img/z46WpHTGmF-487.jpeg 487w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;In the above example, you can see that the outcomes of &lt;strong&gt;badly&lt;/strong&gt; and &lt;strong&gt;pharmacies&lt;/strong&gt; are invalid words.&lt;/p&gt;
&lt;h3 id=&quot;porter-stemmer&quot; tabindex=&quot;-1&quot;&gt;Porter Stemmer&lt;/h3&gt;
&lt;p&gt;The Porter stemming algorithm (or “Porter stemmer”) uses suffix-stemming to produce stems. Here is a python code using nltk to create a stemmer object and generate results.&lt;/p&gt;
&lt;p&gt;Code Snippet to perform Porter Stemming:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
from nltk.stem import PorterStemmer
words = [&amp;quot;plays&amp;quot;, &amp;quot;playing&amp;quot;, &amp;quot;played&amp;quot;, &amp;quot;player&amp;quot;, &amp;quot;pharmacies&amp;quot;, &amp;quot;badly&amp;quot;]
ps = PorterStemmer()
print([ps.stem(w) for w in words])
Out:
[&#39;play&#39;, &#39;play&#39;, &#39;play&#39;, &#39;player&#39;, &#39;pharmaci&#39;, &#39;badli&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Observing the drawbacks of PorterStemmer, the Snowball Stemming algorithm was introduced.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;snowball-stemmer&quot; tabindex=&quot;-1&quot;&gt;Snowball Stemmer&lt;/h3&gt;
&lt;p&gt;This Snowball Stemming Algorithm is also known as Porter2 Stemmer. It is the best version of Porter Stemmer in which a few of the above-discussed stemming issues are resolved.&lt;/p&gt;
&lt;p&gt;Code Snippet to perform Snowball Stemming:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
from nltk.stem.snowball import SnowballStemmer
words = [&amp;quot;plays&amp;quot;, &amp;quot;playing&amp;quot;, &amp;quot;played&amp;quot;, &amp;quot;player&amp;quot;, &amp;quot;pharmacies&amp;quot;, &amp;quot;badly&amp;quot;]
ss = SnowballStemmer(language=&#39;english&#39;)
print([ss.stem(w) for w in words])
Out:
[&#39;play&#39;, &#39;play&#39;, &#39;play&#39;, &#39;player&#39;, &#39;pharmaci&#39;, &#39;bad&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, we can see that the word “&lt;em&gt;&lt;strong&gt;badly&lt;/strong&gt;&lt;/em&gt;” is a valid stem, but the word “&lt;em&gt;&lt;strong&gt;pharmacies&lt;/strong&gt;&lt;/em&gt;” is still an invalid stem.&lt;/p&gt;
&lt;h3 id=&quot;lancaster-stemmer&quot; tabindex=&quot;-1&quot;&gt;Lancaster Stemmer&lt;/h3&gt;
&lt;p&gt;Compared to snowball and porter stemming, lancaster is the most aggressive stemming algorithm because it tends to over-stem a lot of words. It tries to reduce the word to the shortest stem possible. Here is an example:&lt;/p&gt;
&lt;p&gt;Here is an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;salty&amp;quot; —- &amp;quot;sal&amp;quot;
&amp;quot;sales&amp;quot; —- &amp;quot;sal&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Code Snippet to perform Lancaster Stemming:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
from nltk.stem import LancasterStemmer
words = [&amp;quot;plays&amp;quot;, &amp;quot;playing&amp;quot;, &amp;quot;played&amp;quot;, &amp;quot;player&amp;quot;, &amp;quot;pharmacies&amp;quot;, &amp;quot;badly&amp;quot;]
ls = LancasterStemmer()
print([ls.stem(w) for w in words])
Out:
[&#39;play&#39;, &#39;play&#39;, &#39;play&#39;, &#39;play&#39;, &#39;pharm&#39;, &#39;bad&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As mentioned in the beginning, we can reduce the vocabulary and maintain more unique words by stemming.&lt;/p&gt;
&lt;p&gt;Code snippet to perform tokenization and stemming on a paragraph:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;content = &amp;quot;China&#39;s Huawei overtook Samsung Electronics as the world&#39;s biggest seller of mobile phones in the second quarter of 2020, shipping 55.8 million devices compared to Samsung&#39;s 53.7 million, according to data from research firm Canalys. While Huawei&#39;s sales fell 5 per cent from the same quarter a year earlier, South Korea&#39;s Samsung posted a bigger drop of 30 per cent, owing to disruption from the coronavirus in key markets such as Brazil, the United States and Europe, Canalys said. Huawei&#39;s overseas shipments fell 27 per cent in Q2 from a year earlier, but the company increased its dominance of the China market which has been faster to recover from COVID-19 and where it now sells over 70 per cent of its phones. &amp;quot;Our business has demonstrated exceptional resilience in these difficult times,&amp;quot; a Huawei spokesman said. &amp;quot;Amidst a period of unprecedented global economic slowdown and challenges, we&#39;re continued to grow and further our leadership position.&amp;quot; Nevertheless, Huawei&#39;s position as number one seller may prove short-lived once other markets recover given it is mainly due to economic disruption, a senior Huawei employee with knowledge of the matter told Reuters. Apple is due to release its Q2 iPhone shipment data on Friday.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above content will hereafter be used as the input to the code snippets.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
from nltk.stem import PorterStemmer
from nltk.tokenize import word_tokenize
ps = PorterStemmer()
# Porter Stemmed version
porteredContent = [ps.stem(word) for word in word_tokenize(content)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Try testing the above code snippet by replacing the Porter stemmer with Snowball and Lancaster stemmers.&lt;/p&gt;
&lt;p&gt;Let us throw some statistics to compare these three stemming algorithms.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Length of the content is 1041(without spaces)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Length of the content after Porter Stemmer is 943 which took around 0.00499 seconds to process&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Length of the content after Snowball Stemmer is 944 which took around 0.00399 seconds to process&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Length of the content after Lancaster Stemmer is 835 which took around 0.00399 seconds to process&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Obviously, Lancaster Stemmer will have less content length because of its aggressive over-stemming nature. With all the three stemmers discussed above, we weren’t able to get the root word of “&lt;strong&gt;pharmacies”&lt;/strong&gt;. We will now move on to lemmatization since stemming didn’t get us the valid stem word in all cases. While stemming is fast, it is not 100% accurate.&lt;/p&gt;
&lt;h2 id=&quot;lemmatization&quot; tabindex=&quot;-1&quot;&gt;Lemmatization&lt;/h2&gt;
&lt;p&gt;In Lemmatization, the parts of speech(POS) will be determined first, unlike stemming which stems the word to its root form without considering the context. Lemmatization always considers the context and converts the word to its meaningful root/dictionary(WordNet) form called Lemma.&lt;/p&gt;
&lt;h3 id=&quot;wordnet-lemmatizer&quot; tabindex=&quot;-1&quot;&gt;WordNet Lemmatizer&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;WordNet&lt;/strong&gt; is a lexical database (a collection of words) that has been used by major search engines and IR research projects for many years. It offers lemmatization capabilities as well and is one of the earliest and most commonly used lemmatizers.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
from nltk.stem import WordNetLemmatizer
words = [&amp;quot;plays&amp;quot;, &amp;quot;playing&amp;quot;, &amp;quot;played&amp;quot;, &amp;quot;player&amp;quot;, &amp;quot;pharmacies&amp;quot;, &amp;quot;badly&amp;quot;]
lemmatizer = WordNetLemmatizer()
print([lemmatizer.lemmatize(word) for word in words])
Out:
[&#39;play&#39;, &#39;playing&#39;, &#39;played&#39;, &#39;player&#39;, &#39;pharmacy&#39;, &#39;badly&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, we can see that only “&lt;strong&gt;plays&lt;/strong&gt;” and most anticipated “&lt;strong&gt;pharmacies&lt;/strong&gt;” have been converted to their root forms while the remaining words are not. Without the POS tag, WordNet Lemmatizer assumes every word as a noun. We need to pass a respective POS tag along with the word to the WordNet Lemmatizer.&lt;/p&gt;
&lt;h3 id=&quot;wordnet-lemmatizer-with-pos-tag&quot; tabindex=&quot;-1&quot;&gt;WordNet Lemmatizer with POS tag:&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;In:
word = &amp;quot;better&amp;quot;
print(lemmatizer.lemmatize(word, pos=&amp;quot;n&amp;quot;)) # n for noun and it is default
print(lemmatizer.lemmatize(word, pos=&amp;quot;a&amp;quot;)) # a for adjective
print(lemmatizer.lemmatize(word, pos=&amp;quot;v&amp;quot;)) # v for verb
print(lemmatizer.lemmatize(word, pos=&amp;quot;r&amp;quot;)) # r for adverb
Out:
better | good | better | well
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For the word “&lt;strong&gt;better”&lt;/strong&gt;, the output is not the same when the POS is an adjective and an adverb.&lt;/p&gt;
&lt;p&gt;Now, determining the POS for the word will be an extra task for the lemmatization process. When we are converting a large number of text chunks, it will be difficult to pass a POS tag for each word – we need to automate the fetching of POS tags for each word we lemmatize. Here is a function for that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
import nltk
from nltk.corpus import wordnet
def getWordNetPOS(word):
     tag = nltk.pos_tag([word])[0][1][0].upper()
     tagDict = {&amp;quot;J&amp;quot;: wordnet.ADJ,
     &amp;quot;N&amp;quot;: wordnet.NOUN,
     &amp;quot;V&amp;quot;: wordnet.VERB,
     &amp;quot;R&amp;quot;: wordnet.ADV}
    return tagDict.get(tag, wordnet.NOUN)
Out:
getWordNetPOS(&amp;quot;better&amp;quot;) — &amp;quot;r&amp;quot;
get_wordnet_pos(&amp;quot;play&amp;quot;) — &amp;quot;n&amp;quot;
get_wordnet_pos(&amp;quot;bad&amp;quot;) — &amp;quot;a&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Code Snippet to perform WordNet Lemmatization with POS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;In:
from nltk.stem import WordNetLemmatizer
words = [&amp;quot;plays&amp;quot;, &amp;quot;playing&amp;quot;, &amp;quot;played&amp;quot;, &amp;quot;player&amp;quot;, &amp;quot;pharmacies&amp;quot;, &amp;quot;badly&amp;quot;]
lemmatizer = WordNetLemmatizer()
print([lemmatizer.lemmatize(word, get_wordnet_pos(word)) for word in words])
Out:
[&#39;play&#39;, &#39;play&#39;, &#39;played&#39;, &#39;player&#39;, &#39;pharmacy&#39;, &#39;badly&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Spacy Lemmatizer, TextBlob Lemmatizer, Stanford CoreNLP Lemmatizer, Gensim Lemmatizer are the other lemmatizers that can be tried. With a spacy lemmatizer, lemmatization can be done without passing any POS tag.&lt;/p&gt;
&lt;p&gt;Code snippet to perform lemmatization on a paragraph:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from nltk.tokenize import word_tokenize
from nltk.stem import WordNetLemmatizer
wordnetContent = [lemmatizer.lemmatize(word, get_wordnet_pos(word)) for word in word_tokenize(content)] # content defined earlier
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Time taken to process this content on WordNet Lemmatizer is &lt;strong&gt;0.2234&lt;/strong&gt; seconds which is a lot higher when compared to stemming.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Stemming and Lemmatization both generate the root/base form of the word. The only difference is that the stem may not be an actual word whereas the lemma is a meaningful word.&lt;/p&gt;
&lt;p&gt;Compared to stemming, lemmatization is slow but helps to train the accurate ML model. If your data is huge, then snowball stemmer(porter2) is a better alternative. If your ML model uses a count vectorizer and it doesn’t bother with the context of the words/sentences, then stemming is the best process that can be considered.&lt;/p&gt;
&lt;p&gt;For deep learning models and word embeddings in use, lemmatization is the perfect choice because you will not find word embeddings for invalid stem words.&lt;/p&gt;
&lt;p&gt;We recommend you try other methods of lemmatization provided by Spacy, Textblob, Gensim, and Stanford core NLP.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Text Classification using Machine Learning</title>
    <link href="https://turbolab.in/text-classification-using-machine-learning/"/>
    <updated>2021-12-03T05:35:57.000Z</updated>
    <published>2021-10-15T13:11:59.000Z</published>
    <id>https://turbolab.in/text-classification-using-machine-learning/</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;Machine Learning, Deep Learning&lt;/strong&gt;, &lt;strong&gt;Artificial Intelligence&lt;/strong&gt; are the popular buzzwords in present trends.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Artificial Intelligence(AI)&lt;/strong&gt; is the branch of computer science which deals with developing intelligence artificially to the machines which are able to think, act and behave like humans.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Machine Learning(ML)&lt;/strong&gt; is a subset of &lt;strong&gt;AI&lt;/strong&gt; and is the way to implement artificial intelligence. It is the statistical approach where each instance in a data-set is described by a set of features or attributes. Feature Extraction is key in &lt;strong&gt;ML&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Deep Learning(DL)&lt;/strong&gt; is the next evolution and subset of &lt;strong&gt;ML&lt;/strong&gt;. It is a method of statistical learning that extracts features or attributes from raw data. &lt;strong&gt;DL&lt;/strong&gt; uses a network of algorithms called artificial neural networks which imitates the function of the human neural networks present in the brain. &lt;strong&gt;DL&lt;/strong&gt; takes the data into a network of layers(Input, Hidden &amp;amp; Output) to extract the features and to learn from the data. Let’s end about the &lt;strong&gt;DL&lt;/strong&gt; here – We will discuss more in the coming blogs.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/xEYDSnKwpR-480.webp 480w, https://turbolab.in/img/xEYDSnKwpR-960.webp 960w, https://turbolab.in/img/xEYDSnKwpR-1000.webp 1000w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/xEYDSnKwpR-480.png&quot; alt=&quot;&quot; width=&quot;1000&quot; height=&quot;1204&quot; srcset=&quot;https://turbolab.in/img/xEYDSnKwpR-480.png 480w, https://turbolab.in/img/xEYDSnKwpR-960.png 960w, https://turbolab.in/img/xEYDSnKwpR-1000.png 1000w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;outline&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;In &lt;strong&gt;ML/DL&lt;/strong&gt;, there are models that fall into different categories like supervised, unsupervised &amp;amp; reinforcement learning. In this tutorial, we will discuss Supervised learning which involves an output label associated with each instance in the data-set.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/AbbYVpJeKs-480.webp 480w, https://turbolab.in/img/AbbYVpJeKs-711.webp 711w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/AbbYVpJeKs-480.png&quot; alt=&quot;&quot; width=&quot;711&quot; height=&quot;335&quot; srcset=&quot;https://turbolab.in/img/AbbYVpJeKs-480.png 480w, https://turbolab.in/img/AbbYVpJeKs-711.png 711w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Supervised Learning Model Flow Chart&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Text(Document) Classification&lt;/strong&gt;/T&lt;strong&gt;ext(Document) Categorization&lt;/strong&gt; is one of the important and typical tasks in supervised &lt;strong&gt;ML&lt;/strong&gt;. This technique allows machines to understand and then categorize text into known organized groups.&lt;/p&gt;
&lt;p&gt;In this post, we will look into the supervised learning technique of how classification on the document dataset can be approached with &lt;strong&gt;ML&lt;/strong&gt; algorithms.&lt;/p&gt;
&lt;p&gt;Some of the &lt;strong&gt;ML&lt;/strong&gt; algorithms are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Naive Bayes.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decision Trees.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logistic Regression &lt;em&gt;(Linear Model)&lt;/em&gt;.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support Vector Machines &lt;em&gt;(SVM)&lt;/em&gt;.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Random Forest.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;K-Means Clustering.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;K-Nearest Neighbour.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gaussian Mixture Model.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hidden Markov Model.&lt;/strong&gt; &lt;em&gt;et cetera&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Among these &lt;strong&gt;ML&lt;/strong&gt; Algorithms, we will discuss how the &lt;strong&gt;Naive Bayes&lt;/strong&gt;, &lt;strong&gt;Logistic Regression&lt;/strong&gt; and &lt;strong&gt;SVM&lt;/strong&gt; classifier models perform on the data-set feature vectors.&lt;/p&gt;
&lt;h2 id=&quot;dataset&quot; tabindex=&quot;-1&quot;&gt;Dataset&lt;/h2&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/t84lfYsEq9-480.webp 480w, https://turbolab.in/img/t84lfYsEq9-613.webp 613w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/t84lfYsEq9-480.jpeg&quot; alt=&quot;news dataset&quot; width=&quot;613&quot; height=&quot;691&quot; srcset=&quot;https://turbolab.in/img/t84lfYsEq9-480.jpeg 480w, https://turbolab.in/img/t84lfYsEq9-613.jpeg 613w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;news dataset&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Categorized the data-set with the above 10 categories with each category of 1000 entries with &lt;strong&gt;content&lt;/strong&gt; and &lt;strong&gt;label&lt;/strong&gt; as two columns. I would call this dataset a dataframe(&lt;strong&gt;df&lt;/strong&gt;) hereafter in the following code snippets.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/xdNAoFIiEr-480.webp 480w, https://turbolab.in/img/xdNAoFIiEr-512.webp 512w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/xdNAoFIiEr-480.jpeg&quot; alt=&quot;dataset&quot; width=&quot;512&quot; height=&quot;442&quot; srcset=&quot;https://turbolab.in/img/xdNAoFIiEr-480.jpeg 480w, https://turbolab.in/img/xdNAoFIiEr-512.jpeg 512w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;dataset&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;data-cleaning&quot; tabindex=&quot;-1&quot;&gt;Data Cleaning&lt;/h2&gt;
&lt;p&gt;Pre-processing of data will have an impact on the output ie., the accuracy, performance of the model. Some of the data-cleaning steps are as follows&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Removing Stop Words. (&lt;strong&gt;NLTK&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Performing Stemming on the text. (&lt;strong&gt;NLTK&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Removing special characters &amp;amp; extra spaces or keeping only Alpha-Numeric characters in the text.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;# NLTK python module for stemming and stopwords removal
from nltk.stem.snowball import SnowballStemmer
from nltk.corpus import stopwords
import string, re
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;stemmer = SnowballStemmer(&#39;english&#39;) # stemmer
t = str.maketrans(dict.fromkeys(string.punctuation)) # special char removal
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;def clean_text(text):  
    ## Remove Punctuation
    text = text.translate(t) 
    text = text.split()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;    ## Remove stop words
    stops = set(stopwords.words(&amp;quot;english&amp;quot;))
    text = [stemmer.stem(w) for w in text if not w in stops]
    
    text = &amp;quot; &amp;quot;.join(text)
    text = re.sub(&#39; +&#39;,&#39; &#39;, text) # extra consecutive space removal 
    return text

df[&amp;quot;content&amp;quot;] = df[&amp;quot;content&amp;quot;].apply(clean_text)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This data cleaning part is optional – one can test the model accuracy with and without the data cleaning. Removing stop words and performing stemming can take away the context essence from the data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stemming removes or stems the last few characters of a word&lt;/strong&gt;, often leading to meaningless words. Lemmatization considers the context and converts the word to its meaningful base form, which is called Lemma.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/x90rZs3_Ba-380.webp 380w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/x90rZs3_Ba-380.jpeg&quot; alt=&quot;&quot; width=&quot;380&quot; height=&quot;82&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;lemmatization Vs Stemming&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;We have performed the stemming and stop word removal on the &lt;strong&gt;df&lt;/strong&gt; before the data transformation process.&lt;/p&gt;
&lt;h2 id=&quot;data-transformation&quot; tabindex=&quot;-1&quot;&gt;Data Transformation&lt;/h2&gt;
&lt;p&gt;Transforming the data into feature vectors with the following methods&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Count Vectorization.&lt;/li&gt;
&lt;li&gt;TF-IDF Word Vectorization.&lt;/li&gt;
&lt;li&gt;TF-IDF N-Gram Vectorization.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We recommend you go through these feature extraction methods which are explained in detail in one of our &lt;strong&gt;&lt;a href=&quot;https://turbolab.in/feature-extraction-in-natural-language-processing-nlp/&quot;&gt;blogs.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Dataset(**df)**has been split into train and validate samples in the range of 75 and 25% respectively by sklearn’s &lt;strong&gt;train_test_split&lt;/strong&gt; function.&lt;/p&gt;
&lt;p&gt;Code Snippet to transform data into vectors using the &lt;strong&gt;scikit-learn&lt;/strong&gt;(sklearn) module.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from sklearn import model_selection, preprocessing
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&#39;&#39;&#39;Assume df is the dataset with columns &amp;quot;content&amp;quot; and &amp;quot;label&amp;quot;&#39;&#39;&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# split the data into training and validation
train_x, valid_x, train_y, valid_y = model_selection.train_test_split(df[&#39;content&#39;], df[&#39;label&#39;])
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# label encode the target variable 
encoder = preprocessing.LabelEncoder()
train_y = encoder.fit_transform(train_y)
valid_y = encoder.fit_transform(valid_y)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# count vectorization 
count_vect = CountVectorizer(analyzer=&#39;word&#39;, token_pattern=r&#39;&#92;w{1,}&#39;)
count_vect.fit(df[&#39;content&#39;])
xtrain_count = count_vect.transform(train_x)
xvalid_count = count_vect.transform(valid_x)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# word level tf-idf vectorization
tfidf_vect = TfidfVectorizer(analyzer=&#39;word&#39;, token_pattern=r&#39;&#92;w{1,}&#39;, max_features=5000)
tfidf_vect.fit(df[&#39;content&#39;])
xtrain_tfidf = tfidf_vect.transform(train_x)
xvalid_tfidf = tfidf_vect.transform(valid_x)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# ngram level tf-idf vectorization
tfidf_vect_ngram = TfidfVectorizer(analyzer=&#39;word&#39;, token_pattern=r&#39;&#92;w{1,}&#39;, ngram_range=(2,3), max_features=5000)
tfidf_vect_ngram.fit(df[&#39;content&#39;])
xtrain_tfidf_ngram = tfidf_vect_ngram.transform(train_x)
xvalid_tfidf_ngram = tfidf_vect_ngram.transform(valid_x)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;training-with-naive-bayes-logistic-regression-and-svm&quot; tabindex=&quot;-1&quot;&gt;Training with Naive Bayes, Logistic Regression, and SVM&lt;/h2&gt;
&lt;p&gt;We use Naive Bayes, Logistic Regression, and SVM algorithms to train the data-set feature vectors to form classifier models that are used for prediction.&lt;/p&gt;
&lt;p&gt;From the above data transformation snippet, we have respective train and validation vectorization objects along with their label encoder values. We will use them here to fit the respective classifier and predict the model using the validation sample dataset.&lt;/p&gt;
&lt;p&gt;This report_generation function is the common function used by the three ML Algorithms to predict validation data and pass the model’s accuracy.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from sklearn import linear_model, naive_bayes, svm, metrics
from sklearn.metrics import classification_report

target_names = list(encoder.classes_) # output labels for report generation
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;def report_generation(classifier, train_data, valid_data, train_y, valid_y):
   classifier.fit(train_data, train_y)
   predictions = classifier.predict(valid_data)
   print(&amp;quot;Accuracy :&amp;quot;, metrics.accuracy_score(predictions, valid_y))
   report = classification_report(valid_y, predictions, output_dict=True, target_names=target_names)
   return report
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;naive-bayes&quot; tabindex=&quot;-1&quot;&gt;Naive Bayes&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# Naive Bayes
classifier = naive_bayes.MultinomialNB()
report = report_generation(classifier, xtrain_count, xvalid_count, train_y, valid_y)
print(&amp;quot;NB Count Vectorizer Report :&amp;quot;, report[&#39;weighted avg&#39;])

# Results
Accuracy : 0.9436
NB Count Vectorizer Report : {&#39;precision&#39;: 0.9448178637882411, &#39;recall&#39;: 0.9436, &#39;f1-score&#39;: 0.9434664656369504, &#39;support&#39;: 2500}

report = report_generation(classifier, xtrain_tfidf, xvalid_tfidf, train_y, valid_y)
print(&amp;quot;NB TFIDF-Word Report :&amp;quot;, report[&#39;weighted avg&#39;])

# Results
Accuracy : 0.9416
NB Count Vectorizer Report : {&#39;precision&#39;: 0.9430346010709252, &#39;recall&#39;: 0.9416, &#39;f1-score&#39;: 0.9416037073783431, &#39;support&#39;: 2500}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;report = report_generation(classifier, xtrain_tfidf_ngram, xvalid_tfidf_ngram, train_y, valid_y)
print(&amp;quot;NB TFIDF-NGram Report :&amp;quot;, report[&#39;weighted avg&#39;])

# Results
Accuracy : 0.9208
NB Count Vectorizer Report : {&#39;precision&#39;: 0.9233051466162964, &#39;recall&#39;: 0.9208, &#39;f1-score&#39;: 0.9206511260527037, &#39;support&#39;: 2500}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;logistic-regression&quot; tabindex=&quot;-1&quot;&gt;Logistic Regression&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# Logistic Regression
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;classifier = linear_model.LogisticRegression()    
report = report_generation(classifier, xtrain_count, xvalid_count, train_y, valid_y)    
print(&amp;quot;LogisticRegression Count Vectorizer Report :&amp;quot;, report[&#39;weighted avg&#39;])

# Results
Accuracy : 0.9804
LogisticRegression Count Vectorizer Report : {&#39;precision&#39;: 0.9806682334322502, &#39;recall&#39;: 0.9804, &#39;f1-score&#39;: 0.9804527264151257, &#39;support&#39;: 2500}

report = report_generation(classifier, xtrain_tfidf, xvalid_tfidf, train_y, valid_y) 
print(&amp;quot;LogisticRegression TFIDF-Word Report :&amp;quot;, report[&#39;weighted avg&#39;])

# Results
Accuracy : 0.9792
LogisticRegression TFIDF-Word Report : {&#39;precision&#39;: 0.9794911617869886, &#39;recall&#39;: 0.9792, &#39;f1-score&#39;: 0.9792657461379974, &#39;support&#39;: 2500}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;report = report_generation(classifier, xtrain_tfidf_ngram, xvalid_tfidf_ngram, train_y, valid_y)    
print(&amp;quot;LogisticRegression TFIDF-NGram Report :&amp;quot;, report[&#39;weighted avg&#39;])

# Results
Accuracy : 0.932
LogisticRegression TFIDF-NGram Report : {&#39;precision&#39;: 0.9329064009056843, &#39;recall&#39;: 0.932, &#39;f1-score&#39;: 0.9320786137751711, &#39;support&#39;: 2500}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;svm&quot; tabindex=&quot;-1&quot;&gt;SVM&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# Support Vector Machines
    
classifier = svm.SVC(gamma=&amp;quot;scale&amp;quot;)    
report = report_generation(classifier, xtrain_count, xvalid_count, train_y, valid_y)    
print(&amp;quot;SVM Count Vectorizer Report :&amp;quot;, report[&#39;weighted avg&#39;]) 

# Results
Accuracy : 0.9668
SVM Count Vectorizer Report : {&#39;precision&#39;: 0.9687847838287942, &#39;recall&#39;: 0.9668, &#39;f1-score&#39;: 0.9672306318670637, &#39;support&#39;: 2500}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;report = report_generation(classifier, xtrain_tfidf, xvalid_tfidf, train_y, valid_y)    
print(&amp;quot;SVM TFIDF-Word Report :&amp;quot;, report[&#39;weighted avg&#39;]) 

# Results
Accuracy : 0.9804
SVM TFIDF-Word Report : {&#39;precision&#39;: 0.980766234757573, &#39;recall&#39;: 0.9804, &#39;f1-score&#39;: 0.9804795388691244, &#39;support&#39;: 2500}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;report = report_generation(classifier, xtrain_tfidf_ngram, xvalid_tfidf_ngram, train_y, valid_y) 
print(&amp;quot;SVM TFIDF-NGram Report :&amp;quot;, report[&#39;weighted avg&#39;])

# Results
Accuracy : 0.9304
SVM TFIDF-NGram Report : {&#39;precision&#39;: 0.9324797933370057, &#39;recall&#39;: 0.9304, &#39;f1-score&#39;: 0.9306949638900389, &#39;support&#39;: 2500}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;conclusion&lt;/h2&gt;
&lt;p&gt;SVM with TF-IDF Word Vectorizer and Logistic Regression with Count Vectorizer gives better accuracy compared with other ML algorithms tested.&lt;/p&gt;
&lt;p&gt;We recommend you train the model without the data cleaning part to check which ML algorithm works better following the similar approach shown above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; We can not say which model is best here – It all depends on your data. Then, how do we conclude which ML algorithm suits our data?&lt;/p&gt;
&lt;p&gt;Selecting the best model for your &lt;strong&gt;ML&lt;/strong&gt; problem is definitely a difficult task. There is an awesome python library called &lt;strong&gt;Lazy Predict&lt;/strong&gt; which helps to understand which models work better for your data without any parameter tuning. Check out the documentation &lt;strong&gt;&lt;a href=&quot;https://lazypredict.readthedocs.io/en/latest/&quot;&gt;here&lt;/a&gt;&lt;/strong&gt;. In the coming posts, we will discuss the &lt;strong&gt;Lazy Predict&lt;/strong&gt; python module with some examples.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Better Word Embeddings Using GloVe</title>
    <link href="https://turbolab.in/better-word-embeddings-using-glove/"/>
    <updated>2021-10-14T09:11:37.000Z</updated>
    <published>2021-10-14T09:11:37.000Z</published>
    <id>https://turbolab.in/better-word-embeddings-using-glove/</id>
    <content type="html">&lt;p&gt;We talked about word embeddings a bit in our &lt;a href=&quot;https://turbolab.in/feature-extraction-in-natural-language-processing-nlp/&quot;&gt;last article&lt;/a&gt;, using word2vec. Word embeddings are one of the most powerful tools available to NLP developers today, and most NLP tasks will require some kind of word embedding in one of the levels. Thus, it is important to explore them in more detail and see how they work.&lt;/p&gt;
&lt;h2 id=&quot;but-why-do-we-need-word-embeddings&quot; tabindex=&quot;-1&quot;&gt;But Why Do We Need Word Embeddings?&lt;/h2&gt;
&lt;p&gt;Computers understand just numbers, so understanding natural language is a big challenge to it. So, in order to make sense of words, we have to convert them into some kind of numerical representation. In the past, we used some of the primitive methods, like just counting the number of occurrences of the word in a sentence, and then dividing it by the frequencies of other words (count vectorizer and TF-IDF). These methods work fine in trivial use cases, however, we need a more powerful representation for some advanced NLP use cases. These primitive methods also do not take into account the context in the words are used, which is very important in natural language.&lt;/p&gt;
&lt;p&gt;One of the ideas that word embeddings work in is that words that appear together are similar in meaning. For example:&lt;/p&gt;
&lt;p&gt;“It’s a nice day outside”&lt;/p&gt;
&lt;p&gt;“Today was a nice day”.&lt;/p&gt;
&lt;p&gt;Here we gave examples of two sentences. Note that in both sentences, the words &lt;em&gt;nice&lt;/em&gt; and &lt;em&gt;day&lt;/em&gt; appear together. Word vectors will derive that they may be similar in meaning and context.&lt;/p&gt;
&lt;p&gt;If we train this over a large enough corpus, we get close to understanding the context the words are used. We use a matrix of several dimensions to represent these words, thus converting them automatically into a numerical representation.&lt;/p&gt;
&lt;h2 id=&quot;glove-word-embeddings-how-does-it-work&quot; tabindex=&quot;-1&quot;&gt;GloVe Word Embeddings, how does it work?&lt;/h2&gt;
&lt;p&gt;Previously we saw a general idea about word embeddings, in which we said that words that appear together are thought to have the same meaning and context. That may not be the case always, so, instead of just taking words that are just next to each other, we may increase the proximity boundary, and take into account the words which are close to each other. This can be 5 words, 10 words, 15 words, or even more, but an algorithm can automatically optimize the proximity boundary. This is one of the key ideas behind GloVe, which is in short of Global Vectors.&lt;/p&gt;
&lt;p&gt;There are also some common words in English language, such as &lt;em&gt;the, I, at, on&lt;/em&gt;  etc. These words are called stop words. GloVe also takes care that these words are not given too much weight, and less common words also have a chance to form a good vector representation.&lt;/p&gt;
&lt;p&gt;As the last step, GloVe also amplifies words that are in close context to each other and reduces the value of words that are far. This gives words that are more close to each other a final boost in scores, than which are not.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-glove-word-embeddings-with-gensim&quot; tabindex=&quot;-1&quot;&gt;How To Use GloVe Word Embeddings With Gensim&lt;/h2&gt;
&lt;p&gt;The best part about most word embeddings is that you can get pretrained models, which will enable you to use word embeddings right away. Most of them are available in keyed vectors format, which is easily available to import in Gensim. You can download them from &lt;a href=&quot;https://nlp.stanford.edu/projects/glove/&quot;&gt;GloVe site&lt;/a&gt;, we here download the version which contains 6 billion tokens.&lt;/p&gt;
&lt;p&gt;This data is available in which each word is represented as different dimensions. Since it’s a normal text file, you can just give it a glance in a normal text editor.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/rkYkMpWA9l-480.webp 480w, https://turbolab.in/img/rkYkMpWA9l-960.webp 960w, https://turbolab.in/img/rkYkMpWA9l-1064.webp 1064w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/rkYkMpWA9l-480.png&quot; alt=&quot;&quot; width=&quot;1064&quot; height=&quot;560&quot; srcset=&quot;https://turbolab.in/img/rkYkMpWA9l-480.png 480w, https://turbolab.in/img/rkYkMpWA9l-960.png 960w, https://turbolab.in/img/rkYkMpWA9l-1064.png 1064w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;As you can see, each word is represented as a range of numbers, the vectors. Generally, the bigger the dimension of the word is represented in, the better the vector representation will be.&lt;/p&gt;
&lt;p&gt;We can load the keyed vector file in gensim as follows.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import gensim
model = gensim.models.KeyedVectors.load_word2vec_format(&#39;glove.6B.50d.txt&#39;, no_header=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, I am loading the 50-dimensional vector file. You can load other-dimensional files too.&lt;/p&gt;
&lt;p&gt;To check whether a word exists in the vector corpus, we can use the in python operation. Eg,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&#39;king&#39; in model
&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/0kYpD_0ka6-297.webp 297w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/0kYpD_0ka6-297.png&quot; alt=&quot;&quot; width=&quot;297&quot; height=&quot;69&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;We can also get the vector representation of the word:&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/lMQ8W8rUeh-480.webp 480w, https://turbolab.in/img/lMQ8W8rUeh-670.webp 670w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/lMQ8W8rUeh-480.png&quot; alt=&quot;&quot; width=&quot;670&quot; height=&quot;205&quot; srcset=&quot;https://turbolab.in/img/lMQ8W8rUeh-480.png 480w, https://turbolab.in/img/lMQ8W8rUeh-670.png 670w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;A quick way to check the dimensions:&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/r56WePUIRS-240.webp 240w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/r56WePUIRS-240.png&quot; alt=&quot;&quot; width=&quot;240&quot; height=&quot;82&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h2 id=&quot;word-similarity&quot; tabindex=&quot;-1&quot;&gt;Word Similarity&lt;/h2&gt;
&lt;p&gt;Word Vectors are based on the idea that similar words will have similar vectors. We can check that well using GloVe.&lt;/p&gt;
&lt;p&gt;How similar are the words &lt;em&gt;night&lt;/em&gt; and &lt;em&gt;day&lt;/em&gt;? Let’s find out.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/S7k3BIiSqC-373.webp 373w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/S7k3BIiSqC-373.png&quot; alt=&quot;&quot; width=&quot;373&quot; height=&quot;67&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;The value ranges from 0 to 1, so we can say that the words are quite similar. Similar results can be observed for king and queen, cat and dog.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/ulVs6yDONM-353.webp 353w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/ulVs6yDONM-353.png&quot; alt=&quot;&quot; width=&quot;353&quot; height=&quot;61&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/NnAJJztH4u-352.webp 352w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/NnAJJztH4u-352.png&quot; alt=&quot;&quot; width=&quot;352&quot; height=&quot;67&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;However, we can also get a list of similar words, i.e., vectors that are most similar to a word.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/obl1ht7Wc6-303.webp 303w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/obl1ht7Wc6-303.png&quot; alt=&quot;&quot; width=&quot;303&quot; height=&quot;238&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/mvpY00mzFO-331.webp 331w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/mvpY00mzFO-331.png&quot; alt=&quot;&quot; width=&quot;331&quot; height=&quot;220&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h2 id=&quot;a-note-about-dimensions&quot; tabindex=&quot;-1&quot;&gt;A Note About Dimensions&lt;/h2&gt;
&lt;p&gt;So far, we have worked with 50-dimensional word vectors. Word context improves dramatically the more dimensional vectors we take. For example, the same similarity tests now done with 300-dimensional vectors show way better results.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/2Qz5na2eCx-320.webp 320w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/2Qz5na2eCx-320.png&quot; alt=&quot;&quot; width=&quot;320&quot; height=&quot;222&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/ll9g6pJM_s-317.webp 317w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/ll9g6pJM_s-317.png&quot; alt=&quot;&quot; width=&quot;317&quot; height=&quot;225&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;The caveat? More dimensional vectors take up more memory and are slower to process.&lt;/p&gt;
&lt;h2 id=&quot;disadvantages-of-word-vectors&quot; tabindex=&quot;-1&quot;&gt;Disadvantages Of Word Vectors&lt;/h2&gt;
&lt;p&gt;Although powerful, word embeddings can have some disadvantages based on their usage. The major one is that they can’t distinguish between similar-sounding words, e.g. dog bark vs tree bark, both of them are the same in word vector context. They are computing and memory intensive to train, and the corpus of training data needs to be good to obtain good results. Often they can introduce unintended bias&lt;/p&gt;
&lt;p&gt;Despite these disadvantages, word vectors are suited for a major number of tasks for NLP and are widely used in the industry.&lt;/p&gt;
&lt;p&gt;We have studied GloVe and Word2Vec word embeddings so far in our posts. In the next post, we will look at fasttext model, a much more powerful word embedding model, and see how it compares with these two.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Feature Extraction in Natural Language Processing</title>
    <link href="https://turbolab.in/feature-extraction-in-natural-language-processing-nlp/"/>
    <updated>2021-12-03T05:38:55.000Z</updated>
    <published>2021-10-08T10:49:26.000Z</published>
    <id>https://turbolab.in/feature-extraction-in-natural-language-processing-nlp/</id>
    <content type="html">&lt;p&gt;In simple terms, Feature Extraction is transforming textual data into numerical data. In Natural Language Processing, Feature Extraction is a very trivial method to be followed to better understand the context. After cleaning and normalizing textual data, we need to transform it into their features for modeling, as the machine does not compute textual data. So we go for numerical representation for individual words as it’s easy for the computer to process numbers.&lt;/p&gt;
&lt;p&gt;In this blog, we will discuss various feature extraction methods with examples using sklearn and gensim.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Countvectorizer&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;TF-IDF Vectorizer&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Word Embeddings&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;countvectorizer&quot; tabindex=&quot;-1&quot;&gt;Countvectorizer&lt;/h2&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/VHoDEnDmVk-480.webp 480w, https://turbolab.in/img/VHoDEnDmVk-960.webp 960w, https://turbolab.in/img/VHoDEnDmVk-1600.webp 1600w, https://turbolab.in/img/VHoDEnDmVk-1726.webp 1726w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/VHoDEnDmVk-480.png&quot; alt=&quot;&quot; width=&quot;1726&quot; height=&quot;800&quot; srcset=&quot;https://turbolab.in/img/VHoDEnDmVk-480.png 480w, https://turbolab.in/img/VHoDEnDmVk-960.png 960w, https://turbolab.in/img/VHoDEnDmVk-1600.png 1600w, https://turbolab.in/img/VHoDEnDmVk-1726.png 1726w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;It is a simple and flexible way of extracting features from documents. A Countvectorizer model is a representation of text that describes the occurrence of words within a document. We just keep track of word counts and disregard the grammatical details and the word order. It is called a “bag of words” because any information about the order or structure of words in the document is discarded. The model is only concerned with whether known words occur in the document, not wherein the document.&lt;/p&gt;
&lt;p&gt;Here is a basic snippet of using count vectorization to get vectors&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from sklearn.feature_extraction.text import CountVectorizer

corpus = [&amp;quot;We become what we think about&amp;quot;, &amp;quot;Happiness is not something readymade. It comes from your own actions&amp;quot;]

# initialize count vectorizer object
vect = CountVectorizer()

# get counts of each token (word) in text data
X = vect.fit_transform(corpus)

# convert sparse matrix to numpy array to view
X.toarray()

# view token vocabulary and counts
print(&amp;quot;vocabulary&amp;quot;, vect.vocabulary_)
print(&amp;quot;shape&amp;quot;, X.shape)
print(&#39;vectors: &#39;, X.toarray())
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;Vocabulary :  {&#39;we&#39;: 8, &#39;become&#39;: 1, &#39;what&#39;: 9, &#39;think&#39;: 7, &#39;about&#39;: 0, &#39;happiness&#39;: 2, &#39;is&#39;: 3, &#39;not&#39;: 4, &#39;something&#39;: 6, &#39;readymade&#39;: 5}

Shape :  (2, 10)

Vectors :  [[1 1 0 0 0 0 0 1 2 1]
                 [0 0 1 1 1 1 1 0 0 0]]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;tf-idf-vectorizer-term-frequency-inverse-document-frequency&quot; tabindex=&quot;-1&quot;&gt;TF – IDF Vectorizer (Term Frequency – Inverse Document Frequency)&lt;/h2&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/h0SsZK0T0F-480.webp 480w, https://turbolab.in/img/h0SsZK0T0F-960.webp 960w, https://turbolab.in/img/h0SsZK0T0F-1200.webp 1200w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/h0SsZK0T0F-480.png&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;399&quot; srcset=&quot;https://turbolab.in/img/h0SsZK0T0F-480.png 480w, https://turbolab.in/img/h0SsZK0T0F-960.png 960w, https://turbolab.in/img/h0SsZK0T0F-1200.png 1200w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;TF-IDF is short for term frequency-inverse document frequency. It’s designed to reflect how important a word is to a document in a collection or corpus.&lt;/p&gt;
&lt;p&gt;The TF-IDF value increases proportionally to the number of times a word appears in the document and is offset by the number of documents in the corpus that contain the word, which helps to adjust for the fact that some words appear more frequently in general.&lt;/p&gt;
&lt;p&gt;And similar to the Countvectorizer, &lt;em&gt;sklearn.feature_extraction.text&lt;/em&gt; provides a method.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from sklearn.feature_extraction.text import TfidfVectorizer

corpus = [&amp;quot;We become what we think about&amp;quot;, &amp;quot;Happiness is not something readymade.&amp;quot;]

# initialize tf-idf vectorizer object
vectorizer = TfidfVectorizer()

# compute bag of word counts and tf-idf values
tf = vectorizer.fit_transform(corpus)

# convert sparse matrix to numpy array to view
print(&amp;quot;Vocabulary&amp;quot;, vectorizer.vocabulary_)
print(&amp;quot;idf&amp;quot;, vectorizer.idf_)
print(&amp;quot;Vectors&amp;quot;, tf.toarray())
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output:&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;Vocabulary : {&#39;we&#39;: 8, &#39;become&#39;: 1, &#39;what&#39;: 9, &#39;think&#39;: 7, &#39;about&#39;: 0, &#39;happiness&#39;: 2, &#39;is&#39;: 3, &#39;not&#39;: 4, &#39;something&#39;: 6, &#39;readymade&#39;: 5}

idf : [1.40546511 1.40546511 1.40546511 1.40546511 1.40546511 1.40546511
 1.40546511 1.40546511 1.40546511 1.40546511]

Vectors : [[0.35355339 0.35355339 0.         0.         0.         0.
         0.35355339 0.70710678 0.35355339]
      [0.         0.         0.4472136  0.4472136  0.4472136  0.4472136
       0.4472136  0.         0.         0.        ]]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;word-embeddings&quot; tabindex=&quot;-1&quot;&gt;Word Embeddings&lt;/h2&gt;
&lt;p&gt;Word embedding is a learned representation of text, where each word is represented as a real-valued vector in a lower-dimensional space.&lt;/p&gt;
&lt;p&gt;In simple terms, word embeddings are the texts converted into numbers and there may be different numerical representations of the same text, but texts with similar context have similar representations.&lt;/p&gt;
&lt;p&gt;Word embedding preserves contexts and relationships of words so that it detects similar words more accurately.&lt;/p&gt;
&lt;p&gt;Word embedding has several different implementations such as word2vec, GloVe, FastText etc.&lt;/p&gt;
&lt;p&gt;Here we will explain word2vec, as it is the most popular implementation.&lt;/p&gt;
&lt;h3 id=&quot;word2vec&quot; tabindex=&quot;-1&quot;&gt;Word2vec&lt;/h3&gt;
&lt;p&gt;Word2vec is widely used in most of the NLP models. It transforms every word into vectors. Word2vec can make the most accurate predictions about the meaning of words. It can capture the contextual meaning of words very well. Word vectors are positioned in the vector space such that words that share common contexts in the corpus are located close to one another in space.&lt;/p&gt;
&lt;p&gt;There are two neural embedding algorithms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Continuous Bag-of-Words (CBOW) – predicts target word from context&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skip-gram –&lt;/strong&gt; predicts context from the target word&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/9GcJp-ekS9-480.webp 480w, https://turbolab.in/img/9GcJp-ekS9-960.webp 960w, https://turbolab.in/img/9GcJp-ekS9-1600.webp 1600w, https://turbolab.in/img/9GcJp-ekS9-3248.webp 3248w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/9GcJp-ekS9-480.jpeg&quot; alt=&quot;&quot; width=&quot;3248&quot; height=&quot;1228&quot; srcset=&quot;https://turbolab.in/img/9GcJp-ekS9-480.jpeg 480w, https://turbolab.in/img/9GcJp-ekS9-960.jpeg 960w, https://turbolab.in/img/9GcJp-ekS9-1600.jpeg 1600w, https://turbolab.in/img/9GcJp-ekS9-3248.jpeg 3248w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Here is an example of Word2vec using Gensim. Gensim is a python library for NLP.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from gensim.models import Word2Vec

# Get document data.
common_texts = [[&#39;interface&#39;, &#39;computer&#39;, &#39;technology&#39;],
 [&#39;survey&#39;, &#39;computer&#39;, &#39;system&#39;, &#39;response&#39;],
 [ &#39;brother&#39;, &#39;boy&#39;, &#39;man&#39;, &#39;animal&#39;, &#39;human&#39;]]

# Initializing Model
model = Word2Vec(common_texts, window=5, min_count=1, workers=4)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;result-1&quot; tabindex=&quot;-1&quot;&gt;Result 1 :&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;# Get most similar words of “computer”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;model.wv.most_similar(“computer”)&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;Output :&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;[(&#39;technology&#39;, 0.21617145836353302),
 (&#39;system&#39;, 0.09291724115610123),
 (&#39;interface&#39;, 0.06285080313682556),
 (&#39;survey&#39;, 0.027057476341724396),
 (&#39;response&#39;, 0.016134709119796753),
 (&#39;human&#39;, -0.010839173570275307),
 (&#39;boy&#39;, -0.02775038219988346),
 (&#39;animal&#39;, -0.052346907556056976),
 (&#39;brother&#39;, -0.05987627059221268),
 (&#39;man&#39;, -0.111670583486557)]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;result-2&quot; tabindex=&quot;-1&quot;&gt;Result 2 :&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;# Get most similar words of “computer”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;model.wv.most_similar(“human”)&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;Output :&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;[(&#39;man&#39;, 0.0679759532213211),
 (&#39;survey&#39;, 0.03364055976271629),
 (&#39;brother&#39;, 0.00939119141548872),
 (&#39;boy&#39;, 0.004503018222749233),
 (&#39;computer&#39;, -0.010839177295565605),
 (&#39;animal&#39;, -0.02365921437740326),
 (&#39;technology&#39;, -0.09575347602367401),
 (&#39;response&#39;, -0.11410721391439438),
 (&#39;system&#39;, -0.11555543541908264),
 (&#39;interface&#39;, -0.13429945707321167)]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post, we have discovered different types of text Feature Extraction Methods where we moved from non-context vectorization methods (count vectorizer/BOWs) to context preserving methods (TF-IDF/Word Embeddings). We have explored the above methods practically using Scikit-learn (sklearn) and Gensim libraries.&lt;/p&gt;
&lt;p&gt;There are other advanced techniques for Word Embeddings like Facebook’s FastText. We will discuss them in our coming blogs.&lt;/p&gt;
&lt;p&gt;Apart from Word Embeddings, Dimension Reductionality is also a Feature Extraction technique that aims to reduce the number of features in a dataset by creating new features from the existing ones and then discarding the original features.&lt;/p&gt;
&lt;p&gt;Different techniques that you can explore for dimension reductional are Principal Components Analysis (PCA), Linear Discriminant Analysis (LDA), t-distributed Stochastic Neighbor Embedding (t-SNE), and many more.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Abstractive Summarization Using Google’s T5</title>
    <link href="https://turbolab.in/abstractive-summarization-using-googles-t5/"/>
    <updated>2021-11-12T08:07:35.000Z</updated>
    <published>2021-10-04T04:04:00.000Z</published>
    <id>https://turbolab.in/abstractive-summarization-using-googles-t5/</id>
    <content type="html">&lt;p&gt;In this article, we will discuss abstractive summarization using T5, and how it is different from BERT-based models.&lt;/p&gt;
&lt;p&gt;T5 (Text-To-Text Transfer Transformer) is a transformer model that is trained in an end-to-end manner with &lt;strong&gt;text as input&lt;/strong&gt; and modified &lt;strong&gt;text as output&lt;/strong&gt;, in contrast to BERT-style models that can only output either a class label or a span of the input. This text-to-text formatting makes the T5 model fit for multiple &lt;strong&gt;NLP&lt;/strong&gt; tasks like &lt;strong&gt;Summarization&lt;/strong&gt;, &lt;strong&gt;Question-Answering&lt;/strong&gt;, &lt;strong&gt;Machine Translation&lt;/strong&gt;, and &lt;strong&gt;Classification&lt;/strong&gt; problems.&lt;/p&gt;
&lt;h2 id=&quot;how-t5-is-different-from-bert&quot; tabindex=&quot;-1&quot;&gt;How T5 is different from BERT?&lt;/h2&gt;
&lt;p&gt;Both T5 and BERT are trained with MLM (Masked Language Model) approach.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is MLM?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The MLM is a fill-in-the-blank task, where the model masks part of the input text and tries to predict what that masked word should be.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;“I like to eat peanut butter and &amp;lt;MASK&amp;gt; sandwiches,”&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;“I like to eat peanut butter and&lt;/strong&gt;&lt;/em&gt; &lt;strong&gt;jelly&lt;/strong&gt; &lt;em&gt;&lt;strong&gt;sandwiches,”&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The only difference is that T5 replaces multiple consecutive tokens with the single Mask Keyword, unlike, BERT which uses Mask token for each word. This illustration is shown below.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/grFbHKI7uM-480.webp 480w, https://turbolab.in/img/grFbHKI7uM-591.webp 591w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/grFbHKI7uM-480.png&quot; alt=&quot;&quot; width=&quot;591&quot; height=&quot;266&quot; srcset=&quot;https://turbolab.in/img/grFbHKI7uM-480.png 480w, https://turbolab.in/img/grFbHKI7uM-591.png 591w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Source: Journal of Machine Learning&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;about-t5-models&quot; tabindex=&quot;-1&quot;&gt;About T5 Models&lt;/h2&gt;
&lt;p&gt;Google has released the pre-trained T5 text-to-text framework models which are trained on the unlabelled large text corpus called C4 (Colossal Clean Crawled Corpus) using deep learning. C4 is the web extract text of 800Gb cleaned data. The cleaning process involves deduplication, discarding incomplete sentences, and removing offensive or noisy content.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You can get these T5 pre-trained models from the&lt;/strong&gt; &lt;a href=&quot;https://huggingface.co/models?search=T5&quot;&gt;&lt;strong&gt;HuggingFace website&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;T5-small with 60 million parameters.&lt;/li&gt;
&lt;li&gt;T5-base with 220 million parameters.&lt;/li&gt;
&lt;li&gt;T5-large with 770 million parameters.&lt;/li&gt;
&lt;li&gt;T5-3B with 3 billion parameters.&lt;/li&gt;
&lt;li&gt;T5-11B with 11 billion parameters.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/cPr8HFrsvu-480.webp 480w, https://turbolab.in/img/cPr8HFrsvu-960.webp 960w, https://turbolab.in/img/cPr8HFrsvu-1318.webp 1318w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/cPr8HFrsvu-480.jpeg&quot; alt=&quot;&quot; width=&quot;1318&quot; height=&quot;491&quot; srcset=&quot;https://turbolab.in/img/cPr8HFrsvu-480.jpeg 480w, https://turbolab.in/img/cPr8HFrsvu-960.jpeg 960w, https://turbolab.in/img/cPr8HFrsvu-1318.jpeg 1318w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;T5 expects a prefix before the input text to understand the task given by the user. For example, “&lt;strong&gt;summarize&lt;/strong&gt;:” for the summarization, “&lt;strong&gt;cola sentence:&lt;/strong&gt;” for the classification, “&lt;strong&gt;translate&lt;/strong&gt; English to Spanish:” for the machine translation, etc., You can have a look at the below image to understand the above illustration.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/4Qg3TfTKNj-480.webp 480w, https://turbolab.in/img/4Qg3TfTKNj-744.webp 744w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/4Qg3TfTKNj-480.png&quot; alt=&quot;&quot; width=&quot;744&quot; height=&quot;328&quot; srcset=&quot;https://turbolab.in/img/4Qg3TfTKNj-480.png 480w, https://turbolab.in/img/4Qg3TfTKNj-744.png 744w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Source: Google AI Blog&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Every task we consider uses text as input to the model, which is trained to generate some target text. This allows us to use the same model, loss function, and hyperparameters across our diverse set of tasks including translation (green), linguistic acceptability (red), sentence similarity (yellow), and document summarization (blue).&lt;/p&gt;
&lt;p&gt;Besides the improved transformer architecture and massive unsupervised training data, better decoding methods have also played an important role. Currently, the most prominent decoding methods are &lt;strong&gt;Greedy Search&lt;/strong&gt;, &lt;strong&gt;Beam Search&lt;/strong&gt;, &lt;strong&gt;Top-K Sampling,&lt;/strong&gt; and &lt;strong&gt;Top-p Sampling&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Visit this &lt;a href=&quot;https://huggingface.co/blog/how-to-generate&quot;&gt;link&lt;/a&gt; to know the detailed information about these methods.&lt;/p&gt;
&lt;h2 id=&quot;using-t5-through-the-huggingface-transformers&quot; tabindex=&quot;-1&quot;&gt;Using T5 through the HuggingFace transformers:&lt;/h2&gt;
&lt;p&gt;HuggingFace, an open-source NLP library that helps load pre-trained models, which are similar to sci-kit learn for machine learning algorithms.&lt;/p&gt;
&lt;p&gt;We define the content we are going to summarize.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;content = &amp;quot;China&#39;s Huawei overtook Samsung Electronics as the world&#39;s biggest seller of mobile phones in the second quarter of 2020, shipping 55.8 million devices compared to Samsung&#39;s 53.7 million, according to data from research firm Canalys. While Huawei&#39;s sales fell 5 per cent from the same quarter a year earlier, South Korea&#39;s Samsung posted a bigger drop of 30 per cent, owing to disruption from the coronavirus in key markets such as Brazil, the United States and Europe, Canalys said. Huawei&#39;s overseas shipments fell 27 per cent in Q2 from a year earlier, but the company increased its dominance of the China market which has been faster to recover from COVID-19 and where it now sells over 70 per cent of its phones. &amp;quot;Our business has demonstrated exceptional resilience in these difficult times,&amp;quot; a Huawei spokesman said. &amp;quot;Amidst a period of unprecedented global economic slowdown and challenges, we&#39;re continued to grow and further our leadership position.&amp;quot; Nevertheless, Huawei&#39;s position as number one seller may prove short-lived once other markets recover given it is mainly due to economic disruption, a senior Huawei employee with knowledge of the matter told Reuters. Apple is due to release its Q2 iPhone shipment data on Friday.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;importing-the-necessary-packages&quot; tabindex=&quot;-1&quot;&gt;Importing the necessary packages&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;from transformers import T5Tokenizer, T5ForConditionalGeneration
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;loading-the-tokenizer-and-model-architecture-with-weights&quot; tabindex=&quot;-1&quot;&gt;Loading the tokenizer and model architecture with weights&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;T5_PATH = &#39;t5-large&#39; # T5 model name
# initialize the model architecture and weights
t5_model = T5ForConditionalGeneration.from_pretrained(T5_PATH)
# initialize the model tokenizer
t5_tokenizer = T5Tokenizer.from_pretrained(T5_PATH)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The pre-trained model used here is t5-large. Other pre-trained models of t5 are discussed above.&lt;/p&gt;
&lt;h3 id=&quot;encode-the-text&quot; tabindex=&quot;-1&quot;&gt;Encode the text&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# encode the text into tensor of integers using the tokenizer
inputs = tokenizer.encode(&amp;quot;summarize: &amp;quot; + article, return_tensors=&amp;quot;pt&amp;quot;, max_length=512, padding=&#39;max_length&#39;, truncation=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;generate-the-summarized-text-and-decode-it&quot; tabindex=&quot;-1&quot;&gt;Generate the summarized text and decode it&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;summary_ids = t5_model.generate(inputs,
                                    num_beams=int(2),
                                    no_repeat_ngram_size=3,
                                    length_penalty=2.0,
                                    min_length=min_length,
                                    max_length=max_length,
                                    early_stopping=True)
output = t5_tokenizer.decode(summary_ids[0], skip_special_tokens=True, clean_up_tokenization_spaces=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The decoding method used here is &lt;strong&gt;Beam Search&lt;/strong&gt; with &lt;strong&gt;num_beams&lt;/strong&gt; value as 2.&lt;/p&gt;
&lt;p&gt;With &lt;strong&gt;min_length 50&lt;/strong&gt; and &lt;strong&gt;max_length 50&lt;/strong&gt;, the output is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;Huawei overtakes Samsung as world&#39;s biggest seller of mobile phones in second quarter of 2020. Company shipped 55.8 million devices compared to Samsung&#39;s 53.7 million, Canalys says. Sales of Huawei&#39;s&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the time taken to generate the summary is 8.07 seconds with 16 cores CPU host.&lt;/p&gt;
&lt;p&gt;With &lt;strong&gt;min_length 50&lt;/strong&gt; and &lt;strong&gt;max_length 100&lt;/strong&gt;, the output is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;Huawei overtakes Samsung as world&#39;s biggest seller of mobile phones in second quarter of 2020. Company shipped 55.8 million devices compared to Samsung&#39;s 53.7 million, Canalys says. Sales fell 5% from same quarter a year earlier, owing to disruption from coronavirus. But company increased its dominance of the china market which has been faster to recover from COVID-19.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the time taken to generate the summary is 14.32 seconds with 16 cores CPU host.&lt;/p&gt;
&lt;p&gt;With &lt;strong&gt;min_length 100&lt;/strong&gt; and &lt;strong&gt;max_length 200&lt;/strong&gt;, the output is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;Huawei overtakes Samsung as world&#39;s biggest seller of mobile phones in second quarter of 2020. Company shipped 55.8 million devices compared to Samsung&#39;s 53.7 million, Canalys says. Sales fell 5% from same quarter a year earlier, owing to disruption from coronavirus. But Huawei increased its dominance of the china market which has been faster to recover from COVID-19.. Apple is due to release its Q2 iPhone shipment data on friday.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the time taken to generate the summary is 23.15 seconds with 16 cores CPU host.&lt;/p&gt;
&lt;p&gt;As you increase any of these parameters &lt;strong&gt;num_beams&lt;/strong&gt;, &lt;strong&gt;min_lenth,&lt;/strong&gt; and &lt;strong&gt;max_length&lt;/strong&gt;, the time taken to generate the summary is going to increase.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this article, we have used the Beam Search decoding method. For a better summary, we can suggest increasing the beam value and trying the other decoding methods(&lt;strong&gt;Greedy Search&lt;/strong&gt;, &lt;strong&gt;Beam Search&lt;/strong&gt;, &lt;strong&gt;Top-K Sampling,&lt;/strong&gt; and &lt;strong&gt;Top-p Sampling)&lt;/strong&gt; mentioned.&lt;/p&gt;
&lt;p&gt;With Pegasus, we can only perform abstractive summarization but T5 can perform various NLP tasks like Classification tasks (eg: Sentiment Analysis), Question-Answering, Machine Translation, and Document Summarization. We recommend you go through the other NLP tasks of T5.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Abstractive Summarization Using Pegasus</title>
    <link href="https://turbolab.in/abstractive-summarization-using-pegasus/"/>
    <updated>2024-07-26T10:01:52.000Z</updated>
    <published>2021-09-30T06:16:34.000Z</published>
    <id>https://turbolab.in/abstractive-summarization-using-pegasus/</id>
    <content type="html">&lt;p&gt;In the last article, we have seen how to perform extractive summarization of some text, which selects important sentences and gives them out by ranking them, without changing any text. While they are suitable for some cases, they do not achieve the sophistication of human-like summaries. For that, we will need to dive deep into Abstractive Summarization.&lt;/p&gt;
&lt;p&gt;To put abstractive summarization in simple words, a model reads the text and tries to make sense of it. Then it writes out the summary from scratch, putting in the most important information that it finds. This is how a human will summarize text, for this reason, abstractive summarization archives results that are equal to or near human-like summaries.&lt;/p&gt;
&lt;h2 id=&quot;language-models-in-ai&quot; tabindex=&quot;-1&quot;&gt;Language Models In AI&lt;/h2&gt;
&lt;p&gt;Almost all abstractive summarization techniques use some kind of language model. A language model mimics how humans understand and know the natural language. Abstractive summarization is done mostly by using a pre-trained language model and then fine-tuning it to specific tasks, such as summarization, question-answer generation, and more. We will discuss in brief the most popular language model that is available to us, BERT.&lt;/p&gt;
&lt;h2 id=&quot;bert-bidirectional-encoder-representations-from-transformers&quot; tabindex=&quot;-1&quot;&gt;BERT (Bidirectional Encoder Representations from Transformers)&lt;/h2&gt;
&lt;p&gt;BERT was developed by Google to create a model that can understand the human language well and also can be used for several language-related tasks. To make it work, BERT is pre-trained by two unsupervised learning tasks, which are run simultaneously. First is the masked language modeling, where BERT is given a sentence, but with words taken out, and it tries to guess the words that are skipped. Sort of like fill in the blanks. The second task is called Next Sentence Prediction, where BERT is given a sentence, and it tries to guess the next sentence. This process is repeated, and over time, it gets really good at understanding the language context as well as its underlying meaning.&lt;/p&gt;
&lt;p&gt;This creates a basic language model, which is then fine-tuned for specific tasks that we will need the model to do. For example, say we need to train and fine-tune BERT for summarization. We take the model and add some neurons to it, the input being the text and the output being the summary. Since BERT already has an understanding of the language and context of words, this step is pretty easy and doesn’t take much time for it to get trained.&lt;/p&gt;
&lt;h2 id=&quot;the-pegasus-model-and-how-it-is-different&quot; tabindex=&quot;-1&quot;&gt;The Pegasus Model, And How It Is Different&lt;/h2&gt;
&lt;p&gt;Later, people at Google experimented and found out that fine-tuning pre-trained language models for summarization may not work well in all cases. So, they created a language model from scratch, that is specially trained for abstractive summaries.&lt;/p&gt;
&lt;p&gt;They call this new training method as Gap Sentence Generation. The idea is that instead of masking out only words as it happens in BERT, they mask out entire sentences, and ask the model to guess the removed sentences. As the model tries to get the underlying missing context, it gets better at abstractive summarization-like tasks.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/Yfh6u8aufC-480.webp 480w, https://turbolab.in/img/Yfh6u8aufC-594.webp 594w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/Yfh6u8aufC-480.png&quot; alt=&quot;&quot; width=&quot;594&quot; height=&quot;246&quot; srcset=&quot;https://turbolab.in/img/Yfh6u8aufC-480.png 480w, https://turbolab.in/img/Yfh6u8aufC-594.png 594w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;How Pegasus Works&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;using-pegasus-through-huggingface-transformers&quot; tabindex=&quot;-1&quot;&gt;Using Pegasus through HuggingFace Transformers&lt;/h2&gt;
&lt;p&gt;We now show an example of using Pegasus through the HuggingFace transformers.&lt;/p&gt;
&lt;p&gt;The first thing you need to do is install the necessary Python packages.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pip install transformers sentencepiece
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We import them into our file&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from transformers import PegasusForConditionalGeneration, PegasusTokenizer
import torch
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We define the source text we are going to summarize.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src_text = [  &amp;quot;&amp;quot;&amp;quot;China&#39;s Huawei overtook Samsung Electronics as the world&#39;s biggest seller of mobile phones in the second quarter of 2020, shipping 55.8 million devices compared to Samsung&#39;s 53.7 million, according to data from research firm Canalys. While Huawei&#39;s sales fell 5 per cent from the same quarter a year earlier, South Korea&#39;s Samsung posted a bigger drop of 30 per cent, owing to disruption from the coronavirus in key markets such as Brazil, the United States and Europe, Canalys said. Huawei&#39;s overseas shipments fell 27 per cent in Q2 from a year earlier, but the company increased its dominance of the China market which has been faster to recover from COVID-19 and where it now sells over 70 per cent of its phones. &amp;quot;Our business has demonstrated exceptional resilience in these difficult times,&amp;quot; a Huawei spokesman said. &amp;quot;Amidst a period of unprecedented global economic slowdown and challenges, we&#39;re continued to grow and further our leadership position.&amp;quot; Nevertheless, Huawei&#39;s position as number one seller may prove short-lived once other markets recover given it is mainly due to economic disruption, a senior Huawei employee with knowledge of the matter told Reuters. Apple is due to release its Q2 iPhone shipment data on Friday.&amp;quot;&amp;quot;&amp;quot; ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We will be using the pegasus XSUM model, we define it as below.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;model_name = &#39;google/pegasus-xsum&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which device/hardware will we be using to run the model? The CPU or GPU? We define it here below.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;device = &#39;cuda&#39; if torch.cuda.is_available() else &#39;cpu&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we create a tokenizer that will be used to parse and tokenize the input text.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tokenizer = PegasusTokenizer.from_pretrained(model_name)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will download and initialize the model.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;model = PegasusForConditionalGeneration.from_pretrained(model_name).to(device)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We tokenize the text, and it returns us PyTorch tensors.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;batch = tokenizer(src_text, truncation=True, padding=&#39;longest&#39;, return_tensors=&amp;quot;pt&amp;quot;).to(device)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We take these tensors and get the abstractive summary.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;translated = model.generate(**batch)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since the output as tensors is encoded, we have to decode it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tgt_text = tokenizer.batch_decode(translated, skip_special_tokens=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see the tgt_text variable, to get the summary.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; [&#39;Huawei has overtaken Samsung as the world&#39;s biggest seller of mobile phones, according to data from research firm Canalys.&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Here we have implemented a case of doing abstractive summarization using a non-BERT language model. There are some other alternatives to it if you want to specially take a BERT model and fine-tune it for summarization. One such example is &lt;a href=&quot;https://github.com/nlpyang/PreSumm&quot;&gt;PreSumm&lt;/a&gt;, which produces some decent outputs with good performance. If a Pegasus-like model doesn’t suit your task, giving it a try will be a good idea.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Sentiment Analysis: Concepts, Models, and Examples</title>
    <link href="https://turbolab.in/sentiment-analysis-concepts-models-and-examples/"/>
    <updated>2021-09-27T06:30:32.000Z</updated>
    <published>2021-09-27T06:30:32.000Z</published>
    <id>https://turbolab.in/sentiment-analysis-concepts-models-and-examples/</id>
    <content type="html">&lt;p&gt;Sentiment analysis is a sub field of Natural Language Processing (NLP) that identifies and extracts emotions expressed in given texts. It is a machine learning tool that understands the context and determines the polarity of text, whether it is positive, neutral, or negative.&lt;/p&gt;
&lt;p&gt;This article will discuss what sentiment analysis is, where it is being used, and how to use a pre-trained model to analyze sentiments from texts.&lt;/p&gt;
&lt;p&gt;We will also explore the approach on how Machine Learning models are used to build sentiment analytic tools.&lt;/p&gt;
&lt;h3 id=&quot;use-cases-of-sentiment-analysis&quot; tabindex=&quot;-1&quot;&gt;Use cases of sentiment analysis:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Brand Monitoring&lt;/li&gt;
&lt;li&gt;Customers Feedback&lt;/li&gt;
&lt;li&gt;Product Analytics&lt;/li&gt;
&lt;li&gt;Monitoring Market Research&lt;/li&gt;
&lt;li&gt;Analyzing Movie Reviews&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are various pre-trained sentiment analysis tools available in Natural Language Processing (NLP) libraries. Such as NLTK’s Vader sentiment analysis tool, TextBlob, Flair sentiment classifier based on LSTM neural network, etc.&lt;/p&gt;
&lt;h3 id=&quot;part-1-sentiment-analysis-using-a-pre-trained-model-textblob&quot; tabindex=&quot;-1&quot;&gt;Part 1- Sentiment analysis using a pre-trained model (TextBlob)&lt;/h3&gt;
&lt;p&gt;TextBlob is a python library for Natural Language Processing (NLP). It helps you perform complex analysis and operations on textual data.&lt;/p&gt;
&lt;h4&gt;Steps to apply the TextBlob model to achieve sentiments are given here:&lt;/h4&gt;
&lt;p&gt;Before applying Textblob, basic text cleaning should be done. You can check NLTK or Spacy libraries for various text cleaning methods.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from textblob import TextBlob

def sentimental(text: str) -&amp;gt; str:
    sentiment = None
    if text:
        text = &#39; &#39;.join(text.split()).strip() # removing empty strings
        blob = TextBlob(text)
        if blob.sentiment.polarity &amp;gt; 0:
            sentiment = &#39;Positive&#39;
        if blob.sentiment.polarity &amp;lt; 0:
            sentiment = &#39;Negative&#39;
        if blob.sentiment.polarity == 0:
            sentiment = &#39;Neutral&#39;
    return sentiment
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output Result:&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;sentimental(“This is what a true masterpiece looks like. Thrillingly played with a flawless ensemble cast.”)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Out: ‘&lt;strong&gt;Positive&lt;/strong&gt;‘&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;TextBlob returns the ‘polarity’ of a sentence. Polarity lies between [-1,1].&lt;/p&gt;
&lt;p&gt;-1 defines &lt;strong&gt;Negative&lt;/strong&gt;, 0 defines &lt;strong&gt;Neutral,&lt;/strong&gt; and 1 defines &lt;strong&gt;Positive&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;part-2-train-a-machine-learning-model-for-sentiment-analysis&quot; tabindex=&quot;-1&quot;&gt;Part 2 – Train a Machine Learning Model for sentiment analysis&lt;/h3&gt;
&lt;p&gt;In this part, we will be using a Supervised Machine Learning model called Support Vector Machines (SVM) to train the model.&lt;/p&gt;
&lt;h4&gt;Data Gathering:&lt;/h4&gt;
&lt;p&gt;Here we will choose &lt;a href=&quot;http://www.cs.cornell.edu/people/pabo/movie-review-data/&quot;&gt;&lt;strong&gt;sentiment polarity datasets 2.0&lt;/strong&gt;&lt;/a&gt; which is a classified movie dataset with labels, and transformed into CSVs.&lt;/p&gt;
&lt;p&gt;Data is divided into &lt;strong&gt;“trainData”&lt;/strong&gt; and &lt;strong&gt;“testData”.&lt;/strong&gt; The dataset contains “Content” and “Label” columns.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/CgQQ2PuR5A-480.webp 480w, https://turbolab.in/img/CgQQ2PuR5A-888.webp 888w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/CgQQ2PuR5A-480.png&quot; alt=&quot;&quot; width=&quot;888&quot; height=&quot;548&quot; srcset=&quot;https://turbolab.in/img/CgQQ2PuR5A-480.png 480w, https://turbolab.in/img/CgQQ2PuR5A-888.png 888w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h4&gt;Data Vectorization&lt;/h4&gt;
&lt;p&gt;Before feeding our model with data, we need to extract features from our textual dataset, basically converting the text data into vectors. TF-IDF is one of many methods to extract features from text documents. TF-IDF stands for ‘Term Frequency – Inverse Document Frequency.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from sklearn.feature_extraction.text import TfidfVectorizer

# Create feature vectors
vectorizer = TfidfVectorizer(min_df = 5,
                             max_df = 0.8,
                             sublinear_tf = True,
                             use_idf = True)
train_vectors = vectorizer.fit_transform(trainData[&#39;Content&#39;])
test_vectors = vectorizer.transform(testData[&#39;Content&#39;])
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Model Building&lt;/h4&gt;
&lt;p&gt;After generating vectors for both train and test input sets, we can now feed the SVC model with this data and train it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# importing libraries
from sklearn import svm
from sklearn.metrics import classification_report

# Initialising SVM classifier with linear kernel
svm_classifier = svm.SVC(kernel=&#39;linear&#39;)

# training the model with the train data
svm_classifier.fit(train_vectors, trainData[&#39;Label&#39;])

# testing the model in test data content
predicted_result = svm_classifier.predict(test_vectors)

# results
report = classification_report(testData[&#39;Label&#39;], predicted_result, output_dict=True)
print(&#39;Model accuracy: &#39;, report[&#39;accuracy&#39;])
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Model Results and Statistics:&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Model accuracy:  &lt;strong&gt;0.915&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Model accuracy shows the ratio of the number of correctly predicted classes to the total number of input samples. Accuracy is one of many metrics used for evaluating classification problems.&lt;/p&gt;
&lt;p&gt;Here the accuracy is 0.915, which shows that the model has learned the data quite well as the range of accuracy is calculated between 0 to 1.&lt;/p&gt;
&lt;h4&gt;Testing the Model to Predict on Movie Reviews:&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;svm_classifier.predict(vectorizer.transform(“This is what a true masterpiece looks like. Thrillingly played with a flawless ensemble cast.”))&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Out: ‘&lt;strong&gt;Positive&lt;/strong&gt;’&lt;/em&gt;&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/qEGWjWT1-g-480.webp 480w, https://turbolab.in/img/qEGWjWT1-g-960.webp 960w, https://turbolab.in/img/qEGWjWT1-g-996.webp 996w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/qEGWjWT1-g-480.png&quot; alt=&quot;&quot; width=&quot;996&quot; height=&quot;644&quot; srcset=&quot;https://turbolab.in/img/qEGWjWT1-g-480.png 480w, https://turbolab.in/img/qEGWjWT1-g-960.png 960w, https://turbolab.in/img/qEGWjWT1-g-996.png 996w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Classification accuracy alone can be misleading if you have an unequal number of observations. A confusion matrix can give you a better idea of what our model is predicting correctly.&lt;/p&gt;
&lt;p&gt;Here we have taken 200 test samples and as shown in the matrix above, we got 9 False positives, which means it has falsely predicted the negative as positive. There were also 8 False negatives, where it has falsely predicted the positive as negative.&lt;/p&gt;
&lt;p&gt;To reduce these errors we can train the model with a larger dataset.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/v5pM8SCYBz-480.webp 480w, https://turbolab.in/img/v5pM8SCYBz-960.webp 960w, https://turbolab.in/img/v5pM8SCYBz-1338.webp 1338w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/v5pM8SCYBz-480.png&quot; alt=&quot;&quot; width=&quot;1338&quot; height=&quot;916&quot; srcset=&quot;https://turbolab.in/img/v5pM8SCYBz-480.png 480w, https://turbolab.in/img/v5pM8SCYBz-960.png 960w, https://turbolab.in/img/v5pM8SCYBz-1338.png 1338w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h3 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In this article, we have mentioned the TextBlob (pre-trained) Python package and SVM (Machine Learning) model to determine sentiment analysis. But the field of sentiment analysis is an exciting research direction due to a large number of real-world applications where discovering people’s opinions is important in better decision-making.&lt;/p&gt;
&lt;p&gt;Although detecting sentiment using NLP is surprisingly a difficult task, such as when we face sentences that are put in sarcastic ways. These types of textual context can mislead NLP-based model predictions. We can even see that both the model prediction results are not the same for all samples. Here the TextBlob model performs and predicts better with ‘neutral’ tagging of articles. This is because TextBlob is using more data to train the model and has neutral tagged data in the training set.&lt;/p&gt;
&lt;p&gt;To overcome such difficult tasks, we can use deep learning models like LSTM, RNN, etc. We can even make use of transformer-based models like GPT-3 and T5 from google for sentiment analysis.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Types of Text Summarization: Extractive and Abstractive Summarization Basics</title>
    <link href="https://turbolab.in/types-of-text-summarization-extractive-and-abstractive-summarization-basics/"/>
    <updated>2021-12-03T05:40:41.000Z</updated>
    <published>2021-09-20T08:19:52.000Z</published>
    <id>https://turbolab.in/types-of-text-summarization-extractive-and-abstractive-summarization-basics/</id>
    <content type="html">&lt;p&gt;Summarization is one of the most common &lt;strong&gt;Natural Language Processing&lt;/strong&gt; (NLP) tasks. With the amount of new content generated by billions of people and their smartphones everyday, we are inundated with increasing amount of data every day. Humans can only consume a finite amount of information and need a way to filter out the wheat from the chaff and find the information that matters. Text summarization can help achieve that for textual information. We can separate the signal from the noise and take meaningful actions from them.&lt;/p&gt;
&lt;p&gt;In this article, we explore different methods to implement this task and some of the learnings that we have come across on the way. We hope this will be helpful to other folks who would like to implement basic summarization in their data science pipeline for solving different business problems.&lt;/p&gt;
&lt;p&gt;Python provides some excellent libraries and modules to perform Text Summarization. We will provide a simple example of generating Extractive Summarization using the Gensim and HuggingFace modules in this article.&lt;/p&gt;
&lt;h2 id=&quot;uses-of-summarization&quot; tabindex=&quot;-1&quot;&gt;Uses of Summarization?&lt;/h2&gt;
&lt;p&gt;It may be tempting to use summarization for all texts to get useful information from them and spend less time reading. However, for now, NLP summarization has been a successful use case in only a few areas.&lt;/p&gt;
&lt;p&gt;Text summarization works great if a text has a lot of raw facts and can be used to filter important information from them. The NLP models can summarize long documents and represent them in small simpler sentences. News, factsheets, and mailers fall under these categories.&lt;/p&gt;
&lt;p&gt;However, for texts where each sentence builds up upon the previous, text summarization does not work that well. Research journals, medical texts are good examples of texts where summarization might not be very successful.&lt;/p&gt;
&lt;p&gt;Finally, if we take the case of summarizing fiction, summarization methods can work fine. However, it might miss the style and the tone of the text that the author tried to express.&lt;/p&gt;
&lt;p&gt;Hence, Text summarization is helpful only in a handful of use cases.&lt;/p&gt;
&lt;h2 id=&quot;two-types-of-summarization&quot; tabindex=&quot;-1&quot;&gt;Two Types Of Summarization&lt;/h2&gt;
&lt;p&gt;There are two main types of Text Summarization&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/22n4DVkeWG-480.webp 480w, https://turbolab.in/img/22n4DVkeWG-960.webp 960w, https://turbolab.in/img/22n4DVkeWG-964.webp 964w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/22n4DVkeWG-480.jpeg&quot; alt=&quot;&quot; width=&quot;964&quot; height=&quot;693&quot; srcset=&quot;https://turbolab.in/img/22n4DVkeWG-480.jpeg 480w, https://turbolab.in/img/22n4DVkeWG-960.jpeg 960w, https://turbolab.in/img/22n4DVkeWG-964.jpeg 964w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;h3 id=&quot;extractive&quot; tabindex=&quot;-1&quot;&gt;Extractive&lt;/h3&gt;
&lt;p&gt;Extractive summarization methods work just like that. It takes the text, ranks all the sentences according to the understanding and relevance of the text, and presents you with the most important sentences.&lt;/p&gt;
&lt;p&gt;This method does not create new words or phrases, it just takes the already existing words and phrases and presents only that. You can imagine this as taking a page of text and marking the most important sentences using a highlighter.&lt;/p&gt;
&lt;h3 id=&quot;abstractive&quot; tabindex=&quot;-1&quot;&gt;Abstractive&lt;/h3&gt;
&lt;p&gt;Abstractive summarization, on the other hand, tries to guess the meaning of the whole text and presents the meaning to you.&lt;/p&gt;
&lt;p&gt;It creates words and phrases, puts them together in a meaningful way, and along with that, adds the most important facts found in the text. This way, abstractive summarization techniques are more complex than extractive summarization techniques and are also computationally more expensive.&lt;/p&gt;
&lt;h2 id=&quot;comparison-with-practical-example&quot; tabindex=&quot;-1&quot;&gt;Comparison with practical example&lt;/h2&gt;
&lt;p&gt;The best way to illustrate these types is through an example. Here we have run the Input Text below through both types of summarization and the results are shown below.&lt;/p&gt;
&lt;h3 id=&quot;input-text&quot; tabindex=&quot;-1&quot;&gt;Input Text:&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;China&#39;s Huawei overtook Samsung Electronics as the world&#39;s biggest seller of mobile phones in the second quarter of 2020, shipping 55.8 million devices compared to Samsung&#39;s 53.7 million, according to data from research firm Canalys. While Huawei&#39;s sales fell 5 per cent from the same quarter a year earlier, South Korea&#39;s Samsung posted a bigger drop of 30 per cent, owing to disruption from the coronavirus in key markets such as Brazil, the United States and Europe, Canalys said. Huawei&#39;s overseas shipments fell 27 per cent in Q2 from a year earlier, but the company increased its dominance of the China market which has been faster to recover from COVID-19 and where it now sells over 70 per cent of its phones. &amp;quot;Our business has demonstrated exceptional resilience in these difficult times,&amp;quot; a Huawei spokesman said. &amp;quot;Amidst a period of unprecedented global economic slowdown and challenges, we&#39;re continued to grow and further our leadership position.&amp;quot; Nevertheless, Huawei&#39;s position as number one seller may prove short-lived once other markets recover given it is mainly due to economic disruption, a senior Huawei employee with knowledge of the matter told Reuters. Apple is due to release its Q2 iPhone shipment data on Friday.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;extractive-summarization-output&quot; tabindex=&quot;-1&quot;&gt;Extractive Summarization Output:&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;While Huawei&#39;s sales fell 5 per cent from the same quarter a year earlier, South Korea&#39;s Samsung posted a bigger drop of 30 per cent, owing to disruption from the coronavirus in key markets such as Brazil, the United States and Europe, Canalys said. Huawei&#39;s overseas shipments fell 27 per cent in Q2 from a year earlier, but the company increased its dominance of the China market which has been faster to recover from COVID-19 and where it now sells over 70 per cent of its phones.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;abstractive-summarization-output&quot; tabindex=&quot;-1&quot;&gt;Abstractive Summarization Output:&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Huawei overtakes Samsung as world&#39;s biggest seller of mobile phones in the second quarter of 2020. Sales of Huawei&#39;s 55.8 million devices compared to 53.7 million for south Korea&#39;s Samsung. Shipments overseas fell 27 per cent in Q2 from a year earlier, but company increased its dominance of the china market. Position as number one seller may prove short-lived once other markets recover, a senior Huawei employee says.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;extractive-text-summarization-using-gensim&quot; tabindex=&quot;-1&quot;&gt;Extractive Text Summarization Using Gensim&lt;/h2&gt;
&lt;p&gt;Import the required libraries and functions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from gensim.summarization.summarizer import summarize
from gensim.summarization.textcleaner import split_sentences
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We store the article content in a variable called Input (mentioned above). Next, we have to pass it to the summarize function, the second parameter being the ratio we want the summarized text to be. We chose it as 0.4, or the summary will be around 40% of the original text.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;summarize(Input, 0.4)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output:&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;While Huawei&#39;s sales fell 5 per cent from the same quarter a year earlier, South Korea&#39;s Samsung posted a bigger drop of 30 per cent, owing to disruption from the coronavirus in key markets such as Brazil, the United States and Europe, Canalys said. Huawei&#39;s overseas shipments fell 27 per cent in Q2 from a year earlier, but the company increased its dominance of the China market which has been faster to recover from COVID-19 and where it now sells over 70 per cent of its phones.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the parameter &lt;strong&gt;split=True&lt;/strong&gt;, you can see the output as a list of sentences.&lt;/p&gt;
&lt;p&gt;Gensim summarization works with the TextRank algorithm. As the name suggests, it ranks texts and gives you the most important ones back.&lt;/p&gt;
&lt;h2 id=&quot;extractive-text-summarization-using-huggingface-transformers&quot; tabindex=&quot;-1&quot;&gt;Extractive Text Summarization Using Huggingface Transformers&lt;/h2&gt;
&lt;p&gt;We use the same article to summarize as before, but this time, we use a transformer model from Huggingface,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from transformers import pipeline
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have to load the pre-trained summarization model into the pipeline:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;summarizer = pipeline(&amp;quot;summarization&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, to use this model, we pass the text, the minimum length, and the maximum length parameters. We get the following output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;summarizer(Input, min_length=30, max_length=300)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output:&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;China&#39;s Huawei overtook Samsung Electronics as the world&#39;s biggest seller of mobile phones in the second quarter of 2020, shipping 55.8 million devices compared to Samsung&#39;s 53.7 million. Samsung posted a bigger drop of 30 per cent, owing to disruption from coronavirus in key markets such as Brazil, the United States and Europe.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We saw some quick examples of &lt;em&gt;&lt;strong&gt;Extractive summarization&lt;/strong&gt;&lt;/em&gt;, one using Gensim’s TextRank algorithm, and another using Huggingface’s pre-trained transformer model. In further posts, we will go over &lt;strong&gt;LSTM&lt;/strong&gt;, &lt;strong&gt;BERT&lt;/strong&gt;, and &lt;strong&gt;Google’s T5 transformer&lt;/strong&gt; models in-depth and look at how they work to do tasks such as &lt;em&gt;&lt;strong&gt;abstractive summarization&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Key Authentication and Rate Limiting plugins of Kong on Flask API</title>
    <link href="https://turbolab.in/key-authentication-and-rate-limiting-plugins-of-kong-on-flask-api/"/>
    <updated>2018-09-28T12:11:56.000Z</updated>
    <published>2018-09-28T11:45:43.000Z</published>
    <id>https://turbolab.in/key-authentication-and-rate-limiting-plugins-of-kong-on-flask-api/</id>
    <content type="html">&lt;p&gt;In the &lt;a href=&quot;https://turbolab.in/registering-the-api-as-service-in-kong/&quot;&gt;&lt;strong&gt;previous post&lt;/strong&gt;&lt;/a&gt;**,**we discussed about registering the &lt;a href=&quot;https://github.com/Vasistareddy/flaskapi_test_docker.git&quot;&gt;&lt;strong&gt;Flask API&lt;/strong&gt;&lt;/a&gt; to &lt;a href=&quot;https://turbolab.in/kong-api-gateway-installation-guide-for-beginners/&quot;&gt;&lt;strong&gt;KONG&lt;/strong&gt;&lt;/a&gt;service. In this tutorial, we discussed about applying &lt;a href=&quot;https://turbolab.in/kong-api-gateway-installation-guide-for-beginners/&quot;&gt;&lt;strong&gt;KONG&lt;/strong&gt;&lt;/a&gt; plugins like &lt;strong&gt;Key Authentication&lt;/strong&gt; and &lt;strong&gt;Rate Limiting&lt;/strong&gt;on the registered API.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Key-Authentication&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate-limiting&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;key-authentication-plugin&quot; tabindex=&quot;-1&quot;&gt;Key-Authentication Plugin&lt;/h3&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/F2KUKDW0MA-418.webp 418w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/F2KUKDW0MA-418.png&quot; alt=&quot;Access control of consumer over the API&quot; width=&quot;418&quot; height=&quot;87&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Access control of consumer over the API&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;This Key Authentication plugin can be added to a &lt;strong&gt;service&lt;/strong&gt; or a &lt;strong&gt;route&lt;/strong&gt;. Consumers can add their Apikey either in a querystring parameter or a header to authenticate their requests. Plugins registered can be viewed at &lt;a href=&quot;http://localhost:8001/plugins&quot;&gt;http://localhost:8001/plugins&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Adding key-auth plugin to the service&lt;/h4&gt;
&lt;p&gt;You should provide service_id(&lt;code&gt;d4079539–45d0–4798–96a8–6ac39d86b6cb)&lt;/code&gt; or service_name &lt;code&gt;(testApi)&lt;/code&gt; of that specific service to register the key-auth plugin. Get the service details at &lt;code&gt;http://localhost:8001/services.&lt;/code&gt; Register the &lt;code&gt;key-auth&lt;/code&gt; plugin to the service with the following cQuery.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -X POST http://localhost:8001/services/testApi/plugins &#92;   --data &amp;quot;name=key-auth&amp;quot;&lt;/code&gt;&lt;em&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;/em&gt;&lt;code&gt;{“created_at”:1536501460000,”config”:{“key_in_body”:false,”run_on_preflight”:true,”anonymous”:””,”hide_credentials”:false,”key_names”:[“apikey”]},”id”:”0fe22dc7–1bae-4a94–9841-d66469a1faaf”,”enabled”:true,”service_id”:”d4079539–45d0–4798–96a8–6ac39d86b6cb”,”name”:”key-auth”}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The above response clearly tells us to pass &lt;code&gt;“apikey”&lt;/code&gt; has to pass as header or querystring parameter.&lt;/p&gt;
&lt;p&gt;Now see what happens, if we access our API&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -i -X GET --url http://localhost:8000/api/v1/test2 --header &#39;Host: localhost&#39;&lt;/code&gt;&lt;em&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;/em&gt; &lt;code&gt;HTTP/1.1 401 Unauthorized   {&amp;quot;message&amp;quot;:&amp;quot;No API key found in request&amp;quot;}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Our consumers needs&lt;code&gt;“apikey”&lt;/code&gt; to access the service. Lets set &lt;code&gt;apikey&lt;/code&gt; to each consumer we registered with the following query.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -X POST http://localhost:8001/consumers/consumer1/key-auth --data &amp;quot;&amp;quot;&lt;/code&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;/em&gt;&lt;strong&gt;&lt;code&gt;{&amp;quot;id&amp;quot;:&amp;quot;508bee01-613b-4f21-8ced-b098395e0a47&amp;quot;,&amp;quot;created_at&amp;quot;:1536498848000,&amp;quot;key&amp;quot;:&amp;quot;M1PyCiEee7QbI44FWC24G4WK7Bb4vZgm&amp;quot;,&amp;quot;consumer_id&amp;quot;:&amp;quot;abd67a95-a247-4141-b329-d74fe6d3fb06&amp;quot;}&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Pass the &lt;code&gt;“key”&lt;/code&gt; as header or querystring parameter to access the service&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -i -X GET --url http://localhost:8000/api/v1/test2 --header &#39;Host: localhost&#39; --header &#39;apikey: M1PyCiEee7QbI44FWC24G4WK7Bb4vZgm&#39;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;HTTP/1.1 200 OK&lt;/code&gt;&lt;em&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;/em&gt;&lt;strong&gt;&lt;code&gt;{“message”:”second end point &#92;”test2&#92;” is called”,”status_code”:200}&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Consumer keys can be accessed at &lt;a href=&quot;http://localhost:8001/consumers/consumer1/key-auth&quot;&gt;&lt;em&gt;&lt;strong&gt;http://localhost:8001/consumers/consumer1/key-auth&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Adding key-auth plugin to route&lt;/h4&gt;
&lt;p&gt;delete the key-auth plugin of the service and lets add on the route to test.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -i -X DELETE http://localhost:8001/plugins/0fe22dc7-1bae-4a94-9841-d66469a1faaf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;set key-auth plugin to the route &lt;code&gt;/api/v1/test1 with the following query.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -X POST http://localhost:8001/routes/668ac4ab-4226-45f7-9067-e30c032a840f/plugins --data &amp;quot;name=key-auth&amp;quot;&lt;/code&gt;&lt;em&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;/em&gt; &lt;code&gt;{&amp;quot;created_at&amp;quot;:1536508484000,&amp;quot;config&amp;quot;:{&amp;quot;key_in_body&amp;quot;:false,&amp;quot;run_on_preflight&amp;quot;:true,&amp;quot;anonymous&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;hide_credentials&amp;quot;:false,&amp;quot;key_names&amp;quot;:[&amp;quot;apikey&amp;quot;]},&amp;quot;id&amp;quot;:&amp;quot;048d6fcc-f1f0-4f04-b3a4-584754871dd8&amp;quot;,&amp;quot;enabled&amp;quot;:true,&amp;quot;route_id&amp;quot;:&amp;quot;668ac4ab-4226-45f7-9067-e30c032a840f&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;key-auth&amp;quot;}&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/58AJf8rjr7-480.webp 480w, https://turbolab.in/img/58AJf8rjr7-507.webp 507w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/58AJf8rjr7-480.png&quot; alt=&quot;Key-Auth on route id&quot; width=&quot;507&quot; height=&quot;454&quot; srcset=&quot;https://turbolab.in/img/58AJf8rjr7-480.png 480w, https://turbolab.in/img/58AJf8rjr7-507.png 507w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Key-Auth on route id&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Now you can access route &lt;code&gt;/api/v1/test2&lt;/code&gt; without authentication and route &lt;code&gt;/api/v1/test1&lt;/code&gt; with authentication, since we just set the authentication on this route. Lets test this&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ curl -i -X GET --url http://localhost:8000/api/v1/test1 --header &#39;Host: localhost&#39;   HTTP/1.1 401 Unauthorized   {&amp;quot;message&amp;quot;:&amp;quot;No API key found in request&amp;quot;}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The above query passed without &lt;code&gt;apikey&lt;/code&gt; and response is &lt;code&gt;401 Unauthorized&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ curl -i -X GET --url http://localhost:8000/api/v1/test2 --header &#39;Host: localhost&#39;   HTTP/1.1 200 OK   {&amp;quot;message&amp;quot;:&amp;quot;second end point &#92;&amp;quot;test2&#92;&amp;quot; is called&amp;quot;,&amp;quot;status_code&amp;quot;:200}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The above query passed without &lt;code&gt;apikey&lt;/code&gt; and the response is &lt;code&gt;200 OK.&lt;/code&gt;Because we added &lt;code&gt;key-auth&lt;/code&gt;plugin only on&lt;code&gt;/api/v1/test1&lt;/code&gt; route.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ curl -i -X GET --url http://localhost:8000/api/v1/test1 --header &#39;Host: localhost&#39; --header &#39;apikey: M1PyCiEee7QbI44FWC24G4WK7Bb4vZgm&#39;   HTTP/1.1 200 OK   {&amp;quot;message&amp;quot;:&amp;quot;first end point &#92;&amp;quot;test1&#92;&amp;quot; is called&amp;quot;,&amp;quot;status_code&amp;quot;:200}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Here we conclude that we can provide a specific route of the API to specific consumer with &lt;code&gt;key-auth&lt;/code&gt; plugin.&lt;/p&gt;
&lt;h2 id=&quot;rate-limiting-plugin&quot; tabindex=&quot;-1&quot;&gt;Rate Limiting Plugin&lt;/h2&gt;
&lt;p&gt;This plugin helps us to restrict consumer making requests to our API/Service in a given period of time(seconds, minute, hour, month, year).&lt;/p&gt;
&lt;p&gt;This plugin can be enable on a &lt;strong&gt;service or route or consumer with consumer_id&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enabling on Service&lt;/strong&gt; –  restricts every consumer making requests to the service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enabling on route&lt;/strong&gt;  – restricts every consumer making requests to the specific route of the service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enabling on consumer&lt;/strong&gt;  –  restricts only that specified consumer making requests to any routes of the service.&lt;/p&gt;
&lt;h3 id=&quot;adding-rate-limiting-to-the-service&quot; tabindex=&quot;-1&quot;&gt;Adding rate-limiting to the service:&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;$ curl -X POST http://localhost:8001/services/testApi/plugins &#92;   --data &amp;quot;name=rate-limiting&amp;quot; &#92;   --data &amp;quot;config.minute=2&amp;quot; &#92;   --data &amp;quot;config.hour=100&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;/em&gt;&lt;code&gt;{“created_at”:1536558895000,”config”:{“minute”:2,”policy”:”cluster”,”redis_timeout”:2000,”hide_client_headers”:false,”hour”:100,”limit_by”:”consumer”,”redis_port”:6379,”redis_database”:0,”fault_tolerant”:true},”id”:”38586082–7619–4bf7-b418-afcc65d37f28&amp;quot;,”enabled”:true,”service_id”:”d4079539–45d0–4798–96a8–6ac39d86b6cb”,”name”:”rate-limiting”}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This plugin is &lt;strong&gt;by-default limit by consumer&lt;/strong&gt;. From the query above, we can send only &lt;strong&gt;2 requests per minute&lt;/strong&gt; and &lt;strong&gt;100 per hour.&lt;/strong&gt;&lt;br&gt;
Response from Kong after exceeding limit is &lt;code&gt;{“message”:”API rate limit exceeded”}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lets test this by simple python script.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;import requests   from time import sleep   for i in range(1,10):   response = requests.get(“http://localhost:8000/api/v1/test1?apikey=M1PyCiEee7QbI44FWC24G4WK7Bb4vZgm&amp;quot;)   print(response.ok, response.text)   sleep(1)&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/K0DsOcp3hj-480.webp 480w, https://turbolab.in/img/K0DsOcp3hj-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/K0DsOcp3hj-480.png&quot; alt=&quot;Response of rate-limiting plugin&quot; width=&quot;800&quot; height=&quot;440&quot; srcset=&quot;https://turbolab.in/img/K0DsOcp3hj-480.png 480w, https://turbolab.in/img/K0DsOcp3hj-800.png 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Response of rate-limiting plugin&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Similarly you can play around with this rate-limiting plugin on consumer or route of the service too. Specify the consumer_id in the following query to add rate-limiting plugin to the consumer.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ curl -X POST http://localhost:8001/plugins &#92;   --data &amp;quot;name=rate-limiting&amp;quot; &#92;   --data &amp;quot;consumer_id={consumer_id}&amp;quot; &#92;   --data &amp;quot;config.second=5&amp;quot; &#92;   --data &amp;quot;config.hour=10000&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To add rate-limiting plugin on the route of the service, you need to add the route_id to the following query.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ curl -X POST http://localhost:8001/routes/{route_id}/plugins &#92;   --data &amp;quot;name=rate-limiting&amp;quot; &#92;   --data &amp;quot;config.minute=2&amp;quot; &#92;   --data &amp;quot;config.hour=100&amp;quot;&lt;/code&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Registering the API as service in KONG</title>
    <link href="https://turbolab.in/registering-the-api-as-service-in-kong/"/>
    <updated>2018-09-28T11:53:34.000Z</updated>
    <published>2018-09-28T11:19:54.000Z</published>
    <id>https://turbolab.in/registering-the-api-as-service-in-kong/</id>
    <content type="html">&lt;p&gt;In the previous &lt;a href=&quot;https://turbolab.in/kong-api-gateway-installation-guide-for-beginners/&quot;&gt;post&lt;/a&gt;, we have discussed about the API Gateway uses and detailed &lt;a href=&quot;https://konghq.com/&quot;&gt;Kong API&lt;/a&gt; Gateway Installation process. We will proceed to register our API to KONG service and apply Kong plugins like &lt;strong&gt;Key Authentication&lt;/strong&gt; and &lt;strong&gt;Rate-limiting&lt;/strong&gt; on that API.&lt;/p&gt;
&lt;p&gt;Lets break down the tutorial into two parts:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Part 1&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set up the Flask API. &lt;a href=&quot;https://github.com/Vasistareddy/flaskapi_test_docker&quot;&gt;Follow this repo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Register our Flask API as &lt;strong&gt;service&lt;/strong&gt; in Kong.&lt;/li&gt;
&lt;li&gt;Register our endpoints of Flask API as &lt;strong&gt;routes&lt;/strong&gt; in Kong.&lt;/li&gt;
&lt;li&gt;Create Consumers for our &lt;a href=&quot;https://konghq.com/&quot;&gt;Kong&lt;/a&gt; service.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Part 2&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Apply &lt;a href=&quot;https://konghq.com/&quot;&gt;Kong&lt;/a&gt; plugins on the services/routes/consumers.&lt;br&gt;
Detailed work on plugins are discussed in next &lt;a href=&quot;https://medium.com/@vasista/part-2-key-authentication-and-rate-limiting-plugins-of-kong-on-flask-api-9b14f50e5b88&quot;&gt;part&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;set-up-the-flask-api&quot; tabindex=&quot;-1&quot;&gt;Set up the Flask API&lt;/h3&gt;
&lt;p&gt;We need an API to proceed further into the discussion. So, lets setup Flask API from this &lt;a href=&quot;https://github.com/Vasistareddy/flaskapi_test_docker.git&quot;&gt;&lt;strong&gt;link&lt;/strong&gt;&lt;/a&gt;. Steps needed to install are clearly mentioned in that git repo.&lt;/p&gt;
&lt;p&gt;Else, you can proceed if you have an API without setting up the Flask API mentioned above.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;http://localhost:5055&lt;/code&gt; is the domain and port(service) and &lt;code&gt;/api/v1/test1, /api/v1/test2&lt;/code&gt; are the endpoints(routes) which are used to communicate with the Flask API.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/SEW_NeGNBs-480.webp 480w, https://turbolab.in/img/SEW_NeGNBs-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/SEW_NeGNBs-480.png&quot; alt=&quot;Flask API with endpoints&quot; width=&quot;800&quot; height=&quot;131&quot; srcset=&quot;https://turbolab.in/img/SEW_NeGNBs-480.png 480w, https://turbolab.in/img/SEW_NeGNBs-800.png 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Flask API with endpoints&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id=&quot;register-our-flask-api-as-service-in-kong&quot; tabindex=&quot;-1&quot;&gt;Register our Flask API as service in Kong:&lt;/h3&gt;
&lt;p&gt;Kong restful framework makes our job easy for Administration purposes. One can check the registered services at &lt;code&gt;http://localhost:8001/services&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can register our Flask API as service in Kong with the below query&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -i -X POST &#92;   --url http://localhost:8001/services/ &#92;   --data &#39;name=testApi&#39; &#92;   --data &#39;url=http://localhost:5055&#39;&lt;/code&gt;&lt;em&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;/em&gt; &lt;code&gt;{“host”:”localhost”,”created_at”:1536467002,”connect_timeout”:60000,”id”:”d4079539–45d0–4798–96a8–6ac39d86b6cb”,”protocol”:”http”,”name”:”testApi”,”read_timeout”:60000,”port”:5055,”path”:null,”updated_at”:1536467002,”retries”:5,”write_timeout”:60000}&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/hFhFnWJUXV-478.webp 478w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/hFhFnWJUXV-478.png&quot; alt=&quot;Service Registered&quot; width=&quot;478&quot; height=&quot;422&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Service Registered&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id=&quot;register-end-points-of-flask-api-as-routes-in-kong&quot; tabindex=&quot;-1&quot;&gt;Register end points of Flask API as routes in KONG&lt;/h3&gt;
&lt;p&gt;We registered our Flask APIs domain and port as a service. The end points of Flask API are the key to communicate. So, lets register them as routes in Kong. One can check registered routes of the service at &lt;code&gt;http://localhost:8001/routes&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Register the route &lt;code&gt;/api/v1/test1&lt;/code&gt; to the service with the following query&lt;br&gt;
&lt;code&gt;curl -i -X POST &#92;   --url http://localhost:8001/services/testApi/routes &#92;   --data &#39;hosts[]=localhost&#39; &#92;   --data &#39;paths[]=/api/v1/test1&#39; &#92;   --data &#39;strip_path=false&#39; &#92;   --data &#39;methods[]=GET&#39;&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/OSQC8kNTY0-480.webp 480w, https://turbolab.in/img/OSQC8kNTY0-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/OSQC8kNTY0-480.png&quot; alt=&quot;Response generated from the above query&quot; width=&quot;800&quot; height=&quot;105&quot; srcset=&quot;https://turbolab.in/img/OSQC8kNTY0-480.png 480w, https://turbolab.in/img/OSQC8kNTY0-800.png 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Response generated from the above query&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/_t7uIrAHMe-480.webp 480w, https://turbolab.in/img/_t7uIrAHMe-499.webp 499w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/_t7uIrAHMe-480.png&quot; alt=&quot;endpoint registered to the above service&quot; width=&quot;499&quot; height=&quot;595&quot; srcset=&quot;https://turbolab.in/img/_t7uIrAHMe-480.png 480w, https://turbolab.in/img/_t7uIrAHMe-499.png 499w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;endpoint registered to the above service&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Same way, register the other endpoint too. Confirm the two endpoints &lt;a href=&quot;http://localhost:8001/routes&quot;&gt;here&lt;/a&gt;. Make sure that &lt;code&gt;service id&lt;/code&gt; matches to their respective&lt;code&gt;/routes.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now our requests to API forwards through Kong Gateway at port &lt;code&gt;8000&lt;/code&gt;. since, Kong handles proxy requests on port &lt;code&gt;:8000&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Check our API response at &lt;code&gt;8000   curl -i -X GET &#92;   --url http://localhost:8000/api/v1/test1 &#92;   --header &#39;Host: localhost&#39;&lt;/code&gt;&lt;em&gt;&lt;strong&gt;Response:&lt;br&gt;
HTTP/1.1 200 OK&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;code&gt;{&amp;quot;message&amp;quot;:&amp;quot;first end point &#92;&amp;quot;test1&#92;&amp;quot; is called&amp;quot;,&amp;quot;status_code&amp;quot;:200}&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;create-consumers-for-our-service&quot; tabindex=&quot;-1&quot;&gt;Create consumers for our service&lt;/h3&gt;
&lt;p&gt;Now we just registered our API to Kong. We will have consumers sending multiple requests to our Flask API when it goes to public. How can we set Security and control over API? It can be achieved by adding Kong plugins like Authentication and rate-limiting on services or routes. To test these Kong plugins, we need some consumers. We can register the consumers with &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt; with the following query.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ curl -X POST http://localhost:8001/consumers --data &amp;quot;username=consumer1&amp;quot; --data &amp;quot;custom_id=101&amp;quot;&lt;/code&gt;&lt;em&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;/em&gt;&lt;code&gt;{&amp;quot;custom_id&amp;quot;:&amp;quot;101&amp;quot;,&amp;quot;created_at&amp;quot;:1536496865,&amp;quot;username&amp;quot;:&amp;quot;consumer1&amp;quot;,&amp;quot;id&amp;quot;:&amp;quot;abd67a95-a247-4141-b329-d74fe6d3fb06&amp;quot;}   $ curl -X POST http://localhost:8001/consumers --data &amp;quot;username=consumer2&amp;quot; --data &amp;quot;custom_id=102&amp;quot;&lt;/code&gt;&lt;em&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;/em&gt;&lt;code&gt;{&amp;quot;custom_id&amp;quot;:&amp;quot;102&amp;quot;,&amp;quot;created_at&amp;quot;:1536496883,&amp;quot;username&amp;quot;:&amp;quot;consumer2&amp;quot;,&amp;quot;id&amp;quot;:&amp;quot;57f1a4dd-c551-43ff-9e06-56501f0d39ac&amp;quot;}&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/8DGe60vem3-468.webp 468w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/8DGe60vem3-468.png&quot; alt=&quot;Consumers eager to access our service.&quot; width=&quot;468&quot; height=&quot;378&quot;&gt;&lt;/picture&gt;&lt;figcaption&gt;Consumers eager to access our service.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;One can check registered consumers of the service(s)/route(s) at &lt;code&gt;http://localhost:8001/consumers&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Flask API registered to KONG service and follow this &lt;a href=&quot;https://medium.com/@vasista/part-2-key-authentication-and-rate-limiting-plugins-of-kong-on-flask-api-9b14f50e5b88&quot;&gt;&lt;strong&gt;discussion&lt;/strong&gt;&lt;/a&gt; about applying plugins like Key-Authentication and Rate-Limiting.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://turbolab.in/kong-api-gateway-installation-guide-for-beginners/&quot;&gt;Installation of Kong has discussed in here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/@vasista/part-2-key-authentication-and-rate-limiting-plugins-of-kong-on-flask-api-9b14f50e5b88&quot;&gt;Key Authentication and Rate Limiting plugins of Kong on Flask API&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Kong API Gateway Installation Guide for beginners</title>
    <link href="https://turbolab.in/kong-api-gateway-installation-guide-for-beginners/"/>
    <updated>2018-09-29T08:01:46.000Z</updated>
    <published>2018-09-12T06:55:22.000Z</published>
    <id>https://turbolab.in/kong-api-gateway-installation-guide-for-beginners/</id>
    <content type="html">&lt;p&gt;[et_pb_section admin_label=”section”]&lt;br&gt;
[et_pb_row admin_label=”row”]&lt;br&gt;
[et_pb_column type=”4_4″]&lt;br&gt;
[et_pb_text admin_label=”Text”]&lt;/p&gt;
&lt;h3 id=&quot;kong-api-gateway-installation-guide-for-beginners&quot; tabindex=&quot;-1&quot;&gt;Kong API Gateway Installation Guide for beginners&lt;/h3&gt;
&lt;p&gt;In this post, we will discuss about the uses of API Gateways and the installation of open source KONG API Gateway.&lt;/p&gt;
&lt;p&gt;API Gateways provides security and control over the access by sitting in-front of any number of API services. &lt;a href=&quot;https://konghq.com/&quot;&gt;KONG&lt;/a&gt;, &lt;a href=&quot;https://tyk.io/&quot;&gt;Tyk&lt;/a&gt;, &lt;a href=&quot;https://apiumbrella.io/&quot;&gt;API Umbrella&lt;/a&gt;, &lt;a href=&quot;https://www.getambassador.io/&quot;&gt;Ambassador&lt;/a&gt;, &lt;a href=&quot;https://gravitee.io/&quot;&gt;Gravitee.io&lt;/a&gt; etc., are some of the API Gateways currently available in the market. These Gateways provides services like Authentication, rate-limiting, analysis, logging etc., to your API endpoints.&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/WA0vDTThYa-480.webp 480w, https://turbolab.in/img/WA0vDTThYa-800.webp 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/WA0vDTThYa-480.jpeg&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;600&quot; srcset=&quot;https://turbolab.in/img/WA0vDTThYa-480.jpeg 480w, https://turbolab.in/img/WA0vDTThYa-800.jpeg 800w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Flowchart diagram to illustrate the API Gateway usage&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Why choosing KONG over other gateways? Because, it is most straightforward of the choices above and the community is very much alive.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The latest version of the Kong 0.14.x comes with the support of various platforms. &lt;strong&gt;click here to&lt;/strong&gt; &lt;a href=&quot;https://konghq.com/install/&quot;&gt;&lt;strong&gt;choose&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt; We proceed further with Installing Kong on Ubuntu platform.&lt;/p&gt;
&lt;h3 id=&quot;installing-kong-on-ubuntu&quot; tabindex=&quot;-1&quot;&gt;Installing kong on Ubuntu&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Installation of deb file&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;download the debian file &lt;a href=&quot;https://bintray.com/kong/kong-community-edition-deb/download_file?file_path=dists/kong-community-edition-0.14.1.zesty.all.deb&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;After downloading at the file location, do the following.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;$ sudo apt-get update   $ sudo apt-get install openssl libpcre3 procps perl   $ sudo dpkg -i kong-community-edition-0.14.1.zesty.all.deb&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Database setup&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now, we have to setup database. Kong supports &lt;strong&gt;PostgreSQL&lt;/strong&gt; and &lt;strong&gt;cassandra&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Lets setup &lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-16-04&quot;&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt; for KONG with user, database name and its password.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ sudo apt-get install postgresql postgresql-contrib&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Switch over to the &lt;code&gt;postgres&lt;/code&gt; account on your server which created at the time of installation procedure by typing:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ sudo -i -u postgres&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Type &lt;code&gt;psql&lt;/code&gt; to access a Postgres prompt and &lt;code&gt;&#92;q&lt;/code&gt; to exit the prompt.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Setup USER, DATABASE with password&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;postgres=# CREATE USER kong; CREATE DATABASE kong OWNER kong;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;postgres=# ALTER USER kong WITH PASSWORD &#39;password you set&#39;;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update Kong configuration and run migrations&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Generally the Kong configuration path will be at &lt;code&gt;/etc/kong/kong.conf.default&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ sudo cp /etc/kong/kong.conf.default /etc/kong/kong.conf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;run the migrations job before the start&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ sudo kong migrations up -c /etc/kong/kong.conf   Error: missing password, required for connect   Run with — v (verbose) or — vv (debug) for more details&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The above error might encounter if you don’t update the Kong configuration file. For this, you have to do the following steps.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ sudo nano /etc/kong/kong.conf&lt;/code&gt;and paste the below lines &lt;code&gt;pg_user = kong   pg_password = password you set   pg_database = kong&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Running Kong migrations&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ sudo kong migrations up -c /etc/kong/kong.conf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If this throws an error &lt;code&gt;Error: [postgres error] could not retrieve current migrations: [postgres error] ERROR: function to_regclass(unknown) does not exist (8)&lt;/code&gt; , check the &lt;strong&gt;PostgreSQL&lt;/strong&gt; version here.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ sudo service postgresql status&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Kong requires &lt;strong&gt;PostgreSQL 9.5&lt;/strong&gt; or later. &lt;a href=&quot;https://medium.com/@tk512/upgrading-postgresql-from-9-4-to-9-5-on-ubuntu-14-04-lts-dfd93773d4a5&quot;&gt;Upgrade the older version here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you upgrade to PostgreSQL 9.5 or later, then you don’t have to setup the database, user and password. If you install, you should setup again.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Start Kong&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ sudo kong start -c /etc/kong/kong.conf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Stop Kong&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ sudo kong stop&lt;/code&gt; &lt;strong&gt;#to stop the Kong&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Final step to make sure the installation and setup process succeeded is:&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ curl -i http://localhost:8001/&lt;/code&gt; or &lt;code&gt;http://localhost:8001/&lt;/code&gt; in the browser&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/MroGShsF9l-418.webp 418w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/MroGShsF9l-418.png&quot; alt=&quot;&quot; width=&quot;418&quot; height=&quot;755&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
&lt;p&gt;Welcome to Kong&lt;/p&gt;
&lt;p&gt;That’s the end of Kong setup.&lt;/p&gt;
&lt;p&gt;[/et_pb_text]&lt;br&gt;
[/et_pb_column]&lt;br&gt;
[/et_pb_row]&lt;br&gt;
[/et_pb_section]&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>We are hiring Junior Python Developers to our data gathering team</title>
    <link href="https://turbolab.in/junior-python-developers-to-our-data-gathering-team/"/>
    <updated>2018-09-27T06:11:18.000Z</updated>
    <published>2018-03-11T16:59:40.000Z</published>
    <id>https://turbolab.in/junior-python-developers-to-our-data-gathering-team/</id>
    <content type="html">&lt;p&gt;[et_pb_section bb_built=”1″ _builder_version=”3.0.47″][et_pb_row _builder_version=”3.0.47″ background_size=”initial” background_position=”top_left” background_repeat=”repeat”][et_pb_column type=”4_4″][et_pb_text _builder_version=”3.0.101″ background_size=”initial” background_position=”top_left” background_repeat=”repeat”]&lt;/p&gt;
&lt;p&gt;We are hiring Junior Python Developers again. This time, it is for our Data Gathering Team –  for writing scripts to scrape, clean and store data from the web.  This will be an excellent opportunity for fresh graduates interested in getting into the world of python and data analysis.&lt;/p&gt;
&lt;h2 id=&quot;what-is-the-job-like&quot; tabindex=&quot;-1&quot;&gt;What is the job like?&lt;/h2&gt;
&lt;p&gt;Most of your day would be spent analyzing websites, xpaths and HTML pages to extract structured data from the unstructured web. You will work with a team of 20+ developers who are fun to work with. Here are some of the stuff you would do –&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Build web scrapers using Python, BeautifulSoup, LXML&lt;/li&gt;
&lt;li&gt;Run scrapers in our highly distributed data gathering platform&lt;/li&gt;
&lt;li&gt;Analyze the collected data using data analysis tools like Python-Pandas, OpenRefine, Apache Spark, etc.&lt;/li&gt;
&lt;li&gt;Write tests to make sure the collected data is clean and accurate&lt;/li&gt;
&lt;li&gt;Create Visualisations on the collected data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It would be the first step of getting into more exciting jobs at Turbolab – everyone starts as a developer in the data gathering team before moving into our other teams like Data Analysis &amp;amp;Visualisation, Distributed Platforms and more.&lt;/p&gt;
&lt;h2 id=&quot;what-are-the-requirements&quot; tabindex=&quot;-1&quot;&gt;What are the requirements?&lt;/h2&gt;
&lt;p&gt;We are looking for highly energetic individuals who have a passion for programming and solving challenges.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Know to code&lt;/strong&gt; in at least one programming language. Writing “Hello World” or printing numbers won’t be enough. Knowing Python isn’t mandatory – but should be able to learn to make scripts using python yourself in a week.&lt;/li&gt;
&lt;li&gt;**Comfortable using a Linux environment to work with –**90% of computers in our office run Linux. 98% of the developers here use some flavor of Ubuntu to work on. We prefer to hire people who already know their way around a Linux terminal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You should be a self-learner&lt;/strong&gt;. We are a fast-paced bootstrapped startup – means there is no time for us to put all hires into extensive training programs like large companies. We expect people to learn whatever they’ve got to learn by themselves. This doesn’t mean you are on your own – you can always ask for help when you are stuck, and there will be people here to help you out.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Must be a person who enjoys working with others&lt;/strong&gt;. We place a lot of emphasis on our culture because we are both a team and a family. We want to create an environment that is friendly, warm, and exciting for everyone who works here.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-is-in-it-for-you&quot; tabindex=&quot;-1&quot;&gt;What is in it for you?&lt;/h2&gt;
&lt;p&gt;Here is the most important one&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You will learn a lot more than what you did in your college in less than 2 months&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some less important ones –&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Relaxed, Tension Free Environment&lt;/li&gt;
&lt;li&gt;Good work-life balance – work on your own schedule. We live by “Work Wherever, Wear Whatever, Play  Whenever.”&lt;/li&gt;
&lt;li&gt;Flexible Vacation Policy – leaves are unlimited as long as you get stuff done&lt;/li&gt;
&lt;li&gt;Salary Benefits – we pay you better than most companies in Kochi.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can read more about our work culture in our &lt;a href=&quot;https://turbolab.in/careers/&quot;&gt;careers page&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Go &lt;a href=&quot;https://turbolab.recruiterbox.com/jobs/fk0fynq/&quot;&gt;here&lt;/a&gt; and apply now.&lt;/p&gt;
&lt;p&gt;[/et_pb_text][et_pb_button button_url=”https://turbolab.recruiterbox.com/jobs/fk0fynq/” url_new_window=”on” button_text=”Apply Now” _builder_version=”3.0.101″ /][/et_pb_column][/et_pb_row][/et_pb_section]&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Turbolab Summer Internship 2018</title>
    <link href="https://turbolab.in/turbolab-summer-internship-2018/"/>
    <updated>2024-07-26T10:03:16.000Z</updated>
    <published>2018-03-09T14:25:07.000Z</published>
    <id>https://turbolab.in/turbolab-summer-internship-2018/</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ready to take your education to next level?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Join us for a unique 8 week (04th June to 31st July) internship where you get paid and also offers personal and professional development. Be a part of live real-world projects, training sessions and everything you need to kickstart your career.&lt;/p&gt;
&lt;p&gt;As a technical intern, you will be tackling the technical problems from any of the domains including web scraping, data mining, data analytics, machine learning, web application development, distributed computing etc and much more.&lt;/p&gt;
&lt;h5&gt;Perks of being an intern @ Turbolab:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Be a part of a fun-loving company composed of energetic and talented individuals in a low-stress atmosphere.&lt;/li&gt;
&lt;li&gt;You will have a lot of room to improve yourself.&lt;/li&gt;
&lt;li&gt;We’ve got PS4, CSGO, FIFA, Uno, Exploding kittens etc and much more&lt;/li&gt;
&lt;li&gt;A pantry packed with free food, drinks and coffee&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Prefered qualifications&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Currently pursuing/have completed a professional degree in 2018&lt;/li&gt;
&lt;li&gt;Good problem-solving skills&lt;/li&gt;
&lt;li&gt;Can think out-of-the-box&lt;/li&gt;
&lt;li&gt;Basic knowledge in python&lt;/li&gt;
&lt;li&gt;Basic understanding of data structures and algorithms&lt;/li&gt;
&lt;li&gt;Basic understanding of Linux commands&lt;/li&gt;
&lt;li&gt;Can hustle&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>When a newlywed teammate decided to try sentiment analysis</title>
    <link href="https://turbolab.in/when-a-newlywed-teammate-decided-to-try-sentiment-analysis/"/>
    <updated>2024-07-26T10:03:51.000Z</updated>
    <published>2018-03-09T14:19:15.000Z</published>
    <id>https://turbolab.in/when-a-newlywed-teammate-decided-to-try-sentiment-analysis/</id>
    <content type="html">&lt;p&gt;So this might be what goes through minds of married data scientists&lt;/p&gt;
&lt;figure&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://turbolab.in/img/Ug5ycWl5yN-480.webp 480w, https://turbolab.in/img/Ug5ycWl5yN-661.webp 661w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://turbolab.in/img/Ug5ycWl5yN-480.png&quot; alt=&quot;&quot; width=&quot;661&quot; height=&quot;638&quot; srcset=&quot;https://turbolab.in/img/Ug5ycWl5yN-480.png 480w, https://turbolab.in/img/Ug5ycWl5yN-661.png 661w&quot; sizes=&quot;(min-width: 820px) 760px, 100vw&quot;&gt;&lt;/picture&gt;&lt;/figure&gt;
</content>
  </entry>
</feed>
