<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Farisology: Exploring Data Science and AI Insights for Modern Innovations]]></title><description><![CDATA[Unveiling AI, LLMs, and Data Science Insights. Expert perspectives from a Lead Data Scientist. Explore innovation and practical expertise on Farisology.]]></description><link>https://farisology.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 20:40:39 GMT</lastBuildDate><atom:link href="https://farisology.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[RAG vs Fine-tuning: Which is Better for Your LLM Strategy?]]></title><description><![CDATA[I. This is real!!
Imagine this scenario: a lawyer uses ChatGPT to assist with legal research for a high-stakes case. He trusts the AI’s capabilities, expecting it to streamline his workflow. However, instead of easing his burden, the AI inadvertently...]]></description><link>https://farisology.com/rag-vs-fine-tuning-which-is-better-for-your-llm-strategy</link><guid isPermaLink="true">https://farisology.com/rag-vs-fine-tuning-which-is-better-for-your-llm-strategy</guid><category><![CDATA[llm]]></category><category><![CDATA[AWS]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[generative ai]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Mon, 29 Apr 2024 18:00:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/nGoCBxiaRO0/upload/b142a4a99704e245ef426b831bd8966b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-i-this-is-real">I. This is real!!</h2>
<p>Imagine this scenario: a lawyer uses ChatGPT to assist with legal research for a high-stakes case. He trusts the AI’s capabilities, expecting it to streamline his workflow. However, instead of easing his burden, the AI inadvertently creates chaos. It generates and suggests completely fictitious legal cases and citations, which the lawyer, unaware of the inaccuracies, includes in his official court documents. This leads to a bewildering situation in court, undermining his credibility and affecting the case outcome.</p>
<p>This story isn't just a cautionary tale; it's a reality we face as businesses and professionals increasingly depend on advanced AI language models without fully understanding their limitations. These tools, while sophisticated, can produce erroneous ‘hallucinated’ information that seems entirely plausible.</p>
<p>In this article, I will help you understand the abilities and challenges of current AI technologies and show how we can move towards more dependable systems. We will explore the details of Retrieval-Augmented Generation (RAG) and fine-tuning, assisting you in determining the most suitable approach for your requirements.</p>
<h2 id="heading-ii-how-llms-are-trained">II. How LLMs are Trained</h2>
<p>Let's start with a quick primer on how these powerful language models are trained. Think of them as digital sponges, soaking up vast amounts of textual data from the internet and books. Through a process called self-supervised learning, they learn to predict missing words and understand the context of sentences. It's like solving a massive fill-in-the-blanks puzzle, training the models to understand and generate human-like language.</p>
<p>Because large language models are trained on a huge corpus of textual data. This both gave the models revolutionary capabilities compared to their predecessors and also manifested new challenges. Today we know that the latest model from Meta, llama3 was trained on over 15T tokens of data which is 7 times the training set of its previous model llama2.</p>
<h2 id="heading-iii-challenges-faced-by-llms">III. Challenges Faced by LLMs</h2>
<p>General models like GPT3.5 and llama3 are useful for various tasks. However, they come with challenges that can vary in severity based on the specific use case. What are these challenges?</p>
<ul>
<li><p>Limited access to up-to-date information</p>
</li>
<li><p>Lack of expertise in specific domains</p>
</li>
<li><p>Lack of factualness and accuracy</p>
</li>
<li><p>Hallucinations</p>
</li>
</ul>
<p>You might not notice this clearly if you ask ChatGPT to write you a bio in Star Wars Jedi style. However, if you ask it to help you answer some law-related questions about the state of California, you might encounter laws that do not exist or references to cases that never happened.</p>
<h2 id="heading-iv-generative-ai-approaches">IV. Generative AI Approaches</h2>
<p>There are at least two core factors that we can think of to illustrate these approaches.</p>
<ul>
<li><p>External Data: Dependency on information and external data is widespread. Organizations could have data that is unique or private to them and is not in the public domain. Gauge the dependency on this data to have good GenAI products.</p>
</li>
<li><p>Capability &amp; Domain Understanding: If the model cannot perform the tasks you expect or shows a lack of domain understanding, it can indicate that you have a higher dependency on this metric for your use case.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714411233505/9593edd9-a8f4-4ce2-a18d-6d2c6e142eba.png" alt class="image--center mx-auto" /></p>
<p>The matrix above intuitively illustrates a progression from low dependency on both metrics (external data and domain understanding), representing use cases or problems that can be solved with prompt engineering. You can test this approach with more advanced prompts during evaluation. However, you might end up in the RAG or Finetuning approaches, which are the main focus in this post. Regarding the finetune+RAG, that is an area where both factors (external data and domain understanding) have a high dependency in your use case.</p>
<h3 id="heading-retrieval-augmented-generation-rag">Retrieval-Augmented Generation (RAG)</h3>
<p>RAG is a technique that combines external information retrieval with text generation. In RAG systems, information is retrieved from external sources such as databases or web content and then incorporated into the text generation process. This approach enhances the generated content by grounding it in real-time or domain-specific data, resulting in more accurate and contextually relevant responses.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714407974870/2c2d3551-6476-4019-bfea-6ab8a8741aaa.png" alt class="image--center mx-auto" /></p>
<p>RAG combines two components: a retriever and a generator. The retriever acts like a smart librarian, scouring external knowledge sources (think Wikipedia, web pages, or specialized databases) to find relevant information for a given input or query. The generator, our trusty language model, then takes that retrieved knowledge and crafts a final output, weaving the facts seamlessly into its response.</p>
<p>Imagine asking an AI assistant powered by RAG, "What are the key events that led to the American Revolution?" The retriever would scour its knowledge base, fetching relevant passages about the Boston Tea Party, the Stamp Act, and other historical events. The generator would then use this retrieved information to construct a well-researched, factual answer, providing a comprehensive overview of the revolutionary events.</p>
<p>You can see here that we have anchored our AI model answers with facts and information that are highly relevant. This makes RAG one of the desired approaches today.</p>
<h3 id="heading-fine-tuning-for-domain-or-task-adaptation-and-personalization">Fine-tuning for Domain or Task Adaptation and Personalization</h3>
<p>But what if you want an AI model tailored to a specific domain or task? That's where fine-tuning comes into play. Just like a talented actor preparing for a new role, fine-tuning involves adapting a pre-trained language model to excel in a particular area. It's like giving the model personalized training sessions using task-specific data or carefully crafted prompts.</p>
<p>For instance, let's say you're a legal firm looking to generate error-free contracts and briefs. You could take a general language model and fine-tune it on a vast corpus of legal documents, teaching it the nuances and terminology of the legal domain. Example of fine-tuning methods:</p>
<ul>
<li><p><strong>Task Specific</strong>: Fine-tuning often starts with task-specific datasets, where the model is exposed to examples and labelled data relevant to the target task.</p>
</li>
<li><p><strong>Domain Adaptation</strong>: Fine-tuning can be domain-specific, where the model is adapted to perform well in a particular industry or field. For instance, fine-tuning an LLM on medical literature to generate medical reports.</p>
</li>
<li><p><strong>Style Transfer</strong>: Models can be fine-tuned to mimic a specific writing style or tone. For example, training an LLM to generate content in the style of a famous author.</p>
</li>
</ul>
<h2 id="heading-v-choosing-the-right-technique-rag-or-fine-tuning">V. Choosing the Right Technique: RAG or Fine-tuning?</h2>
<p>So, which technique should you choose: RAG or fine-tuning? The answer depends on your specific needs and resources. Remember the matrix we have started this article with.</p>
<blockquote>
<p>RAG correlates with knowledge and expands it for the model. Whereas Fine-tuning correlates with skills and capabilities that you want the model to acquire or perform better.</p>
</blockquote>
<p>If you're tackling a knowledge-intensive task like open-domain question answering or generating content across various topics, RAG might be your best bet. By tapping into vast external knowledge sources, RAG can provide well-researched, factual outputs on a wide range of subjects.</p>
<p>On the other hand, if you're working on a domain-specific task like medical dialogue systems or technical writing, fine-tuning could be the way to go. By training the model on task-specific data, you can create a highly specialized AI assistant tailored to your particular domain's intricacies.</p>
<p>And for those seeking a truly personalized AI experience, you could combine both techniques. Fine-tune a RAG model on your specific domain data and preferences, unlocking an AI assistant that's not only knowledgeable but also perfectly aligned with your unique needs.</p>
<h2 id="heading-vi-conclusion">VI. Conclusion</h2>
<p>As we delve deeper into the immense capabilities of generative AI, methods such as RAG and fine-tuning are paving the way for new horizons. Advanced iterations of RAG-based systems are being envisioned to enhance performance and address challenges. LORA techniques for fine-tuning are instrumental in constructing compact yet potent models. These innovative methods will progress, offering a multitude of opportunities. I am optimistic that humanity can leverage these advancements to enhance livelihoods. Achieving this goal will demand substantial effort, but for now, democratization can aid in demonstrating the worth and feasibility of these emerging technologies.</p>
<p>So, what's your AI vision? Whether you're an entrepreneur seeking to revolutionize customer service, a researcher pushing the boundaries of natural language processing, or simply someone who loves to tinker with emerging technologies, the time is ripe to dive into the world of RAG and fine-tuning. Unleash the full potential of generative AI and let your imagination soar!</p>
<hr />
<p><a target="_blank" href="https://docs.pinecone.io/examples/notebooks"><em>Pinecone</em></a><em>documentation could help you a lot take your first baby steps into building a RAG.</em> <a target="_blank" href="https://colab.research.google.com/github/pinecone-io/examples/blob/master/docs/gpt-4-langchain-docs.ipynb"><em>Building RAG tutorial using docs</em></a><em>(Colab notebook).</em></p>
]]></content:encoded></item><item><title><![CDATA[Rethinking AI Training: Lessons from the 'Textbooks is All You Need' Study]]></title><description><![CDATA[Introduction
In an era where magnitude is frequently equated with mastery, the realm of artificial intelligence (AI) has been fervently chasing the creation of ever-larger and more intricate models. The prevailing belief among tech giants seems to be...]]></description><link>https://farisology.com/rethinking-ai-training-lessons-from-the-textbooks-is-all-you-need-study</link><guid isPermaLink="true">https://farisology.com/rethinking-ai-training-lessons-from-the-textbooks-is-all-you-need-study</guid><category><![CDATA[Microsoft]]></category><category><![CDATA[large language models]]></category><category><![CDATA[Python]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[natural language processing]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Tue, 26 Sep 2023 10:41:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ZPOoDQc8yMw/upload/620326b660d9a02aa7c12befc9eec999.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>In an era where magnitude is frequently equated with mastery, the realm of artificial intelligence (AI) has been fervently chasing the creation of ever-larger and more intricate models. The prevailing belief among tech giants seems to be that grandeur in AI is synonymous with greatness. Yet, what if our perspective has been skewed? Drawing inspiration from the insightful findings of Microsoft Research in <a target="_blank" href="https://arxiv.org/pdf/2306.11644.pdf">"Textbooks is All You Need"</a> I invite you on a journey to explore an alternative viewpoint. This is a brief summary of the most important highlights of performance, comparison, and findings of the team.</p>
<h2 id="heading-the-importance-of-high-quality-data"><strong>The Importance of High-Quality Data</strong></h2>
<p>In the rapidly evolving landscape of artificial intelligence, data stands as the foundation upon which models are built. The age-old adage "garbage in, garbage out" has never been more relevant than in the context of training AI models. Imagine feeding a child a diet of misinformation. Over time, this child will develop a skewed perception of the world. In much the same way, when we feed our AI models "dirty data," they develop flawed understandings.</p>
<blockquote>
<p>The quality of data determines not just the efficacy of the model, but also its efficiency, ethical implications, and real-world applicability.</p>
</blockquote>
<p>The findings from Microsoft Research's "Textbooks is All You Need" only serve to emphasize this cardinal principle. The recent "textbooks are all you need" study shows that like humans, AI thrives when it learns from clean, high-quality data.</p>
<p>The paper fundamentally demonstrates that having "textbook quality" data can be a game-changer for AI training. Instead of using vast datasets that often contain noise, redundancies, or even errors, the researchers showed that curating a high-quality dataset — akin to a well-structured textbook — dramatically improves the learning efficiency of language models for code.</p>
<h3 id="heading-efficient-learning"><strong>Efficient Learning</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695716312485/9e4c373b-02ba-4910-b66c-54695d2c5d37.png" alt class="image--center mx-auto" /></p>
<p>The research showcased that their model, phi-1, trained on high-quality data, surpassed the capabilities of most open-source models on coding benchmarks like HumanEval and MBPP. Remarkably, this was achieved even though phi-1 is smaller in terms of model size and was trained on a dataset that's 100x smaller than what many other models utilize.</p>
<p>Taking a closer look at model performances, GPT3.5's massive size of 175B stands out when compared to phi-1's smaller 1.3B. However, it's interesting to note that, when tested on the HumanEval metric, phi-1 still manages to outpace GPT3.5, proving that bigger isn't always better.</p>
<h3 id="heading-mimicking-human-learning"><strong>Mimicking Human Learning</strong></h3>
<p>The most effective human learners seek out high-quality educational resources—well-written textbooks, knowledgeable teachers, and clear lessons. AI models, in essence, are no different from these learners. They are digital students. For them, “textbook quality” data, as showcased in the recent research, should become the benchmark.</p>
<p>Here's my own summary of their approaches:</p>
<ol>
<li><p><strong>Filtering with GPT-4's Aid</strong>: Before diving into large-scale model training, they used GPT-4 to annotate the quality of a small subset of code samples. It's akin to having an expert review a chapter before publishing a textbook, ensuring what gets included is of high instructional value.</p>
</li>
<li><p><strong>Synthetic Textbook-Quality Datasets</strong>: Emulating the essence of textbooks, they didn't just rely on organic code samples. They employed GPT-3.5 to generate synthetic Python textbooks. This method served a dual purpose:</p>
<ul>
<li><p>Provides a rich source of explanatory text combined with relevant code snippets, similar to textbook lessons and examples.</p>
</li>
<li><p>Introduces diversity by setting constraints, ensuring the model encounters varied coding scenarios and doesn’t just memorize a few patterns.</p>
</li>
</ul>
</li>
<li><p><strong>Focus on Basic Algorithmic Skills</strong>: The content specifically targeted promoting reasoning and fundamental coding skills, much like a beginner’s textbook.</p>
</li>
<li><p><strong>Emphasis on Function Completion</strong>: With the CodeExercises dataset, the model was trained to take a function description and generate corresponding code, akin to problem-solving exercises in textbooks. This not only tested the model's understanding but also its application skills.</p>
</li>
<li><p><strong>Careful Decontamination</strong>: Just like how textbooks are revised to remove errors, the team was vigilant in ensuring that their training data didn't contain problems that the model would directly encounter during evaluations, avoiding any undue advantage.</p>
</li>
</ol>
<h3 id="heading-impact-and-performance-details"><strong>Impact and Performance Details</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695721847148/26ca084b-bce3-4b14-b339-97735fc0b04c.png" alt class="image--center mx-auto" /></p>
<p>These bars are grouped together to illustrate distinct aspects:</p>
<p><strong>How Hard the Model Works</strong>: Think of it as varying study durations – from a quick skim to an in-depth study session. It ranges from sifting through 26B bits of data to a whopping 76B.</p>
<p><strong>Size of the Model</strong>: Models come in sizes, these bars also represent models of varying 'sizes'. The spectrum extends from a moderate 350M to a more substantial 1.3B.</p>
<p>Within each of these categories, three unique columns emerge, representing distinct training sets:</p>
<p><strong>The Standard Source (Orange Bars)</strong>: This represents how models fared when trained using regular Python files, commonly sourced from platforms like StackOverflow. Picture this as the outcome of learning from widely available study materials.</p>
<p><strong>Their Unique Mix (Light Green Bars)</strong>: The next column represents models trained on 'CodeTextbook', or tailored dataset. Imagine a curriculum that’s been customized for optimal learning with greater connotations of examples and contexts. (<em>the new dataset curated by the researchers</em>)</p>
<p><strong>Exercises Boost (Dark Green Bars)</strong>: The last set signifies how models did after some extra practice sessions using 'CodeExercises'. Think of it as reinforcing knowledge with exercises after a lesson.</p>
<blockquote>
<p>when the researchers augmented their model with the 'CodeExercises', it's score skyrocketed to 51% on the identical test. Furthermore, it astounded them with its remarkable coding capabilities. Hence, it's evident that armed with optimal training materials and a touch of practice, smaller models can indeed rival, if not surpass, their larger counterparts!</p>
</blockquote>
<h3 id="heading-overcoming-the-shortcomings-of-dirty-data"><strong>Overcoming the Shortcomings of "Dirty Data"</strong></h3>
<p>The Microsoft Research team noted several challenges with commonly used datasets. Picture this: attempting to learn a complex subject from a textbook filled with fragmented explanations, missing sections, and occasionally, even misinformation.</p>
<p>Many of the coding snippets in these standard datasets weren't ideal for teaching the intricate nuances of algorithmic reasoning. They frequently lacked the necessary context, often presenting oversimplified or trivial examples. It's akin to trying to understand a deep philosophical concept from only a single quote. Moreover, there were instances where these snippets were accompanied by insufficient documentation, leaving the AI model to 'guess' its way forward.</p>
<p>The implications of such "dirty" data are vast. Models trained on flawed datasets might produce unreliable or incorrect outputs. They may struggle to generalize beyond their training, faltering when presented with real-world challenges. In essence, their foundation is shaky, potentially leading to inefficient or even incorrect decision-making.</p>
<h2 id="heading-the-power-of-smaller-finely-tuned-models"><strong>The Power of Smaller, Finely-Tuned Models</strong></h2>
<p>In our quest for AI supremacy, we've often assumed that larger models are the answer. However, there are pitfalls: they require more resources, have a larger carbon footprint, and can sometimes be like using a sledgehammer to crack a nut. The success of the phi-1 model from "textbooks is all you need" serves as a testament to the prowess of smaller, well-tuned models.</p>
<p>I invite you to read the <a target="_blank" href="https://arxiv.org/pdf/2306.11644.pdf">full paper</a> if you want more granular details beyond the summary I shared here.</p>
<h2 id="heading-crafting-a-conscious-ai-future"><strong>Crafting a Conscious AI Future</strong></h2>
<p>The rapid growth of AI brings forth ethical challenges, from accountability to potential biases. Imagine AI as a student. We wouldn't want this student to cram from every source blindly; rather, we'd prefer it to learn from the most refined, "textbook quality" materials. It's not just about getting smarter but about learning responsibly.</p>
<p>We're in an era where 'bigger is better' is often the mantra. But with the findings from the Microsoft Research team, there's a twist to the tale. Size isn't the only metric of success. Smaller models, like their newly introduced phi-1, can achieve remarkable feats without devouring our planet's precious resources. Especially as AI takes more roles in our daily lives we start depending on AI more and more.</p>
<p>By ensuring our AI gets its knowledge from the best sources, we're taking a step towards responsible, ethical, and, most importantly, beneficial AI for all. And if adopting smaller models that don't drain and require huge computation resources can get us as far then we should perhaps make "Smaller Smarter" our new mantra.</p>
]]></content:encoded></item><item><title><![CDATA[How We Built Casia: A Deep Dive into Our AI Plant Care Assistant]]></title><description><![CDATA[I've always had a taste for fresh, leafy greens in my salads. Yet, as I embarked on my urban farming journey, I often found myself disappointed by the limited variety of fresh produce available in my local market. The store-bought options either lack...]]></description><link>https://farisology.com/how-we-built-casia-a-deep-dive-into-our-ai-plant-care-assistant</link><guid isPermaLink="true">https://farisology.com/how-we-built-casia-a-deep-dive-into-our-ai-plant-care-assistant</guid><category><![CDATA[llm]]></category><category><![CDATA[openai]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[Python]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Sat, 19 Aug 2023 12:52:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zcVArTF8Frs/upload/315d6bc6d38f78a006eac9c62c249ba5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've always had a taste for fresh, leafy greens in my salads. Yet, as I embarked on my urban farming journey, I often found myself disappointed by the limited variety of fresh produce available in my local market. The store-bought options either lacked the freshness I craved or were just unavailable. It was on one of these fruitless shopping trips that I realized growing my own vegetables at home was the only way to enjoy the robust and varied salads I had in mind.</p>
<p>As I started cultivating my own urban garden, I found myself facing a steep learning curve. There were times when I struggled to identify what my plants needed, and my inexperience made it difficult to find effective solutions. It was during these moments of uncertainty that I realized the value of having an accessible, reliable source of information. My mind drifted back to the remarkable capabilities of large language models, and an idea began to take root.</p>
<h2 id="heading-the-spark">The Spark</h2>
<p>What if I could create an AI plant care assistant that could make the expertise and knowledge required for successful gardening available to anyone? Inspired by the challenges I faced in my own garden and the potential of AI to revolutionize plant care, I set out to create Casia. I imagined a world where the power of AI could democratize gardening, making it more accessible and enjoyable for everyone. My personal struggles with finding fresh vegetables for my salad were replaced by a sense of purpose, knowing that I was building a tool that could help countless urban farmers and plant enthusiasts nurture their green spaces with confidence.</p>
<h2 id="heading-the-hackathon">The hackathon</h2>
<p>When I heard about the Pinecone Hackathon, a spark of excitement ignited within me. I realized that this competition could be the perfect platform to build an AI-powered tool that is really useful. One of the requirements was to build a web or phone application so I went to talk to a couple of friends and told them they loved the idea of an AI-powered plant care assistant. This has given me the spirit to register my newly founded team that is 100% remote and just wants to build something real.</p>
<p>The Pinecone Hackathon offered me not only the opportunity to create my AI assistant but also the resources to do so. It provided access to AI tools like openai, cohere and even hugginface, AWS credits, and a supportive community of like-minded individuals. This environment was a stark contrast to my solitary journey in pondering LLM-powered solutions. As part of the hackathon, I would be able to collaborate with others who shared my enthusiasm for AI and my commitment to sustainability. This was proven when a few individuals reached out to me after the hackathon expressing their love for Casia.</p>
<h2 id="heading-building-casia">Building Casia</h2>
<p>Building Casia required multiple skills and different stages to make this vision a reality. I will explain here what we built and how we exactly built it. The core concept in which Casia was built is called <a target="_blank" href="https://docs.aws.amazon.com/sagemaker/latest/dg/jumpstart-foundation-models-customize-rag.html">Retrieval Augmented Generation</a> or RAG. This type of system expands the knowledge of the AI LLM and enhances it with specific types of data. In our case here the expectation is that we want to reduce confabulations and increase accuracy by providing additional knowledge to the model. This data is structured and sourced from various databases, forums etc of urban gardening and relevant topics.</p>
<h3 id="heading-retrieval-augmented-generationhttpsdocsawsamazoncomsagemakerlatestdgjumpstart-foundation-models-customize-raghtml-rag"><a target="_blank" href="https://docs.aws.amazon.com/sagemaker/latest/dg/jumpstart-foundation-models-customize-rag.html">Retrieval Augmented Generation</a> (RAG)</h3>
<p>Foundational models like GPT3/4 and others are trained offline and they are agnostic to any data or domain that is created after the model was trained. Now if you want the model to be robust in performing for a specific problem domain you have two ways. Finetuning, however, is expensive, requires expertise and is not the right solution. Finetuning is the way if you want the model to acquire a new skill. In our case, we want the model to have more knowledge and that can be done with building a RAG system.</p>
<p>I gathered data from various resources and I tried my best that this data provided valuable context to plant care along with information on the plant names in case it was being called by different names (like scientific name and common name). These chunks of data will have the following pieces about each plant:</p>
<ol>
<li><p>Description: names and varieties of the plant if any</p>
</li>
<li><p>Suitable weather: the origin of the plant, what weather and temps for it to thrive</p>
</li>
<li><p>Disease: any known diseases and how to prevent them</p>
</li>
<li><p>Care: watering and light instructions to grow a healthy plant</p>
</li>
</ol>
<p>Different platforms have different ways to present the data and we have tried our best to make these four points present so that our model shares sound advice later on.</p>
<h3 id="heading-creating-the-knowledge-base">Creating the knowledge base</h3>
<p>To create a RAG system you need two components. An embedding model and a vector database. Let's explain embedding. In the core of the RAG system, we are employing a technique called semantic search and this is what requires the embedding.</p>
<p>Embedding is a process in which our text data is converted into a vector. This vector is a mathematical representation of our piece of text. This representation is robust nowadays in giving us insights about the semantics of the text which is a level above the language syntax. This is to say that having the vector gives us the ability to understand the meaning of the text on a contextual level rather than the literal translation of the words. This is the power of semantic search.</p>
<p><img src="https://cdn.sanity.io/images/vr8gru94/production/e016bbd4d7d57ff27e261adf1e254d2d3c609aac-2447x849.png" alt="embedding example diagram where piece of text when passed to the model will result in an output in the form of a vector." class="image--center mx-auto" /></p>
<p>How is this going to help in our application?</p>
<p>Imagine someone searching for caring tips about some plant that belongs to the genus Aloe (the species that Aloe vera belongs to). If you are searching with text matching you might not be able to infer systematically that the user is inquiring about some aloe vera cousin. However, by doing a semantic search we will be able hopefully to infer this relationship and others if existed systematically and present all of this info to our model before answering the user question.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692419624601/19b226c7-c7d8-415c-8daf-6b9151b54cfb.png" alt class="image--center mx-auto" /></p>
<p>This diagram represents our processing from collecting the plant information till we have a knowledge base created and stored in the vector database. This hackathon is by <a target="_blank" href="https://www.pinecone.io">Pinecone</a> which is the vector database we have to use as the core technology.</p>
<h3 id="heading-retrieval">Retrieval</h3>
<p>R in RAG stands for retrieval and I am sure you want to know how this work at a conceptual level. Earlier we learned that the core of the RAG system is the semantic search technique. In operation, we approach the question answering as a search problem. When a user asks a question we have to search in the vector DB for information that is semantically relevant to the user question. This information is then fed to the GPT4 model with the user question to generate the answer. Hence the name retrieval augmented generation. Here is a diagram that resembles this process:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692421064910/75e8af86-f676-453a-8cea-21687dd17b8b.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-application">Application</h3>
<p>Our mobile application was built by my friend <a target="_blank" href="https://github.com/AbdulmalekAlshugaa"><strong>ABDULMALEK AL-SHUGAA</strong></a> using <a target="_blank" href="https://expo.dev/client">Expo go</a> and <a target="_blank" href="https://github.com/AbdulmalekAlshugaa">Aref Asaket</a> been in the backend. All the core components related to the RAG system are built into endpoints using <a target="_blank" href="https://fastapi.tiangolo.com">fastapi</a> which makes up our AI microservice that is integrated into the backend.</p>
<h2 id="heading-challenges">Challenges</h2>
<p>Building Casia wasn't always smooth sailing. Like any significant endeavour, it came with its fair share of struggles and obstacles. From technical hurdles to moments of doubt, the journey was full of unexpected challenges.</p>
<p>One of the most significant technical challenges I encountered was ensuring that the <strong>AI model could accurately recognize and classify a wide range of plant species</strong>. Differentiating between various plants required a substantial amount of data, which wasn't always easy to come by. As mentioned in the RAG system part I have to devise creative methods for data collection, including crowdsourcing and web scraping. But all of this data might not always be in the format and shape or inclusive of the information that is needed.</p>
<p><strong>Evaluating the system performance</strong> was another issue that is hard to solve at least with the tools or problem we have at hand. Merely at how the system can answer 3 random questions doesn't constitute statistical significance. However, we have to take our system at face value by observing how it performs in a few questions.</p>
<p>Apart from the technical challenges, I also experienced <strong>moments of doubt</strong> during the hackathon. The time constraints and pressure of the competition made it challenging to stay focused on the end goal. There were moments when I wondered if the effort was worth it, or if I was pursuing the right idea.</p>
<p><strong>Cost and token size were additional concerns</strong>. Every time a user sends even a "Hi" message our system will go into full gear doing the RAG thing and semantic searching. This has been funny and completely unnecessary but I thought we shouldn't burden our system to RAG the hell out of every message. We have solved this by using another cohere model dedicated to answering short questions like this. It gave us a small room to only unleash the RAG power when the question is more than a few tokens in size, not a perfect approach but it works.</p>
<p>As for the token size we have to shorten our chunks of data when building the knowledge base. In addition to this, we have limited the use of the retrieved data to the top 3 results only. If you guessed using the 16k token window from the openAI GPT3.5 model, you are right we have used that version of the model after spending a lot of time being unaware of its existence.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I'm tremendously excited about the potential of projects like Casia to revolutionize the world of plant care and other domains. By democratizing knowledge and harnessing the power of AI, we can make plant care accessible to everyone, regardless of their background or experience. Imagine a world where anyone can easily grow their own food, create beautiful gardens, or simply enjoy the company of healthy houseplants without the steep learning curve that often accompanies these endeavours.</p>
<p>The potential of AI to bring positive change goes beyond plant care. In education, healthcare, and other critical sectors, AI can democratize access to information and resources, enabling more people to lead fulfilling lives. With projects like Casia, we're taking steps toward a more equitable, sustainable, and connected world where technology serves as a tool for empowerment and progress.</p>
<p>As for the future of Casia, unfortunately, I have not planned anything beyond the hackathon. I am open to any initiatives that would want to adopt my simple system and take to serve more audiences and perhaps grow beyond my initial vision.</p>
<hr />
<p>Thank you for taking the time to read I really appreciate you spending your time on this. Feel free to share with your friends and spread the post.</p>
<p><em>If you want to know more feel free to comment and ask away. Also here is the repository if you want to look into our</em> <a target="_blank" href="https://github.com/farisology/Casia"><em>code for the RAG system</em></a></p>
]]></content:encoded></item><item><title><![CDATA[Getting the Most Out of MLOps with ZenML: 4]]></title><description><![CDATA[Recap
ZenML Steps:

ZenML steps are the building blocks of ML workflows.

Each step represents a specific task or transformation in the ML pipeline.

Steps can include tasks like importing data, preprocessing data, training models, or evaluating mode...]]></description><link>https://farisology.com/getting-the-most-out-of-mlops-with-zenml-4</link><guid isPermaLink="true">https://farisology.com/getting-the-most-out-of-mlops-with-zenml-4</guid><category><![CDATA[mlops]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[Python]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Sat, 17 Jun 2023 16:21:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/KnK98ScsZbU/upload/3973d981068e3febe66eaed7b627c4f2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-recap">Recap</h2>
<p><strong>ZenML Steps:</strong></p>
<ul>
<li><p>ZenML steps are the building blocks of ML workflows.</p>
</li>
<li><p>Each step represents a specific task or transformation in the ML pipeline.</p>
</li>
<li><p>Steps can include tasks like importing data, preprocessing data, training models, or evaluating models.</p>
</li>
<li><p>ZenML provides a set of built-in steps, and you can also create custom steps tailored to your specific needs.</p>
</li>
</ul>
<p><strong>ZenML Pipelines:</strong></p>
<ul>
<li><p>ZenML pipelines define the sequence and dependencies of steps in an ML workflow.</p>
</li>
<li><p>Pipelines connect and orchestrate the steps, creating a cohesive end-to-end process.</p>
</li>
<li><p>Pipelines ensure that the steps are executed in the correct order, with inputs and outputs adequately connected.</p>
</li>
<li><p>ZenML pipelines make creating scalable, reproducible, and maintainable ML workflows easy.</p>
</li>
</ul>
<p><strong>Building ML Workflows with ZenML:</strong></p>
<ul>
<li><p>To construct an ML workflow with ZenML, you define and configure the steps required for your specific task. (see <a target="_blank" href="https://farisology.com/getting-the-most-out-of-mlops-with-zenml-3">article 3</a> in this series)</p>
</li>
<li><p>Each step can be customized with specific parameters and configurations.</p>
</li>
<li><p>Steps can be added, modified, or removed to adapt the workflow as needed.</p>
</li>
<li><p>The sequence of steps and their dependencies are defined in the pipeline, ensuring the proper execution order.</p>
</li>
<li><p>ZenML provides a streamlined way to create, manage, and execute ML workflows, promoting best practices and standardization.</p>
</li>
</ul>
<h2 id="heading-stacks">Stacks</h2>
<p>ZenML stacks are intuitively MLOps stacks which you can think of as the underlying infrastructure that you operate your pipeline on. There has been a time when people built machine learning models into production before the term MLOps and if we looked at what they needed to do that we can think minimally of the following components:</p>
<ul>
<li><p>Orchestrator (Airflow, Kubeflow)</p>
</li>
<li><p>Artefacts store (S3, GCS)</p>
</li>
<li><p>Tracking (MLflow)</p>
</li>
</ul>
<p>Those were the minimal setup that we used to operate our ML pipelines with. In the ZenML context, these three components together make up what you can call a stack. Of course, different use cases might require more components that you can add to your stack.</p>
<blockquote>
<p>ZenML allows you to create different stacks which empower you to have separate environments for your ML pipelines like local, staging, and prod. This also means you can have stacks that are based on different cloud providers too. The possibilities with ZenML are only limited by your imagination.</p>
</blockquote>
<h2 id="heading-creating-zenml-stack">Creating ZenML Stack</h2>
<p>In the <a target="_blank" href="https://farisology.com/getting-the-most-out-of-mlops-with-zenml-3">previous article</a>, we executed our <em>run.py</em> file which has the non-fatty liver pipeline. That execution has been operated by the default stack which zenml creates for you automatically. The default stack is local and all its components are also local. The executor and the artefacts store are both local and if we look at the runs record in our ZenML dashboard we can see that each artefact is stored in a local directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685758604506/9168a382-8ac8-4513-bc80-021ed7fd4b22.png" alt class="image--center mx-auto" /></p>
<p>If we clicked on any of the database symbols and looked at the details view we would see that the URI is a local destination. If we used a remote artefacts store like S3 all exported artefacts will be versioned and stored to the S3 bucket.</p>
<p>Let's simulate creating a production stack with the following components (<em>this is more of a simulation, actual prod will require more components depending on your requirements</em>):</p>
<ul>
<li><p>Orchestrator: Airflow</p>
</li>
<li><p>Artefacts store: S3 bucket</p>
</li>
<li><p>Container registry: ECR</p>
</li>
<li><p>Image builder: Local docker</p>
</li>
</ul>
<h3 id="heading-connect-to-server">Connect to server</h3>
<p>Connecting to the server is the first step that we should perform so that all our work is recorded and can be viewed from the ZenML dashboard. We have deployed our ZenML server in the <a target="_blank" href="https://farisology.com/getting-the-most-out-of-mlops-with-zenml-2">second article</a> of this series using a docker-compose file which makes it easy to replicate.</p>
<blockquote>
<p>I prefer that you deploy your ZenML server (to the cloud, you can get <a target="_blank" href="https://m.do.co/c/610f6dd6088b">$200 from digital ocean upon signup</a>) to keep your server and ZenML client in two different devices at least.</p>
</blockquote>
<p>To connect we use the following command (username is admin as per our deployment file, password will be requested):</p>
<pre><code class="lang-bash">zenml connect --url=zenml_deployment:80/ --username=admin
</code></pre>
<h3 id="heading-installing-zenml-integrations">Installing ZenML Integrations</h3>
<p>To create our stack components we need to install some integrations. First, you may want to observe what integrations are pre-installed. Use this command:</p>
<pre><code class="lang-bash">zenml integration list
</code></pre>
<p>This will give you a table with all integrations and an indicator if the integration is installed. To install our required integrations we use the following commands:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># to use S3 as our artefacts store later</span>
zenml integration install s3 -y

