<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/data-science/</id>
  <link href="https://www.endpointdev.com/blog/tags/data-science/"/>
  <link href="https://www.endpointdev.com/blog/tags/data-science/" rel="self"/>
  <updated>2022-11-28T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>A/B Testing</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2022/11/ab-testing/"/>
      <id>https://www.endpointdev.com/blog/2022/11/ab-testing/</id>
      <published>2022-11-28T00:00:00+00:00</published>
      <author>
        <name>Kürşat Kutlu Aydemir</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2022/11/ab-testing/chemist.webp&#34; alt=&#34;A chemist in complete PPE holds two test tubes holding green liquid.&#34;&gt;&lt;br&gt;
Photo by Mikhail Nilov&lt;/p&gt;
&lt;!-- https://www.pexels.com/photo/chemist-in-complete-ppe-holding-test-tubes-9243513/ --&gt;
&lt;p&gt;In statistics, A/B testing is &amp;ldquo;an experiment with two groups to establish which of two treatments, products, procedures, or the like is superior. Often one of the two treatments is the standard existing treatment, or no treatment&amp;rdquo; (Bruce 2020, 88).&lt;/p&gt;
&lt;p&gt;A/B testing is very useful when adapted to e-commerce and marketing for determining the better of two options for a webpage.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s consider a website where we want to analyze the page visits of page A and page B. Page A is the existing page (the control group), and page B is a new design of the web page (the treatment group).&lt;/p&gt;
&lt;p&gt;To prepare A/B testing we start with the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Define hypotheses: null hypothesis (H&lt;sub&gt;0&lt;/sub&gt;) and alternative hypothesis.&lt;/li&gt;
&lt;li&gt;Prepare control and treatment groups.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then we&amp;rsquo;ll apply the A/B test on the dataset.&lt;/p&gt;
&lt;h3 id=&#34;purpose&#34;&gt;Purpose&lt;/h3&gt;
&lt;p&gt;The new and existing versions of our web page can show different performance in terms of marketing, visitor attention, and &amp;ldquo;conversion&amp;rdquo; to a particular goal. By applying A/B tests we can understand which of the two web pages has better performance. We can also find out if any difference in performance is due to chance or due to a design change.&lt;/p&gt;
&lt;h3 id=&#34;example&#34;&gt;Example&lt;/h3&gt;
&lt;p&gt;For example, let&amp;rsquo;s say we want to compare the conversion rates for visitors of page A and page B. Here are the aggregated results of our collected data for both pages:&lt;/p&gt;
&lt;h4 id=&#34;page-a&#34;&gt;Page A&lt;/h4&gt;
&lt;p&gt;Conversions: 231&lt;br&gt;
Non-conversion visits: 11779&lt;/p&gt;
&lt;h4 id=&#34;page-b&#34;&gt;Page B&lt;/h4&gt;
&lt;p&gt;Conversions: 196&lt;br&gt;
Non-conversion visits: 9823&lt;/p&gt;
&lt;p&gt;The data to be sampled can vary. A very simple dataset could be a list of numeric results of observations: spent time on a control and a treatment web page, the weight of patients with and without treatments, etc. The permutation sampling of these results would be simply picking the values from the combined list of both groups.&lt;/p&gt;
&lt;p&gt;In our conversion example the nature of the groups is similar but the values are slightly different, as they store two states: conversion and not conversion. However, we can still use a simple statistic like the mean to make our permutation test calculation.&lt;/p&gt;
&lt;h3 id=&#34;null-hypothesis&#34;&gt;Null hypothesis&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s build our null hypothesis around our experiment. In this example the null hypothesis would be &amp;ldquo;conversion rate of A ≥ conversion rate of B&amp;rdquo;. So, the alternative hypothesis would be &amp;ldquo;conversion rate of B &amp;gt; conversion rate of A&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;In a significance test we usually aim to answer the question of whether we will reject the null hypothesis or fail to reject the null hypothesis.&lt;/p&gt;
&lt;h3 id=&#34;data-preprocessing-and-clean-up&#34;&gt;Data preprocessing and clean-up&lt;/h3&gt;
&lt;p&gt;Since the conversion/not conversion results are just yes/no (binary) results we might prefer to store them as values of 1 or 0.&lt;/p&gt;
&lt;p&gt;We will use Python with the &lt;code&gt;pandas&lt;/code&gt; library to import conversion samples for Pages A and B as a pandas Series:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;pandas&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;pd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;random&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;conversion = [&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;] * &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;427&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;conversion.extend([&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;] * &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;21602&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;random.shuffle(conversion)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;conversion = pd.Series(conversion)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;permutation-test&#34;&gt;Permutation test&lt;/h3&gt;
&lt;p&gt;To determine if the difference between the control and treatment groups is due to chance or not we can use &lt;a href=&#34;https://en.wikipedia.org/wiki/Permutation_test&#34;&gt;permutation testing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Permutation sampling is performed using the following steps, as listed in Practical Statistics (see the Reference section at the end):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Combine the results from the different groups into a single data set.&lt;/li&gt;
&lt;li&gt;Shuffle the combined data and then randomly draw (without replacement) a resample of the same size as group A (which will contain some data from multiple groups).&lt;/li&gt;
&lt;li&gt;From the remaining data, randomly draw (without replacement) a resample of the same size as group B.&lt;/li&gt;
&lt;li&gt;Do the same for groups C, D, and so on. You have now collected one set of resamples that mirror the sizes of the original samples.&lt;/li&gt;
&lt;li&gt;Whatever statistic or estimate was calculated for the original samples (in our case, the percent difference between two groups), calculate it now for the resamples, and record. This constitutes one permutation iteration.&lt;/li&gt;
&lt;li&gt;Repeat the previous steps &lt;code&gt;R&lt;/code&gt; times to yield a permutation distribution of the test statistic.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For each step of the permutation test we need to calculate the percent difference between successful and unsuccessful conversions. Using our example aggregated data from above, we can do this like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;observed_percentage_diff = 100 * (196 / (196 + 9823) - 231 / (231 + 11779))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Which results in &lt;code&gt;0.032885893156042734&lt;/code&gt; for our observation.&lt;/p&gt;
&lt;p&gt;Below is a simple permutation test implementation from Practical Statistics.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;perm_fun&lt;/span&gt;(x, nA, nB):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    n = nA + nB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    idx_B = &lt;span style=&#34;color:#038&#34;&gt;set&lt;/span&gt;(random.sample(&lt;span style=&#34;color:#038&#34;&gt;range&lt;/span&gt;(n), nB))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    idx_A = &lt;span style=&#34;color:#038&#34;&gt;set&lt;/span&gt;(&lt;span style=&#34;color:#038&#34;&gt;range&lt;/span&gt;(n)) - idx_B
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; x.loc[&lt;span style=&#34;color:#038&#34;&gt;list&lt;/span&gt;(idx_B)].mean() - x.loc[&lt;span style=&#34;color:#038&#34;&gt;list&lt;/span&gt;(idx_A)].mean()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we need to repeat the sampling with a high &lt;code&gt;R&lt;/code&gt; value, we&amp;rsquo;ll use 5000.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;R = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;5000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perm_diffs = [&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt; * perm_fun(conversion, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;12010&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;10019&lt;/span&gt;) &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; _ &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;range&lt;/span&gt;(R)]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;results&#34;&gt;Results&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;perm_diffs&lt;/code&gt; holds the percentage differences of the sampling data we generated. Now we have permutation test sampling differences and observed difference to be plotted.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;plt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plt.hist(perm_diffs, bins=&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;15&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plt.axvline(x = observed_percentage_diff, color=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;black&amp;#39;&lt;/span&gt;, lw=&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plt.show()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&#34;/blog/2022/11/ab-testing/histogram.webp&#34; alt=&#34;The histogram from permutation testing results. The y-axis is labeled &amp;ldquo;frequency&amp;rdquo;. The x-axis spans from -0.6 to 0.8. There is a normal distribution peaking at x = -0.1, with y roughly equaling 1000. The lowest frequency values are at -0.6 and 0.6, with around 10 occurrences each.&#34;&gt;&lt;/p&gt;
&lt;p&gt;This plot shows us that the observed difference is well within the confidence level. Although we can easily identify the location observation, it is always good to check the p-value to be sure.&lt;/p&gt;
&lt;p&gt;In this example our p-value is found with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;numpy&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;p_value = np.mean([diff &amp;gt; observed_percentage_diff &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; diff &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; perm_diffs])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This results in &lt;code&gt;0.4204&lt;/code&gt; for our data. Then we compare &lt;code&gt;p_value&lt;/code&gt; with an alpha value, which is usually &lt;code&gt;0.05&lt;/code&gt;. If the p-value is less then alpha then we reject the null hypothesis. So in our example the p-value is extremely high, meaning we fail to reject the null hypothesis. Therefore, we can say that the difference between group A and group B is most likely due to chance rather than the treatment we applied.&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;The results of a significance test do not explicitly accept the null hypothesis, but rather help to understand if the treatments are affecting the results of the experiments or the results are most likely due to chance. A/B (or in some cases more groups, like C/D/E&amp;hellip;) experiments are helpful to understand whether the treatment or chance is most likely the cause of the results, as well as finding which group performs the best.&lt;/p&gt;
&lt;h3 id=&#34;reference&#34;&gt;Reference&lt;/h3&gt;
&lt;p&gt;Bruce, Peter, Andrew Bruce, and Peter Gedeck. &lt;em&gt;Practical Statistics for Data Scientists&lt;/em&gt;, 2nd Edition. O&amp;rsquo;Reilly Media, Inc., 2020.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Understanding Linear Regression</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2022/06/understanding-linear-regression/"/>
      <id>https://www.endpointdev.com/blog/2022/06/understanding-linear-regression/</id>
      <published>2022-06-01T00:00:00+00:00</published>
      <author>
        <name>Kürşat Kutlu Aydemir</name>
      </author>
      <content type="html">
        &lt;link rel=&#34;stylesheet&#34; href=&#34;https://cdn.jsdelivr.net/npm/katex@0.15.6/dist/katex.min.css&#34; integrity=&#34;sha384-ZPe7yZ91iWxYumsBEOn7ieg8q/o+qh/hQpSaPow8T6BwALcXSCS6C6fSRPIAnTQs&#34; crossorigin=&#34;anonymous&#34;&gt;
&lt;script defer src=&#34;https://cdn.jsdelivr.net/npm/katex@0.15.6/dist/katex.min.js&#34; integrity=&#34;sha384-ljao5I1l+8KYFXG7LNEA7DyaFvuvSCmedUf6Y6JI7LJqiu8q5dEivP2nDdFH31V4&#34; crossorigin=&#34;anonymous&#34;&gt;&lt;/script&gt;
&lt;script defer src=&#34;https://cdn.jsdelivr.net/npm/katex@0.15.6/dist/contrib/auto-render.min.js&#34; integrity=&#34;sha384-+XBljXPPiv+OzfbB3cVmLHf4hdUFHlWNZN5spNQ7rmHTXpd7WvJum6fIACpNNfIR&#34; crossorigin=&#34;anonymous&#34;&gt;&lt;/script&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/understanding-linear-regression/banner.webp&#34; alt=&#34;Green Striped&#34;&gt;
&lt;a href=&#34;https://www.pexels.com/photo/green-striped-wallpaper-136740/&#34;&gt;Photo by Scott Webb&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Linear regression is a regression model which outputs a numeric value. It is used to predict an outcome based on a linear set of input.&lt;/p&gt;
&lt;p&gt;The simplest hypothesis function of linear regression model is a univariate function as shown in the equation below:&lt;/p&gt;
&lt;p&gt;$$
h_θ = θ_0 + θ_1x_1
$$&lt;/p&gt;
&lt;p&gt;As you can guess this function represents a linear line in the coordinate system. The hypothesis function (h&lt;sub&gt;0&lt;/sub&gt;) approximates the output given input.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/understanding-linear-regression/linear-regression-1.webp&#34; alt=&#34;Linear regression plot&#34;&gt;&lt;/p&gt;
&lt;p&gt;θ&lt;sub&gt;0&lt;/sub&gt; is the &lt;em&gt;intercept&lt;/em&gt;, also called &lt;em&gt;bias term&lt;/em&gt;. θ&lt;sub&gt;1&lt;/sub&gt; is the &lt;em&gt;gradient&lt;/em&gt; or &lt;em&gt;slope&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A linear regression model can either represent a univariate or a multivariate problem. So we can generalize the equation of the hypothesis as summation:&lt;/p&gt;
&lt;p&gt;$$
h_θ = \sum{θ_ix_i}
$$&lt;/p&gt;
&lt;p&gt;where x&lt;sub&gt;0&lt;/sub&gt; is always 1.&lt;/p&gt;
&lt;p&gt;We can also represent the hypothesis equation with vector notation:&lt;/p&gt;
&lt;p&gt;$$
h_θ =
\begin{bmatrix}
θ_0 &amp;amp; θ_1 &amp;amp; θ_2   \dots θ_n
\end{bmatrix}
x
\begin{bmatrix}
x_0 \\
x_1 \\
x_2 \\
\vdots \\
x_n
\end{bmatrix}
$$&lt;/p&gt;
&lt;h3 id=&#34;linear-regression-model&#34;&gt;Linear Regression Model&lt;/h3&gt;
&lt;p&gt;I am going to introduce a linear regression model using a &lt;em&gt;gradient descent&lt;/em&gt; algorithm. Each iteration of a gradient descent algorithm calculates the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hypothesis &lt;em&gt;h&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;The loss&lt;/li&gt;
&lt;li&gt;Gradient descent update&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The gradient descent update iteration stops when it reaches the &lt;em&gt;convergence&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Although I am implementing a univariate linear regression model in this section, these steps apply to multivariate linear regression models as well.&lt;/p&gt;
&lt;h4 id=&#34;hypothesis&#34;&gt;Hypothesis&lt;/h4&gt;
&lt;p&gt;We start the initial hypothesis assumption with random parameters. Then we calculate the loss using &lt;a href=&#34;https://en.wikipedia.org/wiki/Norm_(mathematics)#Euclidean_norm&#34;&gt;L2 Loss&lt;/a&gt; function over the training dataset. In Python:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;hypothesis&lt;/span&gt;(X, theta):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; theta[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;] + theta[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;:] * X&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this function we took X input (univariate in this implementation) and theta parameter values. &lt;code&gt;X&lt;/code&gt; represents the feature input of our dataset. Theta is the weights of the features. θ&lt;sub&gt;0&lt;/sub&gt; is called the &lt;em&gt;bias term&lt;/em&gt; and θ&lt;sub&gt;1&lt;/sub&gt; is the &lt;em&gt;gradient&lt;/em&gt; or &lt;em&gt;slope&lt;/em&gt;.&lt;/p&gt;
&lt;h4 id=&#34;l2-loss-function&#34;&gt;L2 Loss Function&lt;/h4&gt;
&lt;p&gt;L2 Loss function — sometimes called Mean Squared Error (MSE) — is the total error of the current hypothesis over the given training dataset. During the training, by calculating the MSE, we can target minimizing the cumulative error.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/understanding-linear-regression/linear-regression-2-mse.webp&#34; alt=&#34;L2 Loss&#34;&gt;&lt;/p&gt;
&lt;p&gt;$$
J(θ) = \frac{\sum{(h_θ(x_i) - y_i)^2}}{2m}
$$&lt;/p&gt;
&lt;p&gt;L2 loss function (MSE) simply calculates the error by summing the squares of each data point error by dividing the size of the dataset.&lt;/p&gt;
&lt;p&gt;The more the linear function is aligned, the optimized center of the data points with an optimized slope would give us a minimized error which is our target in linear regression training.&lt;/p&gt;
&lt;h4 id=&#34;gradients-of-the-loss&#34;&gt;Gradients of the Loss&lt;/h4&gt;
&lt;p&gt;Each time we iterate and calculate a new theta (θ), we get a new theta&lt;sub&gt;1&lt;/sub&gt; (slope) value. If we plot each slope value in the gradient descent batch update we will have a curve like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/06/understanding-linear-regression/linear-regression-3-gradient-descent.webp&#34; alt=&#34;Gradient Descent&#34;&gt;&lt;/p&gt;
&lt;p&gt;This curve has a minimum value which can&amp;rsquo;t get lower. Our goal is to find an optimal low value of theta&lt;sub&gt;1&lt;/sub&gt; that reaches a point where our curve doesn&amp;rsquo;t get lower anymore or the change can be ignored. That is where the convergence is achieved and the loss is minimized.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s do a little bit more math. The gradient of the loss is the partial derivative of θ. We calculate partial differential of loss for θ&lt;sub&gt;0&lt;/sub&gt; and θ&lt;sub&gt;1&lt;/sub&gt; separately. For multivariate functions our θ&lt;sub&gt;1&lt;/sub&gt; is a generalized version for all available θ&lt;sub&gt;i&lt;/sub&gt; since the partial derivatives are calculated similarly. You can simply calculate the partial derivatives of loss function yourself too.&lt;/p&gt;
&lt;p&gt;$$
\frac{∂}{∂θ_0}J(θ_0) = \frac{\sum{(h_0 - y_0)}}{m}
$$&lt;/p&gt;
&lt;p&gt;$$
\frac{∂}{∂θ_0}J(θ_i) = \frac{\sum{(h_i - y_i)x_i}}{m}
$$&lt;/p&gt;
&lt;p&gt;Since we know the hypothesis equation we can replace it in the derivatives as well:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;partial_derivatives&lt;/span&gt;(h, X, y):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; [np.mean((h.flatten() - y)), np.mean((h.flatten() - y) * X.flatten())]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we will calculate the gradients for given hypothesis given theta, X, and y:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;calc_gradients&lt;/span&gt;(theta, X, y):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gradient = [&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    h = hypothesis(X, theta)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gradient = partial_derivatives(h, X, y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; np.array(gradient)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;batch-gradient-descent&#34;&gt;Batch Gradient Descent&lt;/h4&gt;
&lt;p&gt;The gradient descent method I used in this implementation is called &lt;em&gt;batch gradient descent&lt;/em&gt; which uses all the data available through the iterations, which slows down the overall convergence process. There are methods to improve the performance of gradient descent such as &lt;a href=&#34;https://en.wikipedia.org/wiki/Stochastic_gradient_descent&#34;&gt;stochastic gradient descent&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since we calculated the gradients for the given theta we will iterate as much as we can until the convergence.&lt;/p&gt;
&lt;p&gt;$$
θ_1(new) = θ_1(current) - α * J&amp;rsquo;(θ_1(current))
$$&lt;/p&gt;
&lt;p&gt;Here comes the &lt;em&gt;convergence rate&lt;/em&gt; or so called &lt;em&gt;learning rate&lt;/em&gt; (α) factor to decide how long we should jump through the iterations. If &lt;code&gt;α&lt;/code&gt; is too small, convergence can be more accurate, but the performance will be too small. This also leads to &lt;em&gt;overfitting&lt;/em&gt;. If &lt;code&gt;α&lt;/code&gt; is too big, the performance will be better, but convergence couldn&amp;rsquo;t be calculated accurately or well enough.&lt;/p&gt;
&lt;p&gt;There is no strict best value for &lt;code&gt;α&lt;/code&gt; since it depends on the dataset for training the model. By evaluating the model you trained you can find the best alpha value for your dataset. You can refer to statistical measures like R&lt;sup&gt;2&lt;/sup&gt; score to determine the observed variance. But there usually won&amp;rsquo;t be single model parameter, hyperparameter, or statistical variable to refer to for regularization.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;gradient_update&lt;/span&gt;(X, y, theta, alpha, stop_threshold):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# initial loss&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    loss = L2_loss(hypothesis(X, theta), y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    old_loss = loss + stop_threshold
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;while&lt;/span&gt;( &lt;span style=&#34;color:#038&#34;&gt;abs&lt;/span&gt;(old_loss - loss) &amp;gt; stop_threshold ):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;# gradient descent update&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        gradients = calc_gradients(theta, X, y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        theta = theta - alpha * gradients            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        old_loss = loss
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        loss = L2_loss(hypothesis(X, theta), y)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;Gradient Descent training stopped at loss &lt;/span&gt;&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;, with coefficients: &lt;/span&gt;&lt;span style=&#34;color:#33b;background-color:#fff0f0&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&lt;/span&gt; % (loss, theta))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; theta&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By performing batch gradient descent we actually train our algorithm and make it find the best theta values to fit the linear function. Now we can evaluate our algorithm and compare it with &lt;a href=&#34;https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html&#34;&gt;Sci-Kit Learn Linear Regression&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;evaluation&#34;&gt;Evaluation&lt;/h4&gt;
&lt;p&gt;Since linear regression is a regression model, you should train and evaluate this model on regression datasets.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_diabetes.html&#34;&gt;SK-Learn Diabetes dataset&lt;/a&gt; is a good regression dataset example. Below I loaded and prepared the dataset by splitting into training and test datasets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;sklearn&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; datasets
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;sklearn.model_selection&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; train_test_split
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Load the diabetes dataset&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;diabetes = datasets.load_diabetes()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;diabetes_X = diabetes.data[:, np.newaxis, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;diabetes_y = diabetes.target
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;X_train, X_test, y_train, y_test = train_test_split(diabetes.data, diabetes_y, test_size=&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.1&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can evaluate our model:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;sklearn.metrics&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; mean_squared_error, r2_score
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# initial random theta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;theta = [&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stop_threshold = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# learning rate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;alpha = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;theta = gradient_update(X_train, y_train, theta, alpha, stop_threshold)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;y_pred = hypothesis(X_test, theta)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Intercept (theta 0):&amp;#34;&lt;/span&gt;, theta[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Coefficients (theta 1):&amp;#34;&lt;/span&gt;, theta[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;MSE:&amp;#34;&lt;/span&gt;, mean_squared_error(y_test, y_pred))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;R2 Score&amp;#34;&lt;/span&gt;, r2_score(y_test, y_pred))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Plot outputs using test data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plt.scatter(X_test, y_test,  color=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;black&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plt.plot(X_test, y_pred, color=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;, linewidth=&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plt.show()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When I run my linear regression model it finds the optimal theta values, finishes the training, and outputs as below. I noted sample evaluation scores below too.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Gradient Descent training stopped at loss 3753.11429796413, with coefficients: [151.6166715  850.81024746]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Intercept (theta 0): 151.61667150054697
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Coefficients (theta 1): 850.8102474614635
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MSE: 5320.89741757879
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;R2 Score 0.14348916154815183&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&#34;/blog/2022/06/understanding-linear-regression/gd-evaluate.webp&#34; alt=&#34;Linear Regression Plot&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s evaluate the SK-Learn linear regression model with the same training and test datasets we used. I&amp;rsquo;m going to use default parameters without optimizing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Sci-Kit Learn LinearRegression model evaluation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;regr = linear_model.LinearRegression()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;regr.fit(X_train, y_train)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;y_pred = regr.predict(X_test)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Coef:&amp;#34;&lt;/span&gt;, regr.coef_)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Intercept:&amp;#34;&lt;/span&gt;, regr.intercept_)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;MSE:&amp;#34;&lt;/span&gt;, mean_squared_error(y_test, y_pred))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;R2 Score&amp;#34;&lt;/span&gt;, r2_score(y_test, y_pred))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Plot outputs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plt.scatter(X_test, y_test, color=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;black&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plt.plot(X_test, y_pred, color=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;, linewidth=&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plt.show()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The output and plot of the SK-Learn Linear Regression model is as below:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Coef: [993.14228074]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Intercept: 151.5751918329106
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MSE: 5544.283378702411
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;R2 Score 0.10753047228113943&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&#34;/blog/2022/06/understanding-linear-regression/sklearn-lr-evaluate.webp&#34; alt=&#34;SK-Learn Linear Regression Plot&#34;&gt;&lt;/p&gt;
&lt;p&gt;Notice the intercept of my linear regression model and SK-Learn&amp;rsquo;s linear regression model are very close with value of around ~151. MSE values are calculated very close too. Also both plotted their predictions very similarly as well.&lt;/p&gt;
&lt;h3 id=&#34;multivariate-linear-regression&#34;&gt;Multivariate Linear Regression&lt;/h3&gt;
&lt;p&gt;We can add more features as we have more features in a dataset and prepare our hypothesis as below, similar to a univariate hypothesis.&lt;/p&gt;
&lt;p&gt;$$
h_θ(x) = θ_0 + θ_1x_1 + &amp;hellip; + θ_nx_n
$$&lt;/p&gt;
&lt;p&gt;A multivariate dataset can have multiple features and a single output like below.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Feature1&lt;/th&gt;
          &lt;th&gt;Feature2&lt;/th&gt;
          &lt;th&gt;Feature3&lt;/th&gt;
          &lt;th&gt;Feature4&lt;/th&gt;
          &lt;th&gt;Target&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;2&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;100&lt;/td&gt;
          &lt;td&gt;12&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;16&lt;/td&gt;
          &lt;td&gt;10&lt;/td&gt;
          &lt;td&gt;1000&lt;/td&gt;
          &lt;td&gt;121&lt;/td&gt;
          &lt;td&gt;18&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;5&lt;/td&gt;
          &lt;td&gt;5&lt;/td&gt;
          &lt;td&gt;450&lt;/td&gt;
          &lt;td&gt;302&lt;/td&gt;
          &lt;td&gt;14&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Each feature is an independent variable (x&lt;sub&gt;i&lt;/sub&gt;) of a dataset. Parameters (theta) are what we aim to find during the training just like the univariate model.&lt;/p&gt;
&lt;h3 id=&#34;linear-regression-with-polynomial-functions&#34;&gt;Linear Regression with Polynomial Functions&lt;/h3&gt;
&lt;p&gt;Sometimes a line function doesn&amp;rsquo;t fit the data well enough. Although if we are dealing with a polynomial function (having multiple features with exponential versions), it could fit the data better.&lt;/p&gt;
&lt;p&gt;In this case the data itself is not linear but we are lucky that the parameter space is linear and we can still apply the linear regression over the non-linear dataset as well:&lt;/p&gt;
&lt;p&gt;$$
h_θ(x) = θ_0 + θ_1x + θ_1x^2 &amp;hellip; + θ_nx^n
$$&lt;/p&gt;
&lt;p&gt;$$
h_θ =
\begin{bmatrix}
1 &amp;amp; x &amp;amp; x^2   \dots x^n
\end{bmatrix}
x
\begin{bmatrix}
θ_0 \\
θ_1 \\
θ_2 \\
\vdots \\
θ_n
\end{bmatrix}
$$&lt;/p&gt;
&lt;p&gt;Here the data is non-linear but the parameters are linear and we can still apply the gradient descent algorithm.&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In this post I implemented a linear regression model from scratch and evaluated by training it.&lt;/p&gt;
&lt;p&gt;Linear regression is useful when your dataset variables can be related in a linear relation. In the real world, linear regression is very useful in &lt;a href=&#34;https://www.pluralsight.com/courses/understanding-applying-linear-regression?aid=7010a000002BWqGAAW&amp;amp;exp=2&#34;&gt;forecasting&lt;/a&gt;.&lt;/p&gt;
&lt;script&gt;
    document.addEventListener(&#34;DOMContentLoaded&#34;, function() {
        renderMathInElement(document.body, {
          // customised options
          // • auto-render specific keys, e.g.:
          delimiters: [
              {left: &#39;$$&#39;, right: &#39;$$&#39;, display: true},
              {left: &#39;$&#39;, right: &#39;$&#39;, display: false},
              {left: &#39;\\(&#39;, right: &#39;\\)&#39;, display: false},
              {left: &#39;\\[&#39;, right: &#39;\\]&#39;, display: true}
          ],
          // • rendering keys, e.g.:
          throwOnError : false
        });
    });
&lt;/script&gt;

      </content>
    </entry>
  
    <entry>
      <title>Visualizing Data with Pair-Plot Using Matplotlib</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2022/04/visualizing-data-with-pairplot-using-matplotlib/"/>
      <id>https://www.endpointdev.com/blog/2022/04/visualizing-data-with-pairplot-using-matplotlib/</id>
      <published>2022-04-25T00:00:00+00:00</published>
      <author>
        <name>Kürşat Kutlu Aydemir</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2022/04/visualizing-data-with-pairplot-using-matplotlib/pexels-sebastian-361530.webp&#34; alt=&#34;Photo of dark blue glass with lines and right angles, perhaps windows of a modern skyscraper&#34;&gt;
&lt;a href=&#34;https://www.pexels.com/photo/gray-wallpaper-361530/&#34;&gt;Photo by Sebastian&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;pair-plot&#34;&gt;Pair Plot&lt;/h3&gt;
&lt;p&gt;A pair plot is plotting &amp;ldquo;pairwise relationships in a dataset&amp;rdquo; (&lt;a href=&#34;https://seaborn.pydata.org/generated/seaborn.pairplot.html&#34;&gt;seaborn.pairplot&lt;/a&gt;). A few well-known visualization modules for Python are widely used by data scientists and analysts: &lt;a href=&#34;https://matplotlib.org/&#34;&gt;Matplotlib&lt;/a&gt; and &lt;a href=&#34;https://seaborn.pydata.org/&#34;&gt;Seaborn&lt;/a&gt;. There are many others as well but these are de facto standards. In the sense of level we can consider Matplotlib as the more primitive library and Seaborn builds upon Matplotlib and &amp;ldquo;provides a high-level interface for drawing attractive and informative statistical graphics&amp;rdquo; (&lt;a href=&#34;https://seaborn.pydata.org/&#34;&gt;Seaborn project&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Seaborn&amp;rsquo;s higher-level pre-built plot functions give us good features. Pair plot is one of them. With Matplotlib you can plot many plot types like line, scatter, bar, histograms, and so on. Pair-plot is a plotting model rather than a plot type individually. Here is a pair-plot example depicted on the Seaborn site:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/04/visualizing-data-with-pairplot-using-matplotlib/pairplot_3_0.webp&#34; alt=&#34;Seaborn pairplot&#34;&gt;&lt;/p&gt;
&lt;p&gt;Using a pair-plot we aim to visualize the correlation of each feature pair in a dataset against the class distribution. The diagonal of the pairplot is different than the other pairwise plots as you see above. That is because the diagonal plots are rendering for the same feature pairs. So we wouldn&amp;rsquo;t need to plot the correlation of the feature in the diagonal. Instead we can just plot the class distribution for that pair using one kind of plot type.&lt;/p&gt;
&lt;p&gt;The different feature pair plots can be scatter plots or heatmaps so that the class distribution makes sense in terms of correlation. Also the plot type of the diagonal can be chosen among the mostly used kind of plots such as histogram or KDE (kernel density estimate), which essentially plots the density distribution of the classes.&lt;/p&gt;
&lt;p&gt;Since a pair plot visually gives an idea of correlation of each feature pair, it helps us to understand and quickly analyse the correlation matrix (Pearson) of the dataset as well.&lt;/p&gt;
&lt;h3 id=&#34;custom-pair-plot-using-matplotlib&#34;&gt;Custom Pair-Plot using Matplotlib&lt;/h3&gt;
&lt;p&gt;Since Matplotlib is relatively primitive and doesn&amp;rsquo;t provide a ready-to-use pair-plot function, we can do it ourselves in a similar way to how Seaborn does. You normally won&amp;rsquo;t necessarily create such home-made functions if they are already available in modules like Seaborn. But implementing your visualization methods in a custom way give you a chance to know what you plot and may be sometimes very different than the existing ones. I am not going to introduce an exceptional case here but creating our pair-plot grid using Matplotlib.&lt;/p&gt;
&lt;h4 id=&#34;plot-grid-area&#34;&gt;Plot Grid Area&lt;/h4&gt;
&lt;p&gt;Initially we need to create a grid plot area using the &lt;code&gt;subplots&lt;/code&gt; function of &lt;code&gt;matplotlib&lt;/code&gt; like below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fig, axis = plt.subplots(nrows=&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;, ncols=&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For a pair-plot grid you should give the same row and column size because we are going to plot pairwise. Now we can prepare a plot function for the plot grid area we created. If we have 3 features in our dataset as this example we can loop through the features per feature like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; j &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        plotPair()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For cleaner code it is better to move the single pair plotting to another function.&lt;/p&gt;
&lt;p&gt;Below is a function I created for one of my master&amp;rsquo;s degree coursework assignments in December 2021 at the University of London. Plotting a single pair in a grid needs to get the current axis for the current grid cell and identify the current feature data values on the current axis. Another thing to consider is where to render the labels of axes. If we were plotting a single chart it would be easy to render the labels on each axis of the chart. But in a pair plot it is better to plot the labels on the left-most and bottom-most of the grid area so that we won&amp;rsquo;t bother the inner subplots with the dirty labeling.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;plot_single_pair&lt;/span&gt;(ax, feature_ind1, feature_ind2, _X, _y, _features, colormap):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Plots single pair of features.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    Parameters
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    ----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    ax : Axes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        matplotlib axis to be plotted
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    feature_ind1 : int
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        index of first feature to be plotted
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    feature_ind2 : int
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        index of second feature to be plotted
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    _X : numpy.ndarray
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        Feature dataset of of shape m x n
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    _y : numpy.ndarray
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        Target list of shape 1 x n
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    _features : list of str
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        List of n feature titles
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    colormap : dict
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        Color map of classes existing in target
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    Returns
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    -------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    None
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# Plot distribution histogram if the features are the same (diagonal of the pair-plot).&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; feature_ind1 == feature_ind2:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tdf = pd.DataFrame(_X[:, [feature_ind1]], columns = [_features[feature_ind1]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tdf[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;target&amp;#39;&lt;/span&gt;] = _y
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; c &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; colormap.keys():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            tdf_filtered = tdf.loc[tdf[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;target&amp;#39;&lt;/span&gt;]==c]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ax[feature_ind1, feature_ind2].hist(tdf_filtered[_features[feature_ind1]], color = colormap[c], bins = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;# other wise plot the pair-wise scatter plot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tdf = pd.DataFrame(_X[:, [feature_ind1, feature_ind2]], columns = [_features[feature_ind1], _features[feature_ind2]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tdf[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;target&amp;#39;&lt;/span&gt;] = _y
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; c &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; colormap.keys():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            tdf_filtered = tdf.loc[tdf[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;target&amp;#39;&lt;/span&gt;]==c]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ax[feature_ind1, feature_ind2].scatter(x = tdf_filtered[_features[feature_ind2]], y = tdf_filtered[_features[feature_ind1]], color=colormap[c])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# Print the feature labels only on the left side of the pair-plot figure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# and bottom side of the pair-plot figure. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# Here avoiding printing the labels for inner axis plots.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; feature_ind1 == &lt;span style=&#34;color:#038&#34;&gt;len&lt;/span&gt;(_features) - &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ax[feature_ind1, feature_ind2].set(xlabel=_features[feature_ind2], ylabel=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; feature_ind2 == &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; feature_ind1 == &lt;span style=&#34;color:#038&#34;&gt;len&lt;/span&gt;(_features) - &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ax[feature_ind1, feature_ind2].set(xlabel=_features[feature_ind2], ylabel=_features[feature_ind1])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ax[feature_ind1, feature_ind2].set(xlabel=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, ylabel=_features[feature_ind1])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;rsquo;s go back to the initial plotting of the grid area and adjust the call of &lt;code&gt;plot_single_pair&lt;/code&gt; function. We can adjust the figure size of the grid area using &lt;code&gt;fig.set_size_inches&lt;/code&gt; depending on the feature count so that we can prepare a well-scaled area.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;colormap={&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;red&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;green&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;blue&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fig.set_size_inches(feature_count * &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;4&lt;/span&gt;, feature_count * &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Iterate through features to plot pairwise.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; j &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        plot_single_pair(axis, i, j, X, y, features, colormap)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plt.show()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In my &lt;code&gt;plot-single_pair&lt;/code&gt; function notice that I also used a &lt;code&gt;colormap&lt;/code&gt; dictionary. This dictionary is used to color the classes (labels) of the dataset to distinguish in a scatter plot or a histogram and makes it look more beautiful.&lt;/p&gt;
&lt;p&gt;Here is my final grid plot function for pair-plot:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;myplotGrid&lt;/span&gt;(X, y, features, colormap={&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;red&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;green&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;blue&amp;#34;&lt;/span&gt;}):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Plots a pair grid of the given features.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    Parameters
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    ----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    X : numpy.ndarray
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        Dataset of shape m x n
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    y : numpy.ndarray
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        Target list of shape 1 x n
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    features : list of str
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;        List of n feature titles
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    Returns
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    -------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    None
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    feature_count = &lt;span style=&#34;color:#038&#34;&gt;len&lt;/span&gt;(features)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# Create a matplot subplot area with the size of [feature count x feature count]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fig, axis = plt.subplots(nrows=feature_count, ncols=feature_count)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# Setting figure size helps to optimize the figure size according to the feature count.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fig.set_size_inches(feature_count * &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;4&lt;/span&gt;, feature_count * &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;# Iterate through features to plot pairwise.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, feature_count):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; j &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#038&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, feature_count):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            plot_single_pair(axis, i, j, X, y, features, colormap)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    plt.show()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id=&#34;pair-plot-a-dataset&#34;&gt;Pair-Plot a Dataset&lt;/h4&gt;
&lt;p&gt;Now let&amp;rsquo;s prepare a dataset and plot using our custom pair-plot implementation. Notice that in my &lt;code&gt;plot_single_pair&lt;/code&gt; function I passed the feature and target values as the &lt;code&gt;numpy.ndarray&lt;/code&gt; type.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get the &lt;code&gt;iris&lt;/code&gt; dataset from the &lt;a href=&#34;https://scikit-learn.org/&#34;&gt;SciKit-Learn&lt;/a&gt; dataset collection and do a quick exploratory data analysis.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;sklearn&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; datasets
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iris = datasets.load_iris()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here are the targets (classes) of the iris dataset:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iris.target_names
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;array([&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;setosa&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;versicolor&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;virginica&amp;#39;&lt;/span&gt;], dtype=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;U10&amp;#39;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And here we can see the feature names and a few lines of the dataset values.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iris_df = pd.DataFrame(iris.data, columns = iris.feature_names)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iris_df.head()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;sepal length (cm)&lt;/td&gt;
    &lt;td&gt;sepal width (cm)&lt;/td&gt;
    &lt;td&gt;petal length (cm)&lt;/td&gt;
    &lt;td&gt;petal width (cm)&lt;/td&gt;
  &lt;tr&gt;
  &lt;tr&gt;
    &lt;td&gt;0&lt;/td&gt;
    &lt;td&gt;5.1&lt;/td&gt;
    &lt;td&gt;3.5&lt;/td&gt;
    &lt;td&gt;1.4&lt;/td&gt;
    &lt;td&gt;0.2&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;4.9&lt;/td&gt;
    &lt;td&gt;3.0&lt;/td&gt;
    &lt;td&gt;1.4&lt;/td&gt;
    &lt;td&gt;0.2&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Since &lt;code&gt;iris.data&lt;/code&gt; and &lt;code&gt;iris.target&lt;/code&gt; are already of type &lt;code&gt;numpy.ndarray&lt;/code&gt; as I implemented my function I don&amp;rsquo;t need any further dataset manipulation here. Now let&amp;rsquo;s finally call &lt;code&gt;myplotGrid&lt;/code&gt; function and render the pair-plot for the iris dataset.&lt;/p&gt;
&lt;p&gt;Note that you can change color per target in &lt;code&gt;colormap&lt;/code&gt; as you wish.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;myplotGrid(iris.data, iris.target, iris.feature_names, colormap={&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;red&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;green&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;blue&amp;#34;&lt;/span&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And here is my custom pair-plot output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2022/04/visualizing-data-with-pairplot-using-matplotlib/pairplot-output.webp&#34; alt=&#34;Pair-Plot output&#34;&gt;&lt;/p&gt;
&lt;p&gt;For further research I encourage you to go and do your exploratory data analysis and take a look at the correlation coefficient analysis to get more insights for pair-wise analysis.&lt;/p&gt;

      </content>
    </entry>
  
</feed>
