<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Ceren Iyim on Medium]]></title>
        <description><![CDATA[Stories by Ceren Iyim on Medium]]></description>
        <link>https://medium.com/@cereniyim?source=rss-287e9909d3b5------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*XdF_RF3nq82ZCdcClaMfxQ.jpeg</url>
            <title>Stories by Ceren Iyim on Medium</title>
            <link>https://medium.com/@cereniyim?source=rss-287e9909d3b5------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 02:46:57 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@cereniyim/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Trendyol AI Workflows ]]></title>
            <link>https://medium.com/trendyol-tech/trendyol-ai-workflows-6ea2674abaef?source=rss-287e9909d3b5------2</link>
            <guid isPermaLink="false">https://medium.com/p/6ea2674abaef</guid>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[workflow-automation]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[llm-applications]]></category>
            <dc:creator><![CDATA[Ceren Iyim]]></dc:creator>
            <pubDate>Fri, 23 May 2025 06:04:58 GMT</pubDate>
            <atom:updated>2025-06-02T08:09:24.855Z</atom:updated>
            <content:encoded><![CDATA[<h4>Unlock the potential of automations with AI</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*kOWB1-Fk0wC8DVBS" /><figcaption>Photo by <a href="https://unsplash.com/@spacex?utm_source=medium&amp;utm_medium=referral">SpaceX</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>As Trendyol’s Platform — Extensibility team, we set out to solve a clear problem:</p><blockquote>Give every team at Trendyol the ability to automate with AI, without needing to be experts or have a technical background.</blockquote><p>Like many teams, we embraced the rise of Large Language Models (LLMs) and, a year ago, built a Retrieval-Augmented Generation (RAG)-based chatbot. By leveraging company document sources, our chatbot provided answers on Slack, minimizing context switching.</p><p>However, its success led to an influx of feature requests, overwhelming our ability to keep up.</p><p>Recognizing the need for a more scalable solution, we envisioned a platform where anyone, regardless of technical expertise, could build applications using LLMs or by integrating internal Trendyol tools.</p><blockquote>This vision led to the birth of Trendyol AI Workflows 🚀</blockquote><blockquote>A low-code platform that democratizes automations with AI</blockquote><blockquote>Enabling teams across the company to create powerful, context-aware tools tailored to their needs.</blockquote><p>Let’s take a closer look at Trendyol AI Workflows:</p><ol><li><strong>Getting Started: </strong>A simple path for users to jump in and create their first workflow</li><li><strong>Model Garden and Activities: </strong>How we offer flexibility with multiple LLMs and internal tools</li><li><strong>Architecture Deep Dive: </strong>The engine that powers Trendyol AI Workflows</li><li><strong>How Teams Are Using It? </strong>Use cases and the value it’s delivering across Trendyol</li></ol><h3><strong>Getting Started</strong></h3><p><strong><em>Jump in and create the first workflow </em></strong>🏃‍♀</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x5aaBjt_002AFOSYf5sR-Q.gif" /></figure><p>Trendyol AI Workflows makes building LLM-powered apps as easy as dragging and dropping. With its intuitive, no-code UI, anyone — from engineers to business teams — can spin up a custom automation tool <em>in minutes</em>.</p><p>The core building blocks of a workflow are called <strong>activities</strong>. Think of them as modular tasks that you can connect to shape your app’s logic. Unsurprisingly, over 90% of our workflows are anchored around the LLM activity, which serves as the brain behind the operation.</p><p>As a result of a workflow, you get an API endpoint where you can freely integrate further into your automations, businesses, and apps.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iQlgdSrUiJAxTbzhgiQ6Jw.gif" /></figure><p>Next, let’s explore how we expanded the building blocks and LLM capabilities to meet automation requests and growing demands.</p><h3><strong>Activities and Model Garden</strong></h3><p><strong><em>Flexibility at your fingertips 👆</em></strong></p><p>We started small — with just the essentials: Input, Output,<strong> </strong>and the AI activity. But as usage grew and teams got more creative, so did our toolbox. We introduced powerful additions like <strong>HTTP Request</strong>, <strong>Slack</strong>, <strong>BigQuery</strong>, and conditional logic with the <strong>If</strong> activity.</p><p>Trendyol has its own technology ecosystem, so we built activities tailored to our internal needs. For example, we integrated our Stack Overflow-like Q&amp;A platform into the <strong>Knowledge Base</strong> activity, making domain-specific answers instantly accessible.</p><p>Security was non-negotiable from day one. Almost every activity, from Slack to HTTP Request, needs secrets to execute. So we created a dedicated <strong>Secret</strong> activity. It securely pulls tokens from a backend Vault, abstracting away the risk and hassle for users.</p><p>On the LLM front, we embraced the best of both worlds. The <strong>AI activity</strong> supports models from OpenAI, Google, and Anthropic, while also powering up workflows with <a href="https://huggingface.co/Trendyol/Trendyol-LLM-7b-base-v0.1"><strong>Trendyol’s self-hosted models</strong> </a>— because sometimes, you want full control at lower cost.</p><p>But we know, choosing the right model can be overwhelming, especially for non-AI folks. That’s why we built the <strong>Model Garden</strong> — a curated space where users can browse models, understand their strengths, and pick the best fit for their use case.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LQwzXFeub2Ug1UvX6OH7FQ.png" /></figure><p>The real power of Trendyol AI Workflows lies in the model portfolio and flexibility to utilize them <strong>💪 </strong>You can mix and match any combination of activities, LLMs, and automate with workflows to build scalable, production-grade services.</p><p>Curious how it scales under the hood? Hold that thought — we’ll break it down in the next section.</p><h3><strong>Architecture Deep Dive</strong></h3><p><strong><em>The engine that powers AI Workflows </em>🤖</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-uEccqZXnZDeFEdPcD_ILQ.png" /></figure><p>Trendyol AI Workflows is built on <a href="https://github.com/temporalio"><strong>Temporal</strong></a>, an open-source orchestration engine that ensures reliable, durable, and scalable execution.</p><p>When a workflow is triggered from the TY AI Workflows UI, the TY AI API acts as the starter. It generates a DSL and sends a gRPC call to Temporal to initiate the workflow.</p><p>Temporal places the request into a task queue, where dedicated <strong>workers</strong> pick it up and execute the defined activities — from calling LLMs and posting to Slack, to querying BigQuery or internal tools like our knowledge base.</p><p>Durability and observability are built-in: Temporal handles retries, state management, and offers a UI to trace workflow execution.</p><p>The system integrates with both internal and open-source components — <a href="https://github.com/BerriAI/litellm"><strong>LiteLLM</strong></a> for LLM proxying, <a href="https://github.com/onyx-dot-app/onyx"><strong>Onyx</strong></a> for document indexing, and <a href="https://github.com/vespa-engine/vespa/"><strong>Vespa</strong></a> as Vector DB for fast RAG-style retrieval.</p><h3><strong><em>How Teams Are Using It?</em></strong></h3><p><strong><em>Use cases and the value it’s delivering across Trendyol </em>⭐️</strong></p><p>Product managers are spinning up AI-based tools without writing a line of code. Developers are diagnosing production issues by analyzing pod logs, Prometheus metrics, and Cloudflare traces — all in seconds, thanks to automated workflows.</p><p>Our international sellers are generating thousands of product entries at scale, complete with attributes, tags, and descriptions, slashing manual effort to near zero.</p><p>We’ve automated meal claim processing by combining image analysis with claim reasoning, reducing call center workload by 80%.</p><p>More than 100 teams have already been onboarded, and we’re just getting started. With new capabilities like cron jobs and loop support on the way, the possibilities keep expanding.</p><p><strong>The future of AI-driven automation is here — and it’s being built, used, and scaled daily at Trendyol.</strong></p><h3>Join Us</h3><p>Do you want to be a part of our growing company? We’re hiring! Check out our open positions from the links below.</p><p><a href="https://careers.trendyol.com/">Home - Trendyol Careers</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6ea2674abaef" width="1" height="1" alt=""><hr><p><a href="https://medium.com/trendyol-tech/trendyol-ai-workflows-6ea2674abaef">Trendyol AI Workflows 🚀</a> was originally published in <a href="https://medium.com/trendyol-tech">Trendyol Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Meet Marvin: Trendyol’s Helpful AI Assistant]]></title>
            <link>https://medium.com/trendyol-tech/meet-marvin-trendyols-helpful-ai-assistant-d630ed0fbf57?source=rss-287e9909d3b5------2</link>
            <guid isPermaLink="false">https://medium.com/p/d630ed0fbf57</guid>
            <category><![CDATA[nlp]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[mlops]]></category>
            <dc:creator><![CDATA[Ceren Iyim]]></dc:creator>
            <pubDate>Wed, 17 Apr 2024 13:57:31 GMT</pubDate>
            <atom:updated>2026-09-26T12:14:48.303Z</atom:updated>
            <content:encoded><![CDATA[<h4>Leveraging LLMs to automate our processes</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*E3XVJh560VBIE9JAEnEyaQ.png" /><figcaption>Image by <a href="https://medium.com/u/afee45315b65">Omar Elcircevi</a></figcaption></figure><p>At Trendyol, we operate as <strong>one team</strong>. This is only possible through open and direct communication in a hybrid working setup. So, Slack is our indispensable tool for day-to-day work. We receive and resolve technical issues, clarify HR-related questions, and onboard new joiners through Slack.</p><p>We also strive to be better every day. Not to brag but we achieve better constantly with our Trendyol Ways of Working (WoW) 😎</p><p>Adhering to certain standards in our communication and daily tools improves our efficiency. Moreover, it helps us to reduce the cognitive load and context switching during the day so that everyone can focus on the important — <strong>creating the business impact and shipping the features</strong>.</p><p>Bringing those together at the rise of the Large Language Model (LLM) era, <strong>Marvin</strong> was born:</p><blockquote>Our AI Assistant to automate internal know-how search and processes</blockquote><p>Let’s dive deep into Marvin’s capabilities and underlying architecture. I promise to keep it not too technical 🧡</p><ol><li>Capabilities</li><li>Architecture and LLM models</li></ol><h4>Capabilities</h4><p>Marvin is an LLM-based tool, aiming to automate Trendyol teams’ daily lives. The core capabilities involve replying to technical and HR-related questions.</p><p>We have an internal technology portal called <a href="https://medium.com/trendyol-tech/the-technology-portal-of-trendyol-aka-pandora-developer-productivity-highlights-from-2023-8a5e295efdad">Pandora</a>. We use Pandora to accumulate technical know-how, measure developer productivity, and provide visibility of developer teams’ work.</p><p>We brought Pandora&#39;s know-how one step closer to the developers with Marvin. Now, they can find answers to their technical questions and resolve bugs with Marvin on Slack channels. We used Mixtral 8x7b model and Pandora documents as a source here.</p><p>Moreover, if the developer is unsatisfied with the answer, Marvin supports the user with links, allowing developers to search further in Pandora. All in all, our developer teams can find solutions to bugs and technical answers <strong><em>with less effort</em></strong>, with Marvin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/924/1*tAdZUd4_X-z7nV8kwOvj6Q.png" /><figcaption>Image by author</figcaption></figure><p>After observing the positive feedback from developers, Marvin started to serve HR teams.</p><p>We are growing fast, and welcoming new team members every month. As expected, they are warming up with the team and processes by asking questions during onboarding. Our HR teams are supporting them so that they adapt Trendyol WoW, culture, and internal processes faster. On average, HR teams spend around 35% of their time each month supporting such questions.</p><p>We automated this process with Marvin where anyone can find answers to their HR-related questions through a Slack bot, <strong><em>faster</em></strong>. We used our internal HR documents as a source here.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/930/1*PqnQIuWsQe5SwtXtryj90Q.png" /><figcaption>Image by author</figcaption></figure><p>Now, let’s look into the inner workings of Marvin 🧐</p><h4>Architecture and LLM models</h4><p><a href="https://blogs.nvidia.com/blog/what-is-retrieval-augmented-generation/">Retrieval Augmented Generation (RAG)</a>, <a href="https://en.wikipedia.org/wiki/Prompt_engineering">Prompt Engineering</a>, and LLMs are at the core of Marvin. We evaluate and store our RAG metrics at Langfuse.</p><p>These components enabled us to use a pre-trained LLM with our internal documents. With prompts, we enabled Marvin to know the context it is in. A detailed architecture with the complete list of components is here:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*t_6mSG5P7h6tp7dZ1XYd3A.png" /><figcaption>Image by author</figcaption></figure><p>We used Chroma DB as our vector DB. Every night, we ingest documents and store them as embeddings. You can think of <em>embedding</em> as a mathematical representation of the words as a vector and a Vector DB solution designed to efficiently store embeddings.</p><p>When LLM receives a question, it provides the answer by finding and retrieving the most similar embedding from Vector DB.</p><p>We selected the open-source Mixtral-8x7B model because it outperformed other LLMs in the global benchmarks. This is not set in stone though, LLM space is advancing wildly, and we are following up with the recent models and advancements.</p><p>Also, we track cost-related and conversational metrics. We carefully monitor answer relevancy, context precision, context relevancy, and faithfulness at Langfuse.</p><p>As the last component, we used Slack adapters for the human-Marvin interaction. This helped us to onboard the team easily to Marvin because Slack is our best friend at Trendyol 👩🏻‍🤝‍👨🏼</p><p>Marvin is growing everyday and 33 teams are using it. We saved 57 hours of our HR teams per month and are receiving positive feedback from our users.</p><p>Our user base is growing every day! So we are currently adding more features. Marvin is improving to support more teams at Trendyol, at scale.</p><p>Stay tuned to learn more about Marvin, and how we automated the technical assignment review within the recruitment process.</p><h3>Join Us</h3><p>Do you want to be a part of our growing company? We’re hiring! Check out our open positions from the links below.</p><p><a href="https://careers.trendyol.com/">https://careers.trendyol.com/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d630ed0fbf57" width="1" height="1" alt=""><hr><p><a href="https://medium.com/trendyol-tech/meet-marvin-trendyols-helpful-ai-assistant-d630ed0fbf57">Meet Marvin: Trendyol’s Helpful AI Assistant</a> was originally published in <a href="https://medium.com/trendyol-tech">Trendyol Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[4 Tips From My Job Search Marathon]]></title>
            <link>https://medium.com/data-science/4-tips-from-my-job-search-marathon-a480613a9309?source=rss-287e9909d3b5------2</link>
            <guid isPermaLink="false">https://medium.com/p/a480613a9309</guid>
            <category><![CDATA[job-search]]></category>
            <category><![CDATA[office-hours]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[careers]]></category>
            <dc:creator><![CDATA[Ceren Iyim]]></dc:creator>
            <pubDate>Thu, 07 Mar 2024 17:44:00 GMT</pubDate>
            <atom:updated>2024-03-07T17:44:00.141Z</atom:updated>
            <content:encoded><![CDATA[<h3>4 Tips from My Job Search Marathon</h3><h4>To navigate challenges, with tools</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GmUcPXQwLD7r7ZI1" /><figcaption>Photo by <a href="https://unsplash.com/@sporlab?utm_source=medium&amp;utm_medium=referral">sporlab</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>I was back in the job search market in August 2023. Despite the challenging status quo and massive layoffs from big tech companies, I took a leap of faith and left my company to dedicate full-time to finding my next role in the Machine Learning/Data Science area.</p><p>Naïvely, I estimated that I would be landing a dream role in a few months. The reality turned out to be longer than this. So, this process has been a marathon rather than a sprint for me. Luckily, I finished the marathon this month 🎉</p><p>Now, I want to share the precious rewards — my learnings — to motivate job seekers and let them know they are not alone in this marathon full of ups and downs.</p><p>Here are the tips I followed and learned while running this marathon:</p><ol><li>Define your criteria for your next role</li><li>Rejections will be more than successful responses</li><li>Don’t spray and pray</li><li>Use AI-based recruiting tools</li></ol><p>P.S. There is a bonus tip at the end 😉</p><blockquote><strong>Disclaimer: </strong>Dedicating full-time to a job search requires careful budget planning and having sufficient financial resources. It is perhaps the most significant consideration I experienced during my marathon. However, I designed this blog post to focus on the navigating the challenges and providing the tools to support you in your interview, CV and Cover Letter preparation.</blockquote><h4>Define your criteria for your next role</h4><p>As you gather more work experience, you become more conscious of which work environments you thrive in. In addition to the role description, the company’s culture and values, the work setup (remote/on-site/hybrid), and the impact/results you create are important factors that add to your success.</p><p>So ask yourself those key questions:</p><ul><li>Are you more productive in a remote/hybrid/in-office setup?</li><li>What kind of leadership and management style is for you?</li><li>What are the cultural elements that you look for? What values resonate with you the most?</li><li>What motivates you day-to-day? Do you want your work to make a positive impact every day?</li></ul><p>These questions will help you solidify your ideal role and company. You can get a gist of these topics by asking the right questions in the interviews, especially for the cultural values.</p><p>I was preparing my interview questions with the help of <a href="https://www.keyvalues.com/">keyvalues.com</a>. It is a great website for designing the right questions for the interviews to get a gist of the company&#39;s cultural values, leadership style, and team’s daily routines.</p><h4>Rejections will be more than successful responses</h4><p>Prepare yourself to receive more rejections than successful responses. This diagram that went viral on LinkedIn is proof of this statement. It shows the application statistics of a job seeker in marketing tech. From my experience, I can tell it is a valid statistic for the data science/machine learning domain.</p><figure><img alt="Post from r/recruitinghell by Reddit. Image link" src="https://cdn-images-1.medium.com/max/1024/1*fGXtag4kaZmnFO_94x6H6Q.jpeg" /><figcaption>Image from r/recruitinghell in Reddit. <a href="https://www.reddit.com/r/recruitinghell/comments/1adbfx8/job_hunting_my_way_out_of_hell_marketing_tech/?utm_source=share&amp;utm_medium=web3x&amp;utm_name=web3xcss&amp;utm_term=1&amp;utm_content=share_button">Image Link</a></figcaption></figure><p>I got 23 successful responses and 5 offers out of 100 applications. The rest was either ghosting or rejections. At first, I was demotivated and felt down with every rejection I received. I even cried after some rejections where I felt a high culture fit with the company and a strong match with my skills 🥲. After several downs, I learned to go through the disappointment of the rejection and not to couple it with my self-worth.</p><p>Also, a rejection applies to a particular role and time. The same position might open again in the future and requirements might change. You likely improved yourself in the meantime.</p><p>For example, I was interviewing with two companies in November 2023 for the MLOps Engineer and Data Scientist roles. I was eliminated from the process after the first interview. Fast forward to February 2024, I got offers from both companies for a Machine Learning Engineer role. So never give up and keep trying ✌🏼</p><h4>Don’t spray and pray</h4><blockquote>“I was applying for as much as 50 jobs a day in two different career tracks”.</blockquote><p>…said the creator of the above image.</p><p>It is almost impossible to tailor a résumé and make 50 applications in a day. This is an example of <a href="https://www.youtube.com/watch?v=iheR2yPLZHQ">the spray-and-pray approach</a>. It is the traditional way of submitting a generic résumé for every job posting through the company’s careers page.</p><p>In today’s competitive job search market, only quality applications pass the first screening. To make a high-quality application, you have to tailor your résumé and cover letter for each application.</p><p>In your CV, order your skills so that the matching skills with the job description appears first, mention your qualities that the job description lists, and make sure you use <a href="https://www.indeed.com/career-advice/resumes-cover-letters/active-verbs#:~:text=Active%20verbs%2C%20also%20called%20%22action,the%20action%20in%20the%20sentence.">active verbs</a>.</p><p>A customized cover letter is also necessary to stand out in the application process. Most companies document their recruitment process, values, and qualities they look for in candidates. Also, learn about the products &amp; problems they are working on before crafting your cover letter. Then embed those learnings and values in your cover letter and ensure to highlight the technical skills listed in the role requirements.</p><p>Most importantly, use your network to pass the initial screening, and don’t hesitate to reach out to your network (ex-colleagues, college friends, etc.). Ask if they want to be a reference for you. You will be surprised to see that people are there to support you. I believe this support is coming from an empathy space where every one of us has been a job seeker in life once 😌</p><p>Moreover, most companies have an employee referral system so it is a win-win situation for both of you if the process ends successfully.</p><h4>Use AI-based recruiting tools</h4><p>Around September, I realized spraying and praying was not working for me. That is where I learned about AI-based tools to boost my CV and cover letter preparation process.</p><p>I chose <a href="https://app.tealhq.com/">Teal</a> from various tools listed <a href="https://www.linkedin.com/feed/update/urn:li:activity:7117854690926628865?updateEntityUrn=urn%3Ali%3Afs_updateV2%3A%28urn%3Ali%3Aactivity%3A7117854690926628865%2CFEED_DETAIL%2CEMPTY%2CDEFAULT%2Cfalse%29">in this post on LinkedIn</a>. I used the Resume Builder feature to build a tailored resume for each application.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-iu_JKmG8lghDODrty-hXA.png" /><figcaption>Image by author</figcaption></figure><p>Also, the Matching section helped me to quantify the match between the job posting and my CV. It calculates a percentage based on the keywords in your CV and job posting. While tailoring your CV, you can aim for a good match score to help you pass the initial screening. Moreover, Teal suggests improvements for your CV in terms of wording and framing your achievements.</p><p>AI-based tools are still our assistants, they are still not there to replace humans in creative writing. I see cover letters and CVs as a form of creative writing in a professional manner. So don’t solely rely on a cover letter or CV prepared by an AI-based tool. Always evaluate their output, and use their suggestions as feedback.</p><p><strong>Bonus Tip: </strong>The job market is more vibrant in the first quarter of the year because of new budgets and people’s tendency to change jobs due to salary adjustments made at the beginning of the year. This is a personal observation and a hint from many years of HR-experienced friend working at Amazon 😉</p><p>Thank you for reading!</p><p>After six months, I completed this marathon with a role that satisfies most of my criteria. It was quite a challenging journey for me with ups and downs.</p><p>I benefitted so much from the tips above so I cannot keep them to myself. I hope my learnings will light your path and support your job search 🤗</p><p>For comments or constructive feedback, you can reach out to me on responses, <a href="https://twitter.com/cereniyim">X (Twitter)</a>, or <a href="http://www.linkedin.com/in/ceren-iyim">LinkedIn</a>!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a480613a9309" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/4-tips-from-my-job-search-marathon-a480613a9309">4 Tips From My Job Search Marathon</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Machine Learning Engineer’s Must-Have Tools]]></title>
            <link>https://medium.com/data-science/a-machine-learning-engineers-must-have-tools-64605bb227de?source=rss-287e9909d3b5------2</link>
            <guid isPermaLink="false">https://medium.com/p/64605bb227de</guid>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[developer-tools]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Ceren Iyim]]></dc:creator>
            <pubDate>Thu, 19 Oct 2023 16:30:44 GMT</pubDate>
            <atom:updated>2023-10-19T16:30:44.640Z</atom:updated>
            <content:encoded><![CDATA[<h4>From both technical and productivity aspects</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HmfdMTn8jVZ-P63F" /><figcaption>Photo by <a href="https://unsplash.com/@jeshoots?utm_source=medium&amp;utm_medium=referral">JESHOOTS.COM</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>I changed my career from <a href="https://towardsdatascience.com/why-i-decided-to-become-a-data-scientist-eec6f8cd435e">SAP Consultant to Data Scientist</a> roughly 4 years ago. After following a curriculum I designed for myself, I secured my Machine Learning Engineer role within a startup ecosystem in a year.</p><p>It isn’t easy to condense all that I’ve learned, the tools I’ve used, and the experiences I’ve had during these past four years into a single article. Nonetheless, I’ll highlight the ones that have particularly benefited me.</p><p>As I progressed in my role, I cultivated software development skills by using a variety of tools and following certain best practices on the job:</p><ol><li>Git and Version Control</li><li>Writing Readable and Clean Code</li><li>Exploring Different Development Tools</li></ol><p>I will not only explain them in this article but also mention how they helped me improve my soft skills and productivity. Let’s get started 🚀</p><h4>Git and Version Control</h4><p><a href="https://en.wikipedia.org/wiki/Git">Git</a> is an open-source version control system widely used in software development. It organizes projects and manages collaboration between developers working on the same project. I was not using Git when I was working solo; I was manually versioning my code and notebooks 🙃</p><p>When collaboration comes into play, Git becomes a necessity. It helps to track the progress of the project and fosters collaboration.</p><p>It is a vast topic to learn from, and great sources are out there (like <a href="https://www.freecodecamp.org/news/git-and-github-for-beginners/">this one</a>). Today, I will focus on the “commit” term and how it helped me organize my thought process.</p><blockquote>Git commit is like taking a snapshot of your code in time.</blockquote><p>One of my first learnings in my early days was to have organized Git commits and concise commit messages.</p><p>Later on, I realized that thinking beforehand about your commits and how to structure them also helps you to organize your work and design your code with a better logical pattern.</p><p>Here is an example of how Git commits can be organized in the context of Data Science from one of my recent projects:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9y9Ozn8ot_G3Si2IPXIQkg.png" /><figcaption>Image by author</figcaption></figure><p>From the collaboration perspective, breaking down commits — so that each code change should have one purpose at a time — will also help your colleagues review your code faster.</p><h4>Writing Readable and Clean Code</h4><p>My previous mentor once told me, “Even your grandma should be able to read your code” — a disclaimer: Not from an ageist perspective but rather to imply that everyone should be able to read and understand your code easily.</p><p>Jokes aside, reflecting your thought process in your code and writing a self-explanatory code will help anyone review your work and understand it faster.</p><p>I learned how to craft readable and clean code both on the job and by reading several industry-wide books:</p><ul><li><em>Clean Code: A Handbook of Agile Software Craftsmanship</em> by Robert C. Martin</li><li><em>Philosophy of Software Design</em> by John Ousterhout.</li></ul><blockquote>“So if you want to go fast, if you want to get done quickly, if you want your code to be easy to write, make it easy to read.”</blockquote><blockquote>Robert C. Martin.</blockquote><p>and an implementation of this practice from my recent work:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1f8ccc1af33d95d5a18db3e715c2d4fb/href">https://medium.com/media/1f8ccc1af33d95d5a18db3e715c2d4fb/href</a></iframe><p>Believe me, your future self will thank you for writing readable and clean code, not only your team!</p><h4>Exploring Different Development Tools</h4><p>When it comes to experimenting with machine learning models or prototyping solutions to test their viability, using notebooks is often the first choice.</p><p>And Jupyter notebooks are a great medium for that.</p><p>Before landing in the Machine Learning Engineer role, I primarily worked on my projects using Jupyter notebooks. As my previous team enforced using PyCharm, I met with my first integrated development environment (IDE).</p><p>I felt a bit overwhelmed by the numerous functionalities and the user interface of PyCharm, as a Data Scientist mostly using one-time notebook solutions.</p><p>In time, PyCharm has become my second-nature tool.</p><p>Its code completion and error-highlighting features have become my indispensable helpers and contributed to my productivity, <strong>a lot</strong>.</p><p>Mastering Git within IDEs has significantly improved my ability to organize work, boosted my coding speed, and enabled me to focus on the task at hand more efficiently. Also, I’m always grateful to myself for writing clean code when I revisit it months later 😉</p><p>Thank you for reading! This blog post holds a special place for me. It signifies my return to blogging and technical writing 🤗</p><p>For comments or constructive feedback, you can reach out to me on responses, <a href="https://twitter.com/cereniyim">Twitter</a>, or <a href="https://www.linkedin.com/in/ceren-iyim">Linkedin</a>!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=64605bb227de" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/a-machine-learning-engineers-must-have-tools-64605bb227de">A Machine Learning Engineer’s Must-Have Tools</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an Automated Machine Learning Pipeline: Part Four]]></title>
            <link>https://medium.com/data-science/building-an-automated-machine-learning-pipeline-part-four-787cdc50a12d?source=rss-287e9909d3b5------2</link>
            <guid isPermaLink="false">https://medium.com/p/787cdc50a12d</guid>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[luigi]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Ceren Iyim]]></dc:creator>
            <pubDate>Tue, 09 Jun 2020 16:50:36 GMT</pubDate>
            <atom:updated>2020-06-10T06:48:42.675Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://towardsdatascience.com/machine-learning/home">MACHINE LEARNING</a></h4><h4>Automate your pipeline with Docker and Luigi</h4><ul><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-one-5c70ae682f35?source=friends_link&amp;sk=8de05327eedb3d0dadcfa4b1a8e8cc75">Part 1: Understand, clean, explore, process data</a></li><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-two-1d3c86e6fe42?source=friends_link&amp;sk=a005d5ead7a844adb7819403ddc6dc0e">Part 2: Set metric and baseline, select and tune model</a></li><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-a74acda76b98?source=friends_link&amp;sk=1790d8dd404126a45828c3905f47432c">Part 3: Train, evaluate and interpret model</a></li><li>Part 4: Automate your pipeline using Docker and Luigi (you are reading now)</li></ul><blockquote><strong>Disclaimer:</strong> This article series is not a tutorial about Docker and Luigi. It is the last article of an article series “Building an Automated Machine Learning Pipeline” that focuses on building end-to-end ML pipeline and showing how to automate it using certain elements of both tools. This article will make more sense to you if you read the previous ones from the links above.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WHxWnEoQDZAdxgKxzBxO2A.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@ekrull?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Eric Krull</a> on <a href="https://unsplash.com/collections/10621375/medium-ejcuhcdfwrs?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>In this article series, we set our course to build a 9-step machine learning (ML) pipeline and automate it using Docker and Luigi.</p><ol><li>Understand &amp; Clean &amp; Format Data</li><li>Exploratory Data Analysis</li><li>Feature Engineering &amp; Pre-processing</li><li>Set Evaluation Metric &amp; Establish Baseline</li><li>Select an ML Model based on the Evaluation Metric</li><li>Perform Hyperparameter Tuning on the Selected Model</li><li>Train and Evaluate the Model</li><li>Interpret Model Predictions</li><li>Draw Conclusions &amp; Document Work</li></ol><p>As a result of this pipeline, we built our ML solution and called it, <strong><em>the wine rating predictor</em></strong> because we are trying to infer the quality of wine represented with the <em>points</em> using <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/data_root/raw/wine_dataset.csv">a sample dataset</a>. We defined the requirements for our wine rating predictor in <a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-one-5c70ae682f35?source=friends_link&amp;sk=8de05327eedb3d0dadcfa4b1a8e8cc75">the first article</a> as:</p><blockquote><strong>- understandable</strong> because our audience will likely have limited knowledge of statistics and ML.</blockquote><blockquote><strong>- performant</strong> because the complete production dataset could have millions of rows.</blockquote><blockquote><strong>- automated</strong> in a way that it can run on any production system without requiring specialized configurations and setups.</blockquote><p>We have so far satisfied the <strong>understandability</strong> and addressed <strong>performance</strong> — to some extent:</p><ul><li>We have selected an <strong>understandable</strong> model, random forest regressor, as the underlying ML algorithm of the wine rating predictor. Moreover, we have explained how random forest regressor works as well as its hyperparameters <a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-two-1d3c86e6fe42?source=friends_link&amp;sk=a005d5ead7a844adb7819403ddc6dc0e">in the second</a> and <a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-a74acda76b98?source=friends_link&amp;sk=1790d8dd404126a45828c3905f47432c">third article</a>.</li><li>We have built a <strong>performant</strong> model by performing hyperparameter tuning on the random forest regressor. We still have room for it though.</li></ul><p>Today, we will wear a software engineer’s hat and address the last requirement — <strong>automation.</strong> We will take the steps below from the ML pipeline, run them on Docker Containers and connect them with Luigi Tasks. (Don’t worry we will elaborate on them throughout the article 🙂)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*X-EVmlK2C7d51BBMVOkm-w.png" /><figcaption>Automation Flow of the ML Pipeline</figcaption></figure><p>If you have noticed we have two additional steps because a typical real-world ML pipeline starts with getting the data from a source. Also, we included the training-test dataset split and the rest is the known steps of the ML pipeline.</p><p>To run the flow above, we will first look at Docker and Luigi and understand their use in the context of this article series. Therefore, we will start by explaining these tools and their necessary elements.</p><p>Then, we will connect the dots using these tools. Eventually, we will put the pieces together and run the flow which will accomplish our mission of automation!</p><ol><li>What Is Docker and How It Is Used for the Wine Rating Predictor?</li><li>What Is Luigi and Why It Is Selected as an Orchestration Tool?</li><li>Put the Pieces of Docker and Luigi Together</li><li>Run and Automate the Pipeline!</li></ol><p>You can find the GitHub Repository here:</p><p><a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model">cereniyim/Wine-Rating-Predictor-ML-Model</a></p><p>One more disclaimer before we start:</p><blockquote><strong>Disclaimer:</strong> Structure of the repository and<strong> </strong>download_data.py , util.py , docker-clean.sh and docker-compose.yml files are provided to me as the basis of the code challenge. Rest of the code is written by me.</blockquote><h3>1. What Is Docker and How It Is Used for the Wine Rating Predictor?</h3><h4>What is Docker?</h4><p><a href="https://en.wikipedia.org/wiki/Docker_(software)">The official definition of Docker from Wikipedia</a> is as follows:</p><blockquote>Docker is a set of platform as a service products that uses operating system-level virtualization to deliver software in packages called <strong>containers</strong>.</blockquote><p>I would define it as creating <a href="https://www.geeksforgeeks.org/python-virtual-environment/">virtual environments</a> for your application/software/data science/ML projects so that it can run seamlessly on any system that has Docker.</p><h4><strong>How do we create virtual environments with Docker?</strong></h4><p>Via <strong>containers</strong>. They are isolated virtual environments to run your applications, for our case, ML solutions.</p><h4>How do we create Docker Containers?</h4><p>From <strong>images</strong>. They are templates that are used to create containers. They contain information about your underlying operating system, environment and libraries — with versions.</p><h4>How do we create Docker Images?</h4><p>By reading the instructions from a <strong>Dockerfile. </strong>It is a set of instructions and commands that a user could call on the command line to create an image. You can create a local image in your system with the docker build Dockerfile -t &lt;image_name&gt; command.</p><h4>How images and containers are connected?</h4><p><strong>Containers</strong> are the running instances of <strong>images</strong>. When you run an image you create a container that is an isolated environment.</p><h4>How did we use Docker to build Wine Rating Predictor?</h4><p>We used Docker to build virtual environments and manage the dependencies of the libraries so that we can run the flow seamlessly. The <strong><em>automation flow</em></strong> below is designed so that each box runs on a separate Docker container.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZlHk1OXN0FbgLVS_mkFK8A.png" /><figcaption>Automation Flow</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/259/1*lzKdcXxKa9afsGrSeH4d4A.png" /><figcaption>Structure of the Wine Rating Predictor Repository</figcaption></figure><p>I am sure you have noticed some directories and files in the repository that we haven’t mentioned yet. You can think of download_data, make_dataset, clean_data, extract_features, transform_data, impute_data, train_model and evaluate_model directories as the boundaries of the boxes in the automation flow that contains a Dockerfile and the source code as a Python file.</p><p>Before looking at how to create a Dockerfile, let’s understand the use of base_docker here.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Whjy6xKUEhCTc2c8_XdEZw.png" /><figcaption>Use of Base Docker in the Automation Flow</figcaption></figure><p>Each step of the automation flow runs on a separate container. However, they are modules written in Python and the only difference between them are the libraries used. So, base_docker is used to specify the common environment variables and install the required Python version and the libraries. It also contributed to the performance of the wine rating predictor by installing required packages once rather than installing them every time on a separate container.</p><h4>How to write a Dockerfile</h4><p>When creating a Dockerfile start by the steps as if you are creating a local environment on your machine. Considering your aim is to deploy an ML solution with Python, you can build your image on top of an existing Python Image in the <a href="https://hub.docker.com/search?q=python&amp;type=image">Docker Hub</a>. An important point here is to <a href="https://pythonspeed.com/articles/base-image-python-docker-images/">select an existing Python Image that is suitable for your case</a> since there are several versions and sizes are available.</p><pre>FROM python:3.7-slim<br>ENV LC_ALL=C.UTF-8<br>ENV LANG=C.UTF-8<br>ENV PYTHONPATH=/opt/orchestrator:$PYTHONPATH<br><br>COPY requirements.txt /opt/base_docker/<br><br>RUN pip install -r /opt/base_docker/requirements.txt<br><br>WORKDIR /opt/base_docker/</pre><p>slim variant is chosen and Python version 3.7 is specified, same Python version as in my local system.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/247/1*14g_Rfl9QDA0pHNb479dWA.png" /><figcaption>Screenshot of requirements.txt</figcaption></figure><p>ENV command is used to update the PATH environment variable for the underlying operating system (Python 3.7-slim for our case) that your container installs.</p><p>Libraries with the versions mentioned in the requirements.txt are copied and installed with the pip_install. In addition to the aforementioned libraries of Python, click is also installed — more on the use of that later.</p><p>As the last instruction, the working directory of a Docker Container is defined with the WORKDIR<strong> </strong>command.</p><p>Now, our base_docker is ready, exploring any <strong>Dockerfile</strong> from the automation flow will be sufficient because all other <strong>Dockerfiles</strong> have been written with the same logic. Here is an example from clean_data:</p><pre>FROM code-challenge/base-docker</pre><pre>COPY . /opt/clean_data/<br><br>WORKDIR /opt/clean_data/</pre><p>Now our base image become the base_docker. Every file in the clean_data directory is copied and a working directory of a Docker container is created.</p><p>It is time to have a look at Spotify’s beloved Luigi!</p><h3>2. What Is Luigi and Why It Is Selected as an Orchestration Tool?</h3><h4>What is Luigi?</h4><p><a href="https://luigi.readthedocs.io/en/stable/">The official definition from the docs</a> is as follows:</p><blockquote>Luigi is a Python package that helps you build complex pipelines of batch jobs. It handles dependency resolution, workflow management, visualization, handling failures, command line integration, and much more.</blockquote><p>It is basically an orchestration tool to stitch many tasks together in a directed acyclic graph (DAG) structure:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HUmxmPt13dIis6FpV4I9UA.png" /><figcaption>Directed Acyclic Graph Example. Image Credits: <a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph">Wikipedia</a></figcaption></figure><h4>Why It Is Selected as an Orchestration Tool?</h4><p>When you build an ML solution and as the scale grows, this can easily become complex and messy. Luigi is a robust workflow management tool that can prevent chaos and complexity.</p><h4>How Luigi Works as an Orchestration Tool?</h4><p>There are two fundamental building blocks of Luigi: <strong>Task</strong> and <strong>Target</strong></p><h4>What is a Luigi Task?</h4><p>The steps of a workflow are <strong>tasks</strong>, usually a single unit of work, where computations are done. A Luigi workflow is built on top of tasks.</p><h4>How Luigi Tasks are connected?</h4><p>Each task is connected with a <strong>target</strong>. A target can be a file, a checkpoint in the workflow or any kind of <strong>output</strong> generated by the task.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OUDR5RXdYLw-DkPEij5PFw.png" /><figcaption>Each step in the automation flow is a task</figcaption></figure><p>We are dumping outputs generated by each task in the data_root:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/510/1*rgrsyLclaLcT-Ofxkl-tLw.png" /></figure><p>In the flow, each task is dependent on the output of the previous task except the initial task download_data. Each file is passed as a Parameter so that it can be consumed by the latter step in the workflow.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CEkllcpG7DquH2bcUg0RjQ.png" /><figcaption>Outputs generated from each task</figcaption></figure><p>When designing a workflow, Luigi recommends the atomic structure: Each task should have a single file as output like in the download_data and train_model tasks.</p><p>For the rest of the tasks, we imitate atomicity with the SUCCESS flag. When we perform computations on both training and test datasets, we create a SUCCESS flag as an output of the task, after dumping the output files in the directory. This way, the next task only checks whether a SUCCESS flag exists.</p><h4>How do we define task dependencies?</h4><p>Task dependencies are defined with the requires() method. Here is a task outline from Luigi documentation:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aa_MewYezE4w_A850Osxrw.png" /><figcaption>Outline of a Luigi Task. Image Credits: <a href="https://luigi.readthedocs.io/en/stable/tasks.html">luigi.readthedocs.io</a></figcaption></figure><p>For our case, task dependencies are obvious since we defined a linear automation flow.</p><h4>How do we run Luigi Workflows?</h4><p>Unfortunately, Luigi does not come with a triggering mechanism. If you want to run a Luigi workflow you use the command line specifying the module name and the last task in the project directory:</p><pre>luigi --module &lt;modul_name&gt; &lt;task_name&gt; </pre><p>When a workflow is triggered, Luigi checks if the output of the last step exists. If not, then it checks backwards if the outputs of the predecessor steps exist. For our case, this would be train_model, impute_data, transform_data, extract_features, clean_data, make_dataset and download_data .</p><p>If an output of a task from any step of the flow exists Luigi resumes the flow where it has left of. This is a very useful and important trait to prevent your ML pipeline from crashing when it contains partial data.</p><p>Now we know the essential elements of Luigi and Docker we can move forward with completing the picture!</p><h3>3. Put the Pieces of Docker and Luigi Together</h3><p>We will put the pieces of Docker and Luigi in the docker-compose.yml and orchestrator directory.</p><p>The utility functions provided by <a href="https://www.datarevenue.com/en-our-team#the-team">the awesome engineers of Data Revenue</a> has enabled me to connect the pieces of Docker and Luigi. Functions and classes available in the util.py played an important role that connected Docker and Luigi for the wine rating predictor. For example, DockerTask — the object that we pass as a parameter between the tasks — <a href="https://luigi.readthedocs.io/en/stable/parameters.html">is not available as a parameter in the Luigi</a> normally.</p><p>First, let’s have a look at task.py in the orchestrator directory where I built the automation flow using utilities. Then, let’s understand the purpose of docker-compose.yml.</p><h4>Define Tasks at Task.py</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/05faba44e393649554b8c230f44cff89/href">https://medium.com/media/05faba44e393649554b8c230f44cff89/href</a></iframe><ul><li><strong>Luigi Parameter:</strong> Each task starts with a LuigiParameter object where we specify the input/output files and directories of the task. For example, the last task EvaluateModel where we evaluate the ML model with the test set takes the test_features,test_target and the trained model file (model.sav) as an input LuigiParameter. Since this task creates multiple files as output (PredictionsVSActuals.png and FeatureImportances.png) we also define a SUCCESS flag to mimic atomicity.</li><li><strong>Image: </strong>We define which Docker Image to use to create the container.</li><li><strong>Dependent Task: </strong>If there are any dependent tasks, define them here with the requires() method. The dependent task of the EvaluateModel is TrainModel.</li><li><strong>Command: </strong>The command to be executed by the container. Here command calls the source code available in the evaluate_model.py with the relevant parameters.</li><li><strong>Output: </strong>The output() method returns one or more Target objects (either the output file or a SUCCESS flag)</li></ul><p>Recall that source codes for each step of the flow is available in the respective directory as Python file. Let’s have a look at the source code of train_model :</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bb789fb21d640f57e884467d44d52a73/href">https://medium.com/media/bb789fb21d640f57e884467d44d52a73/href</a></iframe><p>After defining the helper functions convert_features_to_array and convert_target_to_array, we defined necessary click commands.</p><p><a href="https://click.palletsprojects.com/en/7.x/">Click</a>, as defined in the official documentation:</p><blockquote>It is a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/545/1*QlGYXY1JI8IuYQWet4yi3g.png" /><figcaption>How click commands are used. Image Credits: <a href="https://click.palletsprojects.com/en/7.x/">click.palletsprojects.com</a></figcaption></figure><p>We used Click to be able to pass the arguments to the python scripts from the command line. Finally, we train the model with the fine-tuned parameters that we have decided in the <strong><em>Perform Hyperparameter Tuning on the Selected Model step </em></strong>on the training dataset. Finally, we save the trained model in model.sav file as an output.</p><h4>Use of Docker Compose</h4><p><a href="https://docs.docker.com/compose/">The official definition for Docker Compose from the Docker Docs</a> is as follows:</p><blockquote>Compose is a tool for defining and running multi-container Docker applications. With Compose, <a href="https://towardsdatascience.com/5-reasons-to-use-yaml-files-in-your-machine-learning-projects-d4c7b9650f27">you use a YAML file</a> to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.</blockquote><p>This definition suits to our case since we run the automation flow on 9 containers including base_docker. You can read more about the use and commands of docker-compose <a href="https://docs.docker.com/compose/">here</a>.</p><p>The important part for us here the command to run Luigi tasks is written here, so when we run containers through docker-compose, it will trigger the automation flow with the luigi — module task EvaluateModel-scheduler-host luigiid command.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b741e647f7cf810b08fb09524c98a4c9/href">https://medium.com/media/b741e647f7cf810b08fb09524c98a4c9/href</a></iframe><h3>4. Run and Automate the Pipeline!</h3><p>This is the moment of truth! We are going to run the automation flow and automate the 9-Step ML Pipeline. It is the last of the last step, stick with it for one more minute 😉</p><h4><strong>1. Open your terminal and navigate to the project directory</strong></h4><p>For me this is:</p><pre>cd GitHub/Wine-Rating-Predictor-ML-Model</pre><h4>2. Build Docker Containers</h4><p>Instead of building multiple Docker Containers one by one, we are going to use <a href="https://en.wikipedia.org/wiki/Shell_script">a shell script</a> to build Docker Containers: build-task-images.sh</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1dd10dc67dda6cbe7b0339634001bda9/href">https://medium.com/media/1dd10dc67dda6cbe7b0339634001bda9/href</a></iframe><pre>./build-task-images.sh 0.1</pre><p>The below message shows that Containers are built successfully. So we are good to go for triggering automation flow.</p><pre><strong>Successfully tagged code-challenge/evaluate-model:0.1</strong></pre><h4>4. Trigger Automation Flow from Docker Compose:</h4><p>We will trigger the workflow with</p><pre>docker-compose up orchestrator</pre><p>Upon writing this command, Luigi checks whether each task is complete and outputs the following information:</p><pre><strong>Checking if EvaluateModel(<br>    no_remove_finished=False,<br>    in_test_features_csv=/usr/share/data/interim/test_features.csv,<br>    in_test_target_csv=/usr/share/data/interim/test_target.csv,<br>    in_trained_model=/usr/share/data/output/model.sav,<br>    out_dir=/usr/share/data/output/, <br>    flag=.SUCCESS_EvaluateModel)</strong> <strong>is complete</strong></pre><pre><strong>Checking if TrainModel(<br>   no_remove_finished=False,<br>   in_train_features_csv=/usr/share/data/interim/train_features.csv,<br>   in_train_target_csv=/usr/share/data/interim/train_target.csv,<br>   out_dir=/usr/share/data/output/)</strong> <strong>is complete</strong></pre><pre><strong>Checking if ImputeData(<br>    no_remove_finished=False,<br>    in_train_csv=/usr/share/data/interim/train_transformed.csv,<br>    in_test_csv=/usr/share/data/interim/test_transformed.csv,<br>    out_dir=/usr/share/data/interim/, <br>    flag=.SUCCESS_ImputeData)</strong> <strong>is complete</strong></pre><pre><strong>Checking if TransformData( <br>  no_remove_finished=False,<br>  in_train_csv=/usr/share/data/interim/train_features_extracted.csv,<br>  in_test_csv=/usr/share/data/interim/test_features_extracted.csv,<br>  out_dir=/usr/share/data/interim/, <br>  flag=.SUCCESS_TransformData)</strong> <strong>is complete</strong></pre><pre><strong>Checking if ExtractFeatures(<br>    no_remove_finished=False,<br>    in_train_csv=/usr/share/data/interim/train_cleaned.csv,<br>    in_test_csv=/usr/share/data/interim/test_cleaned.csv,<br>    out_dir=/usr/share/data/interim/, <br>    flag=.SUCCESS_ExtractFeatures)</strong> <strong>is complete</strong></pre><pre><strong>Checking if CleanData(<br>    no_remove_finished=False,<br>    in_train_csv=/usr/share/data/interim/train.csv,<br>    in_test_csv=/usr/share/data/interim/test.csv,<br>    out_dir=/usr/share/data/interim/, <br>    flag=.SUCCESS_CleanData)</strong> <strong>is complete</strong></pre><pre><strong>Checking if MakeDatasets(<br>    no_remove_finished=False,<br>    in_csv=/usr/share/data/raw/wine_dataset.csv,<br>    out_dir=/usr/share/data/interim/, <br>    flag=.SUCCESS_MakeDatasets)</strong> <strong>is complete</strong></pre><pre><strong>Checking if DownloadData(<br>    no_remove_finished=False, <br>    fname=wine_dataset, <br>    out_dir=/usr/share/data/raw/,<br>    url=</strong><a href="https://github.com/datarevenue-berlin/code-challenge-2019/releases/download/0.1.0/dataset_sampled.csv"><strong>https://github.com/datarevenue-berlin/code-challenge-2019/releases/download/0.1.0/dataset_sampled.csv</strong></a><strong>)</strong> <strong>is complete</strong></pre><p>Then runs the task in one by one. Another important information for us is:</p><pre><strong>INFO:evaluate-model:Mean square error of the model is: 4.95</strong></pre><p>After a successful run you see a 🙂:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kXY_3oen8Zo5Tz4oOcaFdw.png" /></figure><p><strong>Bonus Points: Let’s see how Luigi resumes the flow where it has left of</strong><br>Let’s say you prepared training datasets and run the automation flow, then you will build the next steps afterwards starting with the training the model. Luigi won’t repeat successfully run previous steps and only runs TrainModel and EvaluateModel tasks in that case.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lN0sTaafGid7ArzUSi2rMw.png" /></figure><h3>Conclusions</h3><p>I would say Wow!</p><p>It was quite a journey spanning over 4 articles and a month ⛵️</p><p>We started from the very beginning and analyzed every step of the 9-step ML pipeline through the first, second and third article.</p><ul><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-one-5c70ae682f35">Building an Automated Machine Learning Pipeline: Part One</a></li><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-two-1d3c86e6fe42">Building an Automated Machine Learning Pipeline: Part Two</a></li><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-a74acda76b98">Building an Automated Machine Learning Pipeline</a></li></ul><p>In this last article, we introduced the relevant elements of Docker and Luigi and explained their importance and use for the wine rating predictor. We completed the last missing piece of our comprehensive pipeline and did a dry run of an ML solution — just as if it runs on production systems.</p><h4>Special Thanks</h4><p>I think it is time to thank my significant other <a href="https://medium.com/u/87256f335321">Serkan Durusoy</a>. He has been the most precious mentor, editor and study buddy I had in my data science expedition!</p><p>He helped me to overcome the ups and downs of changing a career. Also, I want to acknowledge his support to complete this article series as well as the grit he provided for me. Thank you, my dear ❤️</p><p>Thanks for reading 🙂 Please feel free to use this pipeline, the code and <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model">the repository</a> for your own projects.</p><p>For comments or constructive feedback, you can reach out to me on responses, <a href="https://twitter.com/cereniyim">Twitter</a> or <a href="https://www.linkedin.com/in/ceren-iyim">Linkedin</a>!</p><p>Before we go, I also want to share some of the useful resources that I used to prepare for this project. See you in the next article 👋</p><h4><strong>My Suggested Resources to Learn More About Docker and Luigi:</strong></h4><ul><li><a href="https://www.datarevenue.com/en-blog/how-to-scale-your-machine-learning-pipeline">Scale Your Machine Learning Pipeline</a> by <a href="https://www.datarevenue.com/">Data Revenue</a></li><li><a href="https://www.youtube.com/watch?v=zJ6WbK9zFpI&amp;t=659s">Docker for Beginners: Full Course</a> by <a href="https://www.youtube.com/channel/UCSWj8mqQCcrcBlXPi4ThRDQ">KodeKloud</a></li><li><a href="https://towardsdatascience.com/build-a-docker-container-with-your-machine-learning-model-3cf906f5e07e">Build a Docker Container with Your Machine Learning Model</a> by <a href="https://medium.com/u/e2511f99cdfc">Tina Bu</a></li><li><a href="https://luigi.readthedocs.io/en/stable/index.html">Luigi Documentation</a></li><li><a href="https://docs.docker.com/get-started/">Docker Documentation</a></li><li><a href="https://intoli.com/blog/luigi-jupyter-notebooks/">Building Data Science Pipelines With Luigi and Jupyter Notebooks</a> by <a href="https://mattiaciollaro.github.io/">Mattia Ciollaro</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=787cdc50a12d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/building-an-automated-machine-learning-pipeline-part-four-787cdc50a12d">Building an Automated Machine Learning Pipeline: Part Four</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an Automated Machine Learning Pipeline]]></title>
            <link>https://medium.com/data-science/building-an-automated-machine-learning-pipeline-a74acda76b98?source=rss-287e9909d3b5------2</link>
            <guid isPermaLink="false">https://medium.com/p/a74acda76b98</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[learning]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Ceren Iyim]]></dc:creator>
            <pubDate>Mon, 01 Jun 2020 17:38:11 GMT</pubDate>
            <atom:updated>2020-06-09T17:11:03.635Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://towardsdatascience.com/machine-learning/home">MACHINE LEARNING</a></h4><h3>Building an Automated Machine Learning Pipeline: Part Three</h3><h4>Training and evaluating the model, interpretation of model results and final conclusions</h4><ul><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-one-5c70ae682f35?source=friends_link&amp;sk=8de05327eedb3d0dadcfa4b1a8e8cc75">Part 1: Understand, clean, explore, process data</a></li><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-two-1d3c86e6fe42?source=friends_link&amp;sk=a005d5ead7a844adb7819403ddc6dc0e">Part 2: Set metric and baseline, select and tune model</a></li><li>Part 3: Train, evaluate and interpret model (you are reading now)</li><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-four-787cdc50a12d?source=friends_link&amp;sk=7068bbe294f0aa37f247336afcf3eac0">Part 4: Automate your pipeline using Docker and Luigi</a> (live!)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AHf0EoED5zbb41ZS" /><figcaption>Photo by <a href="https://unsplash.com/@davadventurelife?utm_source=medium&amp;utm_medium=referral">David Espina</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>In this article series, we set our course to build a 9-step machine learning (ML) pipeline and automate it using <a href="https://www.docker.com/">Docker</a> and <a href="https://luigi.readthedocs.io/en/stable/">Luigi</a> — just one step left to that article 😉. We will assemble the steps eventually so that it can run on any production system without requiring specialized configurations and setups.</p><p>We are following an intuitive ML pipeline to build wine rating predictor:</p><ol><li>Understand &amp; Clean &amp; Format Data</li><li>Exploratory Data Analysis</li><li>Feature Engineering &amp; Pre-processing</li><li>Set Evaluation Metric &amp; Establish Baseline</li><li>Select an ML Model based on the Evaluation Metric</li><li>Perform Hyperparameter Tuning on the Selected Model</li><li>Train and Evaluate the Model</li><li>Interpret Model Predictions</li><li>Draw Conclusions &amp; Document Work</li></ol><p>The problem itself is a supervised regression problem because we are trying to determine <em>points</em> (target variable) using the defined feature set. <em>Points</em> is a number between 80 and 100 indicating the quality of the wine.</p><p>Our raw data looked like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ulOsYIFnLMC16rzqLQtaVw.png" /></figure><p>We started by formulating the business problem and explaining our objective:</p><blockquote>The goal of the project is to build a wine rating predictor using a sample dataset to show good prediction is possible, perhaps as a proof of concept for a larger project.</blockquote><p>Through the first three steps of the pipeline covered in <a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-one-5c70ae682f35?source=friends_link&amp;sk=8de05327eedb3d0dadcfa4b1a8e8cc75">the first notebook</a>, we cleaned, understand and formatted the dataset. Moreover, we added and transformed features which prepared the training and test datasets to be used in any ML model ultimately:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cjXIFPVXGNE836CYLUy8AQ.png" /></figure><p>In <a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-two-1d3c86e6fe42?source=friends_link&amp;sk=a005d5ead7a844adb7819403ddc6dc0e">the second notebook</a>, we selected the evaluation metric as the <strong><em>mean square error (MSE)</em></strong> which is an appropriate one for our problem. Then, we calculated the baseline (resulted in <em>9.01</em>) using the mean square error computing logic in the <strong><em>Set Evaluation Metric &amp; Establish Baseline</em></strong>.</p><p>Then, we tested several different ML algorithms and decided to use <a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html">random forest regressor form scikit-learn</a> for building the wine rating predictor in the <strong><em>Select an ML Model based on the Evaluation Metric</em></strong> step. We performed hyperparameter tuning on the selected algorithm and improved our model performance further in the <strong><em>Perform Hyperparameter Tuning on the Selected Model</em></strong> step.</p><blockquote>We have significantly lowered the baseline MSE, from 9.01 to 4.99 which resulted in 45% improvement!</blockquote><p>In this article, we are going to complete the remaining last three steps: We are going to evaluate our model on the test set and interpret the predictions. We will be concluding the overall pipeline and reporting the highlights in the last step.</p><p>The code behind this article can be found <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/notebooks/WineRatingPredictor-3.ipynb">in this notebook</a>. The complete project is available on GitHub:</p><p><a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model">cereniyim/Wine-Rating-Predictor-ML-Model</a></p><p>P.S: I encourage you to read previous articles if you haven’t already before we start!</p><ul><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-one-5c70ae682f35?source=friends_link&amp;sk=8de05327eedb3d0dadcfa4b1a8e8cc75">Part 1: Understand, clean, explore, process data</a></li><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-two-1d3c86e6fe42?source=friends_link&amp;sk=a005d5ead7a844adb7819403ddc6dc0e">Part 2: Set metric and baseline, select and tune model</a></li></ul><h3>Before We Begin:</h3><p>The datasets that we are going to use is available in <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/tree/master/notebooks/transformed">notebooks/transformed</a>. The model that we saved in the previous notebook is available in <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/notebooks">the same directory</a> as this notebook.</p><p>We are going to need the following libraries of Python in this notebook:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/af0ac6e89ab43429782a441ff01549cd/href">https://medium.com/media/af0ac6e89ab43429782a441ff01549cd/href</a></iframe><p>Let’s load the datasets and the model:</p><pre>X_train = pd.read_csv(&quot;transformed/X_train.csv&quot;)<br>y_train = pd.read_csv(&quot;transformed/y_train.csv&quot;)<br><br>X_valid = pd.read_csv(&quot;transformed/X_valid.csv&quot;)<br>y_valid = pd.read_csv(&quot;transformed/y_valid.csv&quot;)<br><br>test_features = pd.read_csv(&quot;transformed/test_features.csv&quot;)<br>test_target = pd.read_csv(&quot;transformed/test_target.csv&quot;)</pre><pre>random_forest_model = (pickle<br>                       .load(<br>                           open(&#39;random_forest_model.sav&#39;, <br>                                &#39;rb&#39;)))</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SRTenzuypxgZP8bDUZ04Rw.png" /><figcaption>Parameters of the random forest model</figcaption></figure><p>Convert them to arrays using the same functions that we used in the second article:</p><pre>X = pd.concat([X_train, X_valid]) <br>y = pd.concat([y_train, y_valid])</pre><pre>X_array = convert_features_to_array(X) <br>y_array = convert_target_to_array(y)</pre><pre>X_test_array = convert_features_to_array(test_features)<br>y_test_array = convert_target_to_array(test_target)</pre><h3>7. Train and Evaluate the Model</h3><p><strong><em>The training set</em></strong>​ will be used to map patterns between the features (X_array) and target (y_array) and to build the wine rating predictor. This process is called ​<strong><em>training the model</em></strong>​ or<strong><em> building the model</em></strong>​. The mapping will be done with the fit method called on our random forest model.</p><pre>random_forest_model.fit(X_array, y_array)</pre><p>Before evaluating the model, the actual target values (y_test_array) are held-out from the test set (X_test_array) to utilize as a comparison to the predicted values. Both will be used to generate <em>points/</em>ratings of wine using the patterns found during the model fitting.</p><p>Feeding the test set into the model and generating predictions is called ​<strong><em>evaluating the model. </em></strong>When we call the<strong><em> </em></strong>predict method on our random forest model, the array of predictions are generated.</p><pre>predictions = random_forest_model.predict(X_test_array)</pre><p><strong>Let’s see how our model performed on the test set (part of the training dataset that our model has never seen before):</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*g9WyzqYO_7peN3x2QFBCBA.png" /></figure><h3>8. Interpret Model Predictions</h3><p>As data scientists, we are the interpreters of machine learning technologies. We should be able to explain how a solution works and what are the further improvement areas. This happens at the <strong><em>Interpret Model Predictions</em></strong> step.</p><p>We are going to interpret the model predictions from below perspectives:</p><ol><li>Visualize a single decision tree</li><li>Compare actual values with the predicted values of <em>points</em></li><li>Look at feature importances</li><li>Examine an individual prediction of the model</li></ol><h4>8.1. Visualize a Single Decision Tree</h4><p>We had defined how the random forest algorithm works in the previous notebook:</p><blockquote><strong><em>Random forest regressor </em></strong>​is an ensemble algorithm that builds multiple decision trees at once and trains them on various sub-samples and various subsets of the features of the dataset.</blockquote><p>Our random forest algorithm consists of 200 decision trees. It may not provide us much information if we plot all trees at once. However, visualizing a single decision tree is sufficient to understand how wine rating predictor generates predictions.</p><p>Let’s visualize the first 3 nodes of a decision tree from our random forest regressor algorithm to understand further how our algorithm works:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FwGOvSxUQVWHKnLjV2J-1Q.png" /></figure><p>Looking at this picture, you can think of a decision tree as a series of yes/no questions asked and answered like a flowchart. This specific tree is built using 5645 data points out of a total of 8948 data points — a random subsample of the complete dataset.</p><p>The root node is initiated by asking if the <em>region_1 </em>is less than 320.5. It can be easily realized that the initial MSE is the same as the baseline estimate of MSE. Predicted <em>points</em> is 88.425.</p><p>The root node is split into two as true and false child nodes consisting of 5018 (88% of the initial subsample) and 627 data points (12% of the initial subsample) respectively.</p><p>The false child node of the root node asks if the <em>price</em> is less than 30.5 and answers this question using the 12% of the initial subsample. The MSE improved slightly compared to the previous node, as an indicator of a more coherent node. Predicted <em>points</em> is 87.818.</p><p>This process continues iteratively until a leaf node is reached. When a node’s MSE does not improve further or when the specified criteria for reaching a leaf node (having a minimum of 2 samples in a leaf node for our model) is met, the process stops.</p><h4>8.2. Compare Actual Values with the Predicted Values of P<em>oints</em></h4><p>To understand how actual <em>points</em> and predicted <em>points</em> differ let’s visualize them side by side with a histogram:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/76cbf40e52580b94ac79658193b0a2e2/href">https://medium.com/media/76cbf40e52580b94ac79658193b0a2e2/href</a></iframe><pre>PlotPredictedVSActual(predictions, y_test_array)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*b-09pKnQOCqk5YKo7keZJQ.png" /></figure><p>Recall that <em>points</em> show a normal distribution and 95% of the <em>points</em> lie in the 82.5–94.5 range. Our model successfully predicted the <em>points</em> within this range but failed to predict the points below 84 and points above 94 which are less-frequent values of the distribution. This is also the reason for the narrower distribution of the predictions.</p><p>This is a further and interesting improvement area for our wine rating predictor, but we will not touch it for now.</p><h4>8.3. Look at Feature Importances</h4><p>Another way to evaluate the model is to look at which features that the model considers most important. Following is the number for the relative contribution of each feature in determining a <em>point</em>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c1a4ed595a240227d90b3e013b7e8cb9/href">https://medium.com/media/c1a4ed595a240227d90b3e013b7e8cb9/href</a></iframe><pre>PlotFeatureImportances(random_forest_model, test_features.columns)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VOqKARUERxyyejhzjvXNGg.png" /></figure><p>According to the model, the strongest predictor is <em>price</em>. It is followed by the <em>region_1</em>, <em>year</em>, <em>variety</em> and the <em>taster_name </em>for predicting the <em>points</em> of wine.</p><p>These are in line with our preliminary observations developed during the <strong><em>Exploratory Data Analysis</em></strong> step.</p><blockquote>Price is an indicator of wine’s quality and age. Therefore, we expect it to be an essential feature of the model.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/298/1*qsBO2npFMy3AQMxFmRDqMw.png" /><figcaption>Top 5 Feature Importances</figcaption></figure><p>Top 5 features form 80% of the total importances. Isn’t it another beautiful example of <a href="https://en.wikipedia.org/wiki/Pareto_principle">Pareto Princinciple</a>?</p><p>From the features extracted, <em>year</em> is the most important among them and whether a wine is sparkling or not is the least important predictor of <em>points</em>.</p><p>Another significant observation is the note and taste-related features extracted from <em>variety</em> and <em>description</em> became moderately-important features for our predictor. A comprehensive use of NLP and sentiment analysis may help to find more valuable features from the <em>description</em> and <em>variety</em> features.</p><p>So far, we have interpreted the predictions of our wine rating predictor from an aggregate perspective. Now, let’s examine an individual prediction from our model.</p><h4>8.4. Examine an Individual Prediction</h4><p>We are going to get some help from an explainer library called <a href="https://github.com/marcotcr/lime">LIME (locally interpretable model-agnostic explanations)</a> to observe a prediction. This library creates an approximate local model in a place where data points are condensed and uses this model to explain individual predictions of any ML algorithm.</p><p>We will observe the most incorrect prediction detected from the maximum of the residuals. Then, we are going to create LimeTabularExplainer object.</p><pre><em># find the residuals and wrong prediction</em><br>residuals = abs(predictions - y_test_array)<br>wrong = X_test_array[np.argmax(residuals), :]</pre><pre><em># Create a lime explainer object</em><br>explainer = lime.lime_tabular.LimeTabularExplainer(<br>    training_data = X_array, <br>    mode = &#39;regression&#39;,<br>    training_labels = y_array,<br>    feature_names = test_features.columns)</pre><p>Following code block will plot how the wine rating predictor concluded a wrong prediction. It predicted 90.3 points whereas the actual point was 82. This is the most incorrect prediction of the model:</p><pre><em># Display the predicted and true value for the wrong instance</em><br>print(&#39;Prediction: <strong>{}</strong>&#39;<br>      .format(random_forest_model.predict(wrong.reshape(1, -1))))<br>print(&#39;Actual Value: <strong>{}</strong>&#39; <br>      .format(y_test_array[np.argmax(residuals)]))<br><br><em># Explanation for wrong prediction</em><br>wrong_exp = explainer.explain_instance(<br>    data_row = wrong, <br>    predict_fn = random_forest_model.predict)<br><br><em># Plot the prediction explaination</em><br>figsize(20, 10)<br>plt.rcParams[&#39;font.size&#39;] = 24</pre><pre>wrong_exp.as_pyplot_figure()<br>plt.title(&#39;Explanation of a Wrong Prediction&#39;, size = 24)<br>plt.xlabel(&#39;Effect on Prediction&#39;, size = 24)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GitE57bc9ctwiiEBR9fgqA.png" /></figure><p>This plot shows the contribution of each feature to the wrong prediction example. Positive contributions are colored in green and negative contributions are colored in red.</p><p>As the <em>price</em> is the strongest predictor and this example has a <em>price</em> above 40, those significantly increased the model’s prediction of points. On the other hand, <em>country</em>, <em>is_red</em> and <em>is_white</em> balanced the predictions by decreasing it. This is a great example of how machine learning algorithms may also fall into the common pitfalls as we humans do. Don’t you ever buy an expensive wine to guarantee the high quality 🙂</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/520/0*YlFFSu_hySJdDHcr.gif" /><figcaption><strong>Is it actually?</strong> Image Credits: A Scene from Black Books Series — S01E03<br>Grapes Of Wrath on <a href="https://blackbooks.gifglobe.com/scene/?id=dRJwMw2SMio6">blackbooks.gifglobe.com</a></figcaption></figure><h3>9. Draw Conclusions &amp; Document Work</h3><p>As we are the interpreters of machine learning technologies, it is important to tailor our message and deliverables according to our audience. Especially, if you are presenting your results to your manager or client you must be very concise and relevant. You might expect that they will be more interested in your reasoning and outcome, so focus on them while presenting your findings 😉</p><p>If you remember from the first article, I built this project as a take-home assignment of the ML Engineer interview process at <a href="https://www.datarevenue.com/">Data Revenue</a>. The objective of the assignment is to decide whether to build a full-production solution by looking at the results of the wine rating predictor. So, I prepared a report to present my decision with the most crucial points of the 9-step ML pipeline and draw conclusions.</p><p><strong>I proposed building the full-production solution counting on</strong></p><blockquote>Given the sample dataset, determined set of features and the tuned random forest regressor, the answer is ​<strong>yes</strong>, a​ ​​full-production solution is applicable with those.</blockquote><blockquote>The model significantly lowered (45%) the baseline MSE and resulted in 4.93 MSE on the test set. This serves as evidence to build the full-production solution.</blockquote><p><strong>.. and highlighted the most two most important findings:</strong></p><blockquote>- The wine rating predictor can infer the points of wine with a reasonable variance (MSE) of 4.9.</blockquote><blockquote>- The most useful predictors of points are determined as price, region_1, year, variety and the taster_name.</blockquote><p><strong>.. and I pointed out the further improvement areas:</strong></p><blockquote><strong>Extending prediction range:</strong> so that the less-frequent target values can be predicted by the model. The current sample dataset is dominated by wines from the most dominant countries (US, Italy, France, Spain), feeding more data from non-present countries might help the model to learn better the determiners of the less-frequent points.</blockquote><blockquote><strong>Using NLP to extract stronger predictors:</strong> currently, the strongest predictor is “price”. Extracting more features from the description related to wine taste and notes can help create strong predictors like price, decreasing prediction error of the model.</blockquote><p>You can find the complete report <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/notebooks/ClientSummaryReport.2020.04.02.pdf">here</a>.</p><p>It ended up as a thorough (<a href="https://towardsdatascience.com/why-i-decided-to-become-a-data-scientist-eec6f8cd435e?source=friends_link&amp;sk=ea90fc26db800fcf4611d37942b23508">a habit I carry from consultancy</a>) but succinct report. Besides, I kept the code aside because the report was prepared for a hypothetical client whose statistics and ML knowledge is limited.</p><p>You can prepare a similar summary report (I prepared in a PDF format) for your own projects or learning purpose by converting your Jupyter notebooks into documents. You can use various download options available in the File &gt; Download As. HTML or LaTeX formats are pretty straightforward to use. (if you have the <a href="https://www.texstudio.org/">LaTeX Studio</a> installed in your machine, then you can convert it to pdf format later on). You can read more on that <a href="https://nbconvert.readthedocs.io/en/latest/">here</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/537/1*AeQ3Drqv_Ro-wmaVZxgsmQ.png" /><figcaption>Some download options are available in Jupyter Notebooks</figcaption></figure><p>We should always keep in mind that the “science” in data science serves a purpose, ultimately for a non-scientific purpose. Our work is mostly used to support decision-making processes in businesses or solving real-world problems. Presenting the results (verbally or written) and adjusting the language according to your audience will be a valuable skill you have.</p><h3>Conclusions for the Complete 9-Step ML Pipeline</h3><p>We came a long way from structuring the raw data to making the meaning out of them. We started by cleaning and formatting the data, then we trained and tuned the selected model (random forest regressor). We concluded the 9-step pipeline by evaluating the model and interpreting its results. Finally, we have highlighted the most important outcomes of the project in a report.</p><ol><li>Understand &amp; Clean &amp; Format Data</li><li>Exploratory Data Analysis</li><li>Feature Engineering &amp; Pre-processing</li><li>Set Evaluation Metric &amp; Establish Baseline</li><li>Select an ML Model based on the Evaluation Metric</li><li>Perform Hyperparameter Tuning on the Selected Model</li><li>Train and Evaluate the Model</li><li>Interpret Model Predictions</li><li>Draw Conclusions &amp; Document Work</li></ol><p>We have followed these steps sequentially in the article series. However, I went back and forth between these steps 20% of the time when I was working on this project. All in all, I believe building a machine learning solution is an iterative and experimental process, so never hesitate to improve and revisit the previous steps!</p><h4><strong>Special Thanks</strong></h4><p>I want to thank <a href="https://medium.com/u/e2f299e30cb9">Will Koehrsen</a> here. He is one of the inspirers for me to write about my data science/machine learning projects.</p><p>I first learned this pipeline from <a href="https://towardsdatascience.com/a-complete-machine-learning-walk-through-in-python-part-one-c62152f39420">one of his articles</a> and adjusted it for my own objective and problem. Now, I am using this pipeline as a guide when building any kind of machine learning/data science project. It helps me to organize my thought process and see how individual elements of machine learning is connected!</p><p>We have one last article to go which will automate this pipeline with <a href="https://www.docker.com/">Docker</a> and <a href="https://luigi.readthedocs.io/en/stable/">Luigi</a>. Stay tuned in the next week!</p><p><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-four-787cdc50a12d">Building an Automated Machine Learning Pipeline: Part Four</a></p><p>Thanks for reading 🙂 Please feel free to use this pipeline, the code and <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model">the repository</a> for your own projects.</p><p>For comments or constructive feedback, you can reach out to me on responses, <a href="https://twitter.com/cereniyim">Twitter</a> or <a href="https://www.linkedin.com/in/ceren-iyim">Linkedin</a>!</p><p>Stay safe and healthy until then 👋</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a74acda76b98" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/building-an-automated-machine-learning-pipeline-a74acda76b98">Building an Automated Machine Learning Pipeline</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an Automated Machine Learning Pipeline: Part Two]]></title>
            <link>https://medium.com/data-science/building-an-automated-machine-learning-pipeline-part-two-1d3c86e6fe42?source=rss-287e9909d3b5------2</link>
            <guid isPermaLink="false">https://medium.com/p/1d3c86e6fe42</guid>
            <category><![CDATA[hyperparameter-tuning]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Ceren Iyim]]></dc:creator>
            <pubDate>Fri, 22 May 2020 15:30:59 GMT</pubDate>
            <atom:updated>2020-06-09T17:07:18.193Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://towardsdatascience.com/machine-learning/home">MACHINE LEARNING</a></h4><h4>Setting the Evaluation Metric &amp; Establishing a Baseline, Selecting the Algorithm and Performing Hyperparameter Tuning steps</h4><ul><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-one-5c70ae682f35?source=friends_link&amp;sk=8de05327eedb3d0dadcfa4b1a8e8cc75">Part 1: Understand, clean, explore, process data</a></li><li>Part 2: Set metric and baseline, select and tune model (you are reading now)</li><li><a href="https://medium.com/p/building-an-automated-machine-learning-pipeline-a74acda76b98?source=email-287e9909d3b5--writer.postDistributed&amp;sk=1790d8dd404126a45828c3905f47432c">Part 3: Train, evaluate and interpret model</a> (live!)</li><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-four-787cdc50a12d?source=friends_link&amp;sk=7068bbe294f0aa37f247336afcf3eac0">Part 4: Automate your pipeline using Docker and Luigi</a> (live!)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*g1xLxEuCxDMJ6W0C" /><figcaption>Photo by <a href="https://unsplash.com/@zachhagy?utm_source=medium&amp;utm_medium=referral">Zachariah Hagy</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>In this article series, we set our course to build a 9-step machine learning (ML) pipeline (we are calling it the wine rating predictor) and automate it. Eventually, we will observe how each step congregates and runs in production systems.</p><p>We are working on a supervised regression problem. We want to develop a performant, understandable and good wine rating predictor that can predict the <em>points</em>, a quality measure of wine.</p><p>In the first article, we defined the problem and our motivation behind building the wine rating predictor. Then, we had a detailed look at the data by visualizing the relationships between the features and the target along with the <strong><em>Understand &amp; Clean &amp; Format Data</em></strong> and <strong><em>Exploratory Data Analysis</em></strong> steps.</p><p>In the <strong><em>Feature Engineering &amp; Pre-processing</em></strong> step, we added new and more useful features. Besides, we prepared the training and test datasets to use during training and evaluation of the model. As the final step of the first article, we created validation dataset out of the training dataset for model selection.</p><p>In this article, we are going to complete the following steps:</p><p>4. Set Evaluation Metric &amp; Establish Baseline</p><p>5. Select an ML Model based on the Evaluation Metric</p><p>6. Perform Hyperparameter Tuning on the Selected Model</p><p>The code behind this article can be found <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/notebooks/WineRatingPredictor-2.ipynb">in this notebook</a>. The complete project is available on GitHub:</p><p><a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model">cereniyim/Wine-Rating-Predictor-ML-Model</a></p><p>Feel free to share, fork, and utilize this repo for your projects!</p><h3>Before We Begin:</h3><p>The datasets that we are going to use is available in <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/tree/master/notebooks/transformed">notebooks/transformed</a></p><ul><li><a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/notebooks/transformed/X_train.csv">X_train</a> consisting of features (<em>country, province, region_1,</em> <em>variety, price,</em> <em>year,</em> <em>taster_name, is_red</em>, <em>is_white</em>, <em>is_rose</em>, <em>is_dry</em>, <em>is_sweet, is_sparkling, is_blend</em>) and <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/notebooks/transformed/y_train.csv">y_train</a> consisting of the target (<em>points)</em> to train the model</li><li><a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/notebooks/transformed/X_valid.csv">X_valid</a> consisting of features and <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/notebooks/transformed/y_valid.csv">y_valid</a> consisting of target<em> </em>to validate the model</li></ul><p>We are going to need the following libraries of Python in this notebook:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/62789a5d17324a951285a2f4b6e030e8/href">https://medium.com/media/62789a5d17324a951285a2f4b6e030e8/href</a></iframe><p>Let’s load the datasets into dataframes and convert to an array using below functions:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3ea9b648651c8e286ffa4dce3d42942d/href">https://medium.com/media/3ea9b648651c8e286ffa4dce3d42942d/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5a207bd16009e285d332b32ba15167f4/href">https://medium.com/media/5a207bd16009e285d332b32ba15167f4/href</a></iframe><pre>X_train = pd.read_csv(&quot;transformed/X_train.csv&quot;)<br>X_train_array = convert_features_to_array(X_train)</pre><pre>X_valid = pd.read_csv(&quot;transformed/X_valid.csv&quot;)<br>X_valid_array = convert_features_to_array(X_valid)</pre><pre>y_train = pd.read_csv(&quot;transformed/y_train.csv&quot;)<br>y_train_array = convert_target_to_array(y_train)</pre><pre>y_valid = pd.read_csv(&quot;transformed/y_valid.csv&quot;)<br>y_valid_array = convert_target_to_array(y_valid)</pre><h3>4. Set Evaluation Metric &amp; Establish Baseline</h3><p>If this was a <a href="https://www.kaggle.com/">Kaggle</a> competition, we would skip this step of the pipeline because we would be given with the evaluation metric.</p><p>However, in real-world applications of data science/machine learning, the evaluation metric is set by data scientists in line with the stakeholder’s expectations from the ML model. That is why this is an important step.</p><p>After we decide on our evaluation metric, to quantify our initial motive — building a good wine rating predictor and to compare our model’s performance against, we are going to form a baseline.</p><h4>4.1. Set Evaluation Metric</h4><p>The <strong><em>mean square error</em></strong> <strong><em>(MSE)</em></strong> is set as the evaluation metric. It is the average of the sum of squared residuals where a ​<strong><em>residual</em></strong> is the subtraction of the actual values from the predicted values of the target variable.</p><p>In other words, evaluation of the model is done by looking at the measure of how large the squared errors (residuals) are spread out.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/959/0*n6zGmU6_uoCBFwlM.jpg" /><figcaption>Image Credits: Mean Square Error Calculation on <a href="https://www.dataquest.io/blog/understanding-regression-error-metrics/">Dataquest.io</a></figcaption></figure><p>We selected MSE because it is interpretable and analogous to variance, and it is a widely-used optimization criterion among ML models. (E.g. linear regression, random forest)</p><h4>4.2. Establish a Baseline</h4><p>A ​<strong><em>baseline</em></strong>​ can be explained as generating a naive guess of the target value by using expert knowledge or a few lines of code. It also helps to measure the performance of the ML model.</p><p>If the built-model (wine rating predictor) cannot beat this baseline, then the selected ML algorithm may not be the best approach to solve this problem or we might want to revisit the previous steps of the pipeline.</p><p>Recall that the <em>points</em> (target) has a normal distribution between 80 and 100. The mean is 88.45 and the variance is 9.1.</p><p>We are going to form the baseline by:</p><ul><li>using these statistics and</li><li>calculating differences between each point in the validation set and the mean of the training dataset, then taking the average of the sum of the squared differences (similar approach of computing MSE):</li></ul><pre><em># set baseline as mean of training set&#39;s target value</em><br>baseline = (np<br>            .mean(<br>                y_train_array))</pre><pre><em># calculate MSE baseline</em><br>mse_baseline = (np<br>                .mean(<br>                    np.square(<br>                        baseline - y_valid_array)))</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gG07QLLNl9KghyjB0z4Bog.png" /></figure><p>It is not a coincidence that the variance of the <em>points</em> and baseline error is almost equal. You can think of this baseline MSE as the manually calculated variance with a smaller set from our dataset.</p><p>This number (9.01) will accompany us in the next step — <strong><em>Select an ML Model based on the Evaluation Metric</em></strong> while we are testing different ML algorithms.</p><h4>5. Select an ML Model Based on the Evaluation Metric</h4><p>I always find useful trying out several algorithms with different rationales behind, because I believe this whole process involves experiment as well! (“scientist” part of being a data scientist makes sense now 🙃)</p><p>While searching for the best algorithm, we are going to observe both the improvement of the MSE and the run time of the algorithms (with %%time magic at the beginning of the cells) and compare the algorithm’s MSE to our baseline MSE. At the same time, we will keep in mind the understandable and performant requirements of the wine rating predictor.</p><p>We are going to experiment with one linear algorithm, two distance-based algorithm and two tree-based algorithms, ordered from the simplest to most complex:</p><ul><li>Linear regression</li><li>K-nearest neighbors regressor</li><li>Support vector regressor</li><li>Random forest regressor</li><li>Light gradient boosting regressor</li></ul><p>We are going to train them with the training set, and compare their generalization performances with the validation set. Below function will do the work for us.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/13649f610f80e2d770bfd80772f35eda/href">https://medium.com/media/13649f610f80e2d770bfd80772f35eda/href</a></iframe><p>At the end of this step, we are going to elaborate on how the selected algorithm works.</p><h4>5.1. Linear Regression:</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cTQlTtClohP_Lrnt2ACpzw.png" /></figure><p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html">Linear regression</a> slightly decreased the baseline metric, showing that it is not a candidate to be a good predictor.</p><h4>5.2. K-Nearest Neighbors Regressor</h4><p>Distance-based models use the euclidian distance (or other distance measures) for training, thus varying ranges causes distance-based models to generate inaccurate predictions. To apply distance-based algorithms, we scaled the datasets with normalization before <a href="https://render.githubusercontent.com/view/ipynb?commit=800ae104b19cb48b4e403ee24aa541e723e1972e&amp;enc_url=68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f636572656e6979696d2f57696e652d526174696e672d507265646963746f722d4d4c2d4d6f64656c2f383030616531303462313963623438623465343033656532346161353431653732336531393732652f6e6f7465626f6f6b732f57696e65526174696e67507265646963746f722d322e6970796e62&amp;nwo=cereniyim%2FWine-Rating-Predictor-ML-Model&amp;path=notebooks%2FWineRatingPredictor-2.ipynb&amp;repository_id=257017095&amp;repository_type=Repository#Normalize-Datasets-for-KNN-and-SVM">here in the notebook</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*z1nttphARXIe4PYrQRsycg.png" /></figure><p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsRegressor.html">K-nearest neighbors regressor</a> performed better than the linear regression. However, MSE is still high, showing that this algorithm is not a good predictor as well.</p><h4>5.3. Support Vector Regressor</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QIwWQAyyR7DnUBIy4EPMig.png" /></figure><p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVR.html">Support vector regressor</a> performed better than the k-nearest neighbors regressor at a higher run-time. All in all, MSE decreased 35% showing that this algorithm might be a candidate for building a good predictor.</p><h4>5.4. Random Forest Regressor</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*huwrk3My_gE5R5z07xgGyg.png" /></figure><p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html">Random forest regressor</a> performed better than the support vector regressor at lesser run-times. It decreased the MSE 44% and replaced support vector regressor in the good-predictor list.</p><h4>5.5. Light Gradient Boosting Regressor</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WJ26tRHqZT1lhDeQhiuHuQ.png" /></figure><p><a href="https://lightgbm.readthedocs.io/en/latest/pythonapi/lightgbm.LGBMRegressor.html#lightgbm.LGBMRegressor">Light gradient boosting regressor</a> (Light GBM) showed the best performance of all tried models. It also lowered the baseline MSE 45% and showed that it is a potential candidate for a good predictor at a lower run time.</p><p><strong>As a summary:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NjOv9eqxy7cA8gaI1awpAw.png" /></figure><p>It might not be a fair selection of algorithms since we only train them with the default hyperparameters. Nevertheless, this is the experimental step of the pipeline, that is why both light GBM and random forest algorithm has been given a chance for further improvements in the <strong><em>Perform Hyperparameter Tuning on the Selected Model</em></strong> step. (You can find it <a href="https://render.githubusercontent.com/view/ipynb?commit=8f4a85d2c45f18c97f086c631778358717a0b0da&amp;enc_url=68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f636572656e6979696d2f57696e652d526174696e672d507265646963746f722d4d4c2d4d6f64656c2f386634613835643263343566313863393766303836633633313737383335383731376130623064612f6e6f7465626f6f6b732f57696e65526174696e67507265646963746f722d322e6970796e62&amp;nwo=cereniyim%2FWine-Rating-Predictor-ML-Model&amp;path=notebooks%2FWineRatingPredictor-2.ipynb&amp;repository_id=257017095&amp;repository_type=Repository#Tune-Hyperparameters-of-the-Models">here in the notebook</a>) In this article, we will use random forest regressor due to the understandable and performant requirements and we will only elaborate on it.</p><p>Before moving on to the next step, let’s understand how random forest regressor works:</p><p><strong><em>Random forest regressor </em></strong>​is an ensemble algorithm that builds multiple decision trees once and trains them on various sub-samples and various subsets of the features of the dataset. Its random selection of the dataset and feature subsamples makes this algorithm more robust.</p><p><strong><em>A Decision tree</em></strong>​ uses a tree-like structure to make predictions. It breaks down a dataset into smaller and smaller subsets while at the same time an associated decision tree is incrementally developed. The final result is a tree with decision nodes and leaf nodes. A decision node has two or more branches, each representing values for the feature tested. Leaf node represents a final decision on the target.</p><h3>6. Perform Hyperparameter Tuning on the Selected Model</h3><p><strong><em>A hyperparameter</em></strong> is the set of defined parameter(s) by the data scientist or ML engineer whose values are not affected by the training process of the model. On the other hand, <strong><em>a parameter</em></strong> of a model is searched and optimized by the model during the training process and affected by the dataset.</p><p>I loved <a href="https://machinelearningmastery.com/difference-between-a-parameter-and-a-hyperparameter/">this quotation</a> from Jason Brownlee on <a href="https://machinelearningmastery.com/">Machine Learning Mastery</a> to prevent confusion of the two:</p><blockquote>“If you have to specify a model parameter manually then, it is probably a model hyperparameter.”</blockquote><p>An example of a parameter from our simplest model: Coefficients of the linear regression model, which are optimized through the model training.</p><p>An example of a hyperparameter from our selected model: The number of trees constructed in a random forest model, which is specified by us or by scikit-learn.</p><p><strong><em>Hyperparameter tuning</em></strong> is the process of defining, searching and perhaps improving the performance of the model further. We are going to search for the best set of parameters with <strong><em>the random search</em></strong> and <strong><em>k-fold cross-validation.</em></strong></p><h4>6.1. Random Search</h4><p><strong><em>Random search</em></strong> is the process of searching for the combination of the defined parameters randomly and comparing the defined score (mean squared error, for this problem) in each iteration. It is fast and run-time-efficient, but you may not always find the most optimal set of hyperparameters due to the searching of a random combination of defined hyperparameters.</p><p>We are going to search for the below hyperparameters of random forest regressor with the hyperparameter_grid dictionary:</p><ul><li>n_estimators: number of trees to be used in the model, default is 100.</li><li>min_samples_split: minimum number of samples required to split an internal node, default value is 2.</li><li>min_samples_leaf: minimum number of samples required to be at a leaf node, default value is 1.</li><li>max_features: number of features to consider when looking for the best split, default value is auto.</li></ul><pre><em># define search parameters</em> <br>n_estimators = [100, 200, 300, 500, 1000] <br>min_samples_split = [2, 4, 6, 10] <br>min_samples_leaf = [1, 2, 4, 6, 8] <br>max_features = [&#39;auto&#39;, &#39;sqrt&#39;, &#39;log2&#39;, <strong>None</strong>]</pre><pre><em># Define the grid of hyperparameters to search</em> <br>hyperparameter_grid = {<br>    &quot;n_estimators&quot;: n_estimators,               <br>    &quot;min_samples_split&quot;: min_samples_split,                       <br>    &quot;min_samples_leaf&quot;: min_samples_leaf,                         <br>    &quot;max_features&quot;: max_features}</pre><h4>6.2. <strong><em>K-Fold </em></strong>Cross-Validation</h4><p><strong><em>K-fold cross-validation</em></strong> is the method used to assess the performance of the model on the complete training dataset. Rather than splitting the dataset into two static subsets of training and validation set, the dataset is divided equally for the given <em>K</em>. Then the model is trained with <em>K-1</em> subsets and tested on <em>Kth</em> subset iteratively. This process makes the model more robust to overfitting — more on that at the end of the article.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/885/0*kOeBDUo9JfSpZQt7.png" /><figcaption>Image Credits: Visual Explanation of k-fold cross-validation on <a href="https://scikit-learn.org/stable/modules/cross_validation.html">scikit-learn</a></figcaption></figure><p>To perform hyperparameter tuning with random search and k-fold cross-validation we are going to add training and validation datasets and continue with one training set from now on.</p><pre><em># add dataframes back for to perform random search and cross-validation</em><br>X = pd.concat([X_train, X_valid])<br>y = pd.concat([y_train, y_valid])</pre><pre>X_array = convert_features_to_array(X)<br>y_array = convert_target_to_array(y)</pre><p>Since we have less than 10.000 rows in the training dataset, we are going to perform 4 fold cross-validation to have sufficient number of data points in each fold. We are going to consolidate random search and k-fold cross-validation in the <a href="https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html">RandomizedSearchCV</a> object:</p><pre>rf_random_cv = RandomizedSearchCV(<br>    estimator=rf,<br>    param_distributions=hyperparameter_grid,<br>    cv=4, <br>    n_iter=25,<br>    scoring=&#39;neg_mean_squared_error&#39;,<br>    n_jobs=-1, <br>    verbose=1,<br>    return_train_score=<strong>True</strong>,<br>    random_state=42)</pre><pre>rf_random_cv.fit(X_array, y_array)</pre><p>With the fit method, we initiate the search for the random combination of the values defined for each hyperparameter in the hyperparameter_grid. At the same time, &quot;neg_mean_squared_error&quot; is calculated for each fold in each iteration. We can observe the determined best set of parameters by calling the best_estimator_ method:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j5Y4shr0Uy1agknM-wpjbw.png" /></figure><p>After hyperparameter tuning, the best set of hyperparameters are determined as:</p><ul><li>n_estimators: 200</li><li>min_samples_split: 4</li><li>min_samples_leaf: 2</li><li>max_features: ‘sqrt’</li></ul><p>Let’s see if those hyperparameters will help us to improve the MSE of the random forest regressor further.</p><h4>6.3. Revisit MSE of Random Forest Regressor After Hyperparameter Tuning</h4><pre>rf_random_cv_model = rf_random_cv.best_estimator_</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*smLL1NRMTRGA_VcMQ5QGng.png" /></figure><p>The MSE is decreased from 5.41 to 4.99 and tuned model’s run-time resulted in 1.12 seconds which is lower than the run-time of the initial random forest model (1.89 seconds). Hyperparameter tuning has not only improved the evaluation metric but also lowered the run-time in our case.</p><p>Given the sample dataset, the determined set of features and the tuned random forest regressor we have successfully built a good wine rating predictor without falling into the underfitting and overfitting areas!</p><h4><strong>Some Notes on </strong><a href="https://machinelearningmastery.com/overfitting-and-underfitting-with-machine-learning-algorithms/"><strong>Overfitting and Underfitting</strong></a></h4><p>Although this topic is another article by itself, I think it is important to address here since we mentioned these concepts.</p><p><strong><em>Overfitting</em></strong> happens when the ML model perfectly fits (or memorizes) the training dataset rather than grasping the common patterns between the features and the target. An overfit model will have a <strong><em>high variance</em></strong>, I find a resemblance between this situation and a fragile glass home. It is perfectly built for its current conditions, but it is less likely to survive if the conditions are changed.</p><blockquote>Did you remember that cross-validation makes our model more robust to overfitting?</blockquote><p>The reason behind is that our model sees a different dataset in each fold during training — like a house already encounters different weather conditions. This improves the generalization performance which makes the model more resistant to overfitting.</p><p><strong><em>Underfitting</em></strong> happens when the ML model fails to grasp the relationships between the features and the target due to not having enough data points or features. It may perform as bad as a random guess about the predictions. An underfit model will have a <strong><em>high bias, </em></strong>I think of this situation as a half-built shed. It should have to be undergone some construction to serve its purpose.</p><blockquote>Did you remember the linear regression model that only showed a slight improvement on the baseline MSE?</blockquote><p>That was an example of an underfitting. Linear regression model resulted in almost the same MSE as the baseline MSE and failed to understand the relationship between the features and the target.</p><p>All in all, both overfitting and underfitting decrease the generalization performance of the machine learning models, and results in unsatisfactory levels of evaluation metric. Although we did not test the tuned random forest regressor specifically the overfitting case, the 45% improvement shows that we are at the fine line between underfitting and overfitting.</p><p>Before moving on to the conclusions let’s save our model in the directory so that we can pick up where we left off in the last article and notebook.</p><pre>filename = &#39;random_forests_model.sav&#39;<br>pickle.dump(rf_random_cv_model, <br>           open(filename, &#39;wb&#39;))</pre><h3>Conclusions</h3><p>In this article, we completed the intermediate steps of the machine learning pipeline. After some quick recap on the <a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-one-5c70ae682f35?source=friends_link&amp;sk=8de05327eedb3d0dadcfa4b1a8e8cc75">first article</a> and objectives, we</p><ol><li>Set the evaluation metric as mean square error due to its wide-use in ML algorithms and explainability.</li><li>Established a baseline aligning with the mean square error calculation which resulted in 9.01.</li><li>Tried several different ML algorithms, and selected random forest regressor which reported MSE of 5.4 at 1.93 seconds run time.</li><li>Fine-tuned hyperparameters of the random forest regressor and achieved 8% performance improvement compared to the initial random forest model (MSE: 4.99 at 1.12 seconds run time).</li></ol><p>If we consider our initial motivation (building a good wine predictor) and the baseline MSE (9.01), we are going on the right path as we approach the end of the pipeline.</p><p>We have significantly lowered the baseline MSE, from 9.01 to 4.99 which results in 45% improvement!</p><p>The third article will start by loading the fine-tuned random forest regressor model and will focus on the evaluation of the model with the test set, as well as the results of it. (steps 7, 8, and 9).</p><p><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-a74acda76b98">Building an Automated Machine Learning Pipeline</a></p><p>The last article will automate this pipeline with <a href="https://www.docker.com/">Docker</a> and <a href="https://luigi.readthedocs.io/en/stable/">Luigi</a>.</p><p><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-four-787cdc50a12d">Building an Automated Machine Learning Pipeline: Part Four</a></p><p>Thanks for reading 😊</p><p>For comments or constructive feedback, you can reach out to me on responses, <a href="https://twitter.com/cereniyim">Twitter</a> or <a href="https://www.linkedin.com/in/ceren-iyim">Linkedin</a>!</p><p>Stay safe and healthy until then 👋</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1d3c86e6fe42" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/building-an-automated-machine-learning-pipeline-part-two-1d3c86e6fe42">Building an Automated Machine Learning Pipeline: Part Two</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an Automated Machine Learning Pipeline: Part One]]></title>
            <link>https://medium.com/data-science/building-an-automated-machine-learning-pipeline-part-one-5c70ae682f35?source=rss-287e9909d3b5------2</link>
            <guid isPermaLink="false">https://medium.com/p/5c70ae682f35</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[feature-engineering]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Ceren Iyim]]></dc:creator>
            <pubDate>Wed, 13 May 2020 15:24:26 GMT</pubDate>
            <atom:updated>2020-06-09T17:04:53.803Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://towardsdatascience.com/machine-learning/home">Machine Learning</a></h4><h4>Data Cleaning, Exploratory Data Analysis and Feature Engineering steps</h4><ul><li>Part 1: Understand, clean, explore, process data (you are reading now)</li><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-two-1d3c86e6fe42?source=friends_link&amp;sk=a005d5ead7a844adb7819403ddc6dc0e">Part 2: Set metric and baseline, select and tune model</a> (live!)</li><li><a href="https://medium.com/p/building-an-automated-machine-learning-pipeline-a74acda76b98?source=email-287e9909d3b5--writer.postDistributed&amp;sk=1790d8dd404126a45828c3905f47432c">Part 3: Train, evaluate and interpret model</a> (live!)</li><li><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-four-787cdc50a12d?source=friends_link&amp;sk=7068bbe294f0aa37f247336afcf3eac0">Part 4: Automate your pipeline using Docker and Luigi</a> (live!)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YgW-CkDn30PFxxmG" /><figcaption>Photo by <a href="https://unsplash.com/@lauraperuchi?utm_source=medium&amp;utm_medium=referral">Laura Peruchi</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>During my data science learning journey, I learned through reading articles on Towards Data Science as much as I learned from online courses and various coding challenges. Following such diverse sources of learning that come with their own interpretations of machine learning (ML) helped me a lot. Today, I will bring a part of my perspective to the ML applications that I distilled throughout this journey and start an article series. It will hopefully show how to build an automated ML pipeline with a beginner-friendly language and structure.</p><p>We are going to follow an intuitive ML pipeline to build <strong><em>a predictor to rate wine quality</em></strong>:</p><ol><li>Understand &amp; Clean &amp; Format Data</li><li>Exploratory Data Analysis</li><li>Feature Engineering &amp; Pre-processing</li><li>Set Evaluation Metric &amp; Establish Baseline</li><li>Select an ML Model based on the Evaluation Metric</li><li>Perform Hyperparameter Tuning on the Selected Model</li><li>Train and Evaluate the Model</li><li>Interpret Model Predictions</li><li>Draw Conclusions &amp; Document Work</li></ol><p>This first article covers steps 1, 2 and 3. The code behind this article can be found <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/notebooks/WineRatingPredictor-1.ipynb">in this notebook</a>. The second and third articles in the series will have covered the entire pipeline.</p><p>After we build the pipeline, the fourth article will focus on how we can automate <strong><em>the wine rating predictor</em></strong> with <a href="https://www.docker.com/">Docker</a> and <a href="https://luigi.readthedocs.io/en/stable/">Luigi</a>. This part is especially exciting for me because it introduced me to concepts and tooling that let me understand how an ML solution runs on production systems.</p><blockquote>Disclaimer: The core structure and utilities in this automation are taken from a <a href="https://github.com/datarevenue-berlin/code-challenge-2020">coding challenge</a> that I took on recently as part of an ML Engineer interview process at an amazing company called <a href="https://www.datarevenue.com/">Data Revenue</a>. I did not get the job because they were looking for someone with more emphasis and experience in engineering whereas I’m more on the science part. Ultimately, I wore a software engineer’s hat and learned a lot during the interview process.</blockquote><p>The complete project is available on GitHub for the impatient:</p><p><a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model">cereniyim/Wine-Rating-Predictor-ML-Model</a></p><h3>Problem Definition &amp; Objective:</h3><p>In this project, we are provided with a sample dataset. In a real-world scenario, one can possibly obtain (perhaps <a href="https://towardsdatascience.com/web-scraping-is-now-legal-6bf0e5730a78">scrape</a>) this data from online sources like <a href="https://www.winemag.com/wine-ratings/">winemag</a>.</p><p><strong>The goal of the project is to build <em>a wine rating predictor</em> using a sample dataset to show good prediction is possible, perhaps as a proof of concept for a larger project.</strong></p><p>We are going to use the results of the wine rating predictor to confirm that ML applications are effective solutions to business problems such as optimizing a wine portfolio for a seller.</p><p>We should always keep in mind that the “science” in data science serves a purpose, ultimately for a non-scientist. A typical project has some implied base requirements.</p><p>Our wine rating predictor should be <strong>understandable</strong> because our audience will likely have limited knowledge of statistics and ML. Furthermore, it should be <strong>performant</strong> because the complete production dataset could have millions of rows. Finally, it should be <strong>automated</strong> in a way that it can run on any production system without requiring specialized configurations and setups.</p><h3>Before We Begin</h3><p>The data for this project is available in <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/data_root/raw/wine_dataset.csv">data_root/raw/wine_dataset</a> in the repository. For now, we will use 90% of it as the training set and the remaining 10% as the test set. They are both available in data_root/interim as <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/data_root/interim/train.csv">train.csv</a> and <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/blob/master/data_root/interim/test.csv">test.csv</a> .</p><p>We are going to use Python 3.7 and will need the following libraries in this notebook:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d9de43533b8281ef4fccf6566689dc03/href">https://medium.com/media/d9de43533b8281ef4fccf6566689dc03/href</a></iframe><h3>1. Understand &amp; Clean &amp; Format Data</h3><p>In this step, we will get ourselves familiar with the dataset, understand what our dataset conveys and clean it by removing redundant rows and columns.</p><p>Let’s load the training and test datasets into data frames and have a look at some rows of the training dataset:</p><pre>train = pd.read_csv(&quot;../data_root/interim/train.csv&quot;) <br>test = pd.read_csv(&quot;../data_root/interim/test.csv&quot;)<br>train.sample(5)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-MQtWz43wFd5Ore6wuctbw.png" /></figure><p>There are some empty rows in the dataset and we have only 2 numeric variables: <em>points</em> and the <em>price</em>.</p><p>Points is the dependent variable that we are trying to predict, and will be referred to as the <strong><em>target</em></strong>. The rest are the independent variables that can be used in determining the target and will be referred to as <strong><em>features</em></strong>.</p><p>We are trying to grasp the relationships between independent variables and a dependent variable and use this relationship to generate predictions, which makes the wine rating predictor a <strong><em>supervised regression machine learning model</em></strong>:</p><ul><li><strong><em>Supervised</em>:</strong> Dataset includes the wine ratings (labelled as <em>points</em>) and independent variables which can be used in determining the <em>points</em>.</li><li><strong><em>Regression</em>:</strong> Our target variable — <em>points</em> consist of continuous integers ranging from 80 to 100.</li></ul><p>Most of the column names are self-explanatory if you ever thought about which wine to buy at a supermarket. However, I think it is important to understand how a particular wine receives <em>points</em> and domain-specific features.</p><p><em>Points</em> are assigned to a wine by a taster. A wine may receive different points from the same taster. When a taster is assigning points to a wine, s/he also provides a <em>description</em> of the notes and taste about the wine.</p><p>The <em>designation</em> is the name of the vineyard and <em>region_1</em> &amp; <em>region_2</em> features describe the places where the grapes of the wine are grown. Here is how a Barlow 2005 Barrouge Red looks like:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KU0zMXcsMCskKDHMaWGnfQ.png" /><figcaption>Image Source: Screenshot of Barlow 2005 Barrouge Red on <a href="https://www.winemag.com/buying-guide/barlow-2005-barrouge-red-napa-valley/">Winemag</a></figcaption></figure><p>Now, let’s have a look at the data types and number of non-empty (non-null) of the training and test dataset:</p><pre>train.info()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Tget5IZiUpAipAOuK5NdGA.png" /></figure><pre>test.info()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kdJiFuSFdWEib5g0MN260w.png" /></figure><p>This is an interesting dataset because 90% of the features are <strong><em>categorical — </em></strong>variables that are in<em> object</em> Dtype. ML models can only work with numerical data and non-null values. Thus, we are going to develop some strategies in the <strong><em>Feature Engineering &amp; Pre-processing</em></strong> to handle the categorical data and missing values in our model.</p><h4><strong>1.1. Missing values of the datasets:</strong></h4><p>The function below will enable us to observe the missing values as a percentage per feature.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bc2f4ca1369b03269b6d50b6a0beb696/href">https://medium.com/media/bc2f4ca1369b03269b6d50b6a0beb696/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wowvDS3l__3temrtzjwUxg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jze-2d3YTZrEGjUL1ssY1g.png" /></figure><p>Features that have missing values of more than 50% are not likely to provide significant information to our model. Therefore, <em>region_2</em> will be dropped from both datasets.</p><p>In this sample dataset, target value has no missing values. If we would have missing values in the target, we would have dropped all the missing values not to distort the existing distribution of the target.</p><h4><strong>1.2. Cardinality of the non-numeric features:</strong></h4><p><strong><em>Cardinality</em></strong> is the number of unique values that a categorical feature has. Let’s have a look at it for our training dataset:</p><pre>object_columns = (train<br>                  .select_dtypes(include=&quot;object&quot;)<br>                  .columns)<br><br><strong>for</strong> column <strong>in</strong> object_columns:<br>    print(&quot;<strong>{}</strong> has <strong>{}</strong> unique values.&quot;<br>          .format(column, <br>                  train[column]<br>                  .nunique()))</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*23eJ9OxlfklW7FkPPfaTDA.png" /></figure><p>We can infer that a feature has a</p><ul><li><strong><em>high cardinality</em></strong> if it has more than 1000 rows out of 9000: <em>description</em>, <em>designation</em>, <em>title </em>and <em>winery.</em></li><li><strong><em>moderate cardinality</em></strong> if it has more than 100 rows: <em>province</em>, <em>region_1 </em>and<em> variety</em>.</li><li><strong><em>low cardinality</em></strong> if it has less than 100 rows: <em>country</em>, <em>region_2,</em> <em>taster_name </em>and<em> taster_twitter_handle.</em></li></ul><p>High cardinality features may cause problems when we are training our model. Even though we transform each unique value of a categorical feature to a new feature, <a href="https://pkghosh.wordpress.com/2017/10/09/combating-high-cardinality-features-in-supervised-machine-learning/">they may bring the curse of dimensionality</a>. So, we are going to use the high cardinality features for adding new features, then we are going to remove them from the datasets.</p><p>Remember that this is a sample dataset. So we cannot guarantee that we have seen all the possible values of each categorical feature when we are training the model. If our wine rating predictor encounters with a new value in the test set, it will throw errors. That is why we are going to revisit this in the <strong><em>Feature Engineering &amp; Pre-processing.</em></strong></p><h4><strong>1.3. Removing collinear features:</strong></h4><p>Two variables are called <strong><em>collinear</em></strong> if there exists a linear association between them. In case of categorical features, they are called <strong><em>collinear</em></strong> if they are providing the same information to predict a target.</p><p>Collinear features decrease the generalization performance on the test set and interpretability of the model. Recall that one of the requirements for our wine rating predictor was interpretability.</p><p>In our sample dataset, <em>taster_name</em> and <em>taster_twitter_handle</em> signals for the collinearity. After making sure that all values of the <em>taster_twitter_handle</em> are covered by the <em>taster_name</em> (<a href="https://render.githubusercontent.com/view/ipynb?commit=b3a9024c9eba68c8d3ef63ae21fcb2eb3a30e16c&amp;enc_url=68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f636572656e6979696d2f57696e652d526174696e672d507265646963746f722d4d4c2d4d6f64656c2f623361393032346339656261363863386433656636336165323166636232656233613330653136632f6e6f7465626f6f6b732f57696e65526174696e67507265646963746f722d312e6970796e62&amp;nwo=cereniyim%2FWine-Rating-Predictor-ML-Model&amp;path=notebooks%2FWineRatingPredictor-1.ipynb&amp;repository_id=257017095&amp;repository_type=Repository#Unique-values-of-taster_name-and-taster_twitter_handle">not shown here but checked here in the notebook</a>), it is removed to build a good and explicable wine rating predictor.</p><h4><strong>1.4. Findings from Understand &amp; Clean &amp; Format Data:</strong></h4><p>Up until now, we had the first glance of the dataset and detected the features to remove:</p><ul><li><em>designation</em> and <em>winery</em> due to the high cardinality</li><li><em>region_2 </em>due to having missing values more than 50%</li><li><em>taster_twitter_handle </em>due to collinearity</li></ul><p>Moreover, the training set contains some duplicate rows. In addition to the list above, we are going to drop them and clean the data with the below function:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c359fc7a61ba0f588ae503d4b2ed89f8/href">https://medium.com/media/c359fc7a61ba0f588ae503d4b2ed89f8/href</a></iframe><pre>drop_columns = [&quot;designation&quot;, &quot;winery&quot;, &quot;taster_twitter_handle&quot;, &quot;region_2&quot;]</pre><pre>train_cleaned = CleanDatat(train, drop_columns, &quot;points&quot;)<br>test_cleaned = CleanData(test, drop_columns, &quot;points&quot;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aV2xDpIUweBIya9kLFkYiA.png" /></figure><p>Now, we are going to use the train_cleaned.csv and test_cleaned.csv to visualize and explore the features and target further in the <strong><em>Exploratory Data Analysis</em></strong>.</p><h3>2. Exploratory Data Analysis</h3><p>Exploratory data analysis (EDA) is the step where we have a detailed look at the variables and visualize the relationships between features and target. In this step, we are going to seek and follow the clues of strong determiners of the target. At the end of this step, we will decide which features to process in the <strong><em>Feature Engineering &amp; Pre-processing</em></strong>.</p><p>First, we will examine the <em>points </em>(target), numeric features and link between them. Then, we will investigate the low-cardinality features and their relationship to the target. As we find valuable insights, we will elaborate on them through the steps of EDA.</p><h4><strong>2.1. Distribution of points:</strong></h4><p><strong><em>Distribution</em></strong> is a description of a variable’s range and how data is spread in that range. We can easily observe a distribution by plotting a histogram:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4f53d86084c24fda6a692793602d05bb/href">https://medium.com/media/4f53d86084c24fda6a692793602d05bb/href</a></iframe><pre>figsize(10, 8)<br>plt.rcParams[&#39;font.size&#39;] = 14<br>plot_histogram(train_cleaned, &quot;points&quot;)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ApGjf2ZaJ0NAWXw2fuhXJw.png" /></figure><p>Points show a normal distribution (a bell-shaped curve is obvious in the distribution) as expected from a random variable. Range of the points is distributed between 80 and 100 with a mean of 88.45 and a median of 88. Moreover, standard deviation — a measure of the spread of a data range is 3.03 resulting in a variance of 9.1 as the squared deviation. Based on the normal distribution, we can confidently say that 95% of the points lie in the 82.5–94.5 range.</p><h4><strong>2.2. Distribution of price:</strong></h4><p>When we plot the histogram of the <em>price</em> it showed a vague picture because it was highly <strong><em>right-skewed</em></strong> (<a href="https://render.githubusercontent.com/view/ipynb?commit=b3a9024c9eba68c8d3ef63ae21fcb2eb3a30e16c&amp;enc_url=68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f636572656e6979696d2f57696e652d526174696e672d507265646963746f722d4d4c2d4d6f64656c2f623361393032346339656261363863386433656636336165323166636232656233613330653136632f6e6f7465626f6f6b732f57696e65526174696e67507265646963746f722d312e6970796e62&amp;nwo=cereniyim%2FWine-Rating-Predictor-ML-Model&amp;path=notebooks%2FWineRatingPredictor-1.ipynb&amp;repository_id=257017095&amp;repository_type=Repository#Distribution-of-price">available here in the notebook</a>). To get a reasonable one, we will observe it in the 0–200 range:</p><pre>figsize(10, 8) <br>plt.rcParams[&#39;font.size&#39;] = 14<br>plot_histogram(train_cleaned, &quot;price&quot;, 200) <br>plt.xlim(0,200)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Afre4PS6dxdlI8Bk0mUTpA.png" /></figure><p>This is still a <strong><em>right-skewed</em></strong> or <strong><em>positively skewed</em></strong> distribution where the right tail is longer and most of the values are concentrated on the left-hand side. Median of the price is 25 and the mean price is 35.5.</p><p>In order to use <em>price</em> as a predictor, we need to assume that the <em>points</em> received do not cause any price change. Otherwise, this will cause <a href="https://machinelearningmastery.com/data-leakage-machine-learning/">data leakage</a> since we’ll be including a predictor at a later point in time. This could potentially spoil our future predictions of <em>points</em>.</p><p>Nonetheless, assuming that <em>price</em> is not affected by the <em>points</em> assigned by a taster, it is an indicator of wine’s quality and age. Therefore, we expect it to be an essential feature of the model.</p><h4>2.3. Points and country:</h4><p>To visualize the relationships of several variables, we will use a <strong><em>density plot</em></strong> where we plot the distribution of target per unique values of a categorical feature. A <strong><em>density plot</em></strong> can be interpreted as the continuous and smoothed version of a histogram which conveys the shape of the distribution easily.</p><p>To keep the plots interpretable, we will plot the distribution of <em>points</em> for the countries with more than 100 occurrences.</p><pre># make a list of countries that has most occurences<br>countries = (train_cleaned[&quot;country&quot;]<br>             .value_counts())<br><br>freq_countries = list(<br>    countries[<br>        countries.values &gt; 300]<br>    .index)<br><br>freq2_countries = list(<br>    countries[<br>        (countries.values &lt;= 300) &amp;<br>        (countries.values &gt;= 100)]<br>    .index)</pre><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/07b9e47c3c71cbce975c3942b7eb9ec1/href">https://medium.com/media/07b9e47c3c71cbce975c3942b7eb9ec1/href</a></iframe><pre>figsize(20, 10)<br>plt.rcParams[&#39;font.size&#39;] = 14<br><br><em># plot points distribution for most frequent countries</em><br>plt.subplot(1, 2, 1)<br>plot_distribution(train_cleaned, &quot;points&quot;,<br>                  freq_countries, &quot;country&quot;)<br><br>plt.subplot(1, 2, 2)<br>plot_distribution(train_cleaned, &quot;points&quot;,<br>                  freq2_countries, &quot;country&quot;)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GnCpSImJ-hcdTYcmZe6yRg.png" /></figure><p>Wine producing market is dominated by the US, France, Italy and Spain which is easily available from the plots. <em>Country</em> is a differentiating feature to determine points of wine. However, there are some exceptions: USA &amp; Portugal or Austria &amp; Germany.</p><h4>2.4. Points and price with country</h4><p>Assuming that the price is an essential determiner for the <em>points</em>, we will explore <em>points</em> and <em>price</em> relationship with <em>country</em>.</p><pre><em># create dataframe of most frequent countries</em><br>points_freq_countries = train_cleaned[<br>    train_cleaned<br>    .country<br>    .isin(freq_countries)]</pre><pre>figsize(20, 10)<br>plt.rcParams[&#39;font.size&#39;] = 14<br><br><em># plot a scatterplot of Points and Price</em><br>plt.subplot(1,2,1)<br>sns.scatterplot(x=&#39;price&#39;, y=&#39;points&#39;,<br>                hue=&#39;country&#39;, <br>                data=points_freq_countries,<br>                alpha=0.7)<br>plt.xlabel(&quot;Price&quot;, size=14)<br>plt.ylabel(&quot;Points&quot;, size=14)<br>plt.title(&quot;Points vs Price for Most Frequent Countries&quot;, <br>          size=16)<br><br><em># plot a scatterplot of Points and Price</em><br>plt.subplot(1,2,2)<br>sns.scatterplot(x=&#39;price&#39;, y=&#39;points&#39;, <br>                data=train_cleaned,<br>                alpha=0.7)<br>plt.xlabel(&quot;Price&quot;, size=14)<br>plt.ylabel(&quot;Points&quot;, size=14)<br>plt.title(&quot;Points vs Price for all Countries with price range 0-200&quot;, size=16)<br>plt.xlim(0,200)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I4XF5DS1dHziT0tiTgkJMw.png" /></figure><p>The plot on the left-hand side shows the <em>points</em> and <em>price</em> relationship for the wines produced by the dominant countries in the complete price range. The plot on the right-hand side shows the points and price relationship for all countries zoomed in 0 and 200 price range.</p><p>Both plots show that there is a strong positive correlation exists between the <em>points</em> and <em>price</em>, which serves as proof that <em>price</em> is an important predictor. Another valuable insight is, there are two wines from Italy and one from France that received full <em>points</em> from tasters, all of their prices are greater than 200.</p><h4>2.5. Points and taster name</h4><p><em>Points</em>, represents the score of a particular wine received from a taster. So, a different taster might imply different interpretations of a wine. To investigate this we are going to plot a violin plot.</p><p><strong><em>Violin plot</em></strong><em> </em>​is <a href="https://towardsdatascience.com/recipes-for-the-visualizations-of-data-distributions-a1527a0faf77">my favourite plot</a> that conveys the distribution of the data shape and <a href="https://www.statisticshowto.com/summary-statistics/">summary statistics</a> with the violins outside and slim rectangles inside respectively.</p><pre>figsize(14, 8)<br>plt.rcParams[&#39;font.size&#39;] = 14<br><br>f = sns.violinplot(data=train_cleaned,<br>                   x=&quot;taster_name&quot;,<br>                   y=&quot;points&quot;)<br><br>f.set_xticklabels(f.get_xticklabels(),<br>                  rotation=90)<br><br>plt.title(&quot;Points from Different Tasters&quot;,<br>          size=16)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0U5r8YKnMp4_QYiKPN5vPQ.png" /></figure><p>Each taster’s summary statistics and distribution of <em>points</em> are unique resulting in different violins above. Looking at this picture, we expect it to be the second most important predictor of the model.</p><h4>2.6. Findings from Exploratory Data Analysis</h4><p>We explored <em>points</em>, <em>price</em>, <em>country</em> and the <em>taster_name </em>and relationships between them. In addition to them, <em>variety, region_1 </em>and<em> province </em>will remain in the final feature list since:</p><ul><li><em>variety</em> and <em>region_1</em> are major elements in differentiating the grapes of the wine so as the wine’s taste and quality</li><li><em>province </em>provides location information when combined with <em>country</em></li></ul><p>Moreover, we observed a normal distribution in the <em>points</em> and identified its mean and variance, which will be useful for us in the <strong><em>Set Evaluation Metric &amp; Establish Baseline. </em></strong>We expect <em>price</em> and <em>taster_name</em> to be the two most important predictors in determining <em>points</em>.</p><p>Now, we will move forward with the long-waited and mentioned <strong><em>Feature Engineering &amp; Pre-processing </em></strong>part.</p><h3>3. Feature Engineering &amp; Pre-processing</h3><p><strong><em>Feature engineering</em></strong> is the process of extracting and transforming information from raw features and potentially create a lot more useful features. We are going to take what we’ve learned about our features in the previous parts and encode that information into new ones. Since our features are mostly categorical, we are going to search for numerical or binary features in the <em>description</em>, <em>variety</em> and <em>title</em>.</p><p>Then, we are going to prepare both datasets to be used as an input for our wine rating predictor. This process is called <strong><em>feature pre-processing</em></strong>. This is a necessary step because ML models can only work with numerical data and non-missing values.</p><p>Building a good wine rating predictor starts with identifying the most useful features to determine <em>points</em>. At the end of this step, we will identify the most effective feature set, which will provide a good and understandable <strong><em>wine rating predictor</em></strong> in return. We are going to follow feature extraction, categorical feature transformation and missing value filling respectively.</p><h4>3.1. Feature extraction</h4><ul><li><em>description:</em><strong> </strong>It contains information about the wine’s colour, taste and notes (like sweet, dry). Taste and colour-related words are searched and extracted from the description with the function below. If a taste or colour-related word exists in the description, the corresponding feature to that word is assigned with a value of 1, otherwise 0.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6d176a72c4b326a15205faa0885b89fe/href">https://medium.com/media/6d176a72c4b326a15205faa0885b89fe/href</a></iframe><ul><li><em>title:</em> It contains the production year of the wine. If year information is not available in the title <em>year</em> is assigned to 0.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/df7ff020ed13b9dcf73df8765780d5e8/href">https://medium.com/media/df7ff020ed13b9dcf73df8765780d5e8/href</a></iframe><ul><li><em>variety:</em> It contains information about whether different types of grapes are blended. <em>is_blend</em> is assigned to 1 if several grape varieties present, otherwise 0.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a228d7c584971b66b31f3f6388e018c5/href">https://medium.com/media/a228d7c584971b66b31f3f6388e018c5/href</a></iframe><p>Now, using those functions above and search keywords below, we are going to add new features.</p><pre><em># create search terms for new features </em><br><em># to be extracted from description</em><br>is_red_list = [&quot;red&quot;, &quot;Red&quot;, &quot;RED&quot;,<br>               &quot;noir&quot;, &quot;NOIR&quot;, &quot;Noir&quot;,<br>               &quot;black&quot;, &quot;BLACK&quot;, &quot;Black&quot;]<br><br>is_white_list = [&quot;white&quot;, &quot;WHITE&quot;, &quot;White&quot;,<br>                 &quot;blanc&quot;, &quot;Blanc&quot;, &quot;BLANC&quot;,<br>                 &quot;bianco&quot;, &quot;Bianco&quot;, &quot;BIANCO&quot;,<br>                 &quot;blanco&quot;, &quot;Blanco&quot;, &quot;BLANCO&quot;,<br>                 &quot;blanca&quot;, &quot;Blanca&quot;, &quot;BLANCA&quot;]<br><br>is_rose_list = [&quot;rose&quot;, &quot;ROSE&quot;, &quot;Rose&quot;,<br>                &quot;rosé&quot;, &quot;Rosé&quot;, &quot;ROSÉ&quot;]<br><br>is_sparkling_list = [&quot;sparkling&quot;, &quot;SPARKLING&quot;, &quot;Sparkling&quot;]<br><br>is_dry_list = [&quot;dry&quot;, &quot;Dry&quot;, &quot;DRY&quot;,<br>               &quot;dried&quot;, &quot;Dried&quot;, &quot;DRIED&quot;]<br><br>is_sweet_list = [&quot;sweet&quot;, &quot;Sweet&quot;, &quot;SWEET&quot;]<br><br>desc_extracting_dict = {<br>    &quot;is_red&quot;: is_red_list,<br>    &quot;is_white&quot;: is_white_list,<br>    &quot;is_rose&quot;: is_rose_list,<br>    &quot;is_sparkling&quot;: is_sparkling_list,<br>    &quot;is_dry&quot;: is_dry_list,<br>    &quot;is_sweet&quot;: is_sweet_list<br>}</pre><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ebcd870e83f5a09cac956b7bbd4e7575/href">https://medium.com/media/ebcd870e83f5a09cac956b7bbd4e7575/href</a></iframe><pre>train_features_added = ExtractFeatures(train_cleaned) test_features_added = ExtractFeatures(test_cleaned)</pre><p>After the feature engineering, we have 14 features in the train_features_added and test_features_added data frames: <em>country, province, region_1,</em> <em>variety, price,</em> <em>year,</em> <em>taster_name, is_red</em>, <em>is_white</em>, <em>is_rose</em>, <em>is_dry</em>, <em>is_sweet, is_sparkling, is_blend.</em></p><h4>3.2. Feature pre-processing</h4><p>As the first part of feature pre-processing steps, categorical features (<em>country</em>, <em>province</em>, <em>region_1</em>, <em>taster_name</em> and <em>variety</em>) will be turned into the numerical features. We selected the ​<strong><em>ordinal encoding</em></strong> ​approach for the transformation, which is the process of assigning positive integers consecutively starting from 1 to each unique value of a particular feature in the order of appearance.</p><p>Remember that this is a sample dataset, so we have to consider the possible values that are not present in this sample dataset but may show up in the test dataset. To manage them we are going to use ordinal encoder from the <a href="http://contrib.scikit-learn.org/category_encoders/">category_encoders library</a>.</p><p>When we set handle_unknown parameter to the &quot;value&quot;, the ordinal_encoder object will assign the first-time seen values of the test set to -1. Then, we run fit method on the training set, ordinal_encoder object maps the values of the given features to the integers. Then, we run transform method on both datasets, the transformation process is completed according to mapping done during fitting and we get full-numeric datasets in return.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8691a0f00148c962a491fb6a299d68c7/href">https://medium.com/media/8691a0f00148c962a491fb6a299d68c7/href</a></iframe><pre>ordinal_encode_cols = [&quot;country&quot;, &quot;province&quot;, &quot;region_1&quot;, &quot;variety&quot;,  &quot;taster_name&quot;]</pre><pre>data_encoded = EncodeCategoricalData(train_features_added,<br>                                     test_features_added)<br>train_encoded = data_encoded[0]<br>test_encoded = data_encoded[1]</pre><p>As the second part of the feature pre-processing, we will handle missing values. An easy option is to drop them. However, we already have only 8500 data points to train the model. Therefore, we are going to proceed by filling them. ​Process of filling missing values of features is called <strong><em>imputation</em></strong>. We are going to use the following strategies for different features:</p><ul><li><em>taster_name</em>: Since we expect <em>taster_name</em> to be one of the most important features, it is imputed with a constant value (0 stands for “Unknown taster”). That way, we can maintain each taster’s effect in determining <em>points</em>.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/15353b6479a373b5290c174b99d6cc9d/href">https://medium.com/media/15353b6479a373b5290c174b99d6cc9d/href</a></iframe><ul><li><em>price</em> and <em>year</em>: Imputed with median value since they are numeric columns and the median is not affected by the extreme values.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/78bd4e3afc76c9b648d2f35bac11dde7/href">https://medium.com/media/78bd4e3afc76c9b648d2f35bac11dde7/href</a></iframe><ul><li><em>country</em>, <em>province</em>, <em>region_1</em> and <em>variety</em>: Imputed with most frequent value since they are categorical and the most frequent values of each feature align. Those are US, California, Napa Valley and Pinot Noir respectively.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c2f22cb8bb431a86ddbdc18512a19b67/href">https://medium.com/media/c2f22cb8bb431a86ddbdc18512a19b67/href</a></iframe><p>One important consideration during imputing is, whatever imputing strategy is selected, both training and test sets are imputed with the same values. For instance, the median of the price in the training dataset is 25 and this value is assigned to missing values of the training dataset and the test dataset to prevent data leakage into the test set.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bc1b47d51a709cca72628bf50b0ab0c0/href">https://medium.com/media/bc1b47d51a709cca72628bf50b0ab0c0/href</a></iframe><pre>transformed_data = ImputeMissingValues(train_encoded, test_encoded)<br><br>train_features = transformed_data[0]<br>train_target = transformed_data[1]<br>test_features = transformed_data[2]<br>test_target = transformed_data[3]</pre><p>Before moving on to the next article and the section, we are going to reserve some part of the training set as a validation set to provide an unbiased evaluation of a model.</p><p>Training dataset will be used for training the machine learning model. <strong><em>Training a machine learning model</em></strong> is the process of the grasping the patterns between the features and the target by our model, and using them for further predictions.</p><p><strong><em>Validation dataset</em></strong> — the held-out part of the training dataset will be used as a measure of how well our model will generalize to a first-time-seen dataset. This measure will be one of the objective selection criteria of the <strong><em>Select an ML Model based on the Evaluation Metric </em></strong>part.</p><p>I can hear you thinking why don’t we use the test set for model selection then? Because, if we used the test set for this purpose, we would be selecting a biased model that is trained perfectly fit to our test set. Moreover, the model performance would not be representative.</p><p>The test set will come into the play when we are evaluating our fully-specified model at the <strong><em>Train and Evaluate the Model</em></strong>.</p><p>In light of the information above, let’s create the validation set by separating 25% of the training set randomly:</p><pre>X_train, X_valid, y_train, y_valid = train_test_split(<br>    train_features, <br>    train_target, <br>    test_size=0.25, <br>    random_state=42)</pre><p>Training, validation and test datasets are available under the <a href="https://github.com/cereniyim/Wine-Rating-Predictor-ML-Model/tree/master/notebooks/transformed">notebooks/transformed</a> in the repository. They are all ready to be fed into the wine rating predictor!</p><h3>Conclusions</h3><p>In this article, we completed the first three steps of a machine learning pipeline. After defining the problem and objectives, we</p><ol><li>Cleaned data by removing redundant and collinear features; and duplicate rows</li><li>Explored data to have a detailed understanding of the target, features and their relationships</li><li>Added more useful features (hopefully!), prepared and transformed both datasets</li></ol><p>We also completed the crucial step of creating a validation set from the training set.</p><p>The second article will show how to select an evaluation metric, establish a baseline, select an ML model and tune its hyperparameters by optimizing the selected model’s evaluation metric (steps 4, 5 and 6).</p><p><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-two-1d3c86e6fe42">Building an Automated Machine Learning Pipeline: Part Two</a></p><p>The third article will train and evaluate the model with the training and test dataset respectively. It will show how to interpret an ML model’s predictions and draw conclusions (steps 7, 8, and 9).</p><p><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-a74acda76b98">Building an Automated Machine Learning Pipeline</a></p><p>The last article will automate this pipeline with <a href="https://www.docker.com/">Docker</a> and <a href="https://luigi.readthedocs.io/en/stable/">Luigi</a>.</p><p><a href="https://towardsdatascience.com/building-an-automated-machine-learning-pipeline-part-four-787cdc50a12d">Building an Automated Machine Learning Pipeline: Part Four</a></p><p>Thanks for reading 😊 now the article series is complete and you can read the next ones!</p><p>For comments or constructive feedback, you can reach out to me on responses, <a href="https://twitter.com/cereniyim">Twitter</a> or <a href="https://www.linkedin.com/in/ceren-iyim">Linkedin</a>!</p><p>Stay safe and healthy until then 👋</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5c70ae682f35" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/building-an-automated-machine-learning-pipeline-part-one-5c70ae682f35">Building an Automated Machine Learning Pipeline: Part One</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Statistical Significance In Action]]></title>
            <link>https://medium.com/data-science/statistical-significance-in-action-84a4f47b51ba?source=rss-287e9909d3b5------2</link>
            <guid isPermaLink="false">https://medium.com/p/84a4f47b51ba</guid>
            <category><![CDATA[hypothesis-testing]]></category>
            <category><![CDATA[normal-distribution]]></category>
            <category><![CDATA[statistical-significance]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[statistics]]></category>
            <dc:creator><![CDATA[Ceren Iyim]]></dc:creator>
            <pubDate>Tue, 14 Apr 2020 15:20:21 GMT</pubDate>
            <atom:updated>2020-04-14T15:20:21.811Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://towardsdatascience.com/data-science/home">Data Science</a></h4><h4>And examples from its practical applications</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ORJuK6-_TvK6C2EmSogquA.png" /><figcaption>Image Source: <a href="https://en.wikipedia.org/wiki/P-value">Wikipedia</a></figcaption></figure><p>Previously on In Action Blog Posts: We looked at the Central Limit Theorem to understand better underlying theorem behind the normal distribution. I encourage you to read if you haven’t already!</p><p><a href="https://towardsdatascience.com/central-limit-theorem-in-action-1d4832599b7f">Central Limit Theorem In Action</a></p><p>Today, we will observe another important statistical concept in action and perform a hypothesis test. I will explain the <strong>statistical significance</strong> not only with a concrete and catchy example but also in simple terms. I will use the same dataset I used to explain the Central Limit Theorem — the life expectancy in the world of 186 countries as of 2018.</p><h4><strong>Let’s revisit the most important plot and calculation from the Central Limit Theorem In Action:</strong></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4GoHcgDFxHX2zgfIAmR6fg.png" /></figure><p>The mean (µ) of average life expectancy in the world is 73 with a standard deviation (σ) 7 and it is an almost normal distribution. Using the Central Limit theorem, <strong>the standard error</strong> was calculated as 0.57 by dividing the population’s standard deviation to the square root of sample size.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AxKFOAjeGFTMWXjZgE0Qwg.png" /></figure><p>Imagine a wanderer statistician who discovered an island where only 50 people live. All inhabitants are perfectly healthy and over 73 years-old. She conducts a small survey and learns that the average life expectancy is 76 on the island. Moreover, she finds out that everybody on the island has been doing <a href="https://en.wikipedia.org/wiki/Intermittent_fasting">intermittent fasting</a>. Considering the average life expectancy of 73, this is an intriguing case!</p><p>Now, our curious statistician wants to know if <em>the intermittent fasting could be the path to live a longer and healthier life putting all other possible determinants aside</em>. So, she decides to perform an <a href="https://en.wikipedia.org/wiki/Experiment">experimental study</a> where she seeks the answer to the question:</p><blockquote>Does intermittent fasting increase human lifespan?</blockquote><p>To understand the wanderer statistician’s study and its results’ significance, we need to understand the terms below:</p><ol><li>Null and Alternative Hypothesis</li><li>Standard Normal Distribution and Z-score</li><li>P-values</li><li>Significance level</li></ol><p>Don’t feel intimidated by them, I will keep my word for simplicity. 😉</p><h4>1. Null and Alternative Hypothesis</h4><p><strong>A hypothesis</strong> is a statement about the relationship between variables. <strong>The hypothesis test</strong> is a way to test the results of a hypothesis, an observation, a claim, or an experiment to see if your results are statistically significant. The hypothesis test is constructed around two contrasting claims: Null hypothesis and alternative hypothesis.</p><p><strong>The null hypothesis</strong> either describes <em>the current status</em> of the population/sample or states that there <em>is no difference</em> between the sample and population parameters. <strong>The alternative hypothesis</strong>, the opposite of the null hypothesis, either describes <em>the future or desired state</em> of the population/sample or states that there is <em>a difference</em> between the sample and population parameters.</p><p>Our statistician sets the null and alternative hypothesis for her study as follows:</p><ul><li>Null hypothesis: Intermittent fasting <em>does not increase</em> the average life expectancy. (µ ≤ 73)</li><li>Alternative hypothesis: Intermittent fasting <em>increases</em> the average life expectancy. (µ &gt;73)</li></ul><p>Her goal is to observe if the intermittent fasting leads to an increase (from 73 to 76.) of the average human lifetime, which makes the hypothesis test <strong>one-tailed directional test</strong>.</p><h4>2. Standard Normal Distribution and Z-score</h4><p>Many theorems assume a population or a sample follows a normal distribution. The widespread use of normal distribution derives from the easiness of assessing data points in terms of the standard deviation. Let’s remember the important properties of the normal distribution:</p><ul><li>It is a continuous and symmetrical distribution.</li><li>68% of data lies within ± 1, 95% of data lies within ± 2 and 99.7% of data lies within ± 3 standard deviations from the mean.</li></ul><p><strong>The standard normal distribution</strong> is a special normal distribution where the mean is 0 and the standard deviation is 1. Any normal distribution can be transformed into a standard normal distribution by subtracting the mean from each data point and dividing the subtraction by the standard deviation. This process is called <strong>standardization</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/675/1*EFdC6z0CGPGHUQOSxxQccQ.png" /><figcaption>Standard Normal Distribution with cumulative probability and z-scores. Image Source: <a href="https://en.wikipedia.org/wiki/Standard_score">Wikipedia</a></figcaption></figure><p><strong>Z-score</strong> is the result of a calculation applied to a data point during the standardization. In the standard normal distribution above, z-scores are on the x-axis (positive z-score indicates the value is above the mean and negative z-score indicates the value is below the mean), whereas cumulative probability values are on the Cumulative % bar and under the distribution.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/279/0*g2pQVu9jwIjUbruE.png" /><figcaption>Z-score calculation. Image Source: <a href="http://www.z-table.com/">Z-table</a></figcaption></figure><p><strong>Z-score</strong> defines the data point’s location in terms of its distance to the mean which is measured by the standard deviation. For example, by looking at the z-score and Cumulative % above:</p><ul><li>The probability of a random variable being less than or equal to 1 is 84.1% (P(x ≤ 1) = 0.841).</li><li>The probability of a random variable being greater than or equal to 2 is 2.3% (P(x ≥ 2) = 0.023)</li></ul><p>We can calculate the probability value, abbreviated as <strong>p-value</strong>, from a z-score or vice-versa.</p><h4>3. P-values</h4><p><strong>P-value </strong>is the probability of obtaining test results at least as extreme as the results actually observed during the test, assuming that the null hypothesis is correct. [Source: <a href="https://en.wikipedia.org/wiki/P-value">Wikipedia</a>]. I put it in more simple terms:</p><blockquote>In a world where the null hypothesis is true, p-value indicates the percentage of random chance or noise involved in getting the test results at least as extreme as actual results.</blockquote><p>Let’s analyze p-value further in our context:</p><ul><li>France is a sample with the mean (x̄) 83 from a normal-like distribution with a mean (µ<em>) </em>73 and the standard deviation (σ<em>) </em>7.</li><li>When we calculate the z-score (83–73)÷7, it is 1.42. This places France 1.42 points above the mean.</li><li>Our world, thus the null hypothesis is: “<em>The average life expectancy in France is higher than the global average by 1.42 points</em>.”</li></ul><p>Say, we took a sample from France and found out that average life expectancy is actually lower than the global average by 1 point with a p-value of 0.16. This means, in a world where the null hypothesis is true, there is a 16% random chance that we would measure the average life expectancy in France at least 1 point lower than the global average.</p><p>In other words, if<em> the average life expectancy in France is actually higher than the global average by 1.42 points</em>, we would still measure it is lower by at least 1 point about 1/6 of the time due to noise. Thus, the lower the p-value the more significant the results are since it is less likely to be caused by random chance or noise.</p><p>P-value can be calculated with the <a href="http://www.z-table.com/">z-table</a> or a library from R or Python. Our curious statistician will take some help from <a href="https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.norm.html">the scipy stats package of Python and the norm object from the same library</a> to denote the standard normal distribution. Furthermore, to calculate the p-value she will use the cumulative density function (cdf) method from the norm object. This method will yield the same probability values for a given z-score as in the Cumulative % in the standard normal distribution above.</p><p>To complete her experimental study the only missing piece left is <strong>the significance level — denoted with α.</strong></p><h4>4. Significance level</h4><p><strong>The significance level (α)</strong> is the threshold p-value set to decide if the test results are <strong>statistically significant</strong>. It also represents how much of randomness we can tolerate in our test/study. The significance level is usually set to 0.05, 0.01 or 0.001.</p><p>If the test result’s p-value is less than the significance level (α), then we can conclude that <em>the obtained test results are statistically significant and they are not due to a random chance or noise</em>.</p><p>It is important to set the significance level before starting the experiment. Otherwise, it won’t be an objective test. Our curious statistician also knows that and sets the significance level to 0.05. Finally, she is going to complete the study and observe the statistical significance in action!</p><h4>Steps performed so far by our wanderer statistician:</h4><ol><li>She decided to perform an experimental study to answer the question:</li></ol><ul><li>Does intermittent fasting increase human lifespan?</li></ul><p>2. She determined the null and alternative hypothesis:</p><ul><li>Null hypothesis: Intermittent fasting <em>does not increase</em> the average life expectancy. (µ ≤ 73)</li><li>Alternative hypothesis: Intermittent fasting <em>increases</em> the average life expectancy. (µ &gt;73)</li></ul><p>3. She set the test statistics and calculated the p-value:</p><ul><li>The discovery of 50 healthily-aged people is just another sample from the average life expectancy distribution in the world. So, she determined the <strong>test statistics</strong> as the average life expectancy on the island where everyone is doing intermittent fasting and calculated the p-value as:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6mIBW-NVq9JED9Wi8yiCkg.png" /></figure><p>4. She determined the significance level at 0.05:</p><ul><li>The region on the right-hand side of the α is called the <strong>critical region. </strong>It denotes the area of p-values smaller than the significance level. If the test statistics fall in this region, she will conclude that the test results are statistically significant. (Z-score of p-value 0.05 for a one-tailed directional test is 1.64)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w7j6d0abIcWJNYwN9KhqLw.png" /></figure><p><strong>When she puts all the pieces together to uncover the path of a healthier and longer life:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j87I-A5h4CTTRXAWiSdn2Q.png" /></figure><p>Test statistics fell into the critical region, it means <strong>the test results are statistically significant and she rejects the null hypothesis!</strong></p><blockquote>There is statistically significant evidence that the intermittent fasting increases the average life expectancy, at significance level 0.05. Obtained test results are not due to a random chance.</blockquote><p>In a world where the average life expectancy is 73, the probability (p-value) of getting 50 sample with mean 76 due to random noise is 0.0015 which is less than the 0.05.</p><p>Whether or not the test results are called statistically<strong> </strong>significant depends on the significance level. With the p-value set to 0.001, the test statistics would no longer fall into the critical region. (Z-score of p-value 0.001 for a one-tailed directional test is 3.09)</p><p>In that case, we would have concluded that test results are not statistically significant and accepted the null hypothesis. (<em>Intermittent fasting does not increase the average life expectancy</em>)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iCRVqpDcSijc1KV88WZ6bg.png" /></figure><h4>Practical Applications of the Statistical Significance</h4><p>The test of our curious statistician is called a <strong>z-test. </strong>If our sample size had been less than 30 or there had been two samples to compare, then this would be a <strong>t-test</strong>. If we had compared two or more samples this would be an <strong>ANOVA (analysis of variance) test</strong>.</p><p>Hypothesis tests and statistical significance are used in almost every discipline from social sciences to physics. We can use them to compare the performances of different models in the context of machine learning. We can confidently perform a hypothesis test and determine which one performs better using statistical significance. <strong>Here is an article that I like about the use of statistical significance in machine learning:</strong></p><p><a href="https://towardsdatascience.com/compare-which-machine-learning-model-performs-better-4912b2ed597d">Compare which Machine Learning Model performs Better</a></p><p>Thanks for reading! If you want to have a closer look at the “action” of the statistical significance, you can check out this <a href="https://beta.deepnote.com/project/0e38bb73-5710-402a-814b-69ca659d301d">Deepnote Notebook</a>. Source of my catchy example is from the <a href="https://open-numbers.github.io/">Gapminder’s Open Numbers</a> which can be found <a href="https://github.com/open-numbers/ddf--gapminder--systema_globalis">here</a>.</p><p>For comments or constructive feedback, you can reach out to me on responses, <a href="https://twitter.com/cereniyim">Twitter</a> or <a href="https://www.linkedin.com/in/ceren-iyim">Linkedin</a>! Stay safe and healthy 👋</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=84a4f47b51ba" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/statistical-significance-in-action-84a4f47b51ba">Statistical Significance In Action</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Central Limit Theorem In Action]]></title>
            <link>https://medium.com/data-science/central-limit-theorem-in-action-1d4832599b7f?source=rss-287e9909d3b5------2</link>
            <guid isPermaLink="false">https://medium.com/p/1d4832599b7f</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[central-limit-theorem]]></category>
            <category><![CDATA[towards-data-science]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[statistics]]></category>
            <dc:creator><![CDATA[Ceren Iyim]]></dc:creator>
            <pubDate>Wed, 11 Mar 2020 17:37:04 GMT</pubDate>
            <atom:updated>2020-04-14T09:11:27.081Z</atom:updated>
            <content:encoded><![CDATA[<h4><a href="https://towardsdatascience.com/data-science/home">Data Science</a></h4><h4>And examples from its practical applications</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AhMCbLVd5s82XV6M4KTK6A.png" /><figcaption>Image Credits: Casey Dunn &amp; Creature Cast on <a href="https://vimeo.com/75089338">Vimeo</a></figcaption></figure><p>Statistics is a must-have knowledge for a data scientist. Central Limit Theorem is the cornerstone of it.</p><p>I learn better when I see any theoretical concept in action. I believe there are more people like me out there, so I will explain Central Limit Theorem with a concrete and catchy example today — hoping to make it permanent in your mind for your use.</p><p><strong>Do you remember what is the average life expectancy in the world today? </strong>(Hint: check out <a href="https://towardsdatascience.com/a-remake-of-the-factfulness-bubble-chart-with-python-and-plotly-cd40ff7b3011?source=friends_link&amp;sk=676e1601e134dc33a8b35d325ec6b3bb">here</a> if you don’t)</p><blockquote>It is 73.</blockquote><p>This is a number summarizing the life expectancy data all over the world, to be precise 186 countries. This number will tell us more if we put it into the full context.</p><p><strong>The context is comprised of statistical terms, so let’s first understand them:</strong></p><p><strong>Population: </strong>The set that contains all data of elements, individuals or measurements from your experimenting space. Our experimenting space is world and population is the life expectancy data from all countries — population size is denoted by <em>N</em>.</p><p><strong>Sample: </strong>It is a<strong> </strong>randomly selected subset from the population — sample size is denoted by <em>n</em>.</p><p><strong>Distribution: </strong>It<strong> </strong>describes the data/population/sample range and how data is spread in that range. Distribution of life expectancy in the world as of 2018, is as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KOmpjh1ELBRciDVBL7MPFA.png" /></figure><p><strong>Mean: </strong>Average value of all data from your population or sample. For this example, population mean is 73 — denoted by <em>µ</em> (Mu) for populations and <em>x̄</em> (x bar) for samples.</p><p><strong>Standard Deviation: </strong>Not all countries’ average life expectancy is 73. They are distributed in a range as we see above. Standard deviation is a measure of how spread your population is — denoted by <em>σ </em>(Sigma).</p><p><strong>Normal Distribution — Bell-Shaped Curve — Gaussian Distribution: </strong>When your population is spread perfectly symmetrical with σ standard deviations around the mean value, you get the following bell-shaped curve:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/769/0*g_XwqIsGDZ4eueUH.PNG" /><figcaption>Normal Distribution on <a href="https://en.wikipedia.org/wiki/Normal_distribution">Wikipedia</a></figcaption></figure><p>We scratched the surface of the necessary statistical terms to be used in explaining Central Limit Theorem, now let’s see the theorem in action!</p><p><strong>What kind of distribution is average life expectancy in the world as of 2018? Is it normally distributed or is it some other distribution?</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*H-nsnGU73NepvinoXMYn7A.png" /></figure><p>Well, it is not a perfectly normal distribution, since it seems to be pulled to the left side, known as left-skewed distribution.</p><p>Now let’s take some samples from the population. In other words, let’s take 1000 subsets of size 150 from the population and plot the distribution of each sample’s mean (x̄). This process is called the <strong>sampling distribution</strong>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3nKFRnbNuj-D7ZZ97AzqgQ.png" /></figure><p>This is a perfect normal distribution! Actually, any sampling distribution from any population shows normal distribution because Central Limit Theorem states that:</p><blockquote>Regardless of the initial shape of the population distribution, sampling distribution will approximate to a normal distribution. As the sample size increases, sampling distribution will get narrower and more normal.</blockquote><p>This video explains the theorem unexpectedly interesting way using rabbits and dragon wings 🙂</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F75089338%3Fapp_id%3D122963&amp;dntp=1&amp;display_name=Vimeo&amp;url=https%3A%2F%2Fvimeo.com%2F75089338&amp;image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F449569217_1280.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=vimeo" width="1280" height="720" frameborder="0" scrolling="no"><a href="https://medium.com/media/229599fdcad62a2a49669d680c352eb6/href">https://medium.com/media/229599fdcad62a2a49669d680c352eb6/href</a></iframe><p>Coming back to our explanation of the Central Limit Theorem, it allows us to calculate the standard deviation — known as the <strong>standard error</strong> — of the sampling distribution with the following formula:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/620/1*3poGSOKbQZHWOtdQjSARsw.png" /><figcaption>Standard Error Formula where <em>σ is the standard deviation and n is the sample size. </em><a href="https://statisticsglobe.com/standard-error-in-r-example"><em>Image Source</em></a></figcaption></figure><p><strong>Let’s look if this calculation also holds for our population and sampling distribution created:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AxKFOAjeGFTMWXjZgE0Qwg.png" /></figure><p>As expected it holds! The intuitive explanation of this formula is; as sample size increases, the sampling distribution will become a more accurate representation of the population parameters (mean and standard deviation).</p><h4>Bonus Theorem: Did you recognize where the center of the sampling distribution is? Do you think that it is a coincidence that both the sampling distribution and population mean is 73?</h4><p>Of course not! This is explained by another fundamental theorem in statistics: <strong>Law of large numbers.</strong> As the more samples are drawn from a population and as the sample size increases, the mean of the sampling distribution will get closer to the population mean.</p><h4>Practical Applications of Central Limit Theorem</h4><p>In any machine learning problem, the given dataset represents a sample from the whole population. Using this sample, we try to catch the main patterns in the data. Then, we try to generalize the patterns in the sample to the population while making the predictions. Central limit theorem helps us to make inferences about the sample and population parameters and construct better machine learning models using them.</p><p>Moreover, the theorem can tell us whether a sample possibly belongs to a population by looking at the sampling distribution. The power of the theorem lies here in too.</p><p>When I typed the first words for this blog post, I intended to write about statistical significance and hypothesis testing but I realized that Central Limit Theorem is at the heart of explaining them. So, I will leave them to the next article. Follow my <a href="https://medium.com/@cereniyim">Medium account</a> to learn about them 😉</p><p>Thanks for reading! If you want to have a closer look at the “action” of the theorem, you can check out this <a href="https://beta.deepnote.com/project/0e38bb73-5710-402a-814b-69ca659d301d">Deepnote Notebook</a>. Source of my catchy example is from the <a href="https://open-numbers.github.io/">Gapminder’s Open Numbers</a> which can be found <a href="https://github.com/open-numbers/ddf--gapminder--systema_globalis">here</a>.</p><p>If you enjoyed this one, you can view some of my other articles here:</p><ul><li><a href="https://towardsdatascience.com/why-i-decided-to-become-a-data-scientist-eec6f8cd435e?source=friends_link&amp;sk=ea90fc26db800fcf4611d37942b23508"><em>Why I Decided to Become a Data Scientist</em></a></li><li><a href="https://towardsdatascience.com/recipes-for-the-visualizations-of-data-distributions-a1527a0faf77?source=friends_link&amp;sk=00343b1f4d854951384cd16161741f58"><em>Recipes for the Visualizations of Data Distributions</em></a></li><li><a href="https://towardsdatascience.com/predicting-forest-cover-types-with-the-machine-learning-workflow-1f6f049bf4df?source=friends_link&amp;sk=d740915895b002b7424703d60a80d2f3"><em>Predicting Forest Cover Types with the Machine Learning Workflow</em></a></li><li><a href="https://towardsdatascience.com/customer-segmentation-with-machine-learning-a0ac8c3d4d84?source=friends_link&amp;sk=91a45f28699eda78766335947bed7044"><em>Customer Segmentation with Machine Learning</em></a></li></ul><p>For comments or constructive feedback, you can reach out to me on responses, <a href="https://twitter.com/cereniyim">Twitter</a> or <a href="https://www.linkedin.com/in/ceren-iyim">Linkedin</a>!</p><p><strong>Sources:</strong></p><p><a href="https://machinelearningmastery.com/a-gentle-introduction-to-the-central-limit-theorem-for-machine-learning/">A Gentle Introduction to the Central Limit Theorem for Machine Learning - Machine Learning Mastery</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1d4832599b7f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/central-limit-theorem-in-action-1d4832599b7f">Central Limit Theorem In Action</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>