<span class="hljs-comment"># to use airflow as our orchestrator</span>
zenml integration install airflow
</code></pre>
<p>So far we have installed the integrations we need, but this doesn't mean our zenml can use them yet. We have to register these into ZenML components.</p>
<h3 id="heading-create-zenml-components">Create ZenML components</h3>
<p>The components we need are the orchestrator, artefacts store, and container registry. We go about the registration using the simple commands as follows:</p>
<pre><code class="lang-bash">zenml orchestrator register &lt;ORCHESTRATOR_NAME&gt; --flavor=airflow --<span class="hljs-built_in">local</span>=True --share
</code></pre>
<p><strong>My orchestrator</strong> is registered as <em>rairflow</em> that is to say it's a remote airflow. Observe how the local flag is False and there is a <em>share</em> flag which to make this orchestrator available to my team and they can use it in their own stack:</p>
<pre><code class="lang-bash">zenml orchestrator register rairflow --flavor=airflow --<span class="hljs-built_in">local</span>=False --share
</code></pre>
<p><strong>My artefacts store</strong> is registered like this:</p>
<pre><code class="lang-bash">
zenml artifact-store register s3_store -f s3 --path=s3://zenml-mlops --share
</code></pre>
<p><strong>My container registry</strong> is registered like this:</p>
<pre><code class="lang-bash">
zenml container-registry register aws_ecr --flavor=aws --uri=&lt;REGISTRY_URI&gt; --share
</code></pre>
<blockquote>
<p><em>You should name your ecr repository zenml that just makes things easier for you while following up our steps here.</em></p>
</blockquote>
<p><strong>Local image builder</strong> registered like this:</p>
<pre><code class="lang-bash">zenml image-builder register local_imb --flavor=<span class="hljs-built_in">local</span> --share
</code></pre>
<h3 id="heading-register-zenml-stack">Register ZenML stack</h3>
<p>Now we have all the components and integrations we need to create our stack. The process is simple we need a name for the stack and the rest should be familiar to you now:</p>
<pre><code class="lang-bash">zenml stack register remote_flow_stack --orchestrator rairflow \
        --artifacts-store s3-store \
        -c ecr_zenml \
        -i local_imb--share
</code></pre>
<p>That will register our stack and we can see that a stack is added to our zenml server dashboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685769488631/faaca2f4-3701-46ee-911c-5f5150de14a8.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-activating-zenml-stack">Activating ZenML Stack</h2>
<p>Our stack is registered but it's not the active stack and there are also two details to get this stack working.</p>
<p><strong>Login for AWS ECR:</strong></p>
<pre><code class="lang-bash"><span class="hljs-comment"># Fill your REGISTRY_URI and REGION in the placeholders in the following command.</span>
<span class="hljs-comment"># You can find the REGION as part of your REGISTRY_URI: `&lt;ACCOUNT_ID&gt;.dkr.ecr.&lt;REGION&gt;.amazonaws.com`</span>
aws ecr get-login-password --region &lt;REGION&gt; | docker login --username AWS --password-stdin &lt;REGISTRY_URI&gt;
</code></pre>
<p><strong>Activation of our stack</strong> This step is important so our ZenML client can push the image of our pipeline into ECR. Then airflow is going to run a dag based on that image. Now let's activate our stack:</p>
<pre><code class="lang-bash">zenml stack <span class="hljs-built_in">set</span> remote_flow_stack
</code></pre>
<p><strong>Describe the stack</strong> maybe you want to look at the configurations of a certain stack. This can be done in ZenML client by simply using the describe command like this:</p>
<pre><code class="lang-bash">zenml stack describe remote_flow_stack
</code></pre>
<p>For our current stack, it looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687016751168/6f20631c-3767-4708-b2b0-1c470b0cd856.png" alt class="image--center mx-auto" /></p>
<p>That's pretty much it. You can see what stacks are in your environment using the following command:</p>
<pre><code class="lang-bash">zenml stack list
</code></pre>
<hr />
<h2 id="heading-running-our-pipeline-in-the-remote-stack">Running our pipeline in the remote stack</h2>
<p>Our Python file that operates the pipeline looks like this (refer to the code in our <a target="_blank" href="https://farisology.com/getting-the-most-out-of-mlops-with-zenml-3">third article</a>):</p>
<pre><code class="lang-bash">from zenml.config.schedule import Schedule
from pipelines.nfld_pipeline import training_nfld_model
from steps.nfld_steps import (import_data, preprocess_data,
                              training_SVC, training_dct
                              )


def main():
    <span class="hljs-comment"># init and run the nfdl classifier training pipeline</span>
    run_nfdl_training = training_nfld_model(
        import_data=import_data(),
        preprocess_data=preprocess_data(),
        training_SVC=training_SVC(),
        training_dct=training_dct()
    )

    run_nfdl_training.run()


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()
</code></pre>
<p>We need to modify it a bit to suit the remote stack this pipeline should run on. The modifications are minor and the new file (<em>I create a new Python module just to keep them clean</em>) looks like this:</p>
<pre><code class="lang-bash">import os
from zenml.config.schedule import Schedule
from pipelines.nfld_pipeline import training_nfld_model
from zenml.integrations.airflow.flavors.airflow_orchestrator_flavor import AirflowOrchestratorSettings
from steps.nfld_steps import (import_data, preprocess_data,
                              training_SVC, training_dct
                              )

airflow_settings = AirflowOrchestratorSettings(
    operator=<span class="hljs-string">"docker"</span>,  <span class="hljs-comment"># or "kubernetes_pod"</span>
    dag_output_dir=f<span class="hljs-string">"{os.getcwd()}/zipped_pipelines"</span>, <span class="hljs-comment">#use your directory path to the zipped_pipes directory</span>
    dag_id=<span class="hljs-string">"non_fatty_liver_training"</span>,
    dag_tags=[<span class="hljs-string">"zenml"</span>, <span class="hljs-string">"MLOPS"</span>, <span class="hljs-string">"Training"</span>],
)

def main():
    <span class="hljs-comment"># init and run the nfdl classifier training pipeline</span>
    schedule = Schedule(cron_expression=<span class="hljs-string">"5-15 * * * *"</span>)
    run_nfdl_training = training_nfld_model(
        import_data=import_data(),
        preprocess_data=preprocess_data(),
        training_SVC=training_SVC(),
        training_dct=training_dct()
    )

    run_nfdl_training.run(settings={<span class="hljs-string">"orchestrator.airflow"</span>: airflow_settings}, schedule=schedule)


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()
</code></pre>
<p>The <em>airflow_settings</em> help us set multiple parameters for our airflow dag and we added a cron scheduler expression to set the running interval. Now if you run this file the output will not be an execution of the code. The output of running this file - <em>with our remote stack being the active stack</em> - will be an image in our aws ECR + a zip file in our zipped_pipelines directory.</p>
<blockquote>
<p>Using GitOps you could run the file in a pipeline and transfer this zip file into the remote airflow of your deployment. That is how it should be done and you have freedom to orchestrate this on your prefered method.</p>
</blockquote>
<hr />
<h2 id="heading-running-our-pipeline-in-a-local-stack">Running our pipeline in a local stack</h2>
<p>To run locally we need to create a local stack and now this should be simple we just need to do a few things differently and create a local stack. The steps along with commands are as follows:</p>
<p><strong>Install the docker operator for airflow:</strong></p>
<pre><code class="lang-bash">pip install apache-airflow-providers-docker
</code></pre>
<p>We need to <strong>register a local airflow orchestrator</strong> because we want to run this locally:</p>
<pre><code class="lang-bash">zenml orchestrator register lairflow --flavor=airflow --<span class="hljs-built_in">local</span>=True --share
</code></pre>
<p><strong>Register a stack</strong> using our local airflow orchestrator and the same components we used before for artefacts store and image registry .. etc:</p>
<pre><code class="lang-bash">zenml stack register local_flow_stack --orchestrator lairflow --artifact-store s3_store -c ecr_zenml -i local_imb --share
</code></pre>
<p>Now this stack is registered you should <strong>set it as the active stack</strong>:</p>
<pre><code class="lang-bash">zenml stack <span class="hljs-built_in">set</span> local_flow_stack
</code></pre>
<p>Now you can <strong>provision the stack</strong> which will spin up a local airflow for you:</p>
<pre><code class="lang-bash">zenml stack up
</code></pre>
<p>The output message of executing this command will give you credentials to log in to the airflow UI. Use generated credentials to log in and observe later how your pipeline is executed locally. This will be helpful when you are debugging or testing your pipeline before deploying it to run in the production stack.</p>
<blockquote>
<p>This local airflow stack provisioning will be deprecated in the future according to ZenML new update. Be aware that in the near future running local airflow orchestrator will be different.</p>
</blockquote>
<p><strong>Running the pipeline locally</strong> is an easy process (similar to running a remote stack) with minor changes to the run script. The output will be a DAG file stored in the directory of airflow dags locally in your machine. You can then trigger your DAG from the Airflow UI to start. The run script will be different as follows:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> zenml.config.schedule <span class="hljs-keyword">import</span> Schedule
<span class="hljs-keyword">from</span> pipelines.nfld_pipeline <span class="hljs-keyword">import</span> training_nfld_model
<span class="hljs-keyword">from</span> zenml.integrations.airflow.flavors.airflow_orchestrator_flavor <span class="hljs-keyword">import</span> AirflowOrchestratorSettings
<span class="hljs-keyword">from</span> steps.nfld_steps <span class="hljs-keyword">import</span> (import_data, preprocess_data,
                              training_SVC, training_dct
                              )

airflow_settings = AirflowOrchestratorSettings(
    operator=<span class="hljs-string">"docker"</span>,  <span class="hljs-comment"># or "kubernetes_pod"</span>
    dag_id=<span class="hljs-string">"non_fatty_liver_training"</span>,
    dag_tags=[<span class="hljs-string">"zenml"</span>, <span class="hljs-string">"MLOPS"</span>, <span class="hljs-string">"Training"</span>],
)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    <span class="hljs-comment"># init and run the nfdl classifier training pipeline</span>
    schedule = Schedule(cron_expression=<span class="hljs-string">"5-15 * * * *"</span>)
    run_nfdl_training = training_nfld_model(
        import_data=import_data(),
        preprocess_data=preprocess_data(),
        training_SVC=training_SVC(),
        training_dct=training_dct()
    )

    run_nfdl_training.run(settings={<span class="hljs-string">"orchestrator.airflow"</span>: airflow_settings}, schedule=schedule)


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()
</code></pre>
<blockquote>
<p>The only difference in this script is the line inside the AirflowOrchestratorSettings that specify the dag output directory. This like is removed because its not helpful for our local airflow stack and we want the DAG to be generated into its respective directory.</p>
</blockquote>
<p><strong>Bring stack down</strong></p>
<p>At the end of testing or debugging our stack, we want to take it down. This should be done in a way that removes everything that was created to provision the stack to avoid issues when you come to test a pipeline locally in the future. You can bring it down with the following command:</p>
<pre><code class="lang-bash">zenml stack down -f
</code></pre>
<h2 id="heading-frequent-errors">Frequent errors</h2>
<ol>
<li><p>AWS ECR login might cause you issues so be aware that it's something you have to deal with.</p>
</li>
<li><p>Server disconnect, you should disconnect and connect to your server after you are done or when you want to start working with ZenML respectively. Leaving the connection active might cause some issues.</p>
</li>
</ol>
<h2 id="heading-repository">Repository</h2>
<p>All the <a target="_blank" href="https://github.com/farisology/MLOps-ZenML">source code</a> for this series is made publically available here.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>ZenML proves to be a game-changer in managing the MLOps stack, offering a seamless experience with its local and remote stack creation capabilities. Although my created stacks lean towards familiar components like Airflow for orchestration and AWS cloud for resources, it's important to note that ZenML offers flexibility to tailor the stack to individual preferences. This article serves as a demonstration of ZenML's potential through a demo project, but it's worth highlighting that ZenML is a dynamic framework, continuously evolving with frequent updates and improvements.</p>
]]></content:encoded></item><item><title><![CDATA[Getting the Most Out of MLOps with ZenML: 3]]></title><description><![CDATA[Intro

In the previous post, we have gone through deploying the ZenML server. The ZenML server is where we can view the dashboard and monitor our pipeline and previous runs with a nice visual graph representing the pipeline. Then we looked into using...]]></description><link>https://farisology.com/getting-the-most-out-of-mlops-with-zenml-3</link><guid isPermaLink="true">https://farisology.com/getting-the-most-out-of-mlops-with-zenml-3</guid><category><![CDATA[Devops]]></category><category><![CDATA[mlops]]></category><category><![CDATA[Python]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[Machine Learning]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Sun, 21 May 2023 14:29:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/rzqjQjGvOBQ/upload/7ee7a062cc4da7025e5b9562697f6389.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-intro">Intro</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684558114198/a89e6b48-2d62-474d-8896-04c41e9f41ba.avif" alt class="image--center mx-auto" /></p>
<p>In the <a target="_blank" href="https://farisology.com/zenml-server-and-client-cli">previous post</a>, we have gone through deploying the ZenML server. The ZenML server is where we can view the dashboard and monitor our pipeline and previous runs with a nice visual graph representing the pipeline. Then we looked into using the CLI to connect to the server. In this post, we will create a simple pipeline and learn how to build pipelines in ZenML.</p>
<h2 id="heading-pipelines">Pipelines</h2>
<p>This is an intuitive concept for any data scientist working with ML. We sometimes call them workflows or DAGs if we adopt the Airflow terminology. In ZenML a pipeline is your ML workflow and is built from smaller blocks called steps.</p>
<h3 id="heading-step">Step</h3>
<p>A step is the equivalent of a task, a function that does one thing. This approach allows you to build decoupled and modular components (read tasks) for your ML workflow (read pipeline). You are empowered then to write a portable and modular code once, and then moving from experimentation to production becomes frictionless.</p>
<blockquote>
<p>"I choose ZenML to build beyond mere pipelines. With ZenML's modular approach, standardizing ML practices for your team becomes effortless. Enjoy simplified maintenance, streamlined development, and embrace software engineering concepts like test-driven development, portable code, and SOLID principles." -Fares Hasan</p>
</blockquote>
<h2 id="heading-fatty-liver-classification-use-case">Fatty liver classification use-case</h2>
<p>So let's build a use case to go through all the concepts and make them clear. If we want to build such a classifier we can think of typical steps that go like this:</p>
<ul>
<li><p>Importing data</p>
</li>
<li><p>Preprocessing (handling duplicates, and missing data)</p>
</li>
<li><p>Train a model</p>
</li>
</ul>
<p>They are steps and all of them together make up our pipeline which we can build in zenml. We are keeping this simple but you get the idea. In some use-case, you might call this the training or modelling pipeline because all it does is train a model at the end. To implement and follow up with this part make sure you have the following:</p>
<ul>
<li><p>create repository or directory to store the code</p>
</li>
<li><p>create a virtual environment (python version 3.7 or above)</p>
</li>
<li><p>installed zenml client with version identical to the zenml server version (version 0.35.1 used by this series of articles)</p>
</li>
<li><pre><code class="lang-python">  <span class="hljs-comment"># connect to zenml server:</span>
  zenml connect --url=http://my-server-address:<span class="hljs-number">8080</span>/ --username=default
</code></pre>
</li>
</ul>
<h3 id="heading-dataset">Dataset</h3>
<p>You can download the dataset from Kaggle <a target="_blank" href="https://www.kaggle.com/datasets/utkarshx27/non-alcohol-fatty-liver-disease">here</a> and we will use the nafld1 file which contains 17.5k rows and 10 columns. Here is a brief catalogue explaining the columns:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Column</td><td>Defintion</td></tr>
</thead>
<tbody>
<tr>
<td>id</td><td>subject identifier</td></tr>
<tr>
<td>age</td><td>age at entry to the study</td></tr>
<tr>
<td>male</td><td>0=female, 1=male</td></tr>
<tr>
<td>weight</td><td>weight in kg</td></tr>
<tr>
<td>height</td><td>height in cm</td></tr>
<tr>
<td>bmi</td><td>body mass index</td></tr>
<tr>
<td>case.id</td><td>the id of the NAFLD case to whom this subject is matched</td></tr>
<tr>
<td>futime</td><td>time to death or last follow-up</td></tr>
<tr>
<td>status</td><td>0= alive at last follow-up, 1=dead</td></tr>
</tbody>
</table>
</div><h3 id="heading-steps">Steps</h3>
<p>We mentioned above the plan for using 3 simple steps to manage to build a classifier for fatty liver detection. In the first step we want to import the data and in this case, our data should be just the CSV file we have downloaded from kaggle.</p>
<p><strong>Importing data</strong></p>
<p>This will be just a simple step that use pandas to read the CSV file and return a dataframe. The typical code will be like this:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">import_data</span>():</span>
     df = pd.read_csv(<span class="hljs-string">"relative_path_to_file"</span>)
     <span class="hljs-keyword">return</span> df
</code></pre>
<p>Now that's a simple Python function, to make this into a ZenML step we can you decorator so it looks more like this:</p>
<pre><code class="lang-python"><span class="hljs-meta">@step</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">import_data</span>():</span>
     df = pd.read_csv(<span class="hljs-string">"relative_path_to_file"</span>)
     <span class="hljs-keyword">return</span> df
</code></pre>
<p>But that is not good enough we could improve it by using type annotation for inputs and outputs and we will have a beautiful function that looks better:</p>
<pre><code class="lang-python"><span class="hljs-meta">@step</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">import_data</span>() -&gt; Output(dataset = pd.DataFrame):</span>
     df = pd.read_csv(<span class="hljs-string">"relative_path_to_file"</span>)
     <span class="hljs-keyword">return</span> df
</code></pre>
<p>Now you have seen how we write the methods nicely I hope you keep it up that way with the rest of the steps we will code together. One thing to keep in mind is that when we code the steps we treat them as separate Python functions with annotated input and output. In a later phase, we stitch them back together in a pipeline.</p>
<p>Another thought that might come to your mind is how you arrange the steps. You can go about this in any way you want, in my implementation here I have all the steps in one Python module calling it for example <em>fatty_liver_steps</em> but that is more of a personal preference. You can see my project file structure <a target="_blank" href="https://github.com/farisology/MLOps-ZenML/tree/main/fatty_liver">here</a>. My approach in this small demo project goes like this:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">fatty_liver:</span>
    <span class="hljs-attr">pipelines:</span>
        <span class="hljs-string">__init__.py</span>
        <span class="hljs-string">nfld_pipeline.py</span>
    <span class="hljs-attr">steps:</span>
        <span class="hljs-string">__init__.py</span>
        <span class="hljs-string">nfld_steps.py</span>

    <span class="hljs-string">nafdl1.csv</span>
    <span class="hljs-string">nlfd_run.py</span>
</code></pre>
<p>Notice where I placed the CSV file for ease of use, in real project you should be reading from a data source.</p>
<p><strong>Preprocessing data</strong></p>
<p>There are a few things that we can do to improve this dataset to simulate real-life scenarios. Here are the steps we will perform in the preprocessing phase:</p>
<ol>
<li><p>Remove redundant columns like identifier columns for the case and etc.</p>
</li>
<li><p>Impute the missing values using KNNImputer</p>
</li>
<li><p>Return the labels and features</p>
</li>
</ol>
<p>Our preprocessing step should look like this:</p>
<pre><code class="lang-python"><span class="hljs-meta">@step</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">preprocess_data</span>(<span class="hljs-params">dataset: pd.DataFrame</span>) -&gt; Output(features=np.ndarray, labels=pd.core.series.Series):</span>
    <span class="hljs-comment"># remove the redundant columns</span>
    data = dataset.drop([<span class="hljs-string">'id'</span>, <span class="hljs-string">'Unnamed: 0'</span>, <span class="hljs-string">'case.id'</span>], axis=<span class="hljs-number">1</span>)
    labels = data.pop(<span class="hljs-string">'status'</span>)

    <span class="hljs-comment"># impute the missing values using the KNNImputer</span>
    imputer = KNNImputer(n_neighbors=<span class="hljs-number">2</span>, weights=<span class="hljs-string">"uniform"</span>)
    imputer = imputer.fit(data)
    features = imputer.transform(data)

    <span class="hljs-keyword">return</span> features, labels
</code></pre>
<p><strong>Training models</strong></p>
<p>In real-life scenarios Data Scientists run multiple experiments but in our little example here we will just train two classifiers and our training steps will take care of each model as follows:</p>
<p><strong>Support Vector Classifier</strong></p>
<pre><code class="lang-python"><span class="hljs-meta">@step</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">training_SVC</span>(<span class="hljs-params">features: np.ndarray, labels: pd.core.series.Series</span>) -&gt; SVC:</span>
    x_train, x_test, y_train, y_test = train_test_split(
        features, labels, test_size=<span class="hljs-number">0.2</span>)
    svc_model = SVC()
    svc_model.fit(x_train, y_train)

    y_pred = svc_model.predict(x_test)
    print(classification_report(y_test, y_pred))
    <span class="hljs-keyword">return</span> svc_model
</code></pre>
<p><strong>Decision Tree Classifier</strong></p>
<pre><code class="lang-python"><span class="hljs-meta">@step</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">training_dct</span>(<span class="hljs-params">features: np.ndarray, labels: pd.core.series.Series</span>) -&gt; DecisionTreeClassifier:</span>
    x_train, x_test, y_train, y_test = train_test_split(
        features, labels, test_size=<span class="hljs-number">0.2</span>)
    dct_model = DecisionTreeClassifier()
    dct_model.fit(x_train, y_train)

    y_pred = dct_model.predict(x_test)
    print(classification_report(y_test, y_pred))
    <span class="hljs-keyword">return</span> dct_model
</code></pre>
<p>Great now you must have all the steps for this fatty liver use-case in one module if you followed my approach. The <em>fatty_liver_steps.py</em> file should be as follows:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">from</span> sklearn.svm <span class="hljs-keyword">import</span> SVC
<span class="hljs-keyword">from</span> zenml.steps <span class="hljs-keyword">import</span> step, Output
<span class="hljs-keyword">from</span> sklearn.impute <span class="hljs-keyword">import</span> KNNImputer
<span class="hljs-keyword">from</span> sklearn.tree <span class="hljs-keyword">import</span> DecisionTreeClassifier
<span class="hljs-keyword">from</span> sklearn.metrics <span class="hljs-keyword">import</span> classification_report
<span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split


<span class="hljs-meta">@step</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">import_data</span>() -&gt; Output(dataset=pd.DataFrame):</span>
    df = pd.read_csv(<span class="hljs-string">"nafld1.csv"</span>)
    <span class="hljs-keyword">return</span> df


<span class="hljs-meta">@step</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">preprocess_data</span>(<span class="hljs-params">dataset: pd.DataFrame</span>) -&gt; Output(features=np.ndarray, labels=pd.core.series.Series):</span>
    <span class="hljs-comment"># remove the redundant columns</span>
    data = dataset.drop([<span class="hljs-string">'id'</span>, <span class="hljs-string">'Unnamed: 0'</span>, <span class="hljs-string">'case.id'</span>], axis=<span class="hljs-number">1</span>)
    labels = data.pop(<span class="hljs-string">'status'</span>)

    <span class="hljs-comment"># impute the missing values using the KNNImputer</span>
    imputer = KNNImputer(n_neighbors=<span class="hljs-number">2</span>, weights=<span class="hljs-string">"uniform"</span>)
    imputer = imputer.fit(data)
    features = imputer.transform(data)

    <span class="hljs-keyword">return</span> features, labels


<span class="hljs-meta">@step</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">training_SVC</span>(<span class="hljs-params">features: np.ndarray, labels: pd.core.series.Series</span>) -&gt; SVC:</span>
    x_train, x_test, y_train, y_test = train_test_split(
        features, labels, test_size=<span class="hljs-number">0.2</span>)
    svc_model = SVC()
    svc_model.fit(x_train, y_train)

    y_pred = svc_model.predict(x_test)
    print(classification_report(y_test, y_pred))
    <span class="hljs-keyword">return</span> svc_model


<span class="hljs-meta">@step</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">training_dct</span>(<span class="hljs-params">features: np.ndarray, labels: pd.core.series.Series</span>) -&gt; DecisionTreeClassifier:</span>
    x_train, x_test, y_train, y_test = train_test_split(
        features, labels, test_size=<span class="hljs-number">0.2</span>)
    dct_model = DecisionTreeClassifier()
    dct_model.fit(x_train, y_train)

    y_pred = dct_model.predict(x_test)
    print(classification_report(y_test, y_pred))
    <span class="hljs-keyword">return</span> dct_model
</code></pre>
<h3 id="heading-pipeline">Pipeline</h3>
<p>This is an easy part, we have multiple steps and a pipeline is just a code that expresses what step is executed first and manages the dependency between steps. For example, if step A depends on a previous step to run. Our pipeline code is as simple as this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> zenml.pipelines <span class="hljs-keyword">import</span> pipeline


<span class="hljs-meta">@pipeline</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">training_nfld_model</span>(<span class="hljs-params">import_data, preprocess_data, training_SVC, training_dct</span>):</span>
    <span class="hljs-string">"""Training non-fatty liver classifier"""</span>
    alldata = import_data()
    x, y = preprocess_data(alldata)
    svc = training_SVC(x, y)
    dct = training_dct(x, y)
</code></pre>
<p>In this pipeline, you see the execution flow takes shape and our project is almost complete. The next action is to create a simple run.py script just to execute the pipeline. It looks like a Python code you are familiar with but comes with more ZenML power and it looks like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pipelines.nfld_pipeline <span class="hljs-keyword">import</span> training_nfld_model
<span class="hljs-keyword">from</span> steps.nfld_steps <span class="hljs-keyword">import</span> (import_data, preprocess_data,
                              training_SVC, training_dct
                              )


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    <span class="hljs-comment"># init and run the nfdl classifier training pipeline</span>
    run_nfdl_training = training_nfld_model(
        import_data=import_data(),
        preprocess_data=preprocess_data(),
        training_SVC=training_SVC(),
        training_dct=training_dct()
    )

    run_nfdl_training.run()


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()
</code></pre>
<p>In simple words, this code is running a pipeline for training a classifier model using ZenML. Here's a breakdown of what's happening:</p>
<ul>
<li><p>The code imports the necessary pipeline and step functions from the respective files.</p>
</li>
<li><p>The <code>main()</code> function is defined, which will be the starting point of the program.</p>
</li>
<li><p>Inside the <code>main()</code> function:</p>
<ul>
<li><p>The <code>run_nfdl_training</code> variable is assigned the result of calling the <code>training_nfld_model</code> pipeline function.</p>
</li>
<li><p>The pipeline function takes several steps as arguments, such as importing data, preprocessing data, training Support Vector Classifier (SVC), and training Decision Tree Classifier (dct).</p>
</li>
<li><p>Each step is called as a function to create an instance of that step.</p>
</li>
<li><p>The pipeline function is then executed using the <code>run()</code> method of the <code>run_nfdl_training</code> variable.</p>
</li>
</ul>
</li>
<li><p>Finally, the <code>main()</code> function is called when the program is run.</p>
</li>
</ul>
<h3 id="heading-run">Run</h3>
<p>Running this pipeline works like running any Python module by simply using the command in the terminal:</p>
<pre><code class="lang-python">python run.py
</code></pre>
<p>The output should look something similar like:</p>
<pre><code class="lang-less"><span class="hljs-selector-tag">Registered</span> <span class="hljs-selector-tag">pipeline</span> <span class="hljs-selector-tag">training_nfld_model</span> (version <span class="hljs-number">5</span>).
<span class="hljs-selector-tag">Running</span> <span class="hljs-selector-tag">pipeline</span> <span class="hljs-selector-tag">training_nfld_model</span> <span class="hljs-selector-tag">on</span> <span class="hljs-selector-tag">stack</span> <span class="hljs-selector-tag">default</span> (caching enabled)
<span class="hljs-selector-tag">Step</span> <span class="hljs-selector-tag">import_data</span> <span class="hljs-selector-tag">has</span> <span class="hljs-selector-tag">started</span>.
<span class="hljs-selector-tag">Using</span> <span class="hljs-selector-tag">cached</span> <span class="hljs-selector-tag">version</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">import_data</span>.
<span class="hljs-selector-tag">Step</span> <span class="hljs-selector-tag">preprocess_data</span> <span class="hljs-selector-tag">has</span> <span class="hljs-selector-tag">started</span>.
<span class="hljs-selector-tag">Using</span> <span class="hljs-selector-tag">cached</span> <span class="hljs-selector-tag">version</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">preprocess_data</span>.
<span class="hljs-selector-tag">Step</span> <span class="hljs-selector-tag">training_SVC</span> <span class="hljs-selector-tag">has</span> <span class="hljs-selector-tag">started</span>.
<span class="hljs-selector-tag">By</span> <span class="hljs-selector-tag">default</span>, <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">PandasMaterializer</span> <span class="hljs-selector-tag">stores</span> <span class="hljs-selector-tag">data</span> <span class="hljs-selector-tag">as</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-class">.csv</span> <span class="hljs-selector-tag">file</span>. <span class="hljs-selector-tag">If</span> <span class="hljs-selector-tag">you</span> <span class="hljs-selector-tag">want</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">store</span> <span class="hljs-selector-tag">data</span> <span class="hljs-selector-tag">more</span> <span class="hljs-selector-tag">efficiently</span>, <span class="hljs-selector-tag">you</span> <span class="hljs-selector-tag">can</span> <span class="hljs-selector-tag">install</span> <span class="hljs-selector-tag">pyarrow</span> <span class="hljs-selector-tag">by</span> <span class="hljs-selector-tag">running</span> '<span class="hljs-selector-tag">pip</span> <span class="hljs-selector-tag">install</span> <span class="hljs-selector-tag">pyarrow</span>'. <span class="hljs-selector-tag">This</span> <span class="hljs-selector-tag">will</span> <span class="hljs-selector-tag">allow</span> <span class="hljs-selector-tag">PandasMaterializer</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">automatically</span> <span class="hljs-selector-tag">store</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">data</span> <span class="hljs-selector-tag">as</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-class">.parquet</span> <span class="hljs-selector-tag">file</span> <span class="hljs-selector-tag">instead</span>.....
<span class="hljs-selector-tag">Step</span> <span class="hljs-selector-tag">training_SVC</span> <span class="hljs-selector-tag">has</span> <span class="hljs-selector-tag">finished</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">0</span><span class="hljs-selector-class">.799s</span>.
<span class="hljs-selector-tag">Step</span> <span class="hljs-selector-tag">training_dct</span> <span class="hljs-selector-tag">has</span> <span class="hljs-selector-tag">started</span>.
<span class="hljs-selector-tag">By</span> <span class="hljs-selector-tag">default</span>, <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">PandasMaterializer</span> <span class="hljs-selector-tag">stores</span> <span class="hljs-selector-tag">data</span> <span class="hljs-selector-tag">as</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-class">.csv</span> <span class="hljs-selector-tag">file</span>. <span class="hljs-selector-tag">If</span> <span class="hljs-selector-tag">you</span> <span class="hljs-selector-tag">want</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">store</span> <span class="hljs-selector-tag">data</span> <span class="hljs-selector-tag">more</span> <span class="hljs-selector-tag">efficiently</span>, <span class="hljs-selector-tag">you</span> <span class="hljs-selector-tag">can</span> <span class="hljs-selector-tag">install</span> <span class="hljs-selector-tag">pyarrow</span> <span class="hljs-selector-tag">by</span> <span class="hljs-selector-tag">running</span> '<span class="hljs-selector-tag">pip</span> <span class="hljs-selector-tag">install</span> <span class="hljs-selector-tag">pyarrow</span>'. <span class="hljs-selector-tag">This</span> <span class="hljs-selector-tag">will</span> <span class="hljs-selector-tag">allow</span> <span class="hljs-selector-tag">PandasMaterializer</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">automatically</span> <span class="hljs-selector-tag">store</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">data</span> <span class="hljs-selector-tag">as</span> <span class="hljs-selector-tag">a</span> <span class="hljs-selector-class">.parquet</span> <span class="hljs-selector-tag">file</span> <span class="hljs-selector-tag">instead</span>......
<span class="hljs-selector-tag">Step</span> <span class="hljs-selector-tag">training_dct</span> <span class="hljs-selector-tag">has</span> <span class="hljs-selector-tag">finished</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">0</span><span class="hljs-selector-class">.342s</span>.
<span class="hljs-selector-tag">Pipeline</span> <span class="hljs-selector-tag">run</span> <span class="hljs-selector-tag">training_nfld_model-2023_05_21-13_53_59_355523</span> <span class="hljs-selector-tag">has</span> <span class="hljs-selector-tag">finished</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">4</span><span class="hljs-selector-class">.035s</span>......
</code></pre>
<h2 id="heading-summary">Summary</h2>
<p>In summary, ZenML steps are the individual components that perform specific tasks, while ZenML pipelines connect and orchestrate these steps to create ML workflows. By leveraging ZenML's step-based approach and pipeline structure, you can easily build and manage end-to-end ML workflows that are scalable, reproducible, and efficient. In the next post, we will look into the concept of Stack and how we create, operate and orchestrate our ML pipeline in an MLOps Stack.</p>
]]></content:encoded></item><item><title><![CDATA[Getting the Most Out of MLOps with ZenML: 2]]></title><description><![CDATA[Intro

To work with ZenML there are two sides we need to create. If you are an ML engineer the ZenML server deployment would be your task and you will have to do it once. For users like data scientists who will use ZenML and or ML engineers who are b...]]></description><link>https://farisology.com/getting-the-most-out-of-mlops-with-zenml-2</link><guid isPermaLink="true">https://farisology.com/getting-the-most-out-of-mlops-with-zenml-2</guid><category><![CDATA[mlops]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Wed, 03 May 2023 17:19:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/UeBFFAPwuj8/upload/ec4d3934d1c9e28a6ad6f9497a5b410e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-intro">Intro</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682236775045/9bcc27ec-f502-427f-8f89-4432adb78912.png" alt class="image--center mx-auto" /></p>
<p>To work with ZenML there are two sides we need to create. If you are an ML engineer the ZenML server deployment would be your task and you will have to do it once. For users like data scientists who will use ZenML and or ML engineers who are building ML workflows, they will use the ZenML client. In this article we will focus first in the ZenML server and how you can deploy it. The diagram above by ZenML illustrates the architecture nicely.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682236762403/f59111b6-146e-420f-b56a-7be6497c9e01.webp" alt class="image--center mx-auto" /></p>
<p>The ZenML server will have a dashboard to visualize your entire MLOps ecosystem. There you can see reports on pipeline runs and failures, the stacks and components registered and it will also give information about who from your team owns the pipeline.</p>
<h2 id="heading-how-to-install-it">How to install it?</h2>
<p>You can simply spin up a ZenML server by running the following command:</p>
<pre><code class="lang-bash">docker run -it -d -p 80:80 --name zenml zenmldocker/zenml-server
</code></pre>
<p>This will run a docker container with local SQLite database. This is fine to experiment with but zenml team recommends using MYSQL for production. If you want a product grade you have to also improve command by specifying the zenml server image version and it's highly recommended to use a similar version for the server and the zenml client.</p>
<h3 id="heading-docker-deployment">Docker deployment</h3>
<pre><code class="lang-bash">docker run -it -d -p 8080:8080 --name zenml \
    --env ZENML_STORE_URL=mysql://username:password@host/zenmldb \
    zenmldocker/zenml-server:0.35.1
</code></pre>
<h3 id="heading-deployment-with-docker-compose">Deployment with docker compose</h3>
<p>You can run both zenml server and MySQL database containers using the docker compose. Create a file name <mark>docker-compose.yml</mark> and past the following to it:</p>
<pre><code class="lang-bash">version: <span class="hljs-string">"3.9"</span>

services:
  mysql:
    container_name: mysql_zenml
    restart: always
    image: mysql:8.0
    ports:
      - 3306:3306
    environment:
      - MYSQL_ROOT_PASSWORD=password
    volumes:
      - <span class="hljs-string">"<span class="hljs-variable">$PWD</span>/mysql-data:/var/lib/mysql"</span>
  zenml:
    container_name: zenml_server
    image: zenmldocker/zenml-server:0.35.1
    ports:
      - <span class="hljs-string">"8080:8080"</span> <span class="hljs-comment">#zenml dashboard</span>
    environment:
      - ZENML_STORE_URL=mysql://root:password@host.docker.internal/zenml
      - ZENML_DEFAULT_USER_NAME=admin
      - ZENML_DEFAULT_USER_PASSWORD=zenml
    links:
      - mysql
    depends_on:
      - mysql
    extra_hosts:
      - <span class="hljs-string">"host.docker.internal:host-gateway"</span>
    restart: on-failure
</code></pre>
<p>For other deployment options you can follow from <a target="_blank" href="https://docs.zenml.io/getting-started/deploying-zenml">Deploying ZenML Documentation</a></p>
<p>You can simply launch this with the command:</p>
<pre><code class="lang-bash">docker-compose up -d
</code></pre>
<p>This will start up your zenml server with MySQL database. You can open the localhost in the browser or the IP address of your EC2 to see the dashboard. Remember the credentials username, password and change them to something more secure. If you have used the docker deployment -it's my current implementation- the user name will be <mark>default</mark> and leave the password empty</p>
<p>Yup that's it you have made your zenml server deployment go live!!</p>
<hr />
<h2 id="heading-zenml-client-cli">ZenML Client CLI</h2>
<p>ZenML client is our main way of communicating with the server -ZenML server and dashboard-. This client will help us create mlops stacks and share them with our team and or execute certain pipelines locally before pushing them to production.</p>
<h3 id="heading-first-install">First: Install</h3>
<p>The first thing we should do as best practice is to install ZenML client version that is similar to our ZenML server. If you have been following closely you will see that our server is using version <mark>0.35.1 </mark> we should stick to that version when it comes to using the client. Don't forget to create a virtualenv for this project.</p>
<pre><code class="lang-bash">pip install zenml==0.35.1
</code></pre>
<h3 id="heading-second-connect">Second: Connect</h3>
<p>Once you have installed the ZenML client its time to connect with zenml server.</p>
<pre><code class="lang-bash">zenml connect --url=http://my-server-address:8080/ --username=default
</code></pre>
<p>Be aware that my user name is default because I used the docker deployment above. If you used the docker-compose you will use a different username.</p>
<h3 id="heading-third-well-maybe-check-the-status">Third: well maybe check the status</h3>
<p><strong>Status</strong>: zenml status will show you the current status with information that you may want to know and it looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682613757523/852a309b-dacb-4f72-843b-ae100a493b45.png" alt class="image--center mx-auto" /></p>
<p>As you see my client is connected to ZenML server that we deployed earlier and there is no stack other than the default stack which is currently active.</p>
<h2 id="heading-summary">Summary</h2>
<p>That was a step-by-step guide on how to install and deploy the ZenML server and use the ZenML client CLI. The ZenML server comes with a dashboard that visualizes the entire MLOps ecosystem and reports on pipeline runs and failures, while the ZenML client allows for the creation of MLOps stacks, execution of pipelines and sharing of stacks with a team. ZenML's extensibility makes it easy to scale ML models efficiently and effectively. Try it out for yourself by following the simple installation and deployment steps. In the next article we will build a simple use case to demo execution.</p>
<h3 id="heading-reading-more">Reading more</h3>
<p>I think ZenML has an amazing documentation and I encourage you to read more there for other aspects that are not covered here:</p>
<ul>
<li><p>Deploying ZenML: <a target="_blank" href="https://docs.zenml.io/getting-started/deploying-zenml">https://docs.zenml.io/getting-started/deploying-zenml</a></p>
</li>
<li><p>ZenML dashboard and connection <a target="_blank" href="https://docs.zenml.io/v/0.35.1/starter-guide/pipelines/dashboard">https://docs.zenml.io/v/0.35.1/starter-guide/pipelines/dashboard</a></p>
</li>
<li><p>Troubleshooting: <a target="_blank" href="https://docs.zenml.io/getting-started/deploying-zenml/troubleshooting">https://docs.zenml.io/getting-started/deploying-zenml/troubleshooting</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Getting the Most Out of MLOps with ZenML: 1]]></title><description><![CDATA[TLDR

This series of articles focuses on getting the most out of MLOps using ZenML, an open-source framework that unifies the entire machine learning stack.

MLOps is critical to operationalizing and scaling ML models, leading to better decision-maki...]]></description><link>https://farisology.com/getting-the-most-out-of-mlops-with-zenml-1</link><guid isPermaLink="true">https://farisology.com/getting-the-most-out-of-mlops-with-zenml-1</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[mlops]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[Python]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Thu, 27 Apr 2023 07:52:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ObpCE_X3j6U/upload/bd60b25a6c51592a3611d43a5d1e69a2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-tldr">TLDR</h2>
<ul>
<li><p><em>This series of articles focuses on getting the most out of MLOps using ZenML, an open-source framework that unifies the entire machine learning stack.</em></p>
</li>
<li><p><em>MLOps is critical to operationalizing and scaling ML models, leading to better decision-making and increased efficiency.</em></p>
</li>
<li><p><em>ZenML offers features like automated caching, data versioning, and metadata tracking that simplify the entire ML pipeline.</em></p>
</li>
<li><p><em>ZenML provides Continuous Training and Deployment (CT/CD) capabilities, a pipeline workflow architecture, and a ZenML stack that brings flexibility to handle pipelines.</em></p>
</li>
<li><p><em>By providing a unified and automated solution for ML workflows, ZenML empowers organizations to scale their ML models efficiently and effectively.</em></p>
</li>
</ul>
<h2 id="heading-whats-mlops">What's MLOps?</h2>
<p>Databricks defines MLOps as a core function of Machine Learning engineering, focused on streamlining the process of taking machine learning models to production and then maintaining and monitoring them.</p>
<h2 id="heading-why-mlops">Why MLOps?</h2>
<p>MLOps is important because it enables organizations to effectively operationalize and scale their machine learning models, leading to better decision-making, increased efficiency, and ultimately, greater business success.</p>
<p>Without MLOps, data scientists and engineers may struggle to deploy, monitor, and maintain models, leading to suboptimal performance, wasted resources, and an increased risk of errors.</p>
<p>For example, imagine a financial institution that wants to use machine learning to predict fraudulent transactions. If they don't have proper MLOps processes in place, they may struggle to deploy their model to production, monitor it for performance and accuracy, and update it as necessary. This could lead to missed fraud detection, false positives, and ultimately, financial losses.</p>
<p>On the other hand, with MLOps and a tool like ZenML, the financial institution can streamline the entire ML lifecycle, from data preparation to model training to deployment and beyond. They can easily monitor the performance of their model, detect and address drift, and continuously improve their predictions over time. This results in more accurate fraud detection, better decision-making, and ultimately, a stronger bottom line.</p>
<h2 id="heading-how-does-zenml-help-with-mlops">How does ZenML help with MLOps?</h2>
<p>ZenML helps with MLOps by providing a comprehensive open-source framework that unifies the entire machine learning stack, making it easy to develop, train, and deploy models with a seamless transition from development to deployment.</p>
<p>With features such as local development with Python, automated caching, versioning of data, and automated metadata tracking, ZenML streamlines ML workflows and saves time and resources. Additionally, it allows for collaboration among teams and the ability to visualize ML workflows for improved design.</p>
<blockquote>
<p>ZenML is more than just an MLOps framework - it's a holistic solution that seamlessly integrates the entire machine learning stack, empowering teams to develop, train, and deploy models with ease and efficiency. - ChadGPT</p>
</blockquote>
<p>One of the key benefits of ZenML is its extensibility, as it can be tailored to meet specific needs and workflows. ZenML also provides a single place to link up and manage different MLOps tools, with support for popular infrastructure like Kubeflow, AWS Sagemaker, Azure ML, and Vertex AI GCP.</p>
<p>The new thing in town is called Continuous Training and Deployment (CT/CD) capabilities, allowing for end-to-end ML workflows that can deploy models in local or production-grade environments with integrations like MLFlow and Seldon Core. By providing a unified and automated solution for ML workflows, ZenML empowers organizations to scale their ML models efficiently and effectively.</p>
<h2 id="heading-a-brief-overview-of-the-zenml-workflow">A brief overview of the ZenML workflow</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682235040091/fefbe9d3-acf4-4a2f-b73f-55fb3806e756.png" alt="Image by ZenML Core Consepts: https://docs.zenml.io/getting-started/core-concepts" class="image--center mx-auto" /></p>
<h3 id="heading-steps-andamp-pipelines">Steps &amp; Pipelines</h3>
<p>ZenML is built around the pipeline workflow architecture. The simplest unit of the workflow is a step which you can look at as a single process or Python function. You can create your steps in any way that aligns with your use case, for example, you may have an importer step. The importer step imports data, and then preprocessing steps which will apply to preprocess your data and so on. These steps can have dependencies among your steps where some steps will depend on the output of another step. The collection of a few steps can form a pipeline.</p>
<h3 id="heading-stacks">Stacks</h3>
<p>So to handle your pipeline you can use ZenML stack which is an abstract layer built for this purpose. For example, you may have a stack with components to handle artefact storage, orchestrator and experiment tracker. Upon running the pipeline this stack will handle the process. This brings flexibility in the sense that you may have a local stack for pipeline or a project for testing, and there is a remote stack which is for production.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682235097681/14704e28-4e23-45d3-bf5d-e8af7d543b14.png" alt="Image by ZenML Core Consepts: https://docs.zenml.io/getting-started/core-concepts" class="image--center mx-auto" /></p>
<h2 id="heading-summary">Summary</h2>
<p>MLOps is an essential part of Machine Learning engineering that involves streamlining the process of taking ML models to production and maintaining and monitoring them. Without MLOps, organizations risk suboptimal performance, wasted resources, and increased error risks. ZenML provides an open-source solution that simplifies the entire ML pipeline and provides features like automated caching, data versioning, and automated metadata tracking. It seamlessly integrates the entire machine learning stack and supports popular infrastructure like Kubeflow, AWS Sagemaker, Azure ML, and Vertex AI GCP. ZenML also offers Continuous Training and Deployment (CT/CD) capabilities for end-to-end ML workflows that deploy models in local or production-grade environments. The ZenML workflow is built around pipeline architecture with a collection of steps that form a pipeline. ZenML stack is an abstract layer built to handle these pipelines, bringing flexibility in the sense of having a local stack for a pipeline, a project for testing, and a remote stack for production.</p>
]]></content:encoded></item><item><title><![CDATA[MLOps is not DevOps but why?]]></title><description><![CDATA[After a few months as an ML operations engineer, I discovered some of the many misconceptions surrounding the field. These misconceptions came from various directions and the online space is one of them. One of the most prevalent is the belief that M...]]></description><link>https://farisology.com/mlops-is-not-devops-but-why</link><guid isPermaLink="true">https://farisology.com/mlops-is-not-devops-but-why</guid><category><![CDATA[mlops]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Python]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Sat, 21 Jan 2023 17:11:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/f1c1154cacc1a32e1fdda3c50c1347e8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After a few months as an ML operations engineer, I discovered some of the many misconceptions surrounding the field. These misconceptions came from various directions and the online space is one of them. One of the most prevalent is the belief that MLOps is simply the application of DevOps principles to machine learning. While there are certainly similarities, the reality is that MLOps is a unique and complex discipline, requiring a deep understanding of both the technical and organizational aspects of machine learning. In this article, I will delve deeper into the distinctions between MLOps and DevOps, and provide a more comprehensive understanding of the role and responsibilities of an MLOps engineer.</p>
<h3 id="heading-definition-of-mlops">Definition of MLOps:</h3>
<p>Nvidia defines Machine learning operations, as "<em>best practices for businesses to run AI successfully with help from an expanding smorgasbord of software products and cloud services</em>."</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670134798108/df0f32a6-2cde-4e83-8b7e-cfc7d6444f5e.png" alt="MLOPS-process-Gartner-1280.png" /></p>
<p>Databricks' definition brings in more context as it defines MLOps as a core function of Machine Learning engineering, focused on streamlining the process of taking machine learning models to production, and then maintaining and monitoring them.</p>
<p>From both definitions, we can agree that our piece of software is a machine-learning model that is created during training. Maintaining such a model in production implies monitoring or tracking performance. The model changes if we have trained it with a different set of data and this brings the need for data and model versioning.</p>
<h3 id="heading-definition-of-devops">Definition of DevOps</h3>
<p>"DevOps is a set of practices that combines software development and IT operations. It aims to shorten the systems development life cycle and provide continuous delivery with high software quality" -<em>Wikipedia</em>.</p>
<p>DevOps have been around for at least a decade now and it grew and matured over time. I often remember it with this infinity diagram.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670122359765/716d332b-8b7f-4e50-b745-b57ff4e3a478.png" alt="DevOps.png" /></p>
<p>--photo by agapeconsultinggroup</p>
<p>There are a few concepts that stand out, although some are shared across the ML domain they are not necessarily applied in the same manner.</p>
<h3 id="heading-overview-of-the-differences-between-mlops-and-devops">Overview of the differences between MLOps and DevOps</h3>
<p>Version control is a software famous portion that when looked at in the light of MLOps we see that it's not about just the code. We need to version our data and models but until recently there was not an easy way to do it. Version control was built for code and that was tailored to software engineering needs not machine learning engineering needs. This in simple terms means even though DevOps and MLOps do version control, they are applying them differently with different tools.</p>
<blockquote>
<p>MLOps is not DevOps because it is specifically designed to automate and streamline the process of building, training, and deploying machine learning models. It focuses on the unique challenges of managing machine learning models, such as data versioning, model versioning, and model monitoring. --<strong><em>AI coauthored answer to the question in the title</em></strong></p>
</blockquote>
<h2 id="heading-why-mlops-is-different-from-devops">Why MLOps is Different from DevOps</h2>
<h3 id="heading-mlops-focuses-on-machine-learning">MLOps Focuses on Machine Learning</h3>
<p>MLOps is specifically designed to streamline the process of building, training, and deploying machine learning models. Building these models and deploying them comes with unique challenges that the MLOps engineer has to solve. Data versioning, model versioning, and model tracking are unique essential challenges for machine learning that aren't addressed by DevOps. In addition to this, there are other aspects of ML system design that don't exist in the software engineering paradigm. For example features generation, provisioning, and processing. Generating features from data is a unique component of machine learning systems and comes with various levels of complexity from an operational perspective if the system is online versus offline. The necessity for all these operational infrastructures increases with the growing governance rules and reproducibility becomes more than a feature.</p>
<h3 id="heading-mlops-requires-different-tools">MLOps Requires Different Tools</h3>
<p>Code version control has been one of the most remarkable artefacts of the tech industry today. A tool like Git grew and inspired different projects like Github, Gitlab and all the other Git-something out there. The current tooling was built with code in mind and as machine learning became an integral part of different systems there comes the need to track the model, data and performance.</p>
<p>To address the need for tracking and versioning there are tools to be added to the stack. Among these tools:</p>
<ul>
<li><p><strong>DVC</strong> is a tool for data tracking that is compatible with git. DVC helps you version your data and track any changes as if it's a piece of code.</p>
</li>
<li><p><strong>MLflow</strong> brings more to your stack to streamline and facilitate model versioning via its registry and tracking of experiments with complete logging capabilities for most machine learning frameworks.</p>
</li>
</ul>
<p>The required tools for MLOps are different and they are not as simple as alternatives to Git, but full-fledged capabilities that needed to be added to the stack of operations. The two examples of DVC and MLflow are simple examples and such tools will keep evolving.</p>
<p>The revolution continues with pre-trained models and LLMs. GPT and the like will bring about a new set of tooling that allows and facilitates working with foundational models. These new tools for prompts engineering and others will naturally add to the MLOps stack unless time proves a new age of LLMOps.</p>
<h3 id="heading-mlops-requires-different-skills">MLOps Requires Different Skills</h3>
<p>MLOps requires a different set of skills than DevOps, as the field is focused on the specific challenges and complexities of machine learning. Some of the key skills that an MLOps engineer should possess include:</p>
<ol>
<li><p><strong>Machine learning expertise</strong>: An understanding of the various types of machine learning algorithms, their strengths and weaknesses, and how to implement them in a production environment.</p>
</li>
<li><p><strong>Data science knowledge:</strong> Familiarity with data preprocessing, feature engineering, and model evaluation is essential for MLOps engineers to be able to work effectively with data scientists.</p>
</li>
<li><p><strong>Monitoring and troubleshooting:</strong> Understanding how to monitor machine learning models in a production environment and troubleshoot issues that arise is crucial for maintaining the performance and accuracy of the models.</p>
</li>
<li><p>Understanding of ML Governance, ML Security, ML Privacy, ML Explainability, and ML Fairness.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>MLOps is a unique and complex field that requires a specialized set of tools, skills, and knowledge to manage the specific challenges and complexities of machine learning models and data. It's important to understand that MLOps is not simply the application of DevOps principles to machine learning and that it requires a deep understanding of both the technical and organizational aspects of machine learning. As the field of AI continues to evolve, the distinctions between the two fields must become even more pronounced. Machine learning leaders and practitioners need to recognize these differences and not be held back by assumptions about similarities between the two fields. By recognizing the nuances of MLOps and approaching them with a clear understanding, organizations can more effectively deploy and manage their machine learning models in production.</p>
]]></content:encoded></item><item><title><![CDATA[Learning what to learn: a guide for intermediate data scientists]]></title><description><![CDATA[Learning technical skills is a challenging quest. The journey is not always smooth and often learners go through phases. This story is the sequel to my first part Learning How to Learn: A Guide for Aspiring Data Scientists and I want to extend to you...]]></description><link>https://farisology.com/learning-what-to-learn-a-guide-for-intermediate-data-scientists</link><guid isPermaLink="true">https://farisology.com/learning-what-to-learn-a-guide-for-intermediate-data-scientists</guid><category><![CDATA[Data Science]]></category><category><![CDATA[4articles4weeks]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Machine Learning]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Tue, 20 Sep 2022 08:25:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/oqStl2L5oxI/upload/v1663235454054/cLA2KW76s.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Learning technical skills is a challenging quest. The journey is not always smooth and often learners go through phases. This story is the sequel to my first part <a target="_blank" href="https://farisology.com/learning-how-to-learn-a-guide-for-aspiring-data-scientists">Learning How to Learn: A Guide for Aspiring Data Scientists</a> and I want to extend to you here the map of learning. You may ask what an intermediate data scientist is and how can we quantify these levels. Frankly, there is no data-driven definition I have in mind right now, so if you would agree with me let's adopt some heuristics for the sake of simplicity.</p>
<blockquote>
<p>At a certain level of your growth, curated courses will fall short of fulfilling your learning objectives. This stage of learning is often chartered by your ability to consume the primary source of knowledge like documentation to build your understanding and intuition.</p>
</blockquote>
<p>Hypothetically if the data science learning journey is of some similarity to learning to code, then we can assume that an intermediate level of competence could manifest as the ability to formulate the business problem into a data product requirements/solution, the ability to validate and analyse the model performance and building a successful proof of concept. If you have been tapping into these stages of any data science product then you can safely assume you are at the stage where this story is important for you.</p>
<p>There are several ways in which data scientist can demo their project ideas. In my experience, there were two main frameworks that really helped me do it effectively. <a target="_blank" href="https://dash.plotly.com/introduction">Dash</a> and <a target="_blank" href="https://streamlit.io/">Streamlit</a> were my go-to and I championed their adoption to every team I joined. If you are still in a stage where creating POC with a nice simple UI is not required this story can still hold value in showing you what to learn next.</p>
<h2 id="heading-fastapi-to-build-apis">Fastapi to build APIs</h2>
<p>Learning to build an API is a critical skill for a data scientist thinking of getting her hands-on in production. This skill will not only be your selling point when talking to small teams that are hiring but will also be a competitive advantage for you. It allows you to maximize your impact and drive more projects to that production line. There are so many challenges when thinking of putting a model in production, but API development skills should not be one of them.</p>
<p>Although there are several frameworks that can be used but am biased toward a great one <a target="_blank" href="https://fastapi.tiangolo.com/">FastAPI</a>. I have written a post to help you understand the <a target="_blank" href="https://farisology.com/fastapi-for-everyone">features and advantages of FastAPI</a> for data scientists. The FastAPI documentation is the best course out there, it's almost the golden standard of good documentation.</p>
<h2 id="heading-docker-and-containerised-applications">Docker and containerised applications</h2>
<p>There has been a time when the world of tech was certainly different from what it is today. Virtualisation has simplified many of our needs and boosted how we build systems. The value of learning about containerisation and especially docker is that it brings so much ease and robustness to your products. Deploying your model API via FastAPI is implemented via docker containers and often you would come across tools that are easily deployed as containers. The use cases are a lot and today docker containers are a normal practice where your knowledge of it brings you agility.</p>
<p>There are a few things you need to understand gradually as you learn about docker:</p>
<ul>
<li>What is the use-case it solves?</li>
<li>The difference between virtual machines and containerization.</li>
<li>Building a Docker image.</li>
<li>Running a Docker container from an image.</li>
</ul>
<p>The best course for is from the amazing freecodecamp:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/fqMOX6JJhGo">https://youtu.be/fqMOX6JJhGo</a></div>
<p>If that two hours course is a lot you may check this article by one of hashnode community members:</p>
<p><a target="_blank" href="https://atharvbobade.hashnode.dev/introduction-to-docker-part-1">Introduction to Docker</a></p>
<h2 id="heading-cloud-services">Cloud services</h2>
<p>The cloud is where all the actions take place. Building a functional knowledge of cloud services and concepts is an operational requirement especially if you aspire to take ownership of the complete lifecycle. This stands to be my personal opinion informed by my working experience in the field of data. Cloud services vendors are not a lot but 3 stand to be the most common. Amazon, Google, and Azure from Microsoft are the top 3 but there are other vendors like Digital Ocean and Linode. </p>
<p>Amazon Web Services (AWS) is the most common and widely adopted. Learning AWS will help you learn any other cloud and understand them in the main time ensuring that you have knowledge of the widely used vendor. There a lot of resources to learn AWS but if you are completely new to the concept of cloud maybe you can start with this AWS-made video:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/gv4m1fjuthU">https://youtu.be/gv4m1fjuthU</a></div>
<p>There are a few main services that you need to understand and have a solid hands-on building on them. These services are:</p>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html">Elastic Compute Engine</a> which is a virtual server (EC2): understanding how to create an instance, accessing using SSH, and configure security groups.</li>
<li><a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html">Simple Storage Service</a> (S3): Creating a bucket, pushing a file and reading a file from a bucket using python boto3 library + via the CLI.</li>
<li><a target="_blank" href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Welcome.html">Relational DataBase Service</a> (RDS): Creating an instance, connecting to the database, reading and writing data into a table.</li>
</ul>
<p>The next services that you can learn about are:</p>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html">IAM</a>: identity and access management to understand and learn your way around access management which will improve the security of your practice.</li>
<li><a target="_blank" href="https://docs.aws.amazon.com/AmazonECR/latest/userguide/what-is-ecr.html">ECR</a>: container registry is your gateway to deploying containerized applications in the cloud either into an EC2 or ECS cluster.</li>
<li><a target="_blank" href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html">DynamoDB</a>: adding this no-SQL storage will give your solutions an added advantage in more ways than one. I start thinking you should learn it first in this list.</li>
</ul>
<blockquote>
<p>As you go on learning more advanced concepts the types of learning resources reduce to be left with the primary sources. The documentation of various projects is your first choice, the second source is your own experimentation and hands-on journey.</p>
</blockquote>
<h2 id="heading-final-thoughts">Final thoughts</h2>
<p>The knowledge your gain from learning is compounded by a factor of magnitude when you applied in the next project. You can learn so many concepts and new technologies but that learning remains limited until you start working on problems to solve. In my experience, there are always a set of concepts that can stretch to so many use-cases and every time you apply the same skills but to different problems. The beauty of this is that your skills and experience are enriched each time you work on a new use-case.</p>
<p><em>I hope this list of recommended learning guides you through. May your accuracy by high and your models don't overfit!</em></p>
]]></content:encoded></item><item><title><![CDATA[Embeddings and The Age of Transformers]]></title><description><![CDATA[The prime requirement for most machine learning algorithms is numeric data. All your inputs that represent real-world entities should be translated into numeric values. Applied machine learning is rooted in features engineering techniques to produce ...]]></description><link>https://farisology.com/embeddings-and-the-age-of-transformers</link><guid isPermaLink="true">https://farisology.com/embeddings-and-the-age-of-transformers</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Python]]></category><category><![CDATA[4articles4weeks]]></category><category><![CDATA[nlp]]></category><category><![CDATA[Deep Learning]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Fri, 02 Sep 2022 18:53:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/hsg538WrP0Y/upload/v1662144585020/pjMgi2MWh.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The prime requirement for most machine learning algorithms is numeric data. All your inputs that represent real-world entities should be translated into numeric values. Applied machine learning is rooted in features engineering techniques to produce the best results. This has brought domain knowledge to be of significant importance because crafting new ways to represent real-world entities can be done well with domain expertise. Lately, the emergence of transformers such as BERT has been transformative for natural language processing/understanding NLP/NLU.</p>
<p>With images, numerical representation can be as crude as using pixel intensity values. Other types of data like tabular or textual data have their ways to make these transformations. Here, I will speak in the context of natural language understanding NLU and how the field moved from the lexicon level towards the semantic representation.</p>
<h2 id="heading-review">Review</h2>
<p>Embeddings are a way to represent text numerically. We do this text-to-numeric transformation because again machine learning requires us to do so. Here is an over-simplistic example of representing text for machine learning:</p>
<pre><code>text1 = <span class="hljs-string">"I love bananas"</span>
text2 = <span class="hljs-string">"I love apples"</span>
text3 = <span class="hljs-string">"bananas and apples"</span>

embedding1 = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
embedding2 = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>]
embedding3 = [<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>]
</code></pre><p>As you see from each text we simply denoted each unique word with a single numeric value. The result of this is that we now have each statement represented as a simple low dimension vector. That vector can be processed by machine learning algorithms to perform various tasks be it text classification or others. You can observe that some words are repeated, the purpose of this is to show you have each unique word is given a unique value.</p>
<h3 id="heading-bag-of-words">Bag of words</h3>
<p>The bag of words technique ly a bag-like vector where every column corresponds to a unique word and each row represents one sentence. Each unique term/word will be represented by 0/1 denoting its presence in the sentence. If we use the above example we will have something that looks like this:</p>
<pre><code>    I    love     bananas   apples  and
[ [<span class="hljs-number">1</span>,     <span class="hljs-number">1</span>,         <span class="hljs-number">1</span>,                <span class="hljs-number">0</span>,          <span class="hljs-number">0</span>],
  [<span class="hljs-number">1</span>,     <span class="hljs-number">1</span>,        <span class="hljs-number">0</span>,                 <span class="hljs-number">1</span>,          <span class="hljs-number">0</span>],
  [<span class="hljs-number">0</span>,    <span class="hljs-number">0</span>,        <span class="hljs-number">1</span>,                 <span class="hljs-number">1</span>,           <span class="hljs-number">1</span>]
]
</code></pre><h3 id="heading-tf-idf">Tf-idf</h3>
<p>Term frequency-inverse document frequency comes to enhance what we have from the bag of words. The values, instead of zeros and ones to indicate the presence or absence of a word in a sentence, are used to weigh the importance of the word in the documents. Think of it like the weight of the words and it comprises two parts.</p>
<ul>
<li>Term frequency: <blockquote>
<p>TF(t) = (Number of times term t appears in a document) / (Total number of terms in the document).</p>
</blockquote>
</li>
</ul>
<p>This measures how frequently a term or word appears in a document. Documents are of varying lengths and in long documents, a term might occur more often. So dividing this by the total terms in the document is a normalization step. At this stage, all terms are considered equally important.</p>
<ul>
<li>Inverse document frequency:<blockquote>
<p>IDF(t) = log_e(Total number of documents / Number of documents with term t in it).</p>
</blockquote>
</li>
</ul>
<p>Certain terms like "the" and "is" are of high frequency but we know they are not important. Computing IDF allows measuring the importance of the term by scaling up the weight of rare terms.</p>
<blockquote>
<p>Assume we have a document of 100 words wherein the word fish appeared 3 times. The term frequency (i.e., tf) for fish is then (3 / 100) = 0.03. Now, assume we have 10 million documents and the word fish appears in one thousand of these. Then, the inverse document frequency (i.e., idf) is calculated as log(10,000,000 / 1,000) = 4. Thus, the Tf-idf weight is the product of these quantities: 0.03 <em> 4 = 0.12. - </em>Example from <a target="_blank" href="http://tfidf.com/">tf-idf</a>*</p>
</blockquote>
<p>This change in the way we can represent the sentences has brought with it substantial performance improvements. These two methods are basic and they are thought of more as approaches to represent texts digitally. The field has gone on with the early versions of text embeddings with word2vec, sentence2vec, and doc2vec. Word2vec is generating dense embeddings from words. Under the hood, words are encoded into one-hot vectors and forwarded to a hidden neural layer which produces hidden weights.  These hidden weights are used as embeddings.</p>
<h2 id="heading-pretrained-models">Pretrained models</h2>
<p><a target="_blank" href="https://paperswithcode.com/method/bert">BERT</a> stands for Bidirectional Encoder Representation Transformer and it's pre-trained and developed by Google. The improvements here are from removing the unidirectional constraint that standard transformers have had. You can refer to the original <a target="_blank" href="https://arxiv.org/abs/1810.04805">BERT paper</a> for an in-depth understanding of its architecture.</p>
<p>The second breakthrough came from Generative Pretrained Transformer GPT. The transformer architecture when added with unsupervised learning, has changed the scope of natural language understanding. This means training task-specific models from scratch are relics of the past. But GPT and BERT are the first waves of transformers, today we have ever powerful and advanced models than those changing how we practice NLU.</p>
<p>I firmly believe that we have entered a new era and it calls for your attention to understand how to use pre-trained models. Allow me to show you a couple of applications or perhaps use cases in which I have leveraged these advancements in my projects.</p>
<h3 id="heading-semantic-search">Semantic search</h3>
<p>In today's world we - as users - expect search to be better than text matching. Users implicitly expect search results to be refined and semantically sound. This is challenging without transforms because text vectorisation can only help us learn if two texts are syntactically similar. Transformers however bridge that gap and brings about the ability to measure semantic similarity. Let's have a simple example which was mentioned in an old <a target="_blank" href="https://farisology.com/beneath-the-hood-fave-personalization-39d54b136fed#heading-semantic-encoding">article</a>. </p>
<p>Say you have two terms one is a drink the other is a meal. We know that both are under the food &amp; beverages category and they should be mathematically closer than something like a gadget. If we represented the name of each item using one-hot encoding for example we will have an arbitrary representation that doesn't disclose this semantic meaning. However, if you just used a pre-trained model to give generate embeddings that represent each and then measured the cosine distance we will see that we can tell what sentences are similar. I have curated this simple example to illustrate how we can do this using the sentence transformer library in python.</p>
<pre><code><span class="hljs-keyword">from</span> sentence_transformers <span class="hljs-keyword">import</span> SentenceTransformer, util
model = SentenceTransformer(<span class="hljs-string">'all-MiniLM-L6-v2'</span>)

# Single list <span class="hljs-keyword">of</span> sentences
sentences = [<span class="hljs-string">"chicken burger with fries"</span>,
             <span class="hljs-string">"coke with ice"</span>,
             <span class="hljs-string">"iphone 13 pro with 5k pixels"</span>]

#Compute embeddings
embeddings = model.encode(sentences, convert_to_tensor=True)

#Compute cosine-similarities <span class="hljs-keyword">for</span> each sentence <span class="hljs-keyword">with</span> each other sentence
cosine_scores = util.cos_sim(embeddings, embeddings)

#Find the pairs <span class="hljs-keyword">with</span> the highest cosine similarity scores
pairs = []
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(cosine_scores)<span class="hljs-number">-1</span>):
    <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(i+<span class="hljs-number">1</span>, len(cosine_scores)):
        pairs.append({<span class="hljs-string">'index'</span>: [i, j], <span class="hljs-string">'score'</span>: cosine_scores[i][j]})

#Sort scores <span class="hljs-keyword">in</span> decreasing order
pairs = sorted(pairs, key=lambda x: x[<span class="hljs-string">'score'</span>], reverse=True)

<span class="hljs-keyword">for</span> pair <span class="hljs-keyword">in</span> pairs[<span class="hljs-number">0</span>:<span class="hljs-number">10</span>]:
    i, j = pair[<span class="hljs-string">'index'</span>]
    print(<span class="hljs-string">"{} \t\t {} \t\t Score: {:.4f}"</span>.format(sentences[i], sentences[j], pair[<span class="hljs-string">'score'</span>]))
</code></pre><p>The output of this as per what your human experience:</p>
<pre><code>chicken burger <span class="hljs-keyword">with</span> fries          coke <span class="hljs-keyword">with</span> ice          Score: <span class="hljs-number">0.2669</span>
coke <span class="hljs-keyword">with</span> ice          iphone <span class="hljs-number">13</span> pro <span class="hljs-keyword">with</span> <span class="hljs-number">5</span>k pixels          Score: <span class="hljs-number">0.0684</span>
chicken burger <span class="hljs-keyword">with</span> fries          iphone <span class="hljs-number">13</span> pro <span class="hljs-keyword">with</span> <span class="hljs-number">5</span>k pixels          Score: <span class="hljs-number">0.0613</span>
</code></pre><p>the first two sentences are close which is determined by our human experience and the scores confirm this. The other sentences against each other prove they are of less similarity than the first two. Now, this can too be applied to search engines in a few ways. One way is to add a ranking and sorting logic that takes the results of the search engine before they are presented to the user and rank them based on their semantic similarity score measured against the searching query or sentence.</p>
<h3 id="heading-sentiment-and-text-classification">Sentiment and text classification</h3>
<p>If you are doing any project where are solving a text classification project, you can leverage these pre-trained models to produce embeddings. These dense low-dimensional vectors are rich in their ability to bring not only syntax but semantics-level understanding to your model. Here is a sample code to demo:</p>
<pre><code><span class="hljs-keyword">from</span> sentence_transformers <span class="hljs-keyword">import</span> SentenceTransformer
model = SentenceTransformer(<span class="hljs-string">'all-MiniLM-L6-v2'</span>)

#Our sentences we like to encode
sentences = [<span class="hljs-string">'This framework generates embeddings for each input sentence'</span>]

#Sentences are encoded by calling model.encode()
embeddings = model.encode(sentences)

#Print the embeddings
<span class="hljs-keyword">for</span> sentence, embedding <span class="hljs-keyword">in</span> zip(sentences, embeddings):
    print(<span class="hljs-string">"Sentence:"</span>, sentence)
    print(<span class="hljs-string">"Embedding:"</span>, embedding)
    print(<span class="hljs-string">""</span>)
</code></pre><p>The embedding will look something like this:</p>
<pre><code>[<span class="hljs-number">-1.37173440e-02</span> <span class="hljs-number">-4.28515337e-02</span> <span class="hljs-number">-1.56286079e-02</span>  <span class="hljs-number">1.40537489e-02</span>
  <span class="hljs-number">3.95537838e-02</span>  <span class="hljs-number">1.21796302e-01</span>  <span class="hljs-number">2.94333789e-02</span> <span class="hljs-number">-3.17523852e-02</span>
  <span class="hljs-number">3.54959555e-02</span> <span class="hljs-number">-7.93140158e-02</span>  <span class="hljs-number">1.75878275e-02</span> <span class="hljs-number">-4.04369608e-02</span>
  <span class="hljs-number">4.97259833e-02</span>  <span class="hljs-number">2.54912414e-02</span> <span class="hljs-number">-7.18700588e-02</span>  <span class="hljs-number">8.14968869e-02</span>
  <span class="hljs-number">1.47068209e-03</span>  <span class="hljs-number">4.79627326e-02</span> <span class="hljs-number">-4.50336412e-02</span> <span class="hljs-number">-9.92174968e-02</span>
 <span class="hljs-number">-2.81769391e-02</span>  <span class="hljs-number">6.45046309e-02</span>  <span class="hljs-number">4.44670543e-02</span> <span class="hljs-number">-4.76217493e-02</span>
 <span class="hljs-number">-3.52952704e-02</span>  <span class="hljs-number">4.38672006e-02</span> <span class="hljs-number">-5.28565980e-02</span>  <span class="hljs-number">4.33019130e-04</span>
  <span class="hljs-number">1.01921476e-01</span>  <span class="hljs-number">1.64072122e-02</span>  <span class="hljs-number">3.26996520e-02</span> <span class="hljs-number">-3.45986746e-02</span>
  <span class="hljs-number">1.21339737e-02</span>  <span class="hljs-number">7.94871375e-02</span>  <span class="hljs-number">4.58343467e-03</span>  <span class="hljs-number">1.57778431e-02</span>
 <span class="hljs-number">-9.68210120e-03</span>  <span class="hljs-number">2.87625995e-02</span> <span class="hljs-number">-5.05805984e-02</span> <span class="hljs-number">-1.55793587e-02</span>
 <span class="hljs-number">-2.87906975e-02</span> <span class="hljs-number">-9.62281693e-03</span>  <span class="hljs-number">3.15556452e-02</span>  <span class="hljs-number">2.27348991e-02</span>
  <span class="hljs-number">8.71449485e-02</span> <span class="hljs-number">-3.85027565e-02</span> <span class="hljs-number">-8.84718448e-02</span> <span class="hljs-number">-8.75497889e-03</span>
 <span class="hljs-number">-2.12343168e-02</span>  <span class="hljs-number">2.08923966e-02</span> <span class="hljs-number">-9.02077779e-02</span> <span class="hljs-number">-5.25732227e-02</span>
 <span class="hljs-number">-1.05638737e-02</span>  <span class="hljs-number">2.88311075e-02</span> <span class="hljs-number">-1.61455162e-02</span>  <span class="hljs-number">6.17838977e-03</span>
 <span class="hljs-number">-1.23234931e-02</span> <span class="hljs-number">-1.07337432e-02</span>  <span class="hljs-number">2.83353962e-02</span> <span class="hljs-number">-5.28567694e-02</span>
 <span class="hljs-number">-3.58617976e-02</span> <span class="hljs-number">-5.97989261e-02</span> <span class="hljs-number">-1.09055163e-02</span>  <span class="hljs-number">2.91566737e-02</span>]
</code></pre><p>This powerful representation is revolutionary because we can scale the use of the model to more use cases without the need to retrain from scratch and this saves time and effort. Transformers has been setting new records on benchmarks of NLP tasks for a few years and they are more available to you than ever before. You can copy-paste any of the code examples into a collab and start playing around with them.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I have been fascinated by transformers and how they changed how I do NLP and look at problems. In this short story, I hope to help you in understanding the what, why and where you can use transformers and pre-trained models. I will be glad to know the projects and ideas you will build with transformers.</p>
]]></content:encoded></item><item><title><![CDATA[FastAPI for everyone]]></title><description><![CDATA[Data science is a multidisciplinary field and this versatility brings about people from different backgrounds. Many data scientists are not equipped with a software engineering background and those are not necessarily experts. If you are a data scien...]]></description><link>https://farisology.com/fastapi-for-everyone</link><guid isPermaLink="true">https://farisology.com/fastapi-for-everyone</guid><category><![CDATA[FastAPI]]></category><category><![CDATA[Python]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Fri, 19 Aug 2022 03:36:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660749243752/PRuwDKYf1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Data science is a multidisciplinary field and this versatility brings about people from different backgrounds. Many data scientists are not equipped with a software engineering background and those are not necessarily experts. If you are a data scientist you might have tried or learned about what happens to a model after you are done with training. Particularly about taking your machine learning model to production. This is the stage in which the machine learning model is wrapped in an API to be available as a web service. Even in the case of you coming here from a web-development background, this is still relevant to you.</p>
<p><a target="_blank" href="https://fastapi.tiangolo.com/">FastAPI</a> is a web framework for building a python API that is fast and reliable. It's truly a good addition to your skills and special power when deploying your model falls under your responsibilities. In this preview, I would share a few advantages of using the framework over Flask. </p>
<p><em>I assume you have a brief background on APIs. For example, you can understand what endpoint, request, or query is. If you don't have any idea, you still can follow up to learn about FastAPI but do your research afterwards.</em></p>
<h2 id="heading-intuitive-code">Intuitive code</h2>
<p>Your time is precious and writing a lot of code means higher chances of bugs and errors. There are two ways in which FastAPI reduces the amount of code you type. The first is for reading parameters and the second is for data validation.</p>
<h3 id="heading-reading-parameters">Reading parameters</h3>
<p>This is my favourite part of FastAPI and for one obvious reason, it builds up to more and more awesomeness. One of the ways to define variables in FastAPI is the path in the same fashion as python strings:</p>
<pre><code><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI

app = FastAPI()


<span class="hljs-meta">@app.get("/items/{item_id}")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_item</span>(<span class="hljs-params">item_id</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"item_id"</span>: item_id}
</code></pre><p>Reading the variables and declaring them in the path like python strings is the pythonic way. This is also not unique to FastAPI, but as you read further you will see how it builds up to make a great combination of advantages. If you declared any function parameter that is not in the path, it's automatically understood and treated as <strong>query parameter</strong>. Let's see the simple script here:</p>
<pre><code><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Union
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI

app = FastAPI()


<span class="hljs-meta">@app.get("/items/{item_id}")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_item</span>(<span class="hljs-params">item_id: str, query_param: Union[str, None] = None</span>):</span>
    <span class="hljs-keyword">if</span> query_param:
        <span class="hljs-keyword">return</span> {<span class="hljs-string">"item_id"</span>: item_id, <span class="hljs-string">"query_param"</span>: query_param}
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"item_id"</span>: item_id}
</code></pre><p>The function read_item has one variable parameter which is <em>item_id</em> and another query parameter which is <em>query</em>. The way it's written here - =None-is just to say the query parameter is optional. </p>
<h3 id="heading-automatic-data-validation">Automatic data validation</h3>
<p>Data coming to your API can be in many shapes and formats. Validating the data before processing is important and FastAPI does this via <a target="_blank" href="https://pydantic-docs.helpmanual.io/">pydantic</a>. Pydantic streamlines data validation via python type annotations. The way this is implemented is via several methods for example in the case of query parameter we can have additional string validations. In the following script observe how we define a <em>default value</em> with a <em>max_length</em> of 6 characters.</p>
<pre><code><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Union
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, Query

app = FastAPI()

<span class="hljs-meta">@app.get("/items/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_items</span>(<span class="hljs-params">query_param: Union[str, None] = Query(<span class="hljs-params">default=<span class="hljs-string">"FooBar"</span>, max_length=<span class="hljs-number">6</span></span>)</span>):</span>
    results = {<span class="hljs-string">"items"</span>: [{<span class="hljs-string">"item_id"</span>: <span class="hljs-string">"Foo"</span>}, {<span class="hljs-string">"item_id"</span>: <span class="hljs-string">"Bar"</span>}]}
    <span class="hljs-keyword">if</span> query_param:
        results.update({<span class="hljs-string">"query_param"</span>: query_param})
    <span class="hljs-keyword">return</span> results
</code></pre><p>The developer can as well add numeric validation for path parameters and other, <a target="_blank" href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/">documentation</a>. The other way is also possible simply by using the pydantic BaseModel class which defines the parameters and their data type. </p>
<pre><code><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List, Union
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

app = FastAPI()

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Item</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    description: Union[str, <span class="hljs-literal">None</span>] = <span class="hljs-literal">None</span>
    price: float
    tax: Union[float, <span class="hljs-literal">None</span>] = <span class="hljs-literal">None</span>
    tags: List[str] = []

<span class="hljs-meta">@app.post("/items/", response_model=Item)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_item</span>(<span class="hljs-params">item: Item</span>):</span>
    <span class="hljs-keyword">return</span> item
</code></pre><p>Look at the 3rd raw (counting from the bottom up) which is the decorator and observe that we have defined <strong>response_model</strong> as a parameter there. The value passed is the name of the <strong>BaseModel</strong> so FastAPI is going to use this to:</p>
<ul>
<li>Convert the output data to the declared type.</li>
<li>Perform data validation.</li>
<li>Generate a JSON Schema for the response.</li>
<li>Use it for the automatic documentation systems.</li>
</ul>
<h2 id="heading-auto-documentation">Auto Documentation</h2>
<p>The interactive documentation is automatically generated which is provided by <a target="_blank" href="https://github.com/swagger-api/swagger-ui">swagger-ui</a>. For example, if you are running fastapi locally you can access the docs from <a target="_blank" href="http://127.0.0.1:8000/docs">http://127.0.0.1:8000/docs</a>. Which will look like this:
<img src="https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png" alt="swagger-ui doc" />
(Image by FastAPI documentation)</p>
<p>You also have another optional alternative doc by <a target="_blank" href="https://github.com/Redocly/redoc">redoc</a> from <a target="_blank" href="http://127.0.0.1:8000/redoc">http://127.0.0.1:8000/redoc</a> which will look like this:
<img src="https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png" alt="alternative docs" />
(Image by FastAPI documentation)</p>
<h2 id="heading-performance">Performance</h2>
<p>According to <a target="_blank" href="https://www.techempower.com/benchmarks/#section=test&amp;runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&amp;hw=ph&amp;test=db&amp;l=zijzen-7">techempower</a>, FastAPI is the third fastest python framework coming under Uvicron and starlette which are the backbone of FastAPI. However, I believe this is not the only speed we should care about. The speed of development and building with FastAPI is outstanding. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this draws the image clearer in terms of how concise and elegant the building experience with FastAPI is. This is in addition to the speed and other features I shared with you here. I came across this framework back in 2019 and have been using it for several data science projects in production. There are more points that I didn't cover here because am sure you will have a pleasant time going through the <a target="_blank" href="https://fastapi.tiangolo.com/">FastAPI documentation</a>. It's one of the best-documented projects out there.</p>
]]></content:encoded></item><item><title><![CDATA[How to Rock Data Science One Project a Time]]></title><description><![CDATA[Background
Once upon a time, I opened my Jupyter notebook to show a C-suite manager my work on the project. He had never asked me to show my work ever again after that. If you didn't understand what happened here, imagine the following: a passionate ...]]></description><link>https://farisology.com/how-to-rock-data-science-one-project-a-time</link><guid isPermaLink="true">https://farisology.com/how-to-rock-data-science-one-project-a-time</guid><category><![CDATA[Data Science]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Product Management]]></category><category><![CDATA[Python]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Sun, 14 Aug 2022 07:32:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/iIWDt0fXa84/upload/v1659537874023/FEAEXDHxj.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-background">Background</h2>
<p>Once upon a time, I opened my Jupyter notebook to show a C-suite manager my work on the project. He had never asked me to show my work ever again after that. If you didn't understand what happened here, imagine the following: a passionate fresh grad was asked by a manager to show his work. The young and broke fresh grade with all excitement presented his python code. Nobody has acknowledged my existence in this big organisation and finally, it's my moment to show my magic; or so I thought. Me presenting my code was a spectacular mistake I have done so far in my career. As time goes by I became so attached to showing my models working via prototypes.</p>
<p><strong>Why was this a mistake?</strong> Well, am glad you asked. The manager doesn't understand python and couldn't care less about code in general. He was asking about some reports, insights, or any form that could represent my findings. This is a manager, not your groupmate that you just show him the output of jupyter notebook. </p>
<p>The essential question is <strong>how do you show your work and progress as a data scientist?</strong> Here I want to share what I have practised over years of working in the field and proven to be remarkable.</p>
<h2 id="heading-documentation">Documentation</h2>
<p>I hope this does not come as a surprise to you, but they are by far the best ambassadors of your thoughts. I do believe that writing is not just about explaining our ideas to others, but in the first place, writing is thinking clearly. While you write the process that takes place is building connections among your thoughts. The final output is more than a document, it's also clarity.</p>
<blockquote>
<p>I do believe that writing is not just about explaining our ideas to others, but in the first place, writing is thinking clearly.</p>
</blockquote>
<p><strong>What to write?</strong>
There are several forms of writing or documentation one can do, but I will limit this to 3 types.</p>
<h3 id="heading-one-page">One page</h3>
<p>This document is very simple and straightforward. It is one page that describes what you want to do. You should answer three questions:</p>
<ol>
<li>What is this project about? You can describe the problem and give context.</li>
<li>Why are we doing it? Objectives that you want to achieve.</li>
<li>How are you going to do it? An abstract description with less technical jargon.</li>
</ol>
<p>This document is your first page and you will write them more often. My rule of thumb is that I jump into creating this every time an idea lights up above my head. Often this is what managers will look at to get the gist of what you are working on.</p>
<p><strong>Where to write this?</strong>
You can write this literally anywhere that allows you to share documents or collaborate. It can be as simple as Google docs. I have used <a target="_blank" href="https://www.dropbox.com/paper/start">Dropbox paper</a> and switched to <a target="_blank" href="https://www.notion.so/">Notion</a>. Your company might have a platform for this or you can simply start one.</p>
<h3 id="heading-performance-analysis">Performance analysis</h3>
<p>This could be what you should think of as soon as you start progressing on your exploratory data analysis (EDA). More importantly, if you have built some machine learning model this kind of analysis document is how you keep your stakeholders informed. The medium could be a document page or even a slide if you fancy it.</p>
<h3 id="heading-technical-documentation">Technical documentation</h3>
<p>This document is different in nature. The intent here is to write something that describes the technicalities of the project. In this instance, the targeted audience is fellow data scientists and colleagues. Among the points that you should make clear are:</p>
<ol>
<li>Flow of the system or the workflow preferably visually drawn to help communicate through the image.</li>
<li>The implementation and considerations.</li>
<li>Links to parts of the code or repository.</li>
</ol>
<h2 id="heading-prototyping">Prototyping</h2>
<p>Data science projects under the hood could be a lot of things from machine learning models, preprocessing steps, and even data pipelines that are necessary to keep the product running. Nonetheless, your work has to be ultra simple and impactful in the beginning. That means to think of a minimal viable functionality and build it first. Building data products is way easier today than ever. There are several tools out there but I will mention two:</p>
<h3 id="heading-dash">Dash</h3>
<p><a target="_blank" href="https://dash.plotly.com/installation">Dash</a> is a framework to build web-based data applications. Written on top of plotly.js and React.js which makes it ideal for building the web interface of your machine learning models. Dash abstract and full-stack which is empowering for data scientists to build without the need to understand or manage the complexity behind the scenes. We call products built on dash "dash apps or applications".</p>
<h3 id="heading-streamlit">Streamlit</h3>
<p><a target="_blank" href="https://streamlit.io/">Streamlit</a> takes a data scientist to another level of building full stack applications with crisp clean web interfaces. The power of streamlit comes from a huge set of pre-built widgets with the ability to customize and be up and running in a few minutes.</p>
<h2 id="heading-how-to-do-it">How to do it?</h2>
<p>Now that you know the most important tools, I think in a simple scenario things will go along the lines of the following flowchart.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659771296923/eFdBwFqr_.jpeg" alt="Flowchart.jpeg" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The real-life situation might be different but I hope this draws the image for you. One step omitted here (in the above flowchart) is the technical documentation which is something that can be done once the product is deployed or iteratively written while development is still ongoing.</p>
<p>Through this text I hope you have learnt about:</p>
<ol>
<li>Documentation: types of documents and to whom we write them.</li>
<li>Prototyping: Python Frameworks that are used to build an interactive app.</li>
<li>MVP: Thinking of a minimal viable product for your project.</li>
<li>Workflow: First steps to take when you have a new idea or concept.</li>
</ol>
<p>Remember the following quote by Eric Ries:</p>
<blockquote>
<p>The only way to win is to learn faster than anyone else.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Learning How to Learn: A Guide for Aspiring Data Scientists]]></title><description><![CDATA[Data science is an exciting field with vast areas of applications and skills that you need to acquire. If you are reading this I am sure you have been reading long lists of resources, courses and books. I am trying to do something different here whic...]]></description><link>https://farisology.com/learning-how-to-learn-a-guide-for-aspiring-data-scientists</link><guid isPermaLink="true">https://farisology.com/learning-how-to-learn-a-guide-for-aspiring-data-scientists</guid><category><![CDATA[Data Science]]></category><category><![CDATA[data]]></category><category><![CDATA[Python]]></category><category><![CDATA[python beginner]]></category><category><![CDATA[Machine Learning]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Sun, 10 Jul 2022 17:43:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/ErO0E8wZaTA/upload/v1657464406890/RVfEyp92H.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Data science is an exciting field with vast areas of applications and skills that you need to acquire. If you are reading this I am sure you have been reading long lists of resources, courses and books. I am trying to do something different here which is minimum viable knowledge to get into data science. Let's call it MVK for data science. To be fair and realistic I have to tell you the not very good news, data science means different things to different people. At some companies, it's extensive excel work whereas at some others it's spark jobs and parallel processing. In between the two extremes lies most of the companies with requirements that vary in technicality.</p>
<p>This MVK guide is meant for mainstream data science practice. It's hard to say what's mainstream today, however, I would like to say that skills and knowledge that are core and without any advanced or special requirements. This curated list of skills and resources are of my own so they represent my experience and personal opinion. Almost every course here is something I have taken personally or recommended to more than one of my mentees.</p>
<blockquote>
<p>Minimum Viable Knowledge (MVK) for data science to help you start solid</p>
</blockquote>
<h2 id="heading-fundamentals">Fundamentals</h2>
<p>These are core data science skills and a person must be exposed to at least the main concepts. I do think that having an overview is good enough, however, some depth of knowledge accumulated will take you further in your journey. I don't claim that you need to know everything in this guide to land an internship or an entry-level position. Nonetheless, the more you know the higher your chances are because you set yourself on top of the list in terms of potential.</p>
<h3 id="heading-sql">SQL</h3>
<p>There is no training data set in real life, that pristine CSV doesn't exist. There could be a data warehouse or multiple data storage systems with hundreds of tables where the organization stored their data. It's your responsibility to dive in and build a dataset for the use case at hand. Since almost every data storage has SQL or SQL-like medium to interact with data it's primitive to know how to SQL your way into these systems.</p>
<p>I would go further to say that you will spend 3 quarters of your time interacting with data. Pre and post-modelling work require you to perform a variety of tasks from explorations to analysing data. Being fluent in SQL is essential and therefore you should get yourself into good SQL practices as you grow.</p>
<ol>
<li><a target="_blank" href="https://www.kaggle.com/learn/intro-to-sql">Introduction to SQL from Kaggle is highly recommended</a></li>
<li><a target="_blank" href="https://www.kaggle.com/learn/advanced-sql">Advanced SQL is building on top of the intro course which goes to build your strong SQL foundations</a></li>
</ol>
<h3 id="heading-python">Python</h3>
<p>There are more courses and books for learning python than I could count. So, here is what I think is the best book/course for you, it's what you find good for you!! Myself, I loved the book "Python for informatics" by Charles Severance   and was delighted when I found the course on Coursera "Python for Everybody". The book/course was made for beginners and curated examples and problems that were interesting enough to keep me engaged. Though it's a general python course hence it builds your skills in python as a programming language. I mean this is not the course that teaches pandas and NumPy.</p>
<p>The book is now mostly known as python for everybody and is available as a course on most platforms. It's also available for free online along with its exercise, code and pdf version.</p>
<ul>
<li>Book PDF:<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="http://www.do1.dr-chuck.com/py4inf/EN-us/book.pdf">http://www.do1.dr-chuck.com/py4inf/EN-us/book.pdf</a></div>
</li>
<li>Book Online:<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.py4e.com/html3/">https://www.py4e.com/html3/</a></div>
</li>
<li>Youtube playlist:<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/playlist?list=PLlRFEj9H3Oj7Bp8-DfGpfAfDBiblRfl5p">https://www.youtube.com/playlist?list=PLlRFEj9H3Oj7Bp8-DfGpfAfDBiblRfl5p</a></div>
</li>
<li>Github source code:<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/csev/py4e">https://github.com/csev/py4e</a></div>
</li>
</ul>
<p>Now that python as a programming language course is out of the way, you may ask, what about a data science-oriented course. This one you can learn from different resources as well, however, I would recommend the first two courses from the Coursera specialization "Applied Data Science with Python" By the University of Michigan. There is a steep learning curve to some extent as the learner move from the first course to the second. </p>
<ul>
<li>Applied Data Science with Python:<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.coursera.org/specializations/data-science-python">https://www.coursera.org/specializations/data-science-python</a></div>
</li>
</ul>
<h3 id="heading-machine-learning">Machine Learning</h3>
<p>The best course in machine learning is the one on Coursera by <a target="_blank" href="https://www.andrewng.org/">Andrew NG</a>. Since its launch in 2012, millions have taken that course including me. The second best course is the new version of the same course by Andrew NG launched this year 2022. It's a remake of the first course with switching to teaching python. I cannot give this course justice no matter what I say. There is more to the course than just the topics, the impeccable delivery of concepts is just unmatched.</p>
<ul>
<li>Machine learning specialization by Andrew Ng:<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.coursera.org/specializations/machine-learning-introduction?">https://www.coursera.org/specializations/machine-learning-introduction?</a></div>
</li>
</ul>
<h3 id="heading-statistics">Statistics</h3>
<blockquote>
<p>Machine learning is the new statistics</p>
</blockquote>
<p>Regardless of how true the statement is, what I want you to recognise here is the correlation. This correlation is an anecdote of connection between the two fields. Therefore, having a solid foundation in statistics will strengthen your ability to understand a lot of the inner workings of machine learning algorithms. Here are a few courses that I found to be interesting:</p>
<ul>
<li><p>Introduction to Statistics by Stanford (Free course):</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.coursera.org/learn/stanford-statistics">https://www.coursera.org/learn/stanford-statistics</a></div>
</li>
<li><p>Statistics concepts explained:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/playlist?list=PLVf6vX-h44c2KX5ydZ5NCyy5ly_elT9QT">https://www.youtube.com/playlist?list=PLVf6vX-h44c2KX5ydZ5NCyy5ly_elT9QT</a></div>
</li>
</ul>
<p>I believe that having a grasp of the concepts is essential to make sense of various topics and new concepts in data science. It also helps build a good intuition. Though knowing deeper details and how to calculate is important, you can understand more as you gradually get exposed to more cases and problems.</p>
<h2 id="heading-auxilary-skills">Auxilary skills</h2>
<p>Some skills make you a better candidate or set you up for success in data science. They are not talked about a lot, but they are expected to work in the data field or even generally in tech. Here are the most important ones you should pay attention to.</p>
<h3 id="heading-communication">Communication</h3>
<p>Data scientists do various tasks in various organizations, but there is one task that is in common. They are in constant need to present results and insights. This single skill draws the distinction between data scientists. In data science, finesse is not about building the 98% accurate model only, but rallying everyone to ship a data product into production. You need to be a great communicator to be able to drive projects and make people in your organization take your insights further into their implementation. </p>
<p>Communication to me has the following aspects:</p>
<ol>
<li>Understanding the matter at hand. You are the subject matter expert and you should understand the matter more than anyone in the room.</li>
<li>Content structure. Your ideas need to have a flow that connects and makes a cohesive story. The results have to be organized in a way that is smooth and linked.</li>
<li>Delivery. Here lays the make or break of your quest the ability to deliver results or insights with as little friction as possible. Success here could be in the form of people's positive reactions or questions about how to move to the next step.</li>
</ol>
<p>There are no courses to recommend, it's more of a process and continuous learning. However, here are a few tips that helped me along the way.</p>
<ol>
<li>Learn in public by tweeting and <a target="_blank" href="hashnode.com">Start a blog</a> in Hashnode and document the topics you learned. This will connect you to more people and build your network.</li>
<li>Get involved in the tech community in your town or online via discord and others. Step up at times and explain what you have learned over the weekend in an hour virtual call. The more you speak in meetups the better you communicate.</li>
<li>Try to speak to people from non-tech backgrounds and perhaps try to explain Ai to them in simple terms. This helps you learn to abstract complexities and people will like you for it.</li>
</ol>
<p>Bonus video from MIT which I found to be interesting and helpful:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/Unzc731iCUY">https://youtu.be/Unzc731iCUY</a></div>
<h3 id="heading-git-and-version-control">Git and version control</h3>
<p>Version control systems are nothing new and I thought not to include them here. However, after seeing the number of beginners struggling to make sense of it during internships I thought to bring it up. You must have the basic idea and know your ways around Github. You need to know 3 basic functions, creating a repository, cloning, and pushing changes.</p>
<p>Git and Github crash course:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/RGOj5yH7evk">https://youtu.be/RGOj5yH7evk</a></div>
<h3 id="heading-command-linebash">Command line/bash</h3>
<p>Working with the command line is a good skill to add. Since most of the production servers are Linux based, your familiarity with the command line will help you do more.</p>
<p>Hands-on Introduction to Linux Commands and Shell Scripting:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.coursera.org/learn/hands-on-introduction-to-linux-commands-and-shell-scripting">https://www.coursera.org/learn/hands-on-introduction-to-linux-commands-and-shell-scripting</a></div>
<h2 id="heading-whats-next">What's next?</h2>
<p>Continue learning, and understand the style of learning that works best for you. In my journey I found case-based learning to be the best. For example: when I have a problem be it my model performs 100% accuracy in training but in testing it drops to be 60% accurate. I can go from there and understand all the needed work to solve this problem. There most of the concepts I learned theoretically make more sense and become solid.</p>
<h2 id="heading-at-last">At last</h2>
<blockquote>
<p>If you wondering where is the math, calculus and algebra courses? Well, don't worry about it.</p>
</blockquote>
<p>In my personal opinion:</p>
<ul>
<li>You need math when you feel your math background doesn't help you understand a concept you are currently learning. At that point go to youtube and understand that concept.</li>
<li>You don't need to build algorithms from scratch, it's more important to understand the intuition of algorithms. The ability to code from scratch could be a hobby but don't really expect people are building algorithms from scratch at their day-to-day job.</li>
</ul>
<p><em>I hope this short list is minimal enough and yet meaningful to help you get started or perhaps brush up on some skills. If you have taken any of the courses listed here feel free to comment and share your thoughts.</em></p>
]]></content:encoded></item><item><title><![CDATA[3 Lessons I Learned Building Customer-Facing Data Science Products]]></title><description><![CDATA[Photo by Isaac Smith on Unsplash
When I took my first ML course (By Andrew Ng) in 2015, data science wasn’t something that rings bells, at least not for me. Back then, I was just curious about data, and the possibilities it could unleash, I had parti...]]></description><link>https://farisology.com/3-lessons-i-learned-building-customer-facing-data-science-products-eb044076c270</link><guid isPermaLink="true">https://farisology.com/3-lessons-i-learned-building-customer-facing-data-science-products-eb044076c270</guid><category><![CDATA[Data Science]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Product Management]]></category><category><![CDATA[development]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Sun, 23 Jan 2022 07:57:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916866006/NfgevzhZC.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@isaacmsmith?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Isaac Smith</a> on <a target="_blank" href="https://unsplash.com/s/photos/data?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
<p>When I took my first ML course (By Andrew Ng) in 2015, data science wasn’t something that rings bells, at least not for me. Back then, I was just curious about data, and the possibilities it could unleash, I had participated in an analytics hackathon where I somehow managed to place 3rd. That was not an expected outcome, considering the little skills and knowledge I had. Learning hive queries on the weekend was odyssey and Hortonworks did not even work on my laptop. I felt the least prepared, and the little SQL along with some reading on Big Data was all I had in my toolbox. Winning that day lead me to believe I should pursue a career in Data.</p>
<p>Then, there were only two ways in my mind in which data could deliver value, either creating analytics or serving predictions. 6 years later, I have come to learn even more than I knew possible. The data science field exploded my simplified idea of just analytics and predictions and I’ve had opportunities to pioneer some of these in the companies I’ve worked at.</p>
<p>My first customer-facing data product is a recommendation engine which I have written about before <a target="_blank" href="https://medium.com/fave-engineering/beneath-the-hood-fave-personalization-39d54b136fed">here</a>. I worked on several more projects later on around recommendations, relevancy ranking engine for search tool as well as some others. These were all full-fledged customer-facing data science applications and as I developed these, I have come to appreciate the distinct lessons that come from building data-fuelled tools that influence real-life user’s experiences. Here I will share the most important lessons in my journey so far.</p>
<blockquote>
<p>A <a target="_blank" href="https://www.tableau.com/learn/whitepapers/turn-data-products-data-scientist-data-business-owner#:~:text=A%20data%20product%20is%20an,improve%20their%20decisions%20and%20processes.&amp;text=Reaching%20business%20objectives%20through%20informed,main%20driver%20for%20company%20adoption.">data product</a> is described as “an application or tool that uses data to help businesses improve their decisions and processes”. — Dr. Carlo Velten.</p>
</blockquote>
<h4 id="heading-take-a-hybrid-mindset">Take a hybrid mindset</h4>
<p>Many new data learners come with a fascination of complex machine learning (ML) models. They want to try deep neural networks in most problems and due to that, often hyperparameter tuning comes before any thought of feature engineering. I would not claim that the <a target="_blank" href="https://neptune.ai/blog/data-centric-vs-model-centric-machine-learning">data-centric approach</a> is the best, but I would still advocate for thinking about your data first. In many industry problems, algorithms can only take you halfway. Going the rest of the way will lie in the details of your data and the quality of the features you have crafted.</p>
<blockquote>
<p>These are also popular opinions of <a target="_blank" href="https://www.youtube.com/watch?v=06-AZXmwHjo&amp;t=69s">Prof Andrew Ng: his amazing talk on data-centric AI</a>.</p>
</blockquote>
<iframe src="https://www.youtube.com/embed/06-AZXmwHjo?feature=oembed" width="700" height="393"></iframe>

<p>Let’s be real, context is the most important and therefore a data scientist should optimize his work based on the problem they are trying to solve. Some limitations such as wanting rapid results could determine the options you can explore for a particular problem.</p>
<p>When we want fast results, engineering new features, or devising preprocessing techniques might be the less efficient way forward. Despite my affinity for the data-centric approach, one should understand that some data issues cannot be fixed sustainably downstream. So, be context-aware that there could be times when a working product is what you need to ship first.</p>
<p>In the early phase of the project like when you are building a proof-of-concept (POC), go with the path of least resistance. Getting buy-in is more important than an extra % point in the model accuracy. If you are building for production, you can guess-estimate which approach can improve the performance and optimize with that in mind. In future iterations, you can validate both data and model-centric approaches. That is the time when you can adopt a hybrid approach and explore the best ideas.</p>
<h4 id="heading-business-metrics-first">Business metrics first</h4>
<p>Let me put it this way, business is king. I have spent too much time pointing out my RSME scores or F1 score to people who don’t care. Data scientists are taught in kaggle and in academia to strive for the extra X-% of accuracy, but in the industry, data scientists are expected to bring value and impact. The statistical metrics do not show the value or impact to your business stakeholders. Your stakeholders don’t understand how your RMSE translates into metrics they care about.</p>
<blockquote>
<p>As the field matures and companies focus on the usefulness of data science, one should pay more attention to building her/his business acumen and learn how to prove the impact of his work.</p>
</blockquote>
<p>It’s one of the things that took me a long time to learn. In fact, learning this took me longer than learning backpropagation and gradient descent combined. You have to figure out the language and ways to articulate your model’s impact in terms of revenue, clicks, and conversion.</p>
<h4 id="heading-ui-matters-so-much">UI matters so much</h4>
<p>Fine-tuning parameters and feature engineering can take you far but doesn’t matter if user perception or appeal of the product is lacking. This portion of the data science project is the toughest as it requires A/B testing and synergy with the products and developer teams to help facilitate the experiments. Customer-facing products have the attention of the customer as a pre-requisite and from experience, you can drive significant impact from improvements to the UI.</p>
<p>Additionally, the positioning, wording of the product title are all part of creating the appeal. It goes without saying but often the excitement of having that project out in production might blind the data scientist from these details. As an example, my recommendation carousel was titled “items you may like” resulted in mediocre returns. Interaction spiked from just tweaking the shading of the carousel and using “For you” instead which portrays the personal touch of this section.</p>
<h4 id="heading-finally">Finally</h4>
<p>There are many more lessons but these 3 lessons were the most expensive in terms of time and perhaps most underrated. During this journey, there were times of frustration when I thought my manager or stakeholders are unreasonable. It was tough to work for weeks only to be hindered deployment. Only when I allowed myself to see past my work that I learned what my humble self should have realized earlier. I took time to learn some of the rules and I hope you benefit from this to play a better game in your next project.</p>
]]></content:encoded></item><item><title><![CDATA[Beneath the hood: Fave Personalization]]></title><description><![CDATA[Photo by Stephen Leonardi on Unsplash
At Fave, we in the data science team actively research and innovate new ways to contribute to helping more SMEs become digital. The transformed data team went through a courageous process to expand its impact fro...]]></description><link>https://farisology.com/beneath-the-hood-fave-personalization-39d54b136fed</link><guid isPermaLink="true">https://farisology.com/beneath-the-hood-fave-personalization-39d54b136fed</guid><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Wed, 11 Nov 2020 08:48:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916890695/a-HrAVbQE.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@stephenleo1982?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Stephen Leonardi</a> on <a target="_blank" href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
<p>At Fave, we in the data science team actively research and innovate new ways to contribute to helping more SMEs become digital. The transformed data team went through a courageous process to expand its impact from business intelligence and reporting to building data products. Personalisation stands as one of the essential data products in Fave today, spreading its integration into our consumers, merchants and the Fave app. This motivated us to share how we built a robust recommendations engine in-house, given the unique characteristics of Fave’s offerings and products.</p>
<p>Fave’s most known products are FavePay, a mobile payment method designed to allow users to transact with offline merchants easily, and <a target="_blank" href="https://myfave.com/kuala-lumpur/offers">Fave Deals</a>. The hyper-growth of Fave as a platform and the ubiquity of FavePay in Malaysia and Singapore today brings with it new challenges. In the early days, products (deals/discounts) were listed via hand-crafted localisation logic that brings the highest selling products to the top of the list for each user in a specific neighbourhood (around the user location). It worked but it couldn’t scale as Fave’s inventory covered more and more categories.</p>
<p>As we grew, we have observed a few shortcomings and opportunities:</p>
<ol>
<li>We have a long tail problem (a minority of items outperform the vast majority of items).</li>
<li>New deals will get a slim opportunity to be seen by users compared to older top selling deals.</li>
<li>We have so many offerings our users don’t know exist.</li>
</ol>
<p><strong>Long-tail</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916882461/7PEM0tZsr.png" alt /></p>
<p>As the platform grew in its offerings, fewer and fewer people are able to know what they could find in our app. Users are fed with the highest selling items at the top of the list, so they become fixated on specific deals made visible to them and this feeds sales to that small subset of deals.</p>
<p>It's a real example of an iceberg where your customers can only see the tip of what is on offer. Even as we actively push other products via marketing channels, the iceberg body will still go unnoticed as the platform’s inventory grows.</p>
<h4 id="heading-solution">Solution</h4>
<p>In our analysis of the problem, we saw that our early logic was breeding into the problem by increasing the visibility of a small set of top selling products. The most optimal solution would be curating products based on something better than location and definitely not random. In the age of data science, that is what can be achieved by a recommendation engine. Personalisation could be one prescription to improve many aspects of our growth. Increasing the visibility of more deals will increase the potential of conversion while offering users a unique set of deals with the highest likelihood of being favoured by the user.</p>
<h4 id="heading-challenges">Challenges</h4>
<p>Like most great ideas, there is always a but. Recommending Fave Deals, unlike Netflix’s movie recommendation or Amazon’s book recommendation, have some constraints that are relevant only to Fave.</p>
<p>At Fave, personalisation should adhere to the following constraints:</p>
<p><strong>1-</strong> <strong>Live deals only</strong>; our deals are short-lived, and given the lifestyle pattern of Fave being an everyday app, we cannot afford recommending a product that is not live anymore.</p>
<p><strong>2.</strong> <strong>Location proximity</strong>; as a lifestyle app, insights on user behaviour informs us how our users launch the app and transact. Users won’t travel too far out for a discount. We help users save by discovering deals that are around them.</p>
<p><strong>3.</strong> <strong>Affordability</strong>; relevancy becomes pocket-size too. The price range of deals suggested to a user must not exceed what they can afford.</p>
<p><strong>4.</strong> <strong>Diet restrictions</strong>; As much as possible, we optimise for dietary restrictions. For example, we won’t recommend meals that include pork or alcohol for Muslims.</p>
<p>There have been a few tools in the market that offers a recommendation engine as a service but the challenge is our use case and our circumstances might not necessarily be applicable by that service. In our scenario, there are limitations to using external services: those services probably cannot solve issues that arise in our specific context. For example, <a target="_blank" href="http://surpriselib.com/"><em>SurPRISE</em></a> algorithms were handy to use but could not optimise for Fave’s constraints and therefore performed poorly in relevancy metrics.</p>
<blockquote>
<p>We cannot simply pick a recommendation service or a model from a framework. Though that is easier to do, it is proven to score low in relevancy metrics.</p>
</blockquote>
<h4 id="heading-approach">Approach</h4>
<p>Our solution was to implement a hybrid form of collaborative filtering (CF) recommendations. CF generates predictions about the users’ interests by looking at a collection of preference information from a group of users, hence collaboration. Bear in mind that these predictions (recommendations) are for a particular user, despite using information discovered from a group of users.</p>
<p>At the end of each day, the engine is fed with a set of data containing the following:</p>
<ul>
<li>Purchase date/time</li>
<li>User behaviour in the app</li>
<li>Clicked image</li>
<li>Location</li>
<li>Price range</li>
<li>Merchant name</li>
<li>Category of the item</li>
<li>Demographics</li>
<li>Device information</li>
</ul>
<p>There are two types of data consumed by the model. These are explicit data which is simply transactional in nature: what deal has the user purchased in the past? and implicit data such as the items/images the user has clicked on. By combining explicit and implicit data types, we cover a wider spectrum of the user’s behaviour, tastes and preferences. There will always be a wealth of implicit data in every organisation as users will browse through several items and perhaps add a few to their wish lists before transacting. As a result the ratio of explicit to implicit is always 1:m. It is then strategically important to find ways to incorporate such implicit data into our systems and find ways to capitalise on it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916883772/iHRX4oa-o.png" alt /></p>
<p>Fave recommendation engine concept</p>
<p>The model builds a user profile in a multi-dimensional space where a user is represented by a matrix of what they have purchased/shown interest in. Successfully applying machine learning depends on its data and the way data has been treated. “<em>Applied machine learning’ is basically feature engineering</em>” (<strong>Andrew Ng</strong>). So a user matrix can be only as good as the data we use to build it.</p>
<h4 id="heading-semantic-encoding">Semantic encoding</h4>
<p>The features are what make machine learning algorithms work. Domain knowledge is the backbone of an effective features engineering process. Let’s take a simple example from our data, the category feature of each item is descriptive nominal data like the food category or the beauty category. We will use an encoding method to translate the nominal categorical values into numeric values in a typical machine learning problem. The one-hot-encoding method is one that is used for this purpose but it is limited in the depth of information it represents for our context.</p>
<p>Let’s think of a deal for a 2 person dinner in a Thai restaurant. It belongs to the food category. How would you compare this deal to another deal from the drinks category?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916885286/SiUknxxgn.png" alt /></p>
<p>one-hot encoding problem</p>
<blockquote>
<p>if Joe bought the 2 person Thai dinner ( food category) and Kamilla bought a deal for a 2 days staycation (travel category) and we have the signature drink deal to recommend. Which user is closer to the signature drink?</p>
</blockquote>
<p>Looking at the image, you can see that the first two deals are similar but the similarity isn’t represented in the encoding. Both are food and beverages respectively and if we encode using the one-hot method, we will end up in a totally different conclusion mathematically. To understand this, you can calculate the euclidean distance between the food and drink (we <a target="_blank" href="https://www.calculatorsoup.com/calculators/geometry-solids/distance-two-points.php">calculate</a> first 3 values for simplicity) — d=1.414214. If you tried the same calculator to compute the distance between food and travel, d is also 1.414214. By this calculation, you can see that one-hot encoding features adds a naive dimension without transcending any semantic information (human knowledge).</p>
<p>This problem can be easily solved by using some function to calculate semantic similarity in the two texts of category. In this context, imagine something like:</p>
<blockquote>
<p><em>f(drink, food) = 0.79</em></p>
</blockquote>
<p>Now the drink deal vector will look like this:</p>
<blockquote>
<p><em>[0.79, 1, 0 ,0]</em></p>
</blockquote>
<p>In our human knowledge, food and drink are similar, and using the one-hot encoding method alone will not give us such knowledge. The semantic similarity by mapping human sentence to a higher dimension space gives our basic encoding the details it needs to be meaningful.</p>
<p>What is the harm of using pure one-hot-encoding? Well, in an engine that doesn’t understand some aspects of the real world, we risk getting higher irrelevancy in our recommendations. If left with vague representations, the machine will fail to make sensible associations and will contradict our human world and that defies the purpose of building a recommendation engine: generating a relevant and interesting list of products for the user.</p>
<blockquote>
<p>The machine if left with vague representations will fail to make sensible associations and will contradict our human world</p>
</blockquote>
<p>Localisation of recommendations is another benefit gained by enhancing using location encoding. If we have 3 unique locations: <em>Cyberjaya, Putrajaya,</em> and <em>Dengkil</em> and our deal location is tagged as <em>Dengkil,</em> we will want to represent distances in our encoding and not arbitrary categorical values.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916886668/p6gpe3Z0E.png" alt /></p>
<p>Distance matrix</p>
<p>If you have a deal tagged <em>Cyberjaya</em> you will have a vector <em>[0, 3, 11]</em> with such a distance-based encoding (you may even scale the values between 0–1). We allow for a more realistic representation of the real world by doing this.</p>
<p>You can see how Fave’s RecSys goes beyond and attributes its success to the amount of attention paid to the details and these details are best known by the team most familiar with the data. Our engine is localised and understands that you should get recommended something in Georgetown, Penang if you have been shopping around there and this is what brings our users back for more interesting deals.</p>
<h4 id="heading-workflow">Workflow</h4>
<p>The whole workflow to get from data to recommendations is fully automated and we leverage Airflow as our workflow orchestration system. It takes 12 steps to reach the final recommendations that then can be consumed by the product. In Fave we are using multiple channels to deliver a personalised experience from direct marketing emails (EDMs), push notifications, through the home page of the Fave consumer app and across all possible channels.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916888043/duZ79h7dS.png" alt /></p>
<p>Fave RecSys workflow</p>
<p>In the early days of developing the engine we have tried generating recommendations on-the-fly whenever a user launches the app. The process was limiting in several ways like it worked only within the app and could not serve other channels. Changing our approach to pre-generating recommendations and storing them in an inventory for all users at least once a day brought several benefits. Another change we made was to utilise real-time data delivered by our <a target="_blank" href="https://medium.com/fave-engineering/how-python-novices-revolutionised-faves-data-warehouse-with-on-the-fly-transformations-1520c24c160c">on-the-fly transformations solution</a> and that made it possible for tonight’s recommendations to train on this morning’s user-app interactions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916889377/8F30kf3bb.png" alt /></p>
<p>Personalisation across channels have increased our conversion by 7x</p>
<p>This inventory of recommendations made it possible to curate personalised content for EDMs and have time-optimised push notifications. For example, sending lunch deal recommendations via push notifications to users just before lunch time. In a way, integrating personalisation with marketing allowed the engine to be tweaked to focus on specific categories, specific price ranges or even specific type deals.</p>
<h4 id="heading-summary">Summary</h4>
<p>In our first beta test we couldn’t immediately recognise the difference brought by personalisation and we thought that we needed more time to monitor and validate the impact. For a data science project to come out of its POC phase and pass several experiments in production is a huge leap for us. In fact this is the first successfully productionised data project by our team and is Fave’s first ML model in the app. To get this far is not the rule but the exception, since <a target="_blank" href="https://medium.com/analytics-and-data/challenges-moving-data-science-proof-of-concept-to-production-458d89b6a9a1">most data science projects don’t go beyond the POC phase</a>. The challenge isn’t just to do with the predictability of the model. There are also organisational and contextual factors that impact how likely a data science project will be productionised.</p>
<p>This project has matured over the course of several months and we are excited to democratise personalisation across Fave’s offerings. Today our users across 3 countries receive personalised EDMs and browse through a personalised home page. The future is personalised and so is your Fave experience.</p>
<p><em>Acknowledgement: the first ever attempt for recommendation in Fave was by</em> <a target="_blank" href="https://www.linkedin.com/in/evonnesoon93/"><em>Evonne</em></a> <em>and that paved the way for me to build upwards.</em> <a target="_blank" href="https://www.linkedin.com/in/husein-zolkepli/"><em>Husein Zolkepli</em></a> <em>supported optimisations and scaling of the project. In Fave’s Data Science team, we are empowered to try new things and learn all the time and that is to the credit of</em> <a target="_blank" href="https://www.linkedin.com/in/jatinsolanki/"><em>Jatin Solanki</em></a><em>. Over the course of this project there were countless others who influenced and supported this endeavour and I am grateful for every single one of you.</em></p>
]]></content:encoded></item><item><title><![CDATA[The easier way to handling large files in pandas]]></title><description><![CDATA[Cute panda from pixabay
I have been using a high-performance laptop for some time and EC2 machine for when I needed high computing power. I never encountered issues of performance for as long as I remember with both tools giving me quite a comfortabl...]]></description><link>https://farisology.com/the-easier-way-to-handling-large-files-in-pandas-ad66c68d9936</link><guid isPermaLink="true">https://farisology.com/the-easier-way-to-handling-large-files-in-pandas-ad66c68d9936</guid><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Mon, 31 Dec 2018 10:32:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916877522/MLypGaPo4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cute panda from pixabay</p>
<p>I have been using a high-performance laptop for some time and EC2 machine for when I needed high computing power. I never encountered issues of performance for as long as I remember with both tools giving me quite a comfortable processing power. Things started to seem awfully different when I downgraded my MacBook and cannot enjoy the privileges of high computing powers on my disposal.</p>
<p>This has forced me to dig down and learn more about Pandas library. So if you are trying to learn about tips to handle your multiple gigabytes files in Pandas this gonna help you. To my surprise batch processing wasn’t the easiest way around handling your file, well in most of the times you are looking into a way to reduce the files size without getting into batch processing.</p>
<h3 id="heading-data-types-in-pandas">Data types in Pandas</h3>
<p>As you know in python we have several variants of the same data type. So for integers, we have <strong>int16, int32, int64</strong> and for floats, we have <strong>float16,float32, float64.</strong> These are extra memory capacities that we might or might not need. Pandas library in default it reads your data in the 64 variant. So, your age column will be between 1–99 and it will be assigned to int64 data type.</p>
<p>Int64 is 8 bytes and can store the figure <strong>-9223372036854775807</strong> up to <strong>+ 9223372036854775807</strong>. The question is do you really need int64 for your age column? This is the question you have to ask yourself for each column in your dataset. When you know the answer then it will be easy for you to shrink the size into something hopefully your machine can handle.</p>
<blockquote>
<p>In a nutshell, you need to give each column the proper data type without instead of the Pandas library default type.</p>
</blockquote>
<h3 id="heading-shrinking-your-file-by-875">Shrinking your file by 87.5%</h3>
<p>I have a CSV file of <strong>2.2 gigabytes</strong> in size and shape <strong>117180 * 2502</strong> for a sparse matrix that I take me a lot of time to load each time I run my Jupiter notebook. I will demo for you how I can take this file into something my machine can handle.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916871389/coU9Lu2Ae.png" alt /></p>
<p>Loading my file (dummy data</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916872576/Pr4RgOicS.png" alt /></p>
<p>my dataset as it look</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916873811/EJuHPhTyp.png" alt /></p>
<p>a few more columns</p>
<p>As you see I have the majority of the columns with small values or Zero values and just two columns with integers that are not large per se. The <strong>int16</strong> data type can store values from <strong>-32768 to +32768.</strong> We technically can use this for our <strong>A</strong> and <strong>B</strong> column in this dataset.</p>
<p>Let’s look at the data frame info:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916874994/vnW7M66vg.png" alt /></p>
<p>Look at the dtypes</p>
<p>We can check the file size and convert it to gigabytes using the following:</p>
<p>start_size = getsizeof(data)/(1024.0**3)<br />print('Dataframe size: %2.2f GB'%start_size)</p>
<h3 id="heading-converting-column-data-types-in-pandas">Converting column data types in pandas</h3>
<p>In my case, there are so many columns to be exact its 2502 columns and by no means, I can go through each column so I used a for loop to convert all the columns of the data frame.</p>
<p>for col in data.columns:<br />    data[col] = pd.to_numeric(data[col], downcast='signed')</p>
<p>Now you may ask what is the downcast parameter? Simply if your columns are float64 like the dataframe I have above, downcast will simply convert them into float16 and if the case they are int it will downcast to the smallest variant of the data type.</p>
<blockquote>
<p>downcast takes only the following values: <em>{‘integer’, ‘signed’, ‘unsigned’, ‘float’}</em></p>
<p><em>-</em> ‘integer’ or ‘signed’: smallest signed int dtype (min.: np.int8)</p>
<p>- ‘unsigned’: smallest unsigned int dtype (min.: np.uint8)</p>
<p>- ‘float’: smallest float dtype (min.: np.float32)</p>
</blockquote>
<p>If you are to use the to_numeric method for each line then you will have to something of the form of:</p>
<p>bigfile['A'] = pd.to_numeric(bigfile['A'], downcast='signed')<br />bigfile['B'] = pd.to_numeric(bigfile['B'], downcast='signed')</p>
<p>For my 2.2 gigabytes file, the for loop took quite some time and this is why you should find better ways to perform the conversions. The result of this conversion was that my file went down on size to:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916876207/lDUEh9n-kY.png" alt /></p>
<p>Do you want to know the percentage?</p>
<p>print('total size reduction: %2.1f'%((1-final_size/start_size)*100))</p>
<h3 id="heading-size-reduce-by-875"><strong>Size reduce by 87.5%</strong></h3>
<p>For me, this has solved my issue and cannot let pandas assigned all type 64 to my columns because most of the time the values are too small and therefore the efficient use of memory is the solution for now.</p>
<p>I hope this helps you to navigate around large files (large for mediocre machines I mean) and you can crunch more data.</p>
<h3 id="heading-have-a-happy-new-year">Have a happy new year….</h3>
<p>2019</p>
]]></content:encoded></item><item><title><![CDATA[The easiest way to build an API for your Machine Learning model]]></title><description><![CDATA[image from the public domain
Among the most frequent questions I get asked about is what is next after We have prepared the data and trained a model and went further to test the performance? Usually in academia we stop at this point and it’s time to ...]]></description><link>https://farisology.com/the-easiest-way-to-build-an-api-for-your-machine-learning-model-a49890b72cb0</link><guid isPermaLink="true">https://farisology.com/the-easiest-way-to-build-an-api-for-your-machine-learning-model-a49890b72cb0</guid><dc:creator><![CDATA[Fares Hasan]]></dc:creator><pubDate>Fri, 09 Nov 2018 15:38:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916905405/aOlDUJm77.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>image from the public domain</p>
<p>Among the most frequent questions I get asked about is what is next after We have prepared the data and trained a model and went further to test the performance? Usually in academia we stop at this point and it’s time to put together a research paper that will hopefully get accepted with less brutal comments from reviewers. Although lately more of the academic work have been made available in which the community benefited from this and brought more enthusiasts to ticker around with these model. In the other hand there are more software engineers who get stuck and often expressed the <a target="_blank" href="https://www.radicalcandor.com/blog/tag/silicon-valley/">radical candor</a> and call machine learning useless. So, if you stuck with people practicing the academia concern of building a model that performs at 1% higher in accuracy this post would be your way to get your models up for deployment as an API.</p>
<h3 id="heading-intention">Intention</h3>
<p>The intention of sharing this is to demo how easy it is to actually deploy your model. In 30 lines of code your model will be ready to for scaling which I believe is as important. I don’t claim that this model or this API is production ready because it is just one step into and for sure there is more to production than just build a simple api. This demo is a simplification of how your model can take its first step. At the end of this publication I will tell you what needs to be done before you actually go live with this api.</p>
<h3 id="heading-preface">Preface</h3>
<p>A typical machine learning workflow will look like the diagram below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916895733/mOja-z58F.jpeg" alt /></p>
<p>For the sake of this fast demo we will go fast through the steps with less details and processes than what it actually takes in real world project. Get your Jupyter notebook up and follow the next steps.</p>
<h3 id="heading-1-getting-the-data">1- Getting the Data.</h3>
<p>The dataset we gonna use here is from <a target="_blank" href="https://archive.ics.uci.edu/ml/datasets/car+evaluation">here</a> but I cannot access that no more so you can get it from <a target="_blank" href="https://www.kaggle.com/elikplim/car-evaluation-data-set">kaggle</a>. The dataset from kaggle is in comma separated values format (CSV) whereas the version I have is in txt file. The dataset has 7 columns:</p>
<ol>
<li>buying price.</li>
<li>maintenance cost.</li>
<li>number of doors.</li>
<li>number of persons.</li>
<li>lug_boot.</li>
<li>safety.</li>
<li>traget or decision column.</li>
</ol>
<p>Basically these features describing the car condition and the last column gives a category if the car is <em>unacceptable, acceptable, good, very good</em>. And in this problem we are trying to build a model that can predict the decision of new data as one fo the four categorise.</p>
<h3 id="heading-reading-the-data">Reading the data</h3>
<p>First we read the data into pandas data frame:</p>
<blockquote>
<p>data = pd.read_csv(‘car.data.txt’, names=[‘Buying’, ‘Maint’,’doors’, ‘persons’,’lug-boot’,’safety’,’target’])</p>
<p>data.head()</p>
</blockquote>
<p>I named the columns as my txt file has no headers but if you have the kaggle version of the dataset then you will see the headers available and therefore there will be no need for the names parameter.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916897161/hNCJxLQUhi.png" alt /></p>
<p>this how the data looks like from the txt file</p>
<p>Reading the data into pandas dataframe will present them in tabular format:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916898461/6TgDywVVK.png" alt /></p>
<p>looks better in tables</p>
<h3 id="heading-pre-processing">Pre-processing</h3>
<p>As you can observe from the table most of the values are categorise and machine learning models expect numeric data as an input to train the model. So, you will have to transform each column into a numerically encoded values. There are multiple ways to do that using scikit learn methods, but here just for demo purpose I will code my own simple way as follow:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916899564/N6XjkARda.png" alt /></p>
<p>I have created one for each column</p>
<p>As you see the function is simple and it caters for each case. Definitely this way has issues but just to clarify the method for you. You can use any other method be it one-hot-encoding or label-encoder from scikit-learn. They do the same thing. We use the apply method to perform the <em>Trans_Buying</em> and you will have to use the apply method for each column to transform the columns.</p>
<p>data['Buying']=data['Buying'].apply(Trans_Buying)</p>
<p>After we are done with transforming all the columns into numeric data then we just need to split the data into training and testing.</p>
<p># let's split data into training and testing<br />feature_columns = ['Buying', 'Maint','doors', 'persons','lug-boot','safety']</p>
<p>labels = data["target"].values<br />features = data[list(feature_columns)].values</p>
<p>X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.3, random_state=42)</p>
<p>Now that you data is ready to be fed into the algorithm for training you can try multiple algorithms to train. The algorithm with better performance can then be used for deployment.</p>
<h3 id="heading-random-forest-classifier">Random Forest Classifier</h3>
<p>RFC = RandomForestClassifier(random_state=101)<br />RFC.fit(X_train, y_train)</p>
<p>print("Score on the training set is: {:2}"<br />      .format(RFC.score(X_train, y_train)))<br />print("Score on the test set is: {:.2}"<br />      .format(RFC.score(X_test, y_test)))</p>
<h3 id="heading-decision-tree-classifier">Decision Tree Classifier</h3>
<p>DTC = tree.DecisionTreeClassifier(criterion = 'entropy')<br />DTC.fit(X_train, y_train)</p>
<p>print("Score on the training set is: {:2}"<br />      .format(DTC.score(X_train, y_train)))<br />print("Score on the test set is: {:.2}"<br />      .format(DTC.score(X_test, y_test)))</p>
<h3 id="heading-exporting-the-model">Exporting the model</h3>
<p>Now after you have trained supposedly multiple algorithms and you have done your performance analysis and decide in which model to take for production. But first we need to serialize the model / export it into a pickle file.</p>
<p># Create persistent model<br />model_filename = 'carDTC.pkl'<br />print("Model exported to {}...".format(model_filename))<br />joblib.dump(DTC, model_filename)</p>
<p>To this stage you have already done with the machine learning workflow and next we need to create the Flask API. Flask is a web development framework from python. We will use it here to create an api for our model and we will deploy locally.</p>
<h3 id="heading-flask-api">Flask API</h3>
<p>Before you start in this phase please make sure you have isntalled Flask library. Then create a file in your favourite text editor and name this file <em>filename.py</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916900865/csn4JzeSN.jpeg" alt /></p>
<p>I use <a target="_blank" href="https://www.sublimetext.com/">sublime</a> and sometimes <a target="_blank" href="https://atom.io/">Atom</a> feel free to use whatever you are comfortable with. Next we gonna create our Flask app and import some important libraries. Loading out serialised model that we have created before this.</p>
<p># importing the libraries<br />from flask import Flask, request, jsonify<br />from sklearn.externals import joblib</p>
<p>#Creating our FlaskAPP<br />app = Flask(__name__)</p>
<p># Load the model<br />MODEL = joblib.load('carDTC.pkl')<br />MODEL_LABELS = ['unacc', 'acc', 'vgood', 'good']</p>
<p>I have created a list of the classes I have because I will need them alter when the model present the prediction. In the next step we create the endpoint with predict function that is supposedly where we received the inputs and then make the predictions.</p>
<p>[@app](http://twitter.com/app "Twitter profile for @app").route('/predict')<br />def predict():  </p>
<pre><code># Retrieve query parameters related to <span class="hljs-keyword">this</span> request.  
Buying = request.args.<span class="hljs-keyword">get</span>(<span class="hljs-string">'Buying'</span>)  
Maint = request.args.<span class="hljs-keyword">get</span>(<span class="hljs-string">'Maint'</span>)  
doors = request.args.<span class="hljs-keyword">get</span>(<span class="hljs-string">'doors'</span>)  
persons = request.args.<span class="hljs-keyword">get</span>(<span class="hljs-string">'persons'</span>)  
lug\_boot = request.args.<span class="hljs-keyword">get</span>(<span class="hljs-string">'lug\_boot'</span>)  
safety = request.args.<span class="hljs-keyword">get</span>(<span class="hljs-string">'safety'</span>)
</code></pre><p># Our model expects a list of records<br />    features = [[Buying, Maint, doors, persons, lug_boot, safety]]</p>
<p># predict the class and probability of the class<br />    label_index = MODEL.predict(features)  </p>
<pre><code><span class="hljs-comment"># get the probabilities list for the prediction  </span>
label\_conf = MODEL.predict\_proba(features)
</code></pre><p># list down each class with the probabilty value<br />    probs = ' Unacceptable = {}, Acceptable = {}, Very Good = {}, Good = {}'.format(label_conf[0][0], label_conf[0][1], label_conf[0][2], label_conf[0][3])</p>
<p># Retrieve the name of the predicted class<br />    label = MODEL_LABELS[label_index[0]]</p>
<p># Create a JSON and send a response<br />    return jsonify(status='complete', label=label, confidence = ''.join(str(label_conf)), probabilities = probs)</p>
<p>Flask will handle the input data from the request and we just need to put these pieces of data into a list that has the same shape as expected by the model. Next step we feed the list to the model and we get the classification result in <strong><em>label_index</em></strong> and by that we try to get the class name from the <strong><em>model_labels</em></strong> for an added step here i tried to use <strong><em>predict_proba</em></strong> which is a method to retrieve the confidence of the model in the classification for each class. In the return function we get everything together using <strong><em>jsonify</em></strong> method to send the response to the API caller.</p>
<p>Congratulations you have a ready API built in flask just add the main function.</p>
<p>if __name__ == '__main__':<br />    app.run(debug=True)</p>
<p>Now save that script and run it in from your terminal:</p>
<p>filename.py</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916902428/aNGpwP5S2.png" alt /></p>
<p>your app is running in the address http://127.0.0.1:5000</p>
<p>Now to test your API you can make a call from your browser as follows:</p>
<p><a target="_blank" href="http://127.0.0.1:5000/predict?Buying=1&amp;Maint=1&amp;doors=1&amp;persons=1&amp;lug_boot=1&amp;safety=1">http://127.0.0.1:5000/predict?Buying=1&amp;Maint=1&amp;doors=1&amp;persons=1&amp;lug_boot=1&amp;safety=1</a></p>
<p>You can see how we list down the features with their values, order here is very important as the model expecting the features to be in the order as in training dataset.</p>
<p>You can also make a call from your jupyter notebook:</p>
<p>import requests<br />response = requests.get('<a target="_blank" href="http://127.0.0.1:5000/predict?Buying=1&amp;Maint=1&amp;doors=1&amp;persons=1&amp;lug_boot=1&amp;safety=1%27">http://127.0.0.1:5000/predict?Buying=1&amp;Maint=1&amp;doors=1&amp;persons=1&amp;lug_boot=1&amp;safety=1'</a>)<br />print(response.text)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656916903813/WdZ-fJbrA.png" alt /></p>
<p>Response from the API</p>
<p>Now you have a simple API running smoothly of course scaling this to be provided to many users will be another task but before that there several aspects you should look at like error handling and later on versioning and CI/CD which are leveraging on software engineering techniques. Also you may want to provide this API in serverless lambda or whatever that suits your need or application.</p>
<p>Full source code with jupyter notebook can be found from here: <a target="_blank" href="https://github.com/farisology/Deploy-ML-as-Flask-API">Car Condition Evaluation.</a> I remembered that I have gone through a similar code a while a go from someone in twoardsdatascience but I don’t remember the exact page so thanks to that person as well.</p>
]]></content:encoded></item></channel></rss>