<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Doc Zamora's ML & AI]]></title><description><![CDATA[Doctor in Computer Sciences. Researcher Professor.
BJJ & Judo Nerd]]></description><link>https://www.doczamora.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1649796366552/DjZMTdXgh.png</url><title>Doc Zamora&apos;s ML &amp; AI</title><link>https://www.doczamora.com</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 10 Sep 2026 10:41:40 GMT</lastBuildDate><atom:link href="https://www.doczamora.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Phoenix Suns vs Oklahoma City Thunder Matchup Prediction with Logistic Regression]]></title><description><![CDATA[In this post, I will review some stats from a sportsbook and build a logistic regression classifier to estimate the probability of a basketball team winning a match. For our experiment, we will use the following metadata collected at 8 am CST from a ...]]></description><link>https://www.doczamora.com/phoenix-suns-vs-oklahoma-city-thunder-matchup-prediction-with-logistic-regression</link><guid isPermaLink="true">https://www.doczamora.com/phoenix-suns-vs-oklahoma-city-thunder-matchup-prediction-with-logistic-regression</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[nba]]></category><category><![CDATA[betting]]></category><category><![CDATA[sports]]></category><category><![CDATA[sports betting]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[logistic regression]]></category><category><![CDATA[Python]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Thu, 11 Dec 2025 18:46:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/OywyPkrDEvg/upload/77e648cd08293a4cb9c1fdeabc47ca44.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this post, I will review some stats from a sportsbook and build a logistic regression classifier to estimate the probability of a basketball team winning a match. For our experiment, we will use the following metadata collected at 8 am CST from a sportsbook page. We will assume that the data on this page is trustworthy and correct. Also, without any means, I suggest you use this exact code to bet, but the math behind it can help build a stronger classifier if more data is provided. For now, we will create a binary classifier that targets the probability that Phoenix (pho) will win over Oklahoma (okc).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765473877669/929095b3-11cc-4488-8ad7-7a6b113e4d64.png" alt class="image--center mx-auto" /></p>
<p><em>Fig1. Sportsbook Data</em></p>
<p>I have translated this data into a JSON wen can use to load the needed stats for our model. Let's use the following definition to hold out the data:</p>
<h2 id="heading-1-load-the-data-into-a-json-object">1 - Load the data into a JSON Object</h2>
<pre><code class="lang-python">pho_vs_okc = {
  <span class="hljs-string">"matchup"</span>: {
    <span class="hljs-string">"date"</span>: <span class="hljs-string">"2025-12-10"</span>,
    <span class="hljs-string">"time_est"</span>: <span class="hljs-string">"7:30 PM"</span>,
    <span class="hljs-string">"venue"</span>: <span class="hljs-string">"Paycom Center, Oklahoma City, OK, USA"</span>
  },
  <span class="hljs-string">"betting_consensus"</span>: {
    <span class="hljs-string">"spread"</span>: {
      <span class="hljs-string">"phoenix"</span>: <span class="hljs-string">"+14.5"</span>,
      <span class="hljs-string">"oklahoma_city"</span>: <span class="hljs-string">"-14.5"</span>,
      <span class="hljs-string">"consensus"</span>: {
        <span class="hljs-string">"phoenix_pct"</span>: <span class="hljs-number">61</span>,
        <span class="hljs-string">"oklahoma_city_pct"</span>: <span class="hljs-number">39</span>
      }
    },
    <span class="hljs-string">"total"</span>: {
      <span class="hljs-string">"over_pct"</span>: <span class="hljs-number">69</span>,
      <span class="hljs-string">"under_pct"</span>: <span class="hljs-number">31</span>
    },
    <span class="hljs-string">"moneyline"</span>: {
      <span class="hljs-string">"phoenix"</span>: <span class="hljs-string">''</span>,
      <span class="hljs-string">"oklahoma_city"</span>: <span class="hljs-string">''</span>
    }
  },
  <span class="hljs-string">"offensive_team_records"</span>: {
    <span class="hljs-string">"phoenix_suns"</span>: {
      <span class="hljs-string">"points_per_game"</span>: <span class="hljs-number">115.88</span>,
      <span class="hljs-string">"points_against_per_game"</span>: <span class="hljs-number">113.46</span>,
      <span class="hljs-string">"first_half_points"</span>: <span class="hljs-number">57.00</span>,
      <span class="hljs-string">"fg_pct"</span>: <span class="hljs-number">46.74</span>,
      <span class="hljs-string">"ft_pct"</span>: <span class="hljs-number">79.03</span>,
      <span class="hljs-string">"three_pt_pct"</span>: <span class="hljs-number">36.76</span>,
      <span class="hljs-string">"off_rebounds"</span>: <span class="hljs-number">8.96</span>,
      <span class="hljs-string">"fg_made"</span>: <span class="hljs-number">42.17</span>,
      <span class="hljs-string">"ft_made"</span>: <span class="hljs-number">16.96</span>,
      <span class="hljs-string">"three_pt_made"</span>: <span class="hljs-number">14.58</span>
    },
    <span class="hljs-string">"oklahoma_city_thunder"</span>: {
      <span class="hljs-string">"points_per_game"</span>: <span class="hljs-number">123.04</span>,
      <span class="hljs-string">"points_against_per_game"</span>: <span class="hljs-number">106.88</span>,
      <span class="hljs-string">"first_half_points"</span>: <span class="hljs-number">60.38</span>,
      <span class="hljs-string">"fg_pct"</span>: <span class="hljs-number">49.72</span>,
      <span class="hljs-string">"ft_pct"</span>: <span class="hljs-number">82.98</span>,
      <span class="hljs-string">"three_pt_pct"</span>: <span class="hljs-number">37.37</span>,
      <span class="hljs-string">"off_rebounds"</span>: <span class="hljs-number">12.83</span>,
      <span class="hljs-string">"fg_made"</span>: <span class="hljs-number">44.13</span>,
      <span class="hljs-string">"ft_made"</span>: <span class="hljs-number">20.92</span>,
      <span class="hljs-string">"three_pt_made"</span>: <span class="hljs-number">13.88</span>
    }
  },
  <span class="hljs-string">"defensive_opponent_stats"</span>: {
    <span class="hljs-string">"phoenix_suns"</span>: {
      <span class="hljs-string">"opp_points_per_game"</span>: <span class="hljs-number">113.46</span>,
      <span class="hljs-string">"opp_rebounds"</span>: <span class="hljs-number">11.17</span>,
      <span class="hljs-string">"opp_fg_pct"</span>: <span class="hljs-number">47.61</span>,
      <span class="hljs-string">"opp_ft_pct"</span>: <span class="hljs-number">81.00</span>,
      <span class="hljs-string">"opp_three_pt_pct"</span>: <span class="hljs-number">35.87</span>
    },
    <span class="hljs-string">"oklahoma_city_thunder"</span>: {
      <span class="hljs-string">"opp_points_per_game"</span>: <span class="hljs-number">106.88</span>,
      <span class="hljs-string">"opp_rebounds"</span>: <span class="hljs-number">11.04</span>,
      <span class="hljs-string">"opp_fg_pct"</span>: <span class="hljs-number">42.80</span>,
      <span class="hljs-string">"opp_ft_pct"</span>: <span class="hljs-number">76.20</span>,
      <span class="hljs-string">"opp_three_pt_pct"</span>: <span class="hljs-number">36.93</span>
    }
  },
  <span class="hljs-string">"best_available_odds"</span>: {
    <span class="hljs-string">"spread"</span>: {
      <span class="hljs-string">"phoenix"</span>: <span class="hljs-string">"+14.5 -110"</span>,
      <span class="hljs-string">"oklahoma_city"</span>: <span class="hljs-string">"-14.5 -105"</span>
    },
    <span class="hljs-string">"total"</span>: {
      <span class="hljs-string">"over"</span>: <span class="hljs-string">"225.5 -110"</span>,
      <span class="hljs-string">"under"</span>: <span class="hljs-string">"225.5 -110"</span>
    },
    <span class="hljs-string">"moneyline"</span>: {
      <span class="hljs-string">"phoenix"</span>: <span class="hljs-string">"+675"</span>,
      <span class="hljs-string">"oklahoma_city"</span>: <span class="hljs-string">"-1000"</span>
    }
  }
}
</code></pre>
<p>From the json object we will be using a limited set of attributes for our model:</p>
<ul>
<li><p><strong>points_per_game (ppg)</strong>: defines how many points per game the team usually achieves.</p>
</li>
<li><p><strong>points_against_per_game (papg)</strong>: average of points that the opposite team scores. This is a measure of how good their defense is.</p>
</li>
<li><p><strong>fg_pct (fgp)</strong>: Field goal percentage is a term used to estimate how many points a team does at any part of the court (like 1 pts and 3 pts shots combined)</p>
</li>
<li><p><strong>ft_pct (ftp)</strong>: This is similar to fg_pct , but only on free throws.</p>
</li>
<li><p><strong>three_pt_pct (tpp)</strong>: This is the three-point percentage per game.</p>
</li>
<li><p><strong>off_rebounds (ofr)</strong>: Offensive rebounds; this indicates an increase in possession. A team with better possession wins the game?</p>
</li>
<li><p><strong>odds_feature (oft)</strong>: this is a new feature to be created as a difference of the Market probability between Pho and Okc with the vig removed (we will discuss this later in this post).</p>
</li>
<li><p><strong>home_feature (hmf)</strong>: -1 if pho is the away team.</p>
</li>
</ul>
<p>Lets load all the raw data into some team-named variables:</p>
<h2 id="heading-2-load-initial-team-named-variables">2 - Load initial team-named variables</h2>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> math

<span class="hljs-comment"># extract stats</span>

pho = pho_vs_okc[<span class="hljs-string">"offensive_team_records"</span>][<span class="hljs-string">"phoenix_suns"</span>]
okc = pho_vs_okc[<span class="hljs-string">"offensive_team_records"</span>][<span class="hljs-string">"oklahoma_city_thunder"</span>]

pho_def = pho_vs_okc[<span class="hljs-string">"defensive_opponent_stats"</span>][<span class="hljs-string">"phoenix_suns"</span>]
okc_def = pho_vs_okc[<span class="hljs-string">"defensive_opponent_stats"</span>][<span class="hljs-string">"oklahoma_city_thunder"</span>]

odds = pho_vs_okc[<span class="hljs-string">"best_available_odds"</span>][<span class="hljs-string">"moneyline"</span>]
</code></pre>
<h2 id="heading-3-baseline-logistic-regression-model">3 - Baseline Logistic Regression Model</h2>
<p>$$\begin{aligned} \text{Let } &amp; \mathbf{x} = \big( \mathrm{ppg},\ \mathrm{papg},\ \mathrm{fgp},\ \mathrm{ftp},\ \mathrm{tpp},\ \mathrm{ofr},\ \mathrm{oft},\ \mathrm{hmf} \big) \\[6pt] \text{and } &amp; \mathbf{w} = \big( w_{\mathrm{ppg}},\ w_{\mathrm{papg}},\ w_{\mathrm{fgp}},\ w_{\mathrm{ftp}},\ w_{\mathrm{tpp}},\ w_{\mathrm{ofr}},\ w_{\mathrm{oft}},\ w_{\mathrm{hmf}} \big), \ \text{with intercept } w_{0}. \end{aligned}$$</p><p>$$z(\mathbf{x}) = w_{0} + w_{\mathrm{ppg}} \cdot \mathrm{ppg} + w_{\mathrm{papg}} \cdot \mathrm{papg} + w_{\mathrm{fgp}} \cdot \mathrm{fgp} + w_{\mathrm{ftp}} \cdot \mathrm{ftp} + w_{\mathrm{tpp}} \cdot \mathrm{tpp} + w_{\mathrm{ofr}} \cdot \mathrm{ofr} + w_{\mathrm{oft}} \cdot \mathrm{oft} + w_{\mathrm{hmf}} \cdot \mathrm{hmf}.$$</p><p>$$P(\text{Pho wins} \mid \mathbf{x}) = \sigma\!\left( z(\mathbf{x}) \right) = \frac{1}{1 + e^{-z(\mathbf{x})}}.$$</p><p>$$\hat{y} = \begin{cases} 1, &amp; \text{if } P(\text{Pho wins} \mid \mathbf{x}) \ge 0.5, \\[6pt] 0, &amp; \text{otherwise}. \end{cases}$$</p><p>Our model is composed of two main components: a linear relationship between the defined variables in x and their weights in w so that $$z(x) = w_0 + xw$$ where w0 is the intercept, x are our variables from the JSON and w are weights calibrated manually. The second component is the logistic function $$\sigma(z(x))$$ which estimates the probability that PHO wins the game. This means that the probability that OKC wins the game is $$1 - \sigma(z(x))$$.</p>
<h3 id="heading-why-this-might-work">Why this might work?</h3>
<p>Well, this model combines all the selected stats into one single score.</p>
<p>Think of the stats from the JSON — things like field-goal percentage, free-throw percentage, points per game, rebounds, turnovers, and so on. Each of these stats gives us a clue about how strong each team is.</p>
<p>The model takes these numbers, multiplies each one by a weight that tells us how much that stat matters, and adds everything together. The result is a single score:</p>
<ul>
<li>A positive score means stats in favor of PHO, and a negative score means stats in favor of OKC</li>
</ul>
<p>This score doesn’t mean “probability” yet — it’s just a raw measure of which team looks stronger on paper. To convert that raw score into something meaningful, we pass it through a “squashing” function. This function takes any number — whether extremely high or extremely low — and compresses it into a value between 0 and 1.</p>
<p>You can think of it like a dial:</p>
<ul>
<li><p>If the score strongly favors PHO → the dial turns closer to 1.0</p>
</li>
<li><p>If the score is neutral → the dial settles around 0.5</p>
</li>
<li><p>If the score favors OKC → the dial moves closer to 0.0</p>
</li>
</ul>
<p>That final value is: The estimated probability that PHO wins the game, because the logictic function is a one-vs all classifier.</p>
<h2 id="heading-4-convert-moneyline-into-market-probabilities-with-no-vig">4 - Convert Moneyline into market probabilities with no vig</h2>
<p>This algorithm takes betting moneyline odds and turns them into clean probabilities of each team winning. It begins by converting each team’s American moneyline into an “implied probability.” Positive moneylines mean the team is an underdog, so the formula uses 100 divided by the moneyline plus 100. Negative moneylines mean the team is a favorite, so the formula uses the absolute value of the line divided by that value plus 100. This gives a raw probability for each team, but sportsbooks include extra margin called the vig, so these raw probabilities add up to more than one. To correct this, the algorithm adds both raw probabilities to find the total vig, then divides each team’s raw probability by that total. After this division, the probabilities are properly scaled so they add up to one and represent the true implied chance of each team winning without the sportsbook’s built-in margin.</p>
<p>The following code makes the convertion and creates the odds_feature as a difference between the clean probabilities between pho and okc with no vig. This is a feature that establishes what the sportbook believes is going to win, but we will penalize this score with a weight so it does not remove importance of other variables.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Convert moneyline odds to Market-implied probabilities</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">implied_prob_from_moneyline</span>(<span class="hljs-params">ml</span>):</span>
    <span class="hljs-string">"""Convert American moneyline to raw implied probability."""</span>
    <span class="hljs-keyword">if</span> ml &gt; <span class="hljs-number">0</span>:  <span class="hljs-comment"># e.g. +675</span>
        <span class="hljs-keyword">return</span> <span class="hljs-number">100</span> / (ml + <span class="hljs-number">100</span>)
    <span class="hljs-keyword">else</span>:       <span class="hljs-comment"># e.g. -1000</span>
        <span class="hljs-keyword">return</span> abs(ml) / (abs(ml) + <span class="hljs-number">100</span>)

pho_raw = implied_prob_from_moneyline(int(odds[<span class="hljs-string">"phoenix"</span>]))
okc_raw = implied_prob_from_moneyline(int(odds[<span class="hljs-string">"oklahoma_city"</span>]))

<span class="hljs-comment"># Normalize (remove vig)</span>
vig = pho_raw + okc_raw
pho_prob = pho_raw / vig
okc_prob = okc_raw / vig

<span class="hljs-comment"># Create the odds feature for the model</span>
<span class="hljs-comment"># Is negative if OKC is favored Is positive if Phoenix is favored</span>
odds_feature = pho_prob - okc_prob
</code></pre>
<h2 id="heading-5-load-all-variables-x-x-delta">5 - Load all variables X (X-Delta)</h2>
<p>Now we load our features as the difference between all selected stats for each team this is the first step toward creating the feature vector X</p>
<pre><code class="lang-python">delta_points = pho[<span class="hljs-string">"points_per_game"</span>] - okc[<span class="hljs-string">"points_per_game"</span>]
delta_points_against = pho[<span class="hljs-string">"points_against_per_game"</span>] - okc[<span class="hljs-string">"points_against_per_game"</span>]
delta_fg_pct = pho[<span class="hljs-string">"fg_pct"</span>] - okc[<span class="hljs-string">"fg_pct"</span>]
delta_ft_pct = pho[<span class="hljs-string">"ft_pct"</span>] - okc[<span class="hljs-string">"ft_pct"</span>]
delta_3pt_pct = pho[<span class="hljs-string">"three_pt_pct"</span>] - okc[<span class="hljs-string">"three_pt_pct"</span>]
delta_off_reb = pho[<span class="hljs-string">"off_rebounds"</span>] - okc[<span class="hljs-string">"off_rebounds"</span>]
home_feature = <span class="hljs-number">-1</span>  <span class="hljs-comment"># Phoenix is the away team</span>
</code></pre>
<h2 id="heading-6-define-some-cherry-picked-weights-w-for-each-value-of-xi">6 - Define some cherry-picked weights W for each value of Xi</h2>
<p>Its important to mention that logistic regression is an algorithm that when exposed to multiple rows of data it can automatically estimate the values of W as an optimization problem. In this case we only have two sets of data from the sportsbook, one line of stats for PHO and one for OKC, so optimization is this case is not an option. This means that we need to place some values for each value of w so that they makes sense. This process is usually done by an expert in the NBA, so because I am not, I used some LLM to help me estimate these parameters. This is the resultant expression:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Define the model weights (hand-built / interpretable) </span>

weights = {
    <span class="hljs-string">"intercept"</span>: <span class="hljs-number">0.0</span>,
    <span class="hljs-string">"points_per_game"</span>: <span class="hljs-number">0.12</span>, <span class="hljs-comment"># weight defined to control best predictor (points)</span>
    <span class="hljs-string">"points_against_per_game"</span>: <span class="hljs-number">-0.10</span>, <span class="hljs-comment"># how good team defense is</span>
    <span class="hljs-string">"fg_pct"</span>: <span class="hljs-number">0.08</span>, <span class="hljs-comment"># field goald percentage / almost as important as ppg</span>
    <span class="hljs-string">"ft_pct"</span>: <span class="hljs-number">0.04</span>, <span class="hljs-comment"># free throw percentage</span>
    <span class="hljs-string">"three_pt_pct"</span>: <span class="hljs-number">0.03</span>, <span class="hljs-comment"># three points percentage</span>
    <span class="hljs-string">"off_rebounds"</span>: <span class="hljs-number">0.06</span>, <span class="hljs-comment"># offensive rebounds (increase posession)</span>
    <span class="hljs-string">"odds_feature"</span>: <span class="hljs-number">1.50</span>, <span class="hljs-comment"># delta between pho_prob - okc_prob with no vig</span>
    <span class="hljs-string">"home_feature"</span>: <span class="hljs-number">-0.60</span> <span class="hljs-comment"># tells if team A (in this case Pho) is home or not</span>
}
</code></pre>
<p>In a logistic regression model, each weight tells you how strongly a feature pushes the prediction toward a win or a loss. The farther a weight is from zero, the more influence that feature has on the final probability.</p>
<p>When a weight is close to 1, it means that increasing that feature pushes the model strongly toward predicting a higher probability of winning. A positive weight acts like a “boost.” Every time that feature increases by one unit, the model becomes noticeably more confident that the team will win. A weight near 1 means the model treats that feature as very important in signaling success.</p>
<p>When a weight is close to –1, it means that increasing that feature pushes the model strongly toward predicting a lower probability of winning. A negative weight acts like a “penalty.” As that feature increases, the model becomes more confident the team will lose. A weight near –1 means the model believes that feature strongly signals weakness.</p>
<p>Weights near zero barely affect the prediction at all, because they don’t push the probability up or down in a meaningful way.</p>
<p>So in simple terms, values near 1 are strong positive influencers toward winning, values near –1 are strong negative influencers toward losing, and values near zero don’t matter much to the model.</p>
<h2 id="heading-7-mix-all-ingredients-and-get-the-final-probability">7 - Mix all ingredients and get the Final Probability</h2>
<pre><code class="lang-python"><span class="hljs-comment"># Logistic function to convert score to win probability</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">logistic</span>(<span class="hljs-params">x</span>):</span>
    <span class="hljs-keyword">return</span> <span class="hljs-number">1</span> / (<span class="hljs-number">1</span> + math.exp(-x))

pho_win_prob = logistic(score)
okc_win_prob = <span class="hljs-number">1</span> - pho_win_prob
</code></pre>
<p>This simple logictic function then estimates the probabilities that either one or the other team will win.</p>
<ul>
<li><p>pho_win_prob: 6.34%</p>
</li>
<li><p>okc_win_prob: 93.65%</p>
</li>
</ul>
<p>So the model concluded that based out on the defined weights and the selected stats, OKC is the clear winner. But, did OKC won? <strong>Yes it did!</strong> look at the game results from CBS Sports</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765478438250/53f32539-d01d-4f7b-b98a-ec6e5b3195fe.png" alt class="image--center mx-auto" /></p>
<p>Oklahoma Thunder was the winner as predicted by the model.</p>
<h2 id="heading-8-was-the-model-lucky">8 - Was the model lucky?</h2>
<p>We dont know for sure. There is no certainty this model works unless we keep executing this code on more games and see if in the long run, we are always right, or wrong.</p>
]]></content:encoded></item><item><title><![CDATA[Checkmate: How Chess Shaped Culture, Science, and Artificial Intelligence]]></title><description><![CDATA[Chess is a board game with characteristics that are quite simple to understand. Two players move a set of 16 pieces on an 8 x 8 board according to a set of movement rules: the pawn moves only forward and captures diagonally; the knight moves in an “L...]]></description><link>https://www.doczamora.com/checkmate-how-chess-shaped-culture-science-and-artificial-intelligence</link><guid isPermaLink="true">https://www.doczamora.com/checkmate-how-chess-shaped-culture-science-and-artificial-intelligence</guid><category><![CDATA[deep blue]]></category><category><![CDATA[AI]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[history]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[revolution]]></category><category><![CDATA[fear]]></category><category><![CDATA[chess]]></category><category><![CDATA[IBM]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Fri, 26 Sep 2025 05:09:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Iq9SaJezkOE/upload/0558b522ca3862a23d88304d4a165d24.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Chess is a board game with characteristics that are quite simple to understand. Two players move a set of 16 pieces on an 8 x 8 board according to a set of movement rules: the pawn moves only forward and captures diagonally; the knight moves in an “L” shape; the bishop moves diagonally; the rook moves horizontally (rows) or vertically (columns); the queen, which is the most powerful piece, can move in any direction; and the king, compared to the queen, can move in any direction but only one square. Each player can move one piece at a time, until the opposing king is cornered with no possible moves left, thus ending the game with “checkmate.” This is the premise that any beginner player uses to play a casual game with a friend without major complexity.</p>
<p>Behind the game of chess lies an interesting and extensive history dating approximately between the 10th and 11th centuries, when the game entered Europe as an evolution of <em>chaturanga</em> from the Gupta Empire (India, 6th century). During the Middle Ages and the Renaissance, reforms were made to the game, introducing the queen, the bishop, and castling. The 19th century marked the beginning of competitive chess, with the first international tournament held in London, where Adolf Anderssen was crowned champion. The 20th century served to professionalize chess; organizations such as FIDE (the International Chess Federation) were founded, and the concept of the “Grandmaster” was established.</p>
<p>An International Grandmaster (GM) is a title awarded by FIDE to players who demonstrate passion and achieve at least 2600 Elo points, are active as international competitors participating in tournaments and official matches against other high-profile players (including other GMs), and are capable of playing multiple games in tournaments.</p>
<p>The GM title is more than just an award; it has also been used as a symbol of intellectual superiority (and still is), especially during the Cold War, when the USSR used chess as a tool of discord to reinforce the country’s image, mainly against the United States and the rest of the world.</p>
<p>Although the rules of chess, as explained earlier, are simple, the implications of moves and strategies are highly complex. Numerically speaking, according to mathematician Claude Shannon, a chess game is estimated to have 10¹²⁰ possible games—more than the number of atoms in the observable universe. The sheer number of possibilities outlines a horizon of unimaginable complexities for humans, who cannot possibly know or understand all the alternatives. This has led to hundreds of books on openings and strategies developed throughout the history of chess.</p>
<p>Thus, the GM is, among all players in the world, the one with the greatest knowledge and practice—capable of challenging even the most difficult opponents in a fierce battle for victory. Historically, there have been great masters who left their mark, such as Wilhelm Steinitz, the first official world champion (1886); Emanuel Lasker, who held the title for 27 years (1894–1921); and the Cuban José Raúl Capablanca (1888–1942), whose magic on the board dazzled the world with his wonderful style.</p>
<p>During the 20th century, chess hegemony belonged to the Soviet Union, where numerous chess stars emerged, including Mikhail Tal (Latvia), world champion in 1960 and 1961; Anatoly Karpov, world champion from 1975 to 1985 and again from 1993 to 1999; and the greatest representative of Russian chess (and according to some experts, the world), Garry Kasparov, world champion from 1985 to 2000.</p>
<p>International chess also had its luminaries, such as Bobby Fischer (U.S.), world champion from 1972 to 1975, and Nigel Short (England), who challenged for the world title in 1993, losing to Kasparov.</p>
<p>The world of technology, especially video games, was not left behind and began developing programs capable of playing chess. In 1950, Claude Shannon published a paper on the possibility of programming a computer to play chess. In 1951, Alan Turing (the father of Artificial Intelligence) designed the first algorithm to play chess before it could even be programmed into a computer. In 1957, IBM developed the IBM 704 Chess Program, one of the first executable programs capable of playing chess, and in 1967, Mac Hack VI from MIT became the first program to defeat a human player in an official tournament.</p>
<p>From there, chess programs grew more complex and capable, but they were never strong enough to defeat a GM. The sheer number of moves combined with the processing and memory limitations of computers at the time prevented the development of algorithms able to analyze many moves ahead. One approach used was <em>deep search</em>, which considered multiple alternatives three to five moves deep for all available pieces. This caused slow responses, as the computer took too long to determine the next move that maximized winning chances. Lack of positional intuition, limited opening databases, poor evaluation of complex pawn structures, static piece value assessments, and almost no dynamic compensation (limited ability to sacrifice pieces for greater gains) were typical shortcomings of programs of the era. Intermediate and advanced players knew this, which created predictability in the computer’s moves.</p>
<p>Gradually, chess programs improved these limitations, but overall, they remained machines without real understanding of the problem.</p>
<p>In 1989, IBM invested in developing a machine capable of executing millions of moves per second, something unique for the time, with help from Carnegie Mellon University students. The first version was ready in 1995 and was officially presented as the supercomputer “Deep Blue.” Its VLSI processors were specifically created for chess, capable of processing and calculating many positions quickly. Minimax algorithms were used to reduce the number of positions to explore, and chess heuristics were designed with the help of grandmasters. In addition, the algorithm was reinforced with a database of thousands of openings and strategies, allowing Deep Blue to become the final frontier of computational chess.</p>
<p>In 1997, IBM made a bold move and challenged grandmaster Garry Kasparov to a set of chess games. The conditions set by IBM were: six classical games, forty moves in two hours, and then an additional hour for twenty more moves. The games were played under FIDE rules, and Kasparov could make claims or moves as in normal play. However, Kasparov had only limited access to Deep Blue; he could not touch or modify it. IBM controlled the input of moves into the computer exclusively.</p>
<p>The event took place from May 3 to 11, 1997, at the Equitable Center in New York City, where Garry Kasparov lost the series 3½–2½ in favor of Deep Blue. This was the first time in history that a GM lost to a computer.</p>
<p>After the event, Kasparov reacted explosively, pointing out that the moves—especially in the second game—were too creative to have come from a machine. This sparked a heated debate over whether IBM had other GMs manipulating Deep Blue’s moves. Adding to the mystery, IBM denied Kasparov a rematch, cementing this milestone in the company’s (and the world’s) history as the moment when Deep Blue defeated the grandmaster of grandmasters.</p>
<p>IBM’s supercomputer was perhaps the foundation of more advanced, general-purpose computational capabilities, reigniting investment and research into machines not only capable of solving specific problems like chess but also of going beyond games with finite rules and domains, to perhaps, someday, compete intellectually with humans.</p>
<p>The miniaturization of computers, the drop in memory costs, instant access to massive data storage, the exponential growth of processing power since the 1980s, and the relentless globalization of scientific research have created fertile ground for new technologies. In the first quarter of the 21st century alone, more progress has been made in developing intelligent technologies than in the hundred years before 2000.</p>
<p>In the blink of an eye, today we have self-driving cars, vacuum cleaners that sweep the house and return to their charging bases with minimal human intervention, smartphones capable of accessing all human knowledge and answering questions instantly in real time. Today, machines generate music, art, and poetry; process medical diagnoses; help scientists discover new proteins in seconds; and are used to develop medicines and disease treatments. All this happened in a breath and has generated many reactions among people—some filled with awe, others with fear at the evolution of technology, which they barely understand.</p>
<p>The fear of the population toward new technologies and advancements is something humanity has experienced before, from the invention of the steam engine by James Watt in 1769, to electricity and the light bulb by Edison and Swan in 1879, the development of computers with ENIAC in 1945, and the rise of intelligent machines and big data around 2010.</p>
<p>Are you scared?</p>
]]></content:encoded></item><item><title><![CDATA[Tensor vs Matrix: an example with computer vision]]></title><description><![CDATA[Today's post will try to answer the question: What is the difference between a tensor and a matrix?
The Matrix
If you have a basic understanding of algebra, you should already know that a Matrix is an object with a rectangular shape of values, such a...]]></description><link>https://www.doczamora.com/tensor-vs-matrix-an-example-with-computer-vision</link><guid isPermaLink="true">https://www.doczamora.com/tensor-vs-matrix-an-example-with-computer-vision</guid><category><![CDATA[Computer Vision]]></category><category><![CDATA[Computer Science]]></category><category><![CDATA[Algebra]]></category><category><![CDATA[TensorFlow]]></category><category><![CDATA[Python]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[#codenewbies]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Mon, 09 Sep 2024 00:25:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/MOODfC5oKIk/upload/9a6ba8f9aaf0a6d25389ddeee6a85379.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today's post will try to answer the question: <em>What is the difference between a tensor and a matrix?</em></p>
<h2 id="heading-the-matrix">The Matrix</h2>
<p>If you have a basic understanding of algebra, you should already know that a Matrix is an object with a rectangular shape of values, such as rows and columns, to describe something. For example, I can create a matrix of 5 rows and 3 columns to represent movie preferences for five different people. In the following example, we will use a table representing a matrix <em>M</em> for movies. One means the person likes the movie, and zero otherwise.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Kung-Fu Panda</td><td>Terminator 2</td><td>White Chicks</td></tr>
</thead>
<tbody>
<tr>
<td>Juan</td><td>1</td><td>1</td><td>0</td></tr>
<tr>
<td>Peter</td><td>1</td><td>0</td><td>1</td></tr>
<tr>
<td>Stacy</td><td>0</td><td>1</td><td>0</td></tr>
<tr>
<td>Ann</td><td>1</td><td>1</td><td>1</td></tr>
<tr>
<td>Greg</td><td>1</td><td>1</td><td>0</td></tr>
</tbody>
</table>
</div><p>Mathematically speaking, we can represent this matrix like:</p>
<p>$$M = \begin{pmatrix} a_{11} &amp; a_{12} &amp; a_{13} \\ a_{21} &amp; a_{22} &amp; a_{23} \\ a_{31} &amp; a_{32} &amp; a_{33} \\ a_{41} &amp; a_{42} &amp; a_{43} \\ a_{51} &amp; a_{52} &amp; a_{53} \end{pmatrix}$$</p><p>Where ( a_11 ) is the first cell where Juan likes Kung-fu panda. If we replace each cell with the table values, our matrix will look like this:</p>
<p>$$A = \begin{pmatrix} 1 &amp; 1 &amp; 0 \\ 1 &amp; 0 &amp; 1 \\ 0 &amp; 1 &amp; 0 \\ 1 &amp; 1 &amp; 1 \\ 1 &amp; 1 &amp; 0 \end{pmatrix}$$</p><p>With this, we get into a more concrete definition of a matrix: a rectangular array of numbers, symbols, or expressions arranged in rows and columns. It's an object of 1 or 2 dimensions that describes something.</p>
<h2 id="heading-the-tensor">The Tensor</h2>
<p>It is like a matrix but with high dimensionality. Yes, we can now build a 3D or 4D matrix! The best way to explain a matrix is by describing an image in its three channels: Red, Green, and Blue.</p>
<p>Let's assume we have an image that is full color and is just 5 x 5 pixels in size. An image is explained as three different matrixes altogether. The first one describes the image as a set of pixels in Red color, the second one as a set of pixels in Green, and the third one as a set of pixels in Blue. The combination of all these matrixes is the final image.</p>
<p>A tensor is then an object that can hold three matrixes of size 5 x 5 pixels. We usually describe this tensor a T with the shape: T(5,5,3), where the 3 represents each color channel.</p>
<p>The mathematical description of this tensor looks like this:</p>
<p>$$\mathcal{T} = \begin{pmatrix} \text{Red Channel} &amp; \begin{pmatrix} r_{11} &amp; r_{12} &amp; r_{13} &amp; r_{14} &amp; r_{15} \\ r_{21} &amp; r_{22} &amp; r_{23} &amp; r_{24} &amp; r_{25} \\ r_{31} &amp; r_{32} &amp; r_{33} &amp; r_{34} &amp; r_{35} \\ r_{41} &amp; r_{42} &amp; r_{43} &amp; r_{44} &amp; r_{45} \\ r_{51} &amp; r_{52} &amp; r_{53} &amp; r_{54} &amp; r_{55} \end{pmatrix}, \\ \text{Green Channel} &amp; \begin{pmatrix} g_{11} &amp; g_{12} &amp; g_{13} &amp; g_{14} &amp; g_{15} \\ g_{21} &amp; g_{22} &amp; g_{23} &amp; g_{24} &amp; g_{25} \\ g_{31} &amp; g_{32} &amp; g_{33} &amp; g_{34} &amp; g_{35} \\ g_{41} &amp; g_{42} &amp; g_{43} &amp; g_{44} &amp; g_{45} \\ g_{51} &amp; g_{52} &amp; g_{53} &amp; g_{54} &amp; g_{55} \end{pmatrix}, \\ \text{Blue Channel} &amp; \begin{pmatrix} b_{11} &amp; b_{12} &amp; b_{13} &amp; b_{14} &amp; b_{15} \\ b_{21} &amp; b_{22} &amp; b_{23} &amp; b_{24} &amp; b_{25} \\ b_{31} &amp; b_{32} &amp; b_{33} &amp; b_{34} &amp; b_{35} \\ b_{41} &amp; b_{42} &amp; b_{43} &amp; b_{44} &amp; b_{45} \\ b_{51} &amp; b_{52} &amp; b_{53} &amp; b_{54} &amp; b_{55} \end{pmatrix} \end{pmatrix}$$</p><p>The T tensor is the 5x5x3 object. We can add another dimension called Alpha for opacity if we like. You can keep adding as many dimensions as your heart desires.</p>
<h2 id="heading-sample-tensor-in-python-with-no-library">Sample Tensor in Python with No Library</h2>
<p>The following code creates a custom-made Tensor to display an image for the three color matrixes. (No Pytorch or Tensorflow)</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Create a 5x5 matrix for the red channel</span>
red_channel = np.array([
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
])

<span class="hljs-comment"># Create a 5x5 matrix for the green channel</span>
green_channel = np.array([
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
])

<span class="hljs-comment"># Create a 5x5 matrix for the blue channel</span>
blue_channel = np.array([
    [<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>],
    [<span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>],
    [<span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>],
    [<span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>],
    [<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>]
])

<span class="hljs-comment"># Stack the color channels to create a 5x5x3 tensor</span>
image_tensor = np.stack([red_channel, green_channel, blue_channel], axis=<span class="hljs-number">-1</span>)

<span class="hljs-comment"># Plot the image</span>
plt.imshow(image_tensor)
plt.title(<span class="hljs-string">'5x5 Image Pattern'</span>)
plt.axis(<span class="hljs-string">'off'</span>)  <span class="hljs-comment"># Hide axes</span>
plt.show()
</code></pre>
<p>The code above generated the following image:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725839998340/37fe6c2d-bd4f-4420-9096-73e29071f017.png" alt class="image--center mx-auto" /></p>
<p>This shows how tensor T with pixels on and off for each channel was able to represent something in the image. The matplotlib uses all channels stacked together (as a sequence) to display the image.</p>
<h2 id="heading-new-tensor-for-alpha-channel">New Tensor for Alpha Channel</h2>
<p>We will slightly change the code to make the Blue tensor all blue, not just the pixels from the boundaries. This adds a new tensor, Alpha, who is responsible for showing opacity.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Create the 5x5 matrices for each color channel</span>
red_channel = np.array([
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
])

green_channel = np.array([
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
])

<span class="hljs-comment"># Create a 5x5 matrix for the blue channel with all pixels set to blue (255)</span>
blue_channel = np.full((<span class="hljs-number">5</span>, <span class="hljs-number">5</span>), <span class="hljs-number">255</span>, dtype=np.uint8)

<span class="hljs-comment"># Create a 5x5 matrix for the alpha channel</span>
alpha_channel = np.array([
    [<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>],
    [<span class="hljs-number">255</span>, <span class="hljs-number">128</span>, <span class="hljs-number">128</span>, <span class="hljs-number">128</span>, <span class="hljs-number">255</span>],
    [<span class="hljs-number">255</span>, <span class="hljs-number">128</span>, <span class="hljs-number">128</span>, <span class="hljs-number">128</span>, <span class="hljs-number">255</span>],
    [<span class="hljs-number">255</span>, <span class="hljs-number">128</span>, <span class="hljs-number">128</span>, <span class="hljs-number">128</span>, <span class="hljs-number">255</span>],
    [<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>]
])

<span class="hljs-comment"># Normalize alpha values to range [0, 1]</span>
alpha_normalized = alpha_channel / <span class="hljs-number">255.0</span>

<span class="hljs-comment"># Blend the red channel with 50% opacity</span>
red_blended = red_channel * alpha_normalized

<span class="hljs-comment"># Stack the color channels to create a 5x5x3 tensor</span>
image_tensor = np.stack([red_blended, green_channel, blue_channel], axis=<span class="hljs-number">-1</span>)

<span class="hljs-comment"># Plot the image</span>
plt.imshow(image_tensor)
plt.title(<span class="hljs-string">'5x5 Image with Blue Channel Fully Set to 255'</span>)
plt.axis(<span class="hljs-string">'off'</span>)  <span class="hljs-comment"># Hide axes</span>
plt.show()
</code></pre>
<p>This code will display the color red at 50% opacity. Please note that the opacity tensor is used as a filter; this means it is multiplied by one or more channels to provide the desired effect.</p>
<p>Remember that there is a blue and green layer, so the colors with 50% opacity will be shown as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725840644769/e953af3b-ac4f-4d8e-b861-3f6123578b55.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-summary">Summary</h1>
<p>Tensors are multi-dimensional arrays that can hold much more information than a simple 1D or 2D matrix. Tensors are used today in computer vision, deep learning, image and video representations, natural language processing, robotics, control systems, reinforcement learning, and recommender systems, among many others!</p>
<p>We usually need to do many calculations using tensors. Some libraries can help speed up the process and provide many functionalities, such as Tensorflow and PyTorch.</p>
<p>If you want to see tensors used with TensorFlow to build a movie recommender system, please review my post on <a target="_blank" href="https://www.doczamora.com/content-based-recommender-system-for-movies-with-tensorflow">Movie Recommendations</a>.</p>
]]></content:encoded></item><item><title><![CDATA[The Bias-Variance Trade-off Explained]]></title><description><![CDATA[What's Bias?
In machine learning, Bias refers to the difference between the predicted and expected values. Bias can also be defined as the error that is introduced by approximating a real-life problem. In supervised learning, we usually have a traini...]]></description><link>https://www.doczamora.com/the-bias-variance-trade-off-explained</link><guid isPermaLink="true">https://www.doczamora.com/the-bias-variance-trade-off-explained</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[bias variance]]></category><category><![CDATA[blog]]></category><category><![CDATA[Concepts]]></category><category><![CDATA[Deep Learning]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Wed, 26 Jun 2024 06:06:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/DX3_dXuHVl8/upload/3ca7d9fde1a74312db4cae2a22d8bf4d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-whats-bias">What's Bias?</h3>
<p>In machine learning, Bias refers to the difference between the predicted and expected values. Bias can also be defined as the error that is introduced by approximating a real-life problem. In supervised learning, we usually have a training and a validation set. The training set produces a model later used to predict the validation set. For example, a regression model that predicts the probability of getting into a pre-diabetic state based on glucose levels will learn the relationship between the levels and the labeled probability from the training set. The validation set contains real-life assessments of patients' glucose and their diagnosis as a probability. We say a model has low bias if the predicted probabilities are close to those in the validation set. Our objective while producing ML models is to reduce Bias as much as possible.</p>
<h3 id="heading-whats-variance">What's Variance?</h3>
<p>Variance measures how much a prediction changes if we change the dataset. In other words, variance targets how strong our model is in making good predictions, given that we are using different datasets. Let's use the Glucose example. Suppose we collect data from San Jose, California, for our training set and train the model. Can the model predict successfully if we use a validation set from Albuquerque, New Mexico? The answer is probably not, and the reason is that both places have different diets that contain more or less sugar. We need to produce ML models that have low variance. This means that regardless of where we are testing the model (people from New Mexico, Ohio, New York, or California), the model should be able to withstand the changing assumptions (and dietary conditions) of the populations under evaluation.</p>
<h3 id="heading-how-are-they-related">How are They Related?</h3>
<p>Bias and Variance are independent, but they affect the models simultaneously. A low-bias model produces good predictions. A high bias produces predictions that are far away from the expected values. A model with low variance is able to produce good predictions regardless of the incoming data, and a high variance model will cause inconsistencies in the results no matter where we test out the model. <em>We always aim for low bias and low variance.</em></p>
<p><img src="https://www.endtoend.ai/assets/blog/misc/bias-variance-tradeoff-in-reinforcement-learning/front.png" alt="Bias-variance Tradeoff in Reinforcement Learning | endtoend.ai" /></p>
<h3 id="heading-why-is-this-important-in-machine-learning">Why is this important in Machine Learning?</h3>
<p>The bias-variance trade-off describes the balance we should consider when building machine learning models. Bias manages the model error (predictive), and the variance measures model sensitivity to changing data. This tells us something very important about this trade-off and how to deal with it: to manage Bias, we look at the model characteristics (features used and their quality, types of machine learning algorithms, hyperparameter tuning, etc.), and with Variance, we look for the quality of the data, sampling techniques, dimensional reduction, regularization, trustability of the data sources and data generalization. Let's look at each one separately.</p>
<h3 id="heading-what-to-do-to-reduce-bias">What to do to reduce Bias?</h3>
<p>Reducing model bias is crucial for improving the performance of a machine-learning model. Here are the main techniques to reduce model bias:</p>
<ol>
<li><p><strong>Increase Model Complexity</strong>:</p>
<ul>
<li><p>Use more complex algorithms or models (e.g., switching from linear regression to polynomial regression or from a simple decision tree to a random forest).</p>
</li>
<li><p>Increase the number of features or use feature engineering to create more informative features.</p>
</li>
</ul>
</li>
<li><p><strong>Ensemble Methods</strong>:</p>
<ul>
<li><p>Use ensemble techniques like bagging, boosting, or stacking to combine the predictions of multiple models, which can reduce bias.</p>
</li>
<li><p>Examples include Random Forests (bagging) and Gradient Boosting Machines (boosting).</p>
</li>
</ul>
</li>
<li><p><strong>Use Better Features</strong>:</p>
<ul>
<li><p>Improve feature selection and engineering to include more relevant features that capture the underlying patterns in the data.</p>
</li>
<li><p>Use domain knowledge to create new features that might better explain the variance in the target variable.</p>
</li>
</ul>
</li>
<li><p><strong>Reduce Underfitting</strong>:</p>
<ul>
<li><p>Ensure that the model is not too simple for the data. This might involve using more sophisticated algorithms or adding more parameters.</p>
</li>
<li><p>Avoid overly aggressive regularization, which can excessively penalize the complexity of the model, leading to high bias.</p>
</li>
</ul>
</li>
<li><p><strong>Data Augmentation</strong>:</p>
<ul>
<li>For problems like image recognition, data augmentation techniques (e.g., rotations, translations, flips) can create additional training examples, helping the model learn better.</li>
</ul>
</li>
<li><p><strong>Increase Training Data</strong>:</p>
<ul>
<li><p>Collect more or better-quality data to provide the model with more information about the underlying patterns.</p>
</li>
<li><p>More data can help the model generalize better, reducing bias.</p>
</li>
</ul>
</li>
<li><p><strong>Hyperparameter Tuning</strong>:</p>
<ul>
<li><p>Carefully tune hyperparameters to find the best settings that reduce bias without introducing too much variance.</p>
</li>
<li><p>Techniques like grid search, random search, or Bayesian optimization can be used for effective hyperparameter tuning.</p>
</li>
</ul>
</li>
<li><p><strong>Addressing Data Imbalance</strong>:</p>
<ul>
<li>For classification problems, ensure that the classes are balanced. Techniques like oversampling, undersampling, or synthetic data generation (e.g., SMOTE) can help.</li>
</ul>
</li>
<li><p><strong>Transfer Learning</strong>:</p>
<ul>
<li>Use pre-trained models (especially in deep learning) that have been trained on large datasets. Fine-tuning these models on your specific dataset can help reduce bias.</li>
</ul>
</li>
<li><p><strong>Regularization with Care</strong>:</p>
<ul>
<li>Use regularization techniques like L1 or L2 regularization judiciously. While they help in reducing variance, overly strong regularization can increase bias.</li>
</ul>
</li>
</ol>
<p>By applying these techniques, you can reduce model bias, helping the model to capture the underlying patterns in the data more accurately, which leads to better performance and generalization.</p>
<h3 id="heading-what-to-do-to-reduce-variance">What to do to reduce Variance?</h3>
<p>Reducing model variance is crucial for improving the generalizability of a machine-learning model. Here are the main techniques to reduce variance:</p>
<ol>
<li><p><strong>Simplify the Model</strong>:</p>
<ul>
<li><p>Use simpler models with fewer parameters, such as linear regression, instead of polynomial regression or smaller decision trees.</p>
</li>
<li><p>This helps avoid overfitting by reducing the model’s capacity to fit the noise in the training data.</p>
</li>
</ul>
</li>
<li><p><strong>Regularization</strong>:</p>
<ul>
<li><p>Regularization techniques like L1 (Lasso) or L2 (Ridge) regularization should be applied to penalize the complexity of the model.</p>
</li>
<li><p>Regularization discourages the model from fitting the noise in the training data, leading to a more generalizable model.</p>
</li>
</ul>
</li>
<li><p><strong>Ensemble Methods</strong>:</p>
<ul>
<li><p>Ensemble techniques, such as bagging (e.g., Random Forests), can reduce variance by averaging the predictions of multiple models.</p>
</li>
<li><p>Boosting methods (e.g., Gradient-Boosting Machines) also help, but they primarily focus on reducing bias and can still improve generalization.</p>
</li>
</ul>
</li>
<li><p><strong>Cross-Validation</strong>:</p>
<ul>
<li><p>Use cross-validation techniques to ensure that the model’s performance is consistent across different subsets of the data.</p>
</li>
<li><p>K-fold cross-validation helps understand how the model generalizes to unseen data and reduces the risk of overfitting.</p>
</li>
</ul>
</li>
<li><p><strong>Increase Training Data</strong>:</p>
<ul>
<li><p>Collect more training data to provide the model with a better representation of the underlying distribution.</p>
</li>
<li><p>More data helps in reducing the model’s sensitivity to specific training examples.</p>
</li>
</ul>
</li>
<li><p><strong>Data Augmentation</strong>:</p>
<ul>
<li><p>For tasks like image recognition, data augmentation techniques (e.g., rotations, translations, and flips) can artificially increase the size of the training dataset.</p>
</li>
<li><p>This helps the model to learn invariant features and reduces overfitting.</p>
</li>
</ul>
</li>
<li><p><strong>Pruning (for Decision Trees)</strong>:</p>
<ul>
<li><p>Apply pruning techniques to decision trees to remove unimportant branches that do not generalize well to new data.</p>
</li>
<li><p>Pruning helps simplify the model and reduce variance.</p>
</li>
</ul>
</li>
<li><p><strong>Early Stopping (for Neural Networks)</strong>:</p>
<ul>
<li><p>Use early stopping during training to halt the training process when performance on a validation set starts to degrade.</p>
</li>
<li><p>This prevents the model from overfitting to the training data.</p>
</li>
</ul>
</li>
<li><p><strong>Dropout (for Neural Networks)</strong>:</p>
<ul>
<li><p>Use dropout regularization in neural networks, where randomly selected neurons are ignored during training.</p>
</li>
<li><p>This prevents the network from becoming overly reliant on specific neurons and helps in reducing overfitting.</p>
</li>
</ul>
</li>
<li><p><strong>Bagging (Bootstrap Aggregating)</strong>:</p>
<ul>
<li><p>Train multiple models on different subsets of the data created through bootstrapping and aggregate their predictions.</p>
</li>
<li><p>This helps in reducing the model’s variance by averaging out the noise.</p>
</li>
</ul>
</li>
<li><p><strong>Parameter Tuning</strong>:</p>
<ul>
<li><p>Carefully tune hyperparameters using grid, random, or Bayesian optimization techniques.</p>
</li>
<li><p>Proper hyperparameter tuning can help find the optimal balance between bias and variance.</p>
</li>
</ul>
</li>
</ol>
<p>By applying these techniques, you can reduce your model's variance, which leads to better generalization and improved performance on unseen data.</p>
<h3 id="heading-where-is-overfitting-in-the-trade-off">Where is overfitting in the trade-off?</h3>
<p>Overfitting is a phenomenon in machine learning where a model learns the details and noise in the training data to such an extent that it negatively impacts the model’s performance on new data. In the context of the bias-variance trade-off, overfitting is primarily associated with high variance.</p>
<p>So, suppose the model has high variance, and the algorithm used in the training set is learning from all that noise. In that case, you will find that the accuracy will drop significantly when predicting the validation set.</p>
<h3 id="heading-solutions-to-overfitting">Solutions to Overfitting</h3>
<p>To mitigate overfitting and find a better balance in the bias-variance trade-off, the following techniques can be used:</p>
<ol>
<li><p><strong>Simplify the Model</strong>: Use a simpler model with fewer parameters.</p>
</li>
<li><p><strong>Regularization</strong>: Add a regularization term to the loss function to penalize complex models (e.g., L1 or L2 regularization).</p>
</li>
<li><p><strong>Cross-Validation</strong>: Use techniques like k-fold cross-validation to ensure the model’s performance is consistent across different subsets of the data.</p>
</li>
<li><p><strong>More Training Data</strong>: Collect more training data to help the model learn the underlying patterns more effectively.</p>
</li>
<li><p><strong>Pruning</strong>: For decision trees, apply pruning techniques to remove branches that do not provide additional power in predicting the target variable.</p>
</li>
<li><p><strong>Dropout</strong>: In neural networks, use dropout to randomly ignore a subset of neurons during training to prevent the network from becoming too reliant on specific neurons.</p>
</li>
<li><p><strong>Early Stopping</strong>: Halt the training process once the performance on a validation set starts to degrade.</p>
</li>
<li><p><strong>Data Augmentation</strong>: For tasks like image recognition, use data augmentation to artificially increase the size and variability of the training dataset.</p>
</li>
</ol>
<h3 id="heading-summary">Summary</h3>
<p>The variance-bias tradeoff is crucial because it helps build accurate and generalizable models, ensuring they perform well on unseen data. Balancing bias and variance is key to effective machine learning.</p>
]]></content:encoded></item><item><title><![CDATA[Custom Annotation for Roboflow Pre-trained Models with CV2]]></title><description><![CDATA[Roboflow has a great playground of models for computer vision, including object detection and tracking. Their web interface allows you to create datasets and labeling tools that can help any team label faster and be more collaborative with their onli...]]></description><link>https://www.doczamora.com/custom-annotation-for-roboflow-pre-trained-models-with-cv2</link><guid isPermaLink="true">https://www.doczamora.com/custom-annotation-for-roboflow-pre-trained-models-with-cv2</guid><category><![CDATA[roboflow]]></category><category><![CDATA[Python]]></category><category><![CDATA[Computer Vision]]></category><category><![CDATA[object detection ]]></category><category><![CDATA[annotations]]></category><category><![CDATA[opencv]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[easy]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Tue, 11 Jun 2024 05:39:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/R1qHDAEnCmc/upload/35625d33efcd19bdf4bb85626e6110f1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Roboflow has a great playground of models for computer vision, including object detection and tracking. Their web interface allows you to create datasets and labeling tools that can help any team label faster and be more collaborative with their online labeling tools.</p>
<p>In addition to the tools for custom labeling, a huge community also publishes datasets and pre-trained models for object detection, classification, segmentation, keypoint detection, and semantic segmentation, among many others.</p>
<p>Today, we will use a model to classify an image for Rock, Paper, or Scissors using the "rock-paper-scissors-sxsw/14" model.</p>
<p>This is the image we will use for our little experiment; feel free to download it and save it as rock.jpg</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718083171048/a3db9fbc-4491-4bb9-8b81-0ab6e529254e.jpeg" alt class="image--center mx-auto" /></p>
<h2 id="heading-open-google-colab">Open Google Colab</h2>
<p>Go to google colab and create a new notebook. Put the rock.jpg at the root directory.</p>
<h3 id="heading-loading-libraries">Loading Libraries</h3>
<p>To use Roboflow's API, we need to create an account and get the API key. The following code will install the inference library.#!pip install inference-sdk</p>
<pre><code class="lang-python">!pip install inference-sdk
</code></pre>
<p>Now, let's load the required libraries. We will use inference_sdk to call the pre-trained model from Roboflow. cv2 will be used to load the rock.jpg image and create the bounding box, and matplotlib will be used to display the image in the lab notebook.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> inference_sdk
<span class="hljs-keyword">import</span> cv2
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
</code></pre>
<h3 id="heading-call-roboflows-inference-api">Call Roboflows Inference API</h3>
<p>This code is provided by Roboflow as part of the snippets they offer for each model. This one uses the InferenceHTTPClient to call the model hosted on Roboflow remotely. The client.infer method will stream the image to the Roboflow API and return a json with the bounding box and the classification and confidence score information.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> inference_sdk <span class="hljs-keyword">import</span> InferenceHTTPClient

CLIENT = InferenceHTTPClient(
    api_url=<span class="hljs-string">"https://detect.roboflow.com"</span>,
    api_key=<span class="hljs-string">"PUT-YOUR-API-KEY-HERE"</span>
)

result = CLIENT.infer(<span class="hljs-string">'rock.jpg'</span>, model_id=<span class="hljs-string">"rock-paper-scissors-sxsw/14"</span>)

result
</code></pre>
<p>The result object is a json that contains the following structure:</p>
<pre><code class="lang-json">{'time': <span class="hljs-number">0.04682349800009433</span>,
 'image': {'width': <span class="hljs-number">1024</span>, 'height': <span class="hljs-number">768</span>},
 'predictions': [{'x': <span class="hljs-number">552.5</span>,
   'y': <span class="hljs-number">383.5</span>,
   'width': <span class="hljs-number">385.0</span>,
   'height': <span class="hljs-number">371.0</span>,
   'confidence': <span class="hljs-number">0.5471271276473999</span>,
   'class': 'Rock',
   'class_id': <span class="hljs-number">1</span>,
   'detection_id': '<span class="hljs-number">90730496</span>-ac1c<span class="hljs-number">-4</span>f26-af09-b03b33409047'}]}
</code></pre>
<h3 id="heading-custom-annotation-with-cv2">Custom Annotation with CV2</h3>
<p>With the JSON structure, we will use cv2 (OpenCV) to create a rectangle object as the bounding-box and a text object to show the class label and the confidence score.</p>
<pre><code class="lang-json"># Load the image
image = cv2.imread(<span class="hljs-string">"rock.jpg"</span>)

# Get image dimensions
image_width = image.shape[<span class="hljs-number">1</span>]
image_height = image.shape[<span class="hljs-number">0</span>]

# Get prediction data from JSON
x = result['predictions'][<span class="hljs-number">0</span>]['x']
y = result['predictions'][<span class="hljs-number">0</span>]['y']
width = result['predictions'][<span class="hljs-number">0</span>]['width']
height = result['predictions'][<span class="hljs-number">0</span>]['height']

# Calculate coordinates for the bounding box
x_min = int(x - width / <span class="hljs-number">2</span>)
y_min = int(y - height / <span class="hljs-number">2</span>)
x_max = int(x + width / <span class="hljs-number">2</span>)
y_max = int(y + height / <span class="hljs-number">2</span>)

# Draw bounding box on the image
color = (<span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>)  # Green color for the bounding box
thickness = <span class="hljs-number">4</span>
image_with_box = cv2.rectangle(image, (x_min, y_min), (x_max, y_max), color, thickness)

# draw label
text = result['predictions'][<span class="hljs-number">0</span>]['class'] + ' ' + str(round(result['predictions'][<span class="hljs-number">0</span>]['confidence'],<span class="hljs-number">2</span>))
position = (x_min, y_min<span class="hljs-number">-10</span>)  # Bottom-left corner of the text (x, y)
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = <span class="hljs-number">1</span>
color = (<span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>)  # Blue color in BGR
thickness = <span class="hljs-number">2</span>
line_type = cv2.LINE_AA

# Add text to the image
cv2.putText(image, text, position, font, font_scale, color, thickness, line_type)

# Display the annotated image
plt.imshow(image_with_box)
plt.show()
</code></pre>
<p>This code translates the coordinates provided by the Roboboflow model to something cv2 can understand. The resultant image is shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718083868035/7573852d-3e28-45d4-94fe-e9e01e0ff1a3.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-summary">Summary</h2>
<p>The most complex part is showing the annotation. Roboflow's pre-trained models and tools make it easy to create custom datasets and models trained online with very little coding and very quickly. Roboflow offers a free account with limited functionalities (enough to run this example!). Other plans for computer vision tasks start at $250 USD per month.</p>
<p>So what If I want to do this myself with no Roboflow help? well, you will need to look for an annotation tool (like the COCO Annotator or the Ultralytics Annotator in case you are using one of the YOLO flavors) and an object detection framework such as YOLOv9 to train your models with GPUs from one of your favorite cloud providers such as AWS, Google Cloud or Azure).</p>
]]></content:encoded></item><item><title><![CDATA[Audio Transcription from HuggingFace Pre-Trained Model]]></title><description><![CDATA[One time, somebody asked me if it was possible to transcribe call center conversations to text so they later be analyzed for quality purposes. This is exactly what we will be trying to do here in the most simple way: audio transcription.
Fortunately,...]]></description><link>https://www.doczamora.com/audio-transcription-from-huggingface-pre-trained-model</link><guid isPermaLink="true">https://www.doczamora.com/audio-transcription-from-huggingface-pre-trained-model</guid><category><![CDATA[audio]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Deep Learning]]></category><category><![CDATA[huggingface]]></category><category><![CDATA[Transcription]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Begginers]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Fri, 31 May 2024 20:53:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/1oKxSKSOowE/upload/9129715051f7ca69bfb48eebfc0baad4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One time, somebody asked me if it was possible to transcribe call center conversations to text so they later be analyzed for quality purposes. This is exactly what we will be trying to do here in the most simple way: audio transcription.</p>
<p>Fortunately, companies like Facebook and OpenAI have already invested millions of dollars in producing these technologies, and they placed them on a website called "<a target="_blank" href="https://huggingface.co/">Hugging Face</a>".</p>
<p>For this post, we will be using the pre-trained model "distil-whisper/distil-small.en," which is able to translate audio arrays into text. There are many different models and versions of the "distil-small.en" model based on the number of parameters. It's said that a model with a higher number of parameters might produce better transcriptions but will also convert audio into extremely long sequences, so the final transcription might take a lot of time, depending on how long the audio file is.</p>
<p>For our case, we will be using the smallest model, which has 166 million parameters to convert a sample audio file of 1:51 minutes.</p>
<h3 id="heading-download-the-sample-audio-file">Download the sample Audio File</h3>
<p>Please download this <a target="_blank" href="https://pixabay.com/sound-effects/the-freesound-blog-community-update-december-2019-57877/">sample audio file</a> from this link. This is an mp3 file, but you are welcome to use your own file. Rename the audio file as "speech.mp3" and place the file at the root of your colab directory.</p>
<p>Nicely done! Now, it's time to code. Surprisingly, the code required for this is very simple but requires some tweaking. Let's get our hands dirty.</p>
<h3 id="heading-import-libraries">Import Libraries</h3>
<p>To reproduce this code, you can use Google Colab, so we will need to install the following dependencies:</p>
<pre><code class="lang-python">  !pip install transformers
  !pip install soundfile
  !pip install librosa
</code></pre>
<ul>
<li><p>Transformers: This is the main library that allows us to play with thousands of pre-trained models and download them directly from the model objects.</p>
</li>
<li><p>Soundfile: this library will help us load the wav, flac or mp3 files</p>
</li>
<li><p>Librosa: Its Librosa not LeviOsA. This library will help us with some pre-processing we need to do to the mp3 file such as converting stereo files to mono and downcasting an audio file to another sampling rate.</p>
</li>
</ul>
<p>Great! Now let's load all the libraries we need:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> transformers.utils <span class="hljs-keyword">import</span> logging
logging.set_verbosity_error()

<span class="hljs-keyword">import</span> soundfile <span class="hljs-keyword">as</span> sf
<span class="hljs-keyword">import</span> io
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> librosa

<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> pipeline
</code></pre>
<h3 id="heading-create-the-transcription-pipeline">Create the Transcription Pipeline</h3>
<p>A pipeline is an object that loads a pre-trained model and sets up all the required processing so we don't have to do it ourselves. This is very simple, we just need to create the pipeline object and call the model we will be using for the transcription.</p>
<pre><code class="lang-python">asr = pipeline(<span class="hljs-string">"automatic-speech-recognition"</span>, 
model=<span class="hljs-string">"distil-whisper/distil-small.en"</span>)
</code></pre>
<p>This single line of code will download the model and store it in the ASR model variable. We are almost ready to use it. The only thing we need to do is make sure the audio file is compatible with the model, and for that, we will need to transform the audio file with Librosa.</p>
<h3 id="heading-transforming-the-audio-file">Transforming the Audio File</h3>
<p>The "distil-small.en" has been trained in a specific sampling rate. Concretely this model works with audio that is in the 16Hz sampling rate. We can find this out by checking the model sampling rate:</p>
<pre><code class="lang-python">print(asr.feature_extractor.sampling_rate)
</code></pre>
<p>output: 16000</p>
<p>Now, its time to check the sampling rate of the audio file "speech.mp3"</p>
<pre><code class="lang-python">audio, sampling_rate = sf.read(<span class="hljs-string">'speech.mp3'</span>)
print(sampling_rate)
</code></pre>
<p>output: 44100</p>
<p>No problem, we need to do two things with this audio file. The first one 1) is to make sure the file is mono, as these models work with single-channel audio files and 2) downcast the 44Hz audio file to 16Hz. Let's do exactly that in this single block of code:</p>
<pre><code class="lang-python">audio_transposed = np.transpose(audio)
audio_mono = librosa.to_mono(audio_transposed)

audio_16KHz = librosa.resample(audio_mono,
                               orig_sr=sampling_rate,
                               target_sr=asr.feature_extractor.sampling_rate)
</code></pre>
<p>We will transpose our audio file to a single array to manage a united version of the audio file. The transposed array will now be converted to mono using the Librosa to_mono method. That's it; now the file is in a single channel.</p>
<p>The second part is also very simple. Librosa has a resampling method that allows users to change the sampling rate of a mono audio file. The audio_16KHz object now contains the pre-processed audio file that is compatible with the HuggingFace model for audio transcription.</p>
<h3 id="heading-audio-transcription">Audio Transcription</h3>
<p>This is the most simple part now. We will use the ASR object to translate the audio file into text. We will use some special parameters that allow us to process audio in 30-second chunks. This way, we can process longer audio without error, as the model only processes audio of less than 30 seconds.</p>
<pre><code class="lang-python">asr(
    audio_16KHz,
    chunk_length_s=<span class="hljs-number">30</span>, <span class="hljs-comment"># 30 seconds</span>
    batch_size=<span class="hljs-number">4</span>,
    return_timestamps=<span class="hljs-literal">True</span>,
)[<span class="hljs-string">"chunks"</span>]
</code></pre>
<p>Thats it! just wait some time; you will get a JSON array with the timestamp and text recognized. This is the output of this transcription:</p>
<pre><code class="lang-json">[{'timestamp': (<span class="hljs-number">0.0</span>, 7.0),
  'text': ' Community Update December <span class="hljs-number">2019</span> posted on December <span class="hljs-number">27</span>th <span class="hljs-number">2019</span> by Frederick Font.'},
 {'timestamp': (<span class="hljs-number">7.0</span>, 11.0),
  'text': ' Hi everyone, welcome to a new community update.'},
 {'timestamp': (<span class="hljs-number">11.0</span>, 15.0),
  'text': ' Yeah, we know we have not been updating you very regularly lately,'},
 {'timestamp': (<span class="hljs-number">15.0</span>, 18.0),
  'text': ' but this does not mean we have not been working hard on free sound.'},
 {'timestamp': (<span class="hljs-number">18.0</span>, 25.6),
  'text': ' As has been the case for the last year, we have not been very much concentrated on working on either under the hood improvements'},
 {'timestamp': (<span class="hljs-number">25.6</span>, 30.56),
  'text': ' or research type of issues which do not have a clearly visible output in the Fresound'},
 {'timestamp': (<span class="hljs-number">30.56</span>, 32.28), 'text': ' website yet.'},
 {'timestamp': (<span class="hljs-number">32.28</span>, 37.12),
  'text': ' But we are indeed working on great things which will definitely end up in the platform.'},
 {'timestamp': (<span class="hljs-number">37.12</span>, 41.6),
  'text': ' Here is a summary of our current main working threads.'},
 {'timestamp': (<span class="hljs-number">41.6</span>, 44.44),
  'text': ' BUG Fixs, General Maintenance and Software updates.'},
 {'timestamp': (<span class="hljs-number">44.44</span>, 45.44),
  'text': ' This is a big one as we are about to carry, and software updates.'},
 {'timestamp': (<span class="hljs-number">45.44</span>, 49.72),
  'text': ' This is a big one as we are about to carry out necessary software updates.'},
 {'timestamp': (<span class="hljs-number">49.72</span>, 55.76),
  'text': ' For nerds, Python, Jango updates, which affect all of our code base and are therefore quite'},
 {'timestamp': (<span class="hljs-number">55.76</span>, 56.2), 'text': ' time-consuming.'},
 {'timestamp': (<span class="hljs-number">56.2</span>, 57.2), 'text': ' New features.'},
 {'timestamp': (<span class="hljs-number">57.2</span>, 63.44),
  'text': ' We are working on new features mostly related to the search page.'},
 {'timestamp': (<span class="hljs-number">63.44</span>, 68.56),
  'text': <span class="hljs-string">" However, all these new features require a lot of previous research work. Don't forget we're a research"</span>},
 {'timestamp': (<span class="hljs-number">68.56</span>, 73.44),
  'text': <span class="hljs-string">" institution, so that's what we do best. And again, features need their time to"</span>},
 {'timestamp': (<span class="hljs-number">73.44</span>, 78.32),
  'text': <span class="hljs-string">" become a reality. The new search features we're working on will allow to cluster"</span>},
 {'timestamp': (<span class="hljs-number">78.32</span>, 86.64),
  'text': ' search results as well as adding new filtering options. New front end. Yes, we have not abandoned this one.'},
 {'timestamp': (<span class="hljs-number">86.64</span>, 91.52),
  'text': ' It is going very slowly, much more than we thought, but it will eventually become a reality'},
 {'timestamp': (<span class="hljs-number">91.52</span>, 93.68), 'text': ' and it is indeed in our roadmap.'},
 {'timestamp': (<span class="hljs-number">93.68</span>, 100.16),
  'text': <span class="hljs-string">" Oh, and by the way, we've just published a tech-oriented post about Free Sound in the Creative Commons open-source"</span>},
 {'timestamp': (<span class="hljs-number">100.16</span>, 101.24), 'text': ' blog.'},
 {'timestamp': (<span class="hljs-number">101.24</span>, 103.44), 'text': ' You might want to check that out.'},
 {'timestamp': (<span class="hljs-number">103.44</span>, 105.6),
  'text': <span class="hljs-string">" And that's it for the short update. Thanks"</span>},
 {'timestamp': (<span class="hljs-number">105.6</span>, 109.92),
  'text': ' for a reading and stay tuned for the updates in the coming year. Big happy new'},
 {'timestamp': (<span class="hljs-number">109.92</span>, 113.04), 'text': ' year to everyone.'}]
</code></pre>
<h3 id="heading-great-success">Great Success</h3>
<iframe src="https://giphy.com/embed/Od0QRnzwRBYmDU3eEO" width="480" height="480" class="giphy-embed"></iframe>]]></content:encoded></item><item><title><![CDATA[Gaussian Mixture Models (GMMs)]]></title><description><![CDATA[Male and Female Weight
Let's suppose we collected some data from some University students. We asked every student their gender (Male = M, Female = F) and their weight. We will build a model that can predict if you are a male or a female based only on...]]></description><link>https://www.doczamora.com/gaussian-mixture-models-gmms</link><guid isPermaLink="true">https://www.doczamora.com/gaussian-mixture-models-gmms</guid><category><![CDATA[Python]]></category><category><![CDATA[statistics]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[sklearn]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Mon, 27 May 2024 01:50:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Xdh_J4xW1QE/upload/e61c4ae02223c07858831150ee39d17a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-male-and-female-weight">Male and Female Weight</h3>
<p>Let's suppose we collected some data from some University students. We asked every student their gender (Male = M, Female = F) and their weight. We will build a model that can predict if you are a male or a female based only on your weight. I know this is not the ideal case for this, but this example will help to demonstrate a statistical trick to discriminate between two populations that show different behaviors in the same dataset.</p>
<h3 id="heading-lets-check-the-data">Let's check the data</h3>
<p>let's add some libraries we will use in our example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> matplotlib <span class="hljs-keyword">import</span> pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> scipy.stats <span class="hljs-keyword">as</span> stats
</code></pre>
<p>We will use some fake data to test this out and we will use sklearn to train-test split the data in a 70/30 proportion.</p>
<pre><code class="lang-python">weight = [<span class="hljs-number">52</span>, <span class="hljs-number">46</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">55</span>, <span class="hljs-number">44</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">44</span>, <span class="hljs-number">54</span>, <span class="hljs-number">52</span>, <span class="hljs-number">55</span>, <span class="hljs-number">55</span>, <span class="hljs-number">53</span>, <span class="hljs-number">42</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">46</span>, <span class="hljs-number">52</span>, <span class="hljs-number">56</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">49</span>, <span class="hljs-number">44</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">42</span>, <span class="hljs-number">37</span>, <span class="hljs-number">43</span>, <span class="hljs-number">53</span>, <span class="hljs-number">57</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">44</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">58</span>, <span class="hljs-number">47</span>, <span class="hljs-number">44</span>, <span class="hljs-number">55</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">36</span>, <span class="hljs-number">49</span>, <span class="hljs-number">55</span>, <span class="hljs-number">49</span>, <span class="hljs-number">55</span>, <span class="hljs-number">55</span>, <span class="hljs-number">42</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">37</span>, <span class="hljs-number">53</span>, <span class="hljs-number">45</span>, <span class="hljs-number">52</span>, <span class="hljs-number">56</span>, <span class="hljs-number">51</span>, <span class="hljs-number">55</span>, <span class="hljs-number">48</span>, <span class="hljs-number">58</span>, <span class="hljs-number">49</span>, <span class="hljs-number">56</span>, <span class="hljs-number">54</span>, <span class="hljs-number">48</span>, <span class="hljs-number">56</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">57</span>, <span class="hljs-number">55</span>, <span class="hljs-number">58</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">39</span>, <span class="hljs-number">43</span>, <span class="hljs-number">47</span>, <span class="hljs-number">45</span>, <span class="hljs-number">50</span>, <span class="hljs-number">54</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">56</span>, <span class="hljs-number">43</span>, <span class="hljs-number">44</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">36</span>, <span class="hljs-number">53</span>, <span class="hljs-number">47</span>, <span class="hljs-number">43</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">52</span>, <span class="hljs-number">54</span>, <span class="hljs-number">46</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">56</span>, <span class="hljs-number">52</span>, <span class="hljs-number">54</span>, <span class="hljs-number">43</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">56</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">55</span>, <span class="hljs-number">51</span>, <span class="hljs-number">64</span>, <span class="hljs-number">55</span>, <span class="hljs-number">46</span>, <span class="hljs-number">45</span>, <span class="hljs-number">52</span>, <span class="hljs-number">54</span>, <span class="hljs-number">46</span>, <span class="hljs-number">47</span>, <span class="hljs-number">56</span>, <span class="hljs-number">58</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">46</span>, <span class="hljs-number">42</span>, <span class="hljs-number">54</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">42</span>, <span class="hljs-number">55</span>, <span class="hljs-number">45</span>, <span class="hljs-number">54</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">52</span>, <span class="hljs-number">43</span>, <span class="hljs-number">47</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">46</span>, <span class="hljs-number">53</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">57</span>, <span class="hljs-number">55</span>, <span class="hljs-number">51</span>, <span class="hljs-number">48</span>, <span class="hljs-number">55</span>, <span class="hljs-number">45</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">54</span>, <span class="hljs-number">46</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">52</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">34</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">63</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">46</span>, <span class="hljs-number">45</span>, <span class="hljs-number">50</span>, <span class="hljs-number">58</span>, <span class="hljs-number">43</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">48</span>, <span class="hljs-number">54</span>, <span class="hljs-number">45</span>, <span class="hljs-number">54</span>, <span class="hljs-number">46</span>, <span class="hljs-number">43</span>, <span class="hljs-number">51</span>, <span class="hljs-number">40</span>, <span class="hljs-number">57</span>, <span class="hljs-number">51</span>, <span class="hljs-number">45</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">56</span>, <span class="hljs-number">60</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">46</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">45</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">53</span>, <span class="hljs-number">60</span>, <span class="hljs-number">58</span>, <span class="hljs-number">56</span>, <span class="hljs-number">53</span>, <span class="hljs-number">54</span>, <span class="hljs-number">44</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">45</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">42</span>, <span class="hljs-number">55</span>, <span class="hljs-number">54</span>, <span class="hljs-number">53</span>, <span class="hljs-number">45</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">58</span>, <span class="hljs-number">44</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">45</span>, <span class="hljs-number">55</span>, <span class="hljs-number">53</span>, <span class="hljs-number">45</span>, <span class="hljs-number">53</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">58</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">49</span>, <span class="hljs-number">55</span>, <span class="hljs-number">55</span>, <span class="hljs-number">54</span>, <span class="hljs-number">42</span>, <span class="hljs-number">47</span>, <span class="hljs-number">41</span>, <span class="hljs-number">46</span>, <span class="hljs-number">50</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">45</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">61</span>, <span class="hljs-number">51</span>, <span class="hljs-number">41</span>, <span class="hljs-number">55</span>, <span class="hljs-number">43</span>, <span class="hljs-number">56</span>, <span class="hljs-number">53</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">56</span>, <span class="hljs-number">42</span>, <span class="hljs-number">42</span>, <span class="hljs-number">47</span>, <span class="hljs-number">48</span>, <span class="hljs-number">56</span>, <span class="hljs-number">46</span>, <span class="hljs-number">43</span>, <span class="hljs-number">43</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">47</span>, <span class="hljs-number">41</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">44</span>, <span class="hljs-number">50</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">45</span>, <span class="hljs-number">54</span>, <span class="hljs-number">54</span>, <span class="hljs-number">54</span>, <span class="hljs-number">45</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">45</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">53</span>, <span class="hljs-number">55</span>, <span class="hljs-number">46</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">55</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">49</span>, <span class="hljs-number">58</span>, <span class="hljs-number">53</span>, <span class="hljs-number">58</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">42</span>, <span class="hljs-number">51</span>, <span class="hljs-number">46</span>, <span class="hljs-number">45</span>, <span class="hljs-number">61</span>, <span class="hljs-number">50</span>, <span class="hljs-number">40</span>, <span class="hljs-number">44</span>, <span class="hljs-number">40</span>, <span class="hljs-number">58</span>, <span class="hljs-number">46</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">45</span>, <span class="hljs-number">54</span>, <span class="hljs-number">45</span>, <span class="hljs-number">58</span>, <span class="hljs-number">43</span>, <span class="hljs-number">51</span>, <span class="hljs-number">48</span>, <span class="hljs-number">48</span>, <span class="hljs-number">57</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">61</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">56</span>, <span class="hljs-number">49</span>, <span class="hljs-number">40</span>, <span class="hljs-number">46</span>, <span class="hljs-number">53</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">58</span>, <span class="hljs-number">56</span>, <span class="hljs-number">61</span>, <span class="hljs-number">46</span>, <span class="hljs-number">55</span>, <span class="hljs-number">58</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">45</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">53</span>, <span class="hljs-number">45</span>, <span class="hljs-number">52</span>, <span class="hljs-number">53</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">54</span>, <span class="hljs-number">52</span>, <span class="hljs-number">55</span>, <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">53</span>, <span class="hljs-number">42</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">44</span>, <span class="hljs-number">61</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">56</span>, <span class="hljs-number">48</span>, <span class="hljs-number">56</span>, <span class="hljs-number">41</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">57</span>, <span class="hljs-number">57</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">55</span>, <span class="hljs-number">50</span>, <span class="hljs-number">54</span>, <span class="hljs-number">60</span>, <span class="hljs-number">42</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">58</span>, <span class="hljs-number">52</span>, <span class="hljs-number">54</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">46</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">43</span>, <span class="hljs-number">48</span>, <span class="hljs-number">54</span>, <span class="hljs-number">44</span>, <span class="hljs-number">43</span>, <span class="hljs-number">45</span>, <span class="hljs-number">53</span>, <span class="hljs-number">58</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">48</span>, <span class="hljs-number">48</span>, <span class="hljs-number">39</span>, <span class="hljs-number">55</span>, <span class="hljs-number">56</span>, <span class="hljs-number">58</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">54</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">48</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">59</span>, <span class="hljs-number">47</span>, <span class="hljs-number">64</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">54</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">54</span>, <span class="hljs-number">56</span>, <span class="hljs-number">46</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">41</span>, <span class="hljs-number">51</span>, <span class="hljs-number">55</span>, <span class="hljs-number">56</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">45</span>, <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">49</span>, <span class="hljs-number">46</span>, <span class="hljs-number">51</span>, <span class="hljs-number">55</span>, <span class="hljs-number">43</span>, <span class="hljs-number">53</span>, <span class="hljs-number">47</span>, <span class="hljs-number">56</span>, <span class="hljs-number">64</span>, <span class="hljs-number">49</span>, <span class="hljs-number">46</span>, <span class="hljs-number">56</span>, <span class="hljs-number">45</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">41</span>, <span class="hljs-number">44</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">59</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">47</span>, <span class="hljs-number">44</span>, <span class="hljs-number">45</span>, <span class="hljs-number">48</span>, <span class="hljs-number">44</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">56</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">43</span>, <span class="hljs-number">53</span>, <span class="hljs-number">61</span>, <span class="hljs-number">53</span>, <span class="hljs-number">44</span>, <span class="hljs-number">52</span>, <span class="hljs-number">57</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">54</span>, <span class="hljs-number">46</span>, <span class="hljs-number">57</span>, <span class="hljs-number">52</span>, <span class="hljs-number">64</span>, <span class="hljs-number">52</span>, <span class="hljs-number">55</span>, <span class="hljs-number">54</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">57</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">52</span>, <span class="hljs-number">41</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">40</span>, <span class="hljs-number">54</span>, <span class="hljs-number">54</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">53</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">46</span>, <span class="hljs-number">47</span>, <span class="hljs-number">61</span>, <span class="hljs-number">49</span>, <span class="hljs-number">46</span>, <span class="hljs-number">39</span>, <span class="hljs-number">51</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">42</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">55</span>, <span class="hljs-number">49</span>, <span class="hljs-number">46</span>, <span class="hljs-number">46</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">54</span>, <span class="hljs-number">44</span>, <span class="hljs-number">46</span>, <span class="hljs-number">42</span>, <span class="hljs-number">36</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">43</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">55</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">55</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">37</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">53</span>, <span class="hljs-number">47</span>, <span class="hljs-number">52</span>, <span class="hljs-number">56</span>, <span class="hljs-number">46</span>, <span class="hljs-number">58</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">55</span>, <span class="hljs-number">51</span>, <span class="hljs-number">46</span>, <span class="hljs-number">50</span>, <span class="hljs-number">54</span>, <span class="hljs-number">53</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">38</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">43</span>, <span class="hljs-number">47</span>, <span class="hljs-number">48</span>, <span class="hljs-number">48</span>, <span class="hljs-number">48</span>, <span class="hljs-number">43</span>, <span class="hljs-number">53</span>, <span class="hljs-number">64</span>, <span class="hljs-number">56</span>, <span class="hljs-number">46</span>, <span class="hljs-number">55</span>, <span class="hljs-number">55</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">58</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">44</span>, <span class="hljs-number">47</span>, <span class="hljs-number">52</span>, <span class="hljs-number">61</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">61</span>, <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">43</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">52</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">58</span>, <span class="hljs-number">58</span>, <span class="hljs-number">62</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">44</span>, <span class="hljs-number">49</span>, <span class="hljs-number">54</span>, <span class="hljs-number">55</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">44</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">53</span>, <span class="hljs-number">54</span>, <span class="hljs-number">50</span>, <span class="hljs-number">55</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">54</span>, <span class="hljs-number">47</span>, <span class="hljs-number">46</span>, <span class="hljs-number">44</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">43</span>, <span class="hljs-number">46</span>, <span class="hljs-number">51</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">45</span>, <span class="hljs-number">47</span>, <span class="hljs-number">41</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">53</span>, <span class="hljs-number">45</span>, <span class="hljs-number">62</span>, <span class="hljs-number">45</span>, <span class="hljs-number">47</span>, <span class="hljs-number">48</span>, <span class="hljs-number">52</span>, <span class="hljs-number">53</span>, <span class="hljs-number">53</span>, <span class="hljs-number">56</span>, <span class="hljs-number">38</span>, <span class="hljs-number">44</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">46</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">55</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">53</span>, <span class="hljs-number">43</span>, <span class="hljs-number">46</span>, <span class="hljs-number">56</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">40</span>, <span class="hljs-number">51</span>, <span class="hljs-number">57</span>, <span class="hljs-number">50</span>, <span class="hljs-number">57</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">42</span>, <span class="hljs-number">45</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">44</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">56</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">46</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">41</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">42</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">47</span>, <span class="hljs-number">48</span>, <span class="hljs-number">56</span>, <span class="hljs-number">44</span>, <span class="hljs-number">60</span>, <span class="hljs-number">41</span>, <span class="hljs-number">50</span>, <span class="hljs-number">52</span>, <span class="hljs-number">44</span>, <span class="hljs-number">48</span>, <span class="hljs-number">53</span>, <span class="hljs-number">48</span>, <span class="hljs-number">54</span>, <span class="hljs-number">54</span>, <span class="hljs-number">52</span>, <span class="hljs-number">44</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">44</span>, <span class="hljs-number">56</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">54</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">45</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">45</span>, <span class="hljs-number">53</span>, <span class="hljs-number">45</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">45</span>, <span class="hljs-number">51</span>, <span class="hljs-number">44</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">54</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">49</span>, <span class="hljs-number">46</span>, <span class="hljs-number">45</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">43</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">54</span>, <span class="hljs-number">56</span>, <span class="hljs-number">46</span>, <span class="hljs-number">50</span>, <span class="hljs-number">55</span>, <span class="hljs-number">59</span>, <span class="hljs-number">54</span>, <span class="hljs-number">44</span>, <span class="hljs-number">48</span>, <span class="hljs-number">59</span>, <span class="hljs-number">47</span>, <span class="hljs-number">41</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">53</span>, <span class="hljs-number">53</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">43</span>, <span class="hljs-number">59</span>, <span class="hljs-number">47</span>, <span class="hljs-number">44</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">57</span>, <span class="hljs-number">55</span>, <span class="hljs-number">49</span>, <span class="hljs-number">56</span>, <span class="hljs-number">56</span>, <span class="hljs-number">54</span>, <span class="hljs-number">42</span>, <span class="hljs-number">49</span>, <span class="hljs-number">56</span>, <span class="hljs-number">51</span>, <span class="hljs-number">58</span>, <span class="hljs-number">44</span>, <span class="hljs-number">47</span>, <span class="hljs-number">56</span>, <span class="hljs-number">45</span>, <span class="hljs-number">53</span>, <span class="hljs-number">54</span>, <span class="hljs-number">47</span>, <span class="hljs-number">45</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">57</span>, <span class="hljs-number">53</span>, <span class="hljs-number">55</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">46</span>, <span class="hljs-number">44</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">55</span>, <span class="hljs-number">51</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">46</span>, <span class="hljs-number">51</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">43</span>, <span class="hljs-number">49</span>, <span class="hljs-number">46</span>, <span class="hljs-number">46</span>, <span class="hljs-number">56</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">50</span>, <span class="hljs-number">52</span>, <span class="hljs-number">59</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">47</span>, <span class="hljs-number">46</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">42</span>, <span class="hljs-number">47</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">61</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">54</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">42</span>, <span class="hljs-number">55</span>, <span class="hljs-number">41</span>, <span class="hljs-number">54</span>, <span class="hljs-number">55</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">46</span>, <span class="hljs-number">54</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">53</span>, <span class="hljs-number">44</span>, <span class="hljs-number">44</span>, <span class="hljs-number">53</span>, <span class="hljs-number">56</span>, <span class="hljs-number">54</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">59</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">54</span>, <span class="hljs-number">48</span>, <span class="hljs-number">46</span>, <span class="hljs-number">51</span>, <span class="hljs-number">44</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">55</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">39</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">44</span>, <span class="hljs-number">47</span>, <span class="hljs-number">60</span>, <span class="hljs-number">51</span>, <span class="hljs-number">34</span>, <span class="hljs-number">46</span>, <span class="hljs-number">45</span>, <span class="hljs-number">52</span>, <span class="hljs-number">55</span>, <span class="hljs-number">57</span>, <span class="hljs-number">55</span>, <span class="hljs-number">42</span>, <span class="hljs-number">50</span>, <span class="hljs-number">57</span>, <span class="hljs-number">52</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">45</span>, <span class="hljs-number">44</span>, <span class="hljs-number">42</span>, <span class="hljs-number">47</span>, <span class="hljs-number">46</span>, <span class="hljs-number">55</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">57</span>, <span class="hljs-number">46</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">44</span>, <span class="hljs-number">44</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">48</span>, <span class="hljs-number">41</span>, <span class="hljs-number">48</span>, <span class="hljs-number">53</span>, <span class="hljs-number">43</span>, <span class="hljs-number">51</span>, <span class="hljs-number">45</span>, <span class="hljs-number">51</span>, <span class="hljs-number">55</span>, <span class="hljs-number">49</span>, <span class="hljs-number">54</span>, <span class="hljs-number">48</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">55</span>, <span class="hljs-number">43</span>, <span class="hljs-number">54</span>, <span class="hljs-number">48</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">46</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">60</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">53</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">42</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">47</span>, <span class="hljs-number">44</span>, <span class="hljs-number">53</span>, <span class="hljs-number">48</span>, <span class="hljs-number">45</span>, <span class="hljs-number">54</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">46</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">59</span>, <span class="hljs-number">54</span>, <span class="hljs-number">45</span>, <span class="hljs-number">61</span>, <span class="hljs-number">53</span>, <span class="hljs-number">43</span>, <span class="hljs-number">52</span>, <span class="hljs-number">54</span>, <span class="hljs-number">53</span>, <span class="hljs-number">61</span>, <span class="hljs-number">54</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">57</span>, <span class="hljs-number">43</span>, <span class="hljs-number">44</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">43</span>, <span class="hljs-number">56</span>, <span class="hljs-number">46</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">48</span>, <span class="hljs-number">45</span>, <span class="hljs-number">43</span>, <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">48</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">42</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">54</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">53</span>, <span class="hljs-number">42</span>, <span class="hljs-number">45</span>, <span class="hljs-number">46</span>, <span class="hljs-number">52</span>, <span class="hljs-number">55</span>, <span class="hljs-number">50</span>, <span class="hljs-number">42</span>, <span class="hljs-number">52</span>, <span class="hljs-number">45</span>, <span class="hljs-number">44</span>, <span class="hljs-number">44</span>, <span class="hljs-number">54</span>, <span class="hljs-number">48</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">56</span>, <span class="hljs-number">52</span>, <span class="hljs-number">41</span>, <span class="hljs-number">56</span>, <span class="hljs-number">55</span>, <span class="hljs-number">50</span>, <span class="hljs-number">42</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">53</span>, <span class="hljs-number">56</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">52</span>, <span class="hljs-number">53</span>, <span class="hljs-number">46</span>, <span class="hljs-number">57</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">53</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">46</span>, <span class="hljs-number">55</span>, <span class="hljs-number">54</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">45</span>, <span class="hljs-number">45</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">48</span>, <span class="hljs-number">41</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">61</span>, <span class="hljs-number">43</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">53</span>, <span class="hljs-number">54</span>, <span class="hljs-number">49</span>, <span class="hljs-number">44</span>, <span class="hljs-number">47</span>, <span class="hljs-number">55</span>, <span class="hljs-number">58</span>, <span class="hljs-number">48</span>, <span class="hljs-number">58</span>, <span class="hljs-number">46</span>, <span class="hljs-number">44</span>, <span class="hljs-number">54</span>, <span class="hljs-number">55</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">45</span>, <span class="hljs-number">47</span>, <span class="hljs-number">52</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">54</span>, <span class="hljs-number">49</span>, <span class="hljs-number">54</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">56</span>, <span class="hljs-number">48</span>, <span class="hljs-number">56</span>, <span class="hljs-number">60</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">57</span>, <span class="hljs-number">56</span>, <span class="hljs-number">41</span>, <span class="hljs-number">53</span>, <span class="hljs-number">49</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">57</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">52</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">55</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">37</span>, <span class="hljs-number">61</span>, <span class="hljs-number">56</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">67</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">57</span>, <span class="hljs-number">55</span>, <span class="hljs-number">46</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">57</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">56</span>, <span class="hljs-number">60</span>, <span class="hljs-number">42</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">56</span>, <span class="hljs-number">47</span>, <span class="hljs-number">57</span>, <span class="hljs-number">40</span>, <span class="hljs-number">60</span>, <span class="hljs-number">50</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">47</span>, <span class="hljs-number">48</span>, <span class="hljs-number">59</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">39</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">42</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">46</span>, <span class="hljs-number">49</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">45</span>, <span class="hljs-number">55</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">60</span>, <span class="hljs-number">57</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">46</span>, <span class="hljs-number">49</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">38</span>, <span class="hljs-number">52</span>, <span class="hljs-number">55</span>, <span class="hljs-number">51</span>, <span class="hljs-number">44</span>, <span class="hljs-number">48</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">59</span>, <span class="hljs-number">51</span>, <span class="hljs-number">56</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">45</span>, <span class="hljs-number">56</span>, <span class="hljs-number">47</span>, <span class="hljs-number">51</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">53</span>, <span class="hljs-number">59</span>, <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">53</span>, <span class="hljs-number">48</span>, <span class="hljs-number">42</span>, <span class="hljs-number">50</span>, <span class="hljs-number">54</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">60</span>, <span class="hljs-number">50</span>, <span class="hljs-number">65</span>, <span class="hljs-number">58</span>, <span class="hljs-number">54</span>, <span class="hljs-number">47</span>, <span class="hljs-number">45</span>, <span class="hljs-number">55</span>, <span class="hljs-number">44</span>, <span class="hljs-number">51</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">45</span>, <span class="hljs-number">46</span>, <span class="hljs-number">51</span>, <span class="hljs-number">48</span>, <span class="hljs-number">55</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">46</span>, <span class="hljs-number">58</span>, <span class="hljs-number">59</span>, <span class="hljs-number">50</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">53</span>, <span class="hljs-number">61</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">45</span>, <span class="hljs-number">41</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">50</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">55</span>, <span class="hljs-number">44</span>, <span class="hljs-number">50</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">55</span>, <span class="hljs-number">52</span>, <span class="hljs-number">58</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">45</span>, <span class="hljs-number">46</span>, <span class="hljs-number">55</span>, <span class="hljs-number">56</span>, <span class="hljs-number">43</span>, <span class="hljs-number">49</span>, <span class="hljs-number">50</span>, <span class="hljs-number">59</span>, <span class="hljs-number">53</span>, <span class="hljs-number">45</span>, <span class="hljs-number">47</span>, <span class="hljs-number">49</span>, <span class="hljs-number">40</span>, <span class="hljs-number">45</span>, <span class="hljs-number">55</span>, <span class="hljs-number">46</span>, <span class="hljs-number">50</span>, <span class="hljs-number">53</span>, <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">52</span>, <span class="hljs-number">48</span>, <span class="hljs-number">53</span>, <span class="hljs-number">53</span>, <span class="hljs-number">51</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">49</span>, <span class="hljs-number">52</span>, <span class="hljs-number">56</span>, <span class="hljs-number">36</span>, <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">45</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">56</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">46</span>, <span class="hljs-number">50</span>, <span class="hljs-number">48</span>, <span class="hljs-number">48</span>, <span class="hljs-number">47</span>, <span class="hljs-number">52</span>, <span class="hljs-number">39</span>, <span class="hljs-number">44</span>, <span class="hljs-number">51</span>, <span class="hljs-number">55</span>, <span class="hljs-number">48</span>, <span class="hljs-number">55</span>, <span class="hljs-number">46</span>, <span class="hljs-number">53</span>, <span class="hljs-number">45</span>, <span class="hljs-number">54</span>, <span class="hljs-number">55</span>, <span class="hljs-number">57</span>, <span class="hljs-number">53</span>, <span class="hljs-number">49</span>, <span class="hljs-number">46</span>, <span class="hljs-number">53</span>, <span class="hljs-number">49</span>, <span class="hljs-number">49</span>, <span class="hljs-number">53</span>, <span class="hljs-number">52</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">48</span>, <span class="hljs-number">53</span>, <span class="hljs-number">44</span>, <span class="hljs-number">39</span>, <span class="hljs-number">46</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">52</span>, <span class="hljs-number">44</span>, <span class="hljs-number">54</span>, <span class="hljs-number">44</span>, <span class="hljs-number">49</span>, <span class="hljs-number">54</span>, <span class="hljs-number">55</span>, <span class="hljs-number">48</span>, <span class="hljs-number">51</span>, <span class="hljs-number">50</span>, <span class="hljs-number">54</span>, <span class="hljs-number">43</span>, <span class="hljs-number">53</span>, <span class="hljs-number">47</span>, <span class="hljs-number">47</span>, <span class="hljs-number">45</span>, <span class="hljs-number">54</span>, <span class="hljs-number">46</span>, <span class="hljs-number">52</span>, <span class="hljs-number">51</span>, <span class="hljs-number">55</span>, <span class="hljs-number">59</span>, <span class="hljs-number">48</span>, <span class="hljs-number">49</span>, <span class="hljs-number">55</span>, <span class="hljs-number">54</span>, <span class="hljs-number">51</span>, <span class="hljs-number">51</span>, <span class="hljs-number">44</span>, <span class="hljs-number">56</span>, <span class="hljs-number">50</span>, <span class="hljs-number">54</span>, <span class="hljs-number">47</span>, <span class="hljs-number">53</span>, <span class="hljs-number">58</span>, <span class="hljs-number">51</span>, <span class="hljs-number">54</span>, <span class="hljs-number">47</span>, <span class="hljs-number">43</span>, <span class="hljs-number">47</span>, <span class="hljs-number">55</span>, <span class="hljs-number">49</span>, <span class="hljs-number">75</span>, <span class="hljs-number">72</span>, <span class="hljs-number">59</span>, <span class="hljs-number">73</span>, <span class="hljs-number">74</span>, <span class="hljs-number">54</span>, <span class="hljs-number">62</span>, <span class="hljs-number">64</span>, <span class="hljs-number">68</span>, <span class="hljs-number">66</span>, <span class="hljs-number">82</span>, <span class="hljs-number">77</span>, <span class="hljs-number">79</span>, <span class="hljs-number">76</span>, <span class="hljs-number">63</span>, <span class="hljs-number">83</span>, <span class="hljs-number">76</span>, <span class="hljs-number">72</span>, <span class="hljs-number">75</span>, <span class="hljs-number">71</span>, <span class="hljs-number">66</span>, <span class="hljs-number">69</span>, <span class="hljs-number">67</span>, <span class="hljs-number">65</span>, <span class="hljs-number">67</span>, <span class="hljs-number">67</span>, <span class="hljs-number">69</span>, <span class="hljs-number">57</span>, <span class="hljs-number">52</span>, <span class="hljs-number">61</span>, <span class="hljs-number">72</span>, <span class="hljs-number">64</span>, <span class="hljs-number">74</span>, <span class="hljs-number">59</span>, <span class="hljs-number">72</span>, <span class="hljs-number">70</span>, <span class="hljs-number">68</span>, <span class="hljs-number">80</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">72</span>, <span class="hljs-number">74</span>, <span class="hljs-number">78</span>, <span class="hljs-number">73</span>, <span class="hljs-number">76</span>, <span class="hljs-number">65</span>, <span class="hljs-number">68</span>, <span class="hljs-number">70</span>, <span class="hljs-number">75</span>, <span class="hljs-number">73</span>, <span class="hljs-number">68</span>, <span class="hljs-number">81</span>, <span class="hljs-number">76</span>, <span class="hljs-number">93</span>, <span class="hljs-number">73</span>, <span class="hljs-number">69</span>, <span class="hljs-number">66</span>, <span class="hljs-number">65</span>, <span class="hljs-number">61</span>, <span class="hljs-number">74</span>, <span class="hljs-number">74</span>, <span class="hljs-number">69</span>, <span class="hljs-number">76</span>, <span class="hljs-number">79</span>, <span class="hljs-number">73</span>, <span class="hljs-number">73</span>, <span class="hljs-number">82</span>, <span class="hljs-number">61</span>, <span class="hljs-number">62</span>, <span class="hljs-number">71</span>, <span class="hljs-number">83</span>, <span class="hljs-number">76</span>, <span class="hljs-number">61</span>, <span class="hljs-number">66</span>, <span class="hljs-number">77</span>, <span class="hljs-number">64</span>, <span class="hljs-number">72</span>, <span class="hljs-number">67</span>, <span class="hljs-number">68</span>, <span class="hljs-number">66</span>, <span class="hljs-number">67</span>, <span class="hljs-number">53</span>, <span class="hljs-number">79</span>, <span class="hljs-number">75</span>, <span class="hljs-number">61</span>, <span class="hljs-number">66</span>, <span class="hljs-number">71</span>, <span class="hljs-number">67</span>, <span class="hljs-number">71</span>, <span class="hljs-number">60</span>, <span class="hljs-number">72</span>, <span class="hljs-number">72</span>, <span class="hljs-number">72</span>, <span class="hljs-number">71</span>, <span class="hljs-number">69</span>, <span class="hljs-number">71</span>, <span class="hljs-number">78</span>, <span class="hljs-number">61</span>, <span class="hljs-number">71</span>, <span class="hljs-number">80</span>, <span class="hljs-number">69</span>, <span class="hljs-number">59</span>, <span class="hljs-number">64</span>, <span class="hljs-number">72</span>, <span class="hljs-number">75</span>, <span class="hljs-number">74</span>, <span class="hljs-number">69</span>, <span class="hljs-number">69</span>, <span class="hljs-number">70</span>, <span class="hljs-number">62</span>, <span class="hljs-number">61</span>, <span class="hljs-number">66</span>, <span class="hljs-number">77</span>, <span class="hljs-number">66</span>, <span class="hljs-number">67</span>, <span class="hljs-number">62</span>, <span class="hljs-number">64</span>, <span class="hljs-number">77</span>, <span class="hljs-number">69</span>, <span class="hljs-number">73</span>, <span class="hljs-number">78</span>, <span class="hljs-number">79</span>, <span class="hljs-number">63</span>, <span class="hljs-number">70</span>, <span class="hljs-number">72</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">68</span>, <span class="hljs-number">70</span>, <span class="hljs-number">77</span>, <span class="hljs-number">88</span>, <span class="hljs-number">69</span>, <span class="hljs-number">62</span>, <span class="hljs-number">71</span>, <span class="hljs-number">74</span>, <span class="hljs-number">71</span>, <span class="hljs-number">58</span>, <span class="hljs-number">78</span>, <span class="hljs-number">68</span>, <span class="hljs-number">70</span>, <span class="hljs-number">74</span>, <span class="hljs-number">81</span>, <span class="hljs-number">68</span>, <span class="hljs-number">64</span>, <span class="hljs-number">67</span>, <span class="hljs-number">74</span>, <span class="hljs-number">64</span>, <span class="hljs-number">66</span>, <span class="hljs-number">65</span>, <span class="hljs-number">67</span>, <span class="hljs-number">65</span>, <span class="hljs-number">78</span>, <span class="hljs-number">78</span>, <span class="hljs-number">70</span>, <span class="hljs-number">64</span>, <span class="hljs-number">68</span>, <span class="hljs-number">72</span>, <span class="hljs-number">81</span>, <span class="hljs-number">68</span>, <span class="hljs-number">68</span>, <span class="hljs-number">64</span>, <span class="hljs-number">69</span>, <span class="hljs-number">64</span>, <span class="hljs-number">66</span>, <span class="hljs-number">65</span>, <span class="hljs-number">70</span>, <span class="hljs-number">80</span>, <span class="hljs-number">71</span>, <span class="hljs-number">59</span>, <span class="hljs-number">70</span>, <span class="hljs-number">69</span>, <span class="hljs-number">64</span>, <span class="hljs-number">78</span>, <span class="hljs-number">68</span>, <span class="hljs-number">71</span>, <span class="hljs-number">69</span>, <span class="hljs-number">69</span>, <span class="hljs-number">75</span>, <span class="hljs-number">62</span>, <span class="hljs-number">65</span>, <span class="hljs-number">59</span>, <span class="hljs-number">77</span>, <span class="hljs-number">62</span>, <span class="hljs-number">70</span>, <span class="hljs-number">72</span>, <span class="hljs-number">76</span>, <span class="hljs-number">84</span>, <span class="hljs-number">78</span>, <span class="hljs-number">60</span>, <span class="hljs-number">69</span>, <span class="hljs-number">74</span>, <span class="hljs-number">76</span>, <span class="hljs-number">76</span>, <span class="hljs-number">73</span>, <span class="hljs-number">73</span>, <span class="hljs-number">86</span>, <span class="hljs-number">65</span>, <span class="hljs-number">72</span>, <span class="hljs-number">72</span>, <span class="hljs-number">64</span>, <span class="hljs-number">82</span>, <span class="hljs-number">81</span>, <span class="hljs-number">73</span>, <span class="hljs-number">62</span>, <span class="hljs-number">65</span>, <span class="hljs-number">68</span>, <span class="hljs-number">74</span>, <span class="hljs-number">65</span>, <span class="hljs-number">73</span>, <span class="hljs-number">66</span>, <span class="hljs-number">80</span>, <span class="hljs-number">64</span>, <span class="hljs-number">65</span>, <span class="hljs-number">69</span>, <span class="hljs-number">65</span>, <span class="hljs-number">74</span>, <span class="hljs-number">74</span>, <span class="hljs-number">71</span>, <span class="hljs-number">65</span>, <span class="hljs-number">63</span>, <span class="hljs-number">66</span>, <span class="hljs-number">72</span>, <span class="hljs-number">72</span>, <span class="hljs-number">77</span>, <span class="hljs-number">77</span>, <span class="hljs-number">68</span>, <span class="hljs-number">75</span>, <span class="hljs-number">68</span>, <span class="hljs-number">72</span>, <span class="hljs-number">62</span>, <span class="hljs-number">68</span>, <span class="hljs-number">59</span>, <span class="hljs-number">68</span>, <span class="hljs-number">59</span>, <span class="hljs-number">73</span>, <span class="hljs-number">71</span>, <span class="hljs-number">82</span>, <span class="hljs-number">73</span>, <span class="hljs-number">71</span>, <span class="hljs-number">74</span>, <span class="hljs-number">73</span>, <span class="hljs-number">73</span>, <span class="hljs-number">71</span>, <span class="hljs-number">71</span>, <span class="hljs-number">75</span>, <span class="hljs-number">81</span>, <span class="hljs-number">72</span>, <span class="hljs-number">76</span>, <span class="hljs-number">75</span>, <span class="hljs-number">75</span>, <span class="hljs-number">84</span>, <span class="hljs-number">68</span>, <span class="hljs-number">65</span>, <span class="hljs-number">76</span>, <span class="hljs-number">71</span>, <span class="hljs-number">64</span>, <span class="hljs-number">67</span>, <span class="hljs-number">65</span>, <span class="hljs-number">65</span>, <span class="hljs-number">76</span>, <span class="hljs-number">80</span>, <span class="hljs-number">66</span>, <span class="hljs-number">80</span>, <span class="hljs-number">63</span>, <span class="hljs-number">72</span>, <span class="hljs-number">61</span>, <span class="hljs-number">76</span>, <span class="hljs-number">73</span>, <span class="hljs-number">61</span>, <span class="hljs-number">70</span>, <span class="hljs-number">72</span>, <span class="hljs-number">75</span>, <span class="hljs-number">71</span>, <span class="hljs-number">53</span>, <span class="hljs-number">73</span>, <span class="hljs-number">84</span>, <span class="hljs-number">74</span>, <span class="hljs-number">67</span>, <span class="hljs-number">68</span>, <span class="hljs-number">64</span>, <span class="hljs-number">70</span>, <span class="hljs-number">74</span>, <span class="hljs-number">68</span>, <span class="hljs-number">75</span>, <span class="hljs-number">63</span>, <span class="hljs-number">71</span>, <span class="hljs-number">73</span>, <span class="hljs-number">63</span>, <span class="hljs-number">72</span>, <span class="hljs-number">61</span>, <span class="hljs-number">68</span>, <span class="hljs-number">67</span>, <span class="hljs-number">62</span>, <span class="hljs-number">79</span>, <span class="hljs-number">65</span>, <span class="hljs-number">72</span>, <span class="hljs-number">72</span>, <span class="hljs-number">66</span>, <span class="hljs-number">69</span>, <span class="hljs-number">71</span>, <span class="hljs-number">68</span>, <span class="hljs-number">65</span>, <span class="hljs-number">81</span>, <span class="hljs-number">69</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">61</span>, <span class="hljs-number">77</span>, <span class="hljs-number">73</span>, <span class="hljs-number">80</span>, <span class="hljs-number">73</span>, <span class="hljs-number">74</span>, <span class="hljs-number">60</span>, <span class="hljs-number">68</span>, <span class="hljs-number">71</span>, <span class="hljs-number">69</span>, <span class="hljs-number">81</span>, <span class="hljs-number">87</span>, <span class="hljs-number">66</span>, <span class="hljs-number">66</span>, <span class="hljs-number">71</span>, <span class="hljs-number">67</span>, <span class="hljs-number">65</span>, <span class="hljs-number">77</span>, <span class="hljs-number">67</span>, <span class="hljs-number">75</span>, <span class="hljs-number">66</span>, <span class="hljs-number">74</span>, <span class="hljs-number">77</span>, <span class="hljs-number">62</span>, <span class="hljs-number">72</span>, <span class="hljs-number">71</span>, <span class="hljs-number">80</span>, <span class="hljs-number">73</span>, <span class="hljs-number">64</span>, <span class="hljs-number">75</span>, <span class="hljs-number">69</span>, <span class="hljs-number">62</span>, <span class="hljs-number">67</span>, <span class="hljs-number">71</span>, <span class="hljs-number">70</span>, <span class="hljs-number">68</span>, <span class="hljs-number">64</span>, <span class="hljs-number">61</span>, <span class="hljs-number">80</span>, <span class="hljs-number">68</span>, <span class="hljs-number">83</span>, <span class="hljs-number">62</span>, <span class="hljs-number">70</span>, <span class="hljs-number">66</span>, <span class="hljs-number">75</span>, <span class="hljs-number">70</span>, <span class="hljs-number">61</span>, <span class="hljs-number">71</span>, <span class="hljs-number">64</span>, <span class="hljs-number">56</span>, <span class="hljs-number">55</span>, <span class="hljs-number">75</span>, <span class="hljs-number">78</span>, <span class="hljs-number">73</span>, <span class="hljs-number">62</span>, <span class="hljs-number">71</span>, <span class="hljs-number">67</span>, <span class="hljs-number">73</span>, <span class="hljs-number">65</span>, <span class="hljs-number">71</span>, <span class="hljs-number">67</span>, <span class="hljs-number">69</span>, <span class="hljs-number">66</span>, <span class="hljs-number">71</span>, <span class="hljs-number">69</span>, <span class="hljs-number">72</span>, <span class="hljs-number">77</span>, <span class="hljs-number">70</span>, <span class="hljs-number">68</span>, <span class="hljs-number">74</span>, <span class="hljs-number">70</span>, <span class="hljs-number">69</span>, <span class="hljs-number">68</span>, <span class="hljs-number">71</span>, <span class="hljs-number">80</span>, <span class="hljs-number">63</span>, <span class="hljs-number">70</span>, <span class="hljs-number">64</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">68</span>, <span class="hljs-number">71</span>, <span class="hljs-number">65</span>, <span class="hljs-number">67</span>, <span class="hljs-number">63</span>, <span class="hljs-number">64</span>, <span class="hljs-number">73</span>, <span class="hljs-number">71</span>, <span class="hljs-number">62</span>, <span class="hljs-number">85</span>, <span class="hljs-number">73</span>, <span class="hljs-number">75</span>, <span class="hljs-number">73</span>, <span class="hljs-number">78</span>, <span class="hljs-number">69</span>, <span class="hljs-number">69</span>, <span class="hljs-number">77</span>, <span class="hljs-number">69</span>, <span class="hljs-number">70</span>, <span class="hljs-number">66</span>, <span class="hljs-number">61</span>, <span class="hljs-number">70</span>, <span class="hljs-number">71</span>, <span class="hljs-number">72</span>, <span class="hljs-number">68</span>, <span class="hljs-number">64</span>, <span class="hljs-number">60</span>, <span class="hljs-number">58</span>, <span class="hljs-number">68</span>, <span class="hljs-number">67</span>, <span class="hljs-number">71</span>, <span class="hljs-number">82</span>, <span class="hljs-number">60</span>, <span class="hljs-number">65</span>, <span class="hljs-number">73</span>, <span class="hljs-number">70</span>, <span class="hljs-number">74</span>, <span class="hljs-number">71</span>, <span class="hljs-number">69</span>, <span class="hljs-number">81</span>, <span class="hljs-number">60</span>, <span class="hljs-number">76</span>, <span class="hljs-number">70</span>, <span class="hljs-number">62</span>, <span class="hljs-number">67</span>, <span class="hljs-number">66</span>, <span class="hljs-number">67</span>, <span class="hljs-number">63</span>, <span class="hljs-number">72</span>, <span class="hljs-number">71</span>, <span class="hljs-number">62</span>, <span class="hljs-number">63</span>, <span class="hljs-number">65</span>, <span class="hljs-number">70</span>, <span class="hljs-number">66</span>, <span class="hljs-number">68</span>, <span class="hljs-number">79</span>, <span class="hljs-number">76</span>, <span class="hljs-number">79</span>, <span class="hljs-number">70</span>, <span class="hljs-number">68</span>, <span class="hljs-number">62</span>, <span class="hljs-number">66</span>, <span class="hljs-number">66</span>, <span class="hljs-number">75</span>, <span class="hljs-number">77</span>, <span class="hljs-number">68</span>, <span class="hljs-number">67</span>, <span class="hljs-number">73</span>, <span class="hljs-number">80</span>, <span class="hljs-number">58</span>, <span class="hljs-number">64</span>, <span class="hljs-number">78</span>, <span class="hljs-number">69</span>, <span class="hljs-number">65</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">75</span>, <span class="hljs-number">64</span>, <span class="hljs-number">59</span>, <span class="hljs-number">66</span>, <span class="hljs-number">74</span>, <span class="hljs-number">66</span>, <span class="hljs-number">84</span>, <span class="hljs-number">57</span>, <span class="hljs-number">79</span>, <span class="hljs-number">80</span>, <span class="hljs-number">63</span>, <span class="hljs-number">83</span>, <span class="hljs-number">84</span>, <span class="hljs-number">77</span>, <span class="hljs-number">74</span>, <span class="hljs-number">64</span>, <span class="hljs-number">67</span>, <span class="hljs-number">79</span>, <span class="hljs-number">64</span>, <span class="hljs-number">73</span>, <span class="hljs-number">70</span>, <span class="hljs-number">74</span>, <span class="hljs-number">75</span>, <span class="hljs-number">63</span>, <span class="hljs-number">68</span>, <span class="hljs-number">63</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">66</span>, <span class="hljs-number">77</span>, <span class="hljs-number">70</span>, <span class="hljs-number">71</span>, <span class="hljs-number">79</span>, <span class="hljs-number">68</span>, <span class="hljs-number">70</span>, <span class="hljs-number">69</span>, <span class="hljs-number">66</span>, <span class="hljs-number">69</span>, <span class="hljs-number">69</span>, <span class="hljs-number">59</span>, <span class="hljs-number">73</span>, <span class="hljs-number">63</span>, <span class="hljs-number">73</span>, <span class="hljs-number">70</span>, <span class="hljs-number">63</span>, <span class="hljs-number">80</span>, <span class="hljs-number">78</span>, <span class="hljs-number">70</span>, <span class="hljs-number">77</span>, <span class="hljs-number">71</span>, <span class="hljs-number">68</span>, <span class="hljs-number">66</span>, <span class="hljs-number">78</span>, <span class="hljs-number">72</span>, <span class="hljs-number">71</span>, <span class="hljs-number">63</span>, <span class="hljs-number">77</span>, <span class="hljs-number">68</span>, <span class="hljs-number">71</span>, <span class="hljs-number">66</span>, <span class="hljs-number">73</span>, <span class="hljs-number">80</span>, <span class="hljs-number">77</span>, <span class="hljs-number">73</span>, <span class="hljs-number">70</span>, <span class="hljs-number">63</span>, <span class="hljs-number">61</span>, <span class="hljs-number">71</span>, <span class="hljs-number">67</span>, <span class="hljs-number">62</span>, <span class="hljs-number">80</span>, <span class="hljs-number">79</span>, <span class="hljs-number">62</span>, <span class="hljs-number">72</span>, <span class="hljs-number">61</span>, <span class="hljs-number">66</span>, <span class="hljs-number">69</span>, <span class="hljs-number">72</span>, <span class="hljs-number">75</span>, <span class="hljs-number">69</span>, <span class="hljs-number">76</span>, <span class="hljs-number">80</span>, <span class="hljs-number">76</span>, <span class="hljs-number">80</span>, <span class="hljs-number">76</span>, <span class="hljs-number">66</span>, <span class="hljs-number">77</span>, <span class="hljs-number">62</span>, <span class="hljs-number">72</span>, <span class="hljs-number">75</span>, <span class="hljs-number">62</span>, <span class="hljs-number">62</span>, <span class="hljs-number">61</span>, <span class="hljs-number">74</span>, <span class="hljs-number">72</span>, <span class="hljs-number">64</span>, <span class="hljs-number">70</span>, <span class="hljs-number">63</span>, <span class="hljs-number">69</span>, <span class="hljs-number">72</span>, <span class="hljs-number">73</span>, <span class="hljs-number">78</span>, <span class="hljs-number">63</span>, <span class="hljs-number">73</span>, <span class="hljs-number">63</span>, <span class="hljs-number">65</span>, <span class="hljs-number">69</span>, <span class="hljs-number">66</span>, <span class="hljs-number">72</span>, <span class="hljs-number">70</span>, <span class="hljs-number">85</span>, <span class="hljs-number">67</span>, <span class="hljs-number">63</span>, <span class="hljs-number">69</span>, <span class="hljs-number">72</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">75</span>, <span class="hljs-number">76</span>, <span class="hljs-number">63</span>, <span class="hljs-number">66</span>, <span class="hljs-number">70</span>, <span class="hljs-number">67</span>, <span class="hljs-number">76</span>, <span class="hljs-number">74</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">75</span>, <span class="hljs-number">67</span>, <span class="hljs-number">61</span>, <span class="hljs-number">61</span>, <span class="hljs-number">74</span>, <span class="hljs-number">77</span>, <span class="hljs-number">61</span>, <span class="hljs-number">68</span>, <span class="hljs-number">69</span>, <span class="hljs-number">78</span>, <span class="hljs-number">73</span>, <span class="hljs-number">76</span>, <span class="hljs-number">70</span>, <span class="hljs-number">63</span>, <span class="hljs-number">76</span>, <span class="hljs-number">62</span>, <span class="hljs-number">79</span>, <span class="hljs-number">73</span>, <span class="hljs-number">66</span>, <span class="hljs-number">79</span>, <span class="hljs-number">71</span>, <span class="hljs-number">64</span>, <span class="hljs-number">61</span>, <span class="hljs-number">69</span>, <span class="hljs-number">72</span>, <span class="hljs-number">72</span>, <span class="hljs-number">71</span>, <span class="hljs-number">75</span>, <span class="hljs-number">66</span>, <span class="hljs-number">77</span>, <span class="hljs-number">62</span>, <span class="hljs-number">63</span>, <span class="hljs-number">63</span>, <span class="hljs-number">64</span>, <span class="hljs-number">60</span>, <span class="hljs-number">69</span>, <span class="hljs-number">67</span>, <span class="hljs-number">72</span>, <span class="hljs-number">82</span>, <span class="hljs-number">75</span>, <span class="hljs-number">81</span>, <span class="hljs-number">76</span>, <span class="hljs-number">65</span>, <span class="hljs-number">66</span>, <span class="hljs-number">71</span>, <span class="hljs-number">82</span>, <span class="hljs-number">78</span>, <span class="hljs-number">59</span>, <span class="hljs-number">70</span>, <span class="hljs-number">72</span>, <span class="hljs-number">74</span>, <span class="hljs-number">73</span>, <span class="hljs-number">80</span>, <span class="hljs-number">75</span>, <span class="hljs-number">70</span>, <span class="hljs-number">78</span>, <span class="hljs-number">86</span>, <span class="hljs-number">77</span>, <span class="hljs-number">66</span>, <span class="hljs-number">68</span>, <span class="hljs-number">71</span>, <span class="hljs-number">68</span>, <span class="hljs-number">67</span>, <span class="hljs-number">78</span>, <span class="hljs-number">64</span>, <span class="hljs-number">71</span>, <span class="hljs-number">65</span>, <span class="hljs-number">64</span>, <span class="hljs-number">73</span>, <span class="hljs-number">73</span>, <span class="hljs-number">60</span>, <span class="hljs-number">72</span>, <span class="hljs-number">70</span>, <span class="hljs-number">76</span>, <span class="hljs-number">75</span>, <span class="hljs-number">68</span>, <span class="hljs-number">70</span>, <span class="hljs-number">60</span>, <span class="hljs-number">71</span>, <span class="hljs-number">57</span>, <span class="hljs-number">78</span>, <span class="hljs-number">74</span>, <span class="hljs-number">71</span>, <span class="hljs-number">70</span>, <span class="hljs-number">71</span>, <span class="hljs-number">59</span>, <span class="hljs-number">73</span>, <span class="hljs-number">76</span>, <span class="hljs-number">64</span>, <span class="hljs-number">76</span>, <span class="hljs-number">76</span>, <span class="hljs-number">70</span>, <span class="hljs-number">75</span>, <span class="hljs-number">65</span>, <span class="hljs-number">62</span>, <span class="hljs-number">70</span>, <span class="hljs-number">62</span>, <span class="hljs-number">64</span>, <span class="hljs-number">69</span>, <span class="hljs-number">68</span>, <span class="hljs-number">78</span>, <span class="hljs-number">81</span>, <span class="hljs-number">72</span>, <span class="hljs-number">67</span>, <span class="hljs-number">84</span>, <span class="hljs-number">67</span>, <span class="hljs-number">79</span>, <span class="hljs-number">65</span>, <span class="hljs-number">72</span>, <span class="hljs-number">62</span>, <span class="hljs-number">65</span>, <span class="hljs-number">71</span>, <span class="hljs-number">69</span>, <span class="hljs-number">61</span>, <span class="hljs-number">65</span>, <span class="hljs-number">58</span>, <span class="hljs-number">68</span>, <span class="hljs-number">68</span>, <span class="hljs-number">75</span>, <span class="hljs-number">60</span>, <span class="hljs-number">73</span>, <span class="hljs-number">63</span>, <span class="hljs-number">68</span>, <span class="hljs-number">87</span>, <span class="hljs-number">71</span>, <span class="hljs-number">69</span>, <span class="hljs-number">70</span>, <span class="hljs-number">61</span>, <span class="hljs-number">77</span>, <span class="hljs-number">75</span>, <span class="hljs-number">75</span>, <span class="hljs-number">72</span>, <span class="hljs-number">66</span>, <span class="hljs-number">75</span>, <span class="hljs-number">82</span>, <span class="hljs-number">71</span>, <span class="hljs-number">73</span>, <span class="hljs-number">61</span>, <span class="hljs-number">66</span>, <span class="hljs-number">81</span>, <span class="hljs-number">79</span>, <span class="hljs-number">71</span>, <span class="hljs-number">67</span>, <span class="hljs-number">66</span>, <span class="hljs-number">77</span>, <span class="hljs-number">64</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">76</span>, <span class="hljs-number">69</span>, <span class="hljs-number">76</span>, <span class="hljs-number">74</span>, <span class="hljs-number">77</span>, <span class="hljs-number">71</span>, <span class="hljs-number">78</span>, <span class="hljs-number">70</span>, <span class="hljs-number">67</span>, <span class="hljs-number">64</span>, <span class="hljs-number">75</span>, <span class="hljs-number">69</span>, <span class="hljs-number">84</span>, <span class="hljs-number">64</span>, <span class="hljs-number">74</span>, <span class="hljs-number">65</span>, <span class="hljs-number">69</span>, <span class="hljs-number">73</span>, <span class="hljs-number">66</span>, <span class="hljs-number">77</span>, <span class="hljs-number">63</span>, <span class="hljs-number">74</span>, <span class="hljs-number">67</span>, <span class="hljs-number">61</span>, <span class="hljs-number">68</span>, <span class="hljs-number">59</span>, <span class="hljs-number">64</span>, <span class="hljs-number">59</span>, <span class="hljs-number">66</span>, <span class="hljs-number">65</span>, <span class="hljs-number">55</span>, <span class="hljs-number">66</span>, <span class="hljs-number">71</span>, <span class="hljs-number">75</span>, <span class="hljs-number">65</span>, <span class="hljs-number">58</span>, <span class="hljs-number">68</span>, <span class="hljs-number">75</span>, <span class="hljs-number">79</span>, <span class="hljs-number">69</span>, <span class="hljs-number">69</span>, <span class="hljs-number">67</span>, <span class="hljs-number">75</span>, <span class="hljs-number">71</span>, <span class="hljs-number">78</span>, <span class="hljs-number">75</span>, <span class="hljs-number">68</span>, <span class="hljs-number">54</span>, <span class="hljs-number">72</span>, <span class="hljs-number">75</span>, <span class="hljs-number">75</span>, <span class="hljs-number">62</span>, <span class="hljs-number">81</span>, <span class="hljs-number">67</span>, <span class="hljs-number">66</span>, <span class="hljs-number">78</span>, <span class="hljs-number">75</span>, <span class="hljs-number">59</span>, <span class="hljs-number">64</span>, <span class="hljs-number">74</span>, <span class="hljs-number">65</span>, <span class="hljs-number">67</span>, <span class="hljs-number">72</span>, <span class="hljs-number">67</span>, <span class="hljs-number">79</span>, <span class="hljs-number">66</span>, <span class="hljs-number">51</span>, <span class="hljs-number">72</span>, <span class="hljs-number">65</span>, <span class="hljs-number">64</span>, <span class="hljs-number">66</span>, <span class="hljs-number">61</span>, <span class="hljs-number">71</span>, <span class="hljs-number">67</span>, <span class="hljs-number">67</span>, <span class="hljs-number">65</span>, <span class="hljs-number">63</span>, <span class="hljs-number">68</span>, <span class="hljs-number">82</span>, <span class="hljs-number">62</span>, <span class="hljs-number">69</span>, <span class="hljs-number">87</span>, <span class="hljs-number">66</span>, <span class="hljs-number">72</span>, <span class="hljs-number">65</span>, <span class="hljs-number">58</span>, <span class="hljs-number">70</span>, <span class="hljs-number">83</span>, <span class="hljs-number">76</span>, <span class="hljs-number">70</span>, <span class="hljs-number">69</span>, <span class="hljs-number">75</span>, <span class="hljs-number">72</span>, <span class="hljs-number">63</span>, <span class="hljs-number">65</span>, <span class="hljs-number">66</span>, <span class="hljs-number">80</span>, <span class="hljs-number">72</span>, <span class="hljs-number">76</span>, <span class="hljs-number">68</span>, <span class="hljs-number">66</span>, <span class="hljs-number">78</span>, <span class="hljs-number">64</span>, <span class="hljs-number">73</span>, <span class="hljs-number">68</span>, <span class="hljs-number">69</span>, <span class="hljs-number">66</span>, <span class="hljs-number">80</span>, <span class="hljs-number">80</span>, <span class="hljs-number">68</span>, <span class="hljs-number">56</span>, <span class="hljs-number">67</span>, <span class="hljs-number">78</span>, <span class="hljs-number">59</span>, <span class="hljs-number">71</span>, <span class="hljs-number">70</span>, <span class="hljs-number">64</span>, <span class="hljs-number">81</span>, <span class="hljs-number">77</span>, <span class="hljs-number">78</span>, <span class="hljs-number">74</span>, <span class="hljs-number">61</span>, <span class="hljs-number">69</span>, <span class="hljs-number">70</span>, <span class="hljs-number">79</span>, <span class="hljs-number">61</span>, <span class="hljs-number">63</span>, <span class="hljs-number">71</span>, <span class="hljs-number">66</span>, <span class="hljs-number">74</span>, <span class="hljs-number">70</span>, <span class="hljs-number">69</span>, <span class="hljs-number">77</span>, <span class="hljs-number">76</span>, <span class="hljs-number">77</span>, <span class="hljs-number">75</span>, <span class="hljs-number">69</span>, <span class="hljs-number">77</span>, <span class="hljs-number">69</span>, <span class="hljs-number">68</span>, <span class="hljs-number">71</span>, <span class="hljs-number">77</span>, <span class="hljs-number">64</span>, <span class="hljs-number">65</span>, <span class="hljs-number">72</span>, <span class="hljs-number">69</span>, <span class="hljs-number">79</span>, <span class="hljs-number">68</span>, <span class="hljs-number">79</span>, <span class="hljs-number">68</span>, <span class="hljs-number">78</span>, <span class="hljs-number">73</span>, <span class="hljs-number">62</span>, <span class="hljs-number">58</span>, <span class="hljs-number">55</span>, <span class="hljs-number">76</span>, <span class="hljs-number">85</span>, <span class="hljs-number">75</span>, <span class="hljs-number">72</span>, <span class="hljs-number">77</span>, <span class="hljs-number">67</span>, <span class="hljs-number">68</span>, <span class="hljs-number">66</span>, <span class="hljs-number">83</span>, <span class="hljs-number">63</span>, <span class="hljs-number">88</span>, <span class="hljs-number">67</span>, <span class="hljs-number">77</span>, <span class="hljs-number">75</span>, <span class="hljs-number">80</span>, <span class="hljs-number">66</span>, <span class="hljs-number">86</span>, <span class="hljs-number">65</span>, <span class="hljs-number">77</span>, <span class="hljs-number">67</span>, <span class="hljs-number">63</span>, <span class="hljs-number">72</span>, <span class="hljs-number">75</span>, <span class="hljs-number">66</span>, <span class="hljs-number">68</span>, <span class="hljs-number">65</span>, <span class="hljs-number">71</span>, <span class="hljs-number">73</span>, <span class="hljs-number">72</span>, <span class="hljs-number">68</span>, <span class="hljs-number">80</span>, <span class="hljs-number">68</span>, <span class="hljs-number">81</span>, <span class="hljs-number">74</span>, <span class="hljs-number">73</span>, <span class="hljs-number">73</span>, <span class="hljs-number">77</span>, <span class="hljs-number">74</span>, <span class="hljs-number">68</span>, <span class="hljs-number">77</span>, <span class="hljs-number">70</span>, <span class="hljs-number">66</span>, <span class="hljs-number">72</span>, <span class="hljs-number">71</span>, <span class="hljs-number">77</span>, <span class="hljs-number">62</span>, <span class="hljs-number">65</span>, <span class="hljs-number">72</span>, <span class="hljs-number">78</span>, <span class="hljs-number">77</span>, <span class="hljs-number">69</span>, <span class="hljs-number">67</span>, <span class="hljs-number">78</span>, <span class="hljs-number">72</span>, <span class="hljs-number">66</span>, <span class="hljs-number">70</span>, <span class="hljs-number">64</span>, <span class="hljs-number">74</span>, <span class="hljs-number">75</span>, <span class="hljs-number">69</span>, <span class="hljs-number">66</span>, <span class="hljs-number">67</span>, <span class="hljs-number">72</span>, <span class="hljs-number">78</span>, <span class="hljs-number">65</span>, <span class="hljs-number">57</span>, <span class="hljs-number">74</span>, <span class="hljs-number">67</span>, <span class="hljs-number">61</span>, <span class="hljs-number">72</span>, <span class="hljs-number">66</span>, <span class="hljs-number">63</span>, <span class="hljs-number">66</span>, <span class="hljs-number">67</span>, <span class="hljs-number">72</span>, <span class="hljs-number">75</span>, <span class="hljs-number">65</span>, <span class="hljs-number">66</span>, <span class="hljs-number">75</span>, <span class="hljs-number">69</span>, <span class="hljs-number">62</span>, <span class="hljs-number">68</span>, <span class="hljs-number">61</span>, <span class="hljs-number">67</span>, <span class="hljs-number">67</span>, <span class="hljs-number">77</span>, <span class="hljs-number">70</span>, <span class="hljs-number">71</span>, <span class="hljs-number">65</span>, <span class="hljs-number">66</span>, <span class="hljs-number">66</span>, <span class="hljs-number">77</span>, <span class="hljs-number">68</span>, <span class="hljs-number">67</span>, <span class="hljs-number">74</span>, <span class="hljs-number">68</span>, <span class="hljs-number">70</span>, <span class="hljs-number">78</span>, <span class="hljs-number">60</span>, <span class="hljs-number">78</span>, <span class="hljs-number">69</span>, <span class="hljs-number">75</span>, <span class="hljs-number">73</span>, <span class="hljs-number">66</span>, <span class="hljs-number">76</span>, <span class="hljs-number">69</span>, <span class="hljs-number">66</span>, <span class="hljs-number">67</span>, <span class="hljs-number">65</span>, <span class="hljs-number">72</span>, <span class="hljs-number">74</span>, <span class="hljs-number">61</span>, <span class="hljs-number">65</span>, <span class="hljs-number">73</span>, <span class="hljs-number">77</span>, <span class="hljs-number">80</span>, <span class="hljs-number">75</span>, <span class="hljs-number">72</span>, <span class="hljs-number">66</span>, <span class="hljs-number">66</span>, <span class="hljs-number">70</span>, <span class="hljs-number">73</span>, <span class="hljs-number">77</span>, <span class="hljs-number">72</span>, <span class="hljs-number">67</span>, <span class="hljs-number">75</span>, <span class="hljs-number">71</span>, <span class="hljs-number">75</span>, <span class="hljs-number">68</span>, <span class="hljs-number">70</span>, <span class="hljs-number">77</span>, <span class="hljs-number">72</span>, <span class="hljs-number">64</span>, <span class="hljs-number">69</span>, <span class="hljs-number">66</span>, <span class="hljs-number">71</span>, <span class="hljs-number">61</span>, <span class="hljs-number">81</span>, <span class="hljs-number">74</span>, <span class="hljs-number">63</span>, <span class="hljs-number">65</span>, <span class="hljs-number">71</span>, <span class="hljs-number">77</span>, <span class="hljs-number">56</span>, <span class="hljs-number">81</span>, <span class="hljs-number">66</span>, <span class="hljs-number">64</span>, <span class="hljs-number">79</span>, <span class="hljs-number">72</span>, <span class="hljs-number">74</span>, <span class="hljs-number">64</span>, <span class="hljs-number">66</span>, <span class="hljs-number">74</span>, <span class="hljs-number">75</span>, <span class="hljs-number">71</span>, <span class="hljs-number">77</span>, <span class="hljs-number">74</span>, <span class="hljs-number">63</span>, <span class="hljs-number">86</span>, <span class="hljs-number">78</span>, <span class="hljs-number">85</span>, <span class="hljs-number">74</span>, <span class="hljs-number">68</span>, <span class="hljs-number">85</span>, <span class="hljs-number">63</span>, <span class="hljs-number">73</span>, <span class="hljs-number">61</span>, <span class="hljs-number">66</span>, <span class="hljs-number">68</span>, <span class="hljs-number">80</span>, <span class="hljs-number">69</span>, <span class="hljs-number">74</span>, <span class="hljs-number">65</span>, <span class="hljs-number">67</span>, <span class="hljs-number">57</span>, <span class="hljs-number">71</span>, <span class="hljs-number">70</span>, <span class="hljs-number">71</span>, <span class="hljs-number">68</span>, <span class="hljs-number">61</span>, <span class="hljs-number">62</span>, <span class="hljs-number">58</span>, <span class="hljs-number">65</span>, <span class="hljs-number">79</span>, <span class="hljs-number">77</span>, <span class="hljs-number">68</span>, <span class="hljs-number">64</span>, <span class="hljs-number">66</span>, <span class="hljs-number">72</span>, <span class="hljs-number">67</span>, <span class="hljs-number">74</span>, <span class="hljs-number">59</span>, <span class="hljs-number">73</span>, <span class="hljs-number">76</span>, <span class="hljs-number">69</span>, <span class="hljs-number">65</span>, <span class="hljs-number">74</span>, <span class="hljs-number">72</span>, <span class="hljs-number">66</span>, <span class="hljs-number">79</span>, <span class="hljs-number">79</span>, <span class="hljs-number">67</span>, <span class="hljs-number">72</span>, <span class="hljs-number">67</span>, <span class="hljs-number">68</span>, <span class="hljs-number">70</span>, <span class="hljs-number">60</span>, <span class="hljs-number">78</span>, <span class="hljs-number">78</span>, <span class="hljs-number">73</span>, <span class="hljs-number">74</span>, <span class="hljs-number">70</span>, <span class="hljs-number">50</span>, <span class="hljs-number">75</span>, <span class="hljs-number">68</span>, <span class="hljs-number">83</span>, <span class="hljs-number">71</span>, <span class="hljs-number">77</span>, <span class="hljs-number">66</span>, <span class="hljs-number">77</span>, <span class="hljs-number">80</span>, <span class="hljs-number">81</span>, <span class="hljs-number">69</span>, <span class="hljs-number">65</span>, <span class="hljs-number">70</span>, <span class="hljs-number">65</span>, <span class="hljs-number">63</span>, <span class="hljs-number">67</span>, <span class="hljs-number">65</span>, <span class="hljs-number">83</span>, <span class="hljs-number">69</span>, <span class="hljs-number">54</span>, <span class="hljs-number">74</span>, <span class="hljs-number">73</span>, <span class="hljs-number">71</span>, <span class="hljs-number">66</span>, <span class="hljs-number">70</span>, <span class="hljs-number">82</span>, <span class="hljs-number">54</span>, <span class="hljs-number">66</span>, <span class="hljs-number">69</span>, <span class="hljs-number">66</span>, <span class="hljs-number">62</span>, <span class="hljs-number">69</span>, <span class="hljs-number">67</span>, <span class="hljs-number">71</span>, <span class="hljs-number">61</span>, <span class="hljs-number">73</span>, <span class="hljs-number">72</span>, <span class="hljs-number">71</span>, <span class="hljs-number">65</span>, <span class="hljs-number">78</span>, <span class="hljs-number">70</span>, <span class="hljs-number">77</span>, <span class="hljs-number">70</span>, <span class="hljs-number">68</span>, <span class="hljs-number">66</span>, <span class="hljs-number">69</span>, <span class="hljs-number">71</span>, <span class="hljs-number">60</span>, <span class="hljs-number">68</span>, <span class="hljs-number">73</span>, <span class="hljs-number">69</span>, <span class="hljs-number">74</span>, <span class="hljs-number">67</span>, <span class="hljs-number">69</span>, <span class="hljs-number">73</span>, <span class="hljs-number">72</span>, <span class="hljs-number">73</span>, <span class="hljs-number">69</span>, <span class="hljs-number">65</span>, <span class="hljs-number">55</span>, <span class="hljs-number">74</span>, <span class="hljs-number">71</span>, <span class="hljs-number">67</span>, <span class="hljs-number">73</span>, <span class="hljs-number">62</span>, <span class="hljs-number">74</span>, <span class="hljs-number">75</span>, <span class="hljs-number">65</span>, <span class="hljs-number">70</span>, <span class="hljs-number">72</span>, <span class="hljs-number">69</span>, <span class="hljs-number">64</span>, <span class="hljs-number">70</span>, <span class="hljs-number">72</span>, <span class="hljs-number">73</span>, <span class="hljs-number">75</span>, <span class="hljs-number">70</span>, <span class="hljs-number">68</span>, <span class="hljs-number">66</span>, <span class="hljs-number">71</span>, <span class="hljs-number">81</span>, <span class="hljs-number">68</span>, <span class="hljs-number">80</span>, <span class="hljs-number">78</span>, <span class="hljs-number">72</span>, <span class="hljs-number">66</span>, <span class="hljs-number">65</span>, <span class="hljs-number">66</span>, <span class="hljs-number">64</span>, <span class="hljs-number">63</span>, <span class="hljs-number">74</span>, <span class="hljs-number">72</span>, <span class="hljs-number">67</span>, <span class="hljs-number">76</span>, <span class="hljs-number">76</span>, <span class="hljs-number">69</span>, <span class="hljs-number">61</span>, <span class="hljs-number">66</span>, <span class="hljs-number">75</span>, <span class="hljs-number">69</span>, <span class="hljs-number">66</span>, <span class="hljs-number">75</span>, <span class="hljs-number">58</span>, <span class="hljs-number">78</span>, <span class="hljs-number">67</span>, <span class="hljs-number">68</span>, <span class="hljs-number">73</span>, <span class="hljs-number">70</span>, <span class="hljs-number">77</span>, <span class="hljs-number">70</span>, <span class="hljs-number">80</span>, <span class="hljs-number">80</span>, <span class="hljs-number">73</span>, <span class="hljs-number">70</span>, <span class="hljs-number">66</span>, <span class="hljs-number">71</span>, <span class="hljs-number">72</span>, <span class="hljs-number">73</span>, <span class="hljs-number">63</span>, <span class="hljs-number">75</span>, <span class="hljs-number">66</span>, <span class="hljs-number">65</span>, <span class="hljs-number">87</span>, <span class="hljs-number">82</span>, <span class="hljs-number">75</span>, <span class="hljs-number">60</span>, <span class="hljs-number">65</span>, <span class="hljs-number">71</span>, <span class="hljs-number">67</span>, <span class="hljs-number">78</span>, <span class="hljs-number">77</span>, <span class="hljs-number">74</span>, <span class="hljs-number">65</span>, <span class="hljs-number">74</span>, <span class="hljs-number">68</span>, <span class="hljs-number">74</span>, <span class="hljs-number">76</span>, <span class="hljs-number">72</span>, <span class="hljs-number">70</span>, <span class="hljs-number">73</span>, <span class="hljs-number">62</span>, <span class="hljs-number">63</span>, <span class="hljs-number">71</span>, <span class="hljs-number">70</span>, <span class="hljs-number">70</span>, <span class="hljs-number">68</span>, <span class="hljs-number">73</span>, <span class="hljs-number">80</span>, <span class="hljs-number">78</span>, <span class="hljs-number">59</span>, <span class="hljs-number">69</span>, <span class="hljs-number">73</span>, <span class="hljs-number">63</span>, <span class="hljs-number">73</span>, <span class="hljs-number">61</span>, <span class="hljs-number">67</span>, <span class="hljs-number">81</span>, <span class="hljs-number">76</span>, <span class="hljs-number">69</span>, <span class="hljs-number">68</span>, <span class="hljs-number">58</span>, <span class="hljs-number">66</span>, <span class="hljs-number">63</span>, <span class="hljs-number">68</span>, <span class="hljs-number">59</span>, <span class="hljs-number">68</span>, <span class="hljs-number">65</span>, <span class="hljs-number">79</span>, <span class="hljs-number">72</span>, <span class="hljs-number">64</span>, <span class="hljs-number">68</span>, <span class="hljs-number">75</span>, <span class="hljs-number">67</span>, <span class="hljs-number">68</span>, <span class="hljs-number">67</span>, <span class="hljs-number">71</span>, <span class="hljs-number">70</span>, <span class="hljs-number">73</span>, <span class="hljs-number">72</span>, <span class="hljs-number">74</span>, <span class="hljs-number">67</span>, <span class="hljs-number">66</span>, <span class="hljs-number">74</span>, <span class="hljs-number">59</span>, <span class="hljs-number">72</span>, <span class="hljs-number">60</span>, <span class="hljs-number">72</span>, <span class="hljs-number">74</span>, <span class="hljs-number">81</span>, <span class="hljs-number">64</span>, <span class="hljs-number">72</span>, <span class="hljs-number">79</span>, <span class="hljs-number">67</span>, <span class="hljs-number">78</span>]
sex = [<span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'F'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>, <span class="hljs-string">'M'</span>]
</code></pre>
<p>Let's split the data into 70/30 sets.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split
X_train, X_test, y_train, y_test = train_test_split(weight, sex, test_size=<span class="hljs-number">0.3</span>, random_state=<span class="hljs-number">0</span>)
</code></pre>
<p>Now let's plot the data for X_train and X_test colored by gender:</p>
<pre><code class="lang-python">plt.hist([x <span class="hljs-keyword">for</span> (x,y) <span class="hljs-keyword">in</span> list(zip(X_train,y_train)) <span class="hljs-keyword">if</span> y==<span class="hljs-string">'M'</span>], color=<span class="hljs-string">'blue'</span>, alpha=<span class="hljs-number">0.5</span>, bins=<span class="hljs-number">15</span>)
plt.hist([x <span class="hljs-keyword">for</span> (x,y) <span class="hljs-keyword">in</span> list(zip(X_train,y_train)) <span class="hljs-keyword">if</span> y==<span class="hljs-string">'F'</span>], color=<span class="hljs-string">'red'</span>, alpha=<span class="hljs-number">0.5</span>, bins=<span class="hljs-number">15</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716773139762/7505e557-18cd-4e3d-b81f-c2135b8dc141.png" alt class="image--center mx-auto" /></p>
<p>Now its time for the histogram for the test set:</p>
<pre><code class="lang-python">plt.hist([x <span class="hljs-keyword">for</span> (x,y) <span class="hljs-keyword">in</span> list(zip(X_test,y_test)) <span class="hljs-keyword">if</span> y==<span class="hljs-string">'M'</span>], color=<span class="hljs-string">'blue'</span>, alpha=<span class="hljs-number">0.5</span>, bins=<span class="hljs-number">15</span>)
plt.hist([x <span class="hljs-keyword">for</span> (x,y) <span class="hljs-keyword">in</span> list(zip(X_test,y_test)) <span class="hljs-keyword">if</span> y==<span class="hljs-string">'F'</span>], color=<span class="hljs-string">'red'</span>, alpha=<span class="hljs-number">0.5</span>, bins=<span class="hljs-number">15</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716773201898/713484f6-08ff-4d67-9ef5-3bdbc6d1de82.png" alt class="image--center mx-auto" /></p>
<p>As you can observe, it's a multimodal distribution. This is something very typical in many scenarios, such as when there are patients with certain diseases (cancer/no cancer) or maybe in the banking industry, to label if a customer will be labeled as declined for a loan (declined/approved).</p>
<p>We can use a Gaussian Mixture, a probabilistic model that assumes all the data points are generated from a mixture of a finite number of Gaussian distributions with unknown parameters. SKlearn already has this implemented, and we only need to tell the <strong><em>Gaussian mixture</em></strong> class how many labels or classes exist in the dataset. In this case, we know there are only two genders (male and female), so we will set the parameter n_components=2. Sklearn will automatically identify both distributions and estimate each distribution's means. The trick is simple: if new data comes for a prediction, the Gaussian Mixture Model will predict with a value Xi is close to one mean or two the other and will assign the label accordingly:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">from</span> sklearn.mixture <span class="hljs-keyword">import</span> GaussianMixture

X = np.array(X_train).reshape(np.array(X_train).shape[<span class="hljs-number">0</span>], <span class="hljs-number">1</span>)
gm = GaussianMixture(n_components=<span class="hljs-number">2</span>, random_state=<span class="hljs-number">0</span>).fit(X)

print(gm.means_)
</code></pre>
<p>This will print gm.means_[0] = 70.18 and gm.means_[1] = 50.12. We can plot the X_train and y_train distribution again with some vertical lines to check if this works correctly.</p>
<pre><code class="lang-python">plt.hist([x <span class="hljs-keyword">for</span> (x,y) <span class="hljs-keyword">in</span> list(zip(X_train,y_train)) <span class="hljs-keyword">if</span> y==<span class="hljs-string">'M'</span>], color=<span class="hljs-string">'blue'</span>, alpha=<span class="hljs-number">0.5</span>, bins=<span class="hljs-number">15</span>)
plt.hist([x <span class="hljs-keyword">for</span> (x,y) <span class="hljs-keyword">in</span> list(zip(X_train,y_train)) <span class="hljs-keyword">if</span> y==<span class="hljs-string">'F'</span>], color=<span class="hljs-string">'red'</span>, alpha=<span class="hljs-number">0.5</span>, bins=<span class="hljs-number">15</span>)

plt.axvline(gm.means_[<span class="hljs-number">0</span>], color=<span class="hljs-string">'k'</span>, linestyle=<span class="hljs-string">'dashed'</span>, linewidth=<span class="hljs-number">1</span>)
plt.axvline(gm.means_[<span class="hljs-number">1</span>], color=<span class="hljs-string">'k'</span>, linestyle=<span class="hljs-string">'dashed'</span>, linewidth=<span class="hljs-number">1</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716773886358/244a6cbe-020d-48a5-be2e-3e46f81825c8.png" alt class="image--center mx-auto" /></p>
<p>The <strong><em>gm</em></strong> model was trained on the train set data, and the two means were added to the histogram. All looks good. Now, the only thing left is to predict the test set and get the accuracy. The following snippet will do the trick:</p>
<pre><code class="lang-python">y_pred = gm.predict(np.array(X_test).reshape(np.array(X_test).shape[<span class="hljs-number">0</span>], <span class="hljs-number">1</span>))
y_pred = [<span class="hljs-string">'M'</span> <span class="hljs-keyword">if</span> x == <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'F'</span> <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> y_pred]

<span class="hljs-keyword">from</span> sklearn.metrics <span class="hljs-keyword">import</span> accuracy_score
accuracy = accuracy_score(y_test, y_pred)

print(<span class="hljs-string">"Accuracy:"</span>, accuracy)
</code></pre>
<p>Accuracy: 0.97</p>
<h3 id="heading-summary">Summary</h3>
<p>The Gaussian Mixture is a tool for segregating data with multiple distributions. In this case, two normal distributions represented males and females, which SKlearn effortlessly separated. In some cases, the data might be a little more complex with more dimensions; this might require another type of Mixture Model, such as a Variational Bayesian Mixture Model that can help cluster across multiple classes. You can check an example of such a scenario with <a target="_blank" href="https://scikit-learn.org/stable/modules/mixture.html">sklearn mixtures</a>.</p>
<h4 id="heading-acknowledgments">Acknowledgments</h4>
<p>This code was inspired by an old post from Luis Perez, PhD, about when we worked at the university building AI content for students.</p>
]]></content:encoded></item><item><title><![CDATA[Super Hero Search Made-Easy with OpenAI GPT-3 Models]]></title><description><![CDATA[Hey folks, here is another small tutorial now on how to build a small search engine using OpenAI's NLP pre-trained model "text-embedding-ada-002". According to OpenAI, "it replaces five separate models for text search, text similarity, and code searc...]]></description><link>https://www.doczamora.com/super-hero-search-made-easy-with-openai-gpt-3-models</link><guid isPermaLink="true">https://www.doczamora.com/super-hero-search-made-easy-with-openai-gpt-3-models</guid><category><![CDATA[nlp]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[openai]]></category><category><![CDATA[Deep Learning]]></category><category><![CDATA[GPT 3]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Thu, 26 Jan 2023 20:09:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/V3gbV_keH10/upload/33f6dcbda24b657baecdf36d9394e748.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey folks, here is another small tutorial now on how to build a small search engine using OpenAI's NLP pre-trained model "text-embedding-ada-002". According to OpenAI, "<em>it replaces five separate models for text search, text similarity, and code search, and outperforms our previous most capable model, Davinci, at most tasks while being priced 99.8% lower</em>". If you want to explore more about this model, please click <a target="_blank" href="https://openai.com/blog/new-and-improved-embedding-model/">here</a></p>
<p>That sounds good, right? well, let's test it out by building the embeddings out from the description of some superheroes I got in a csv file.</p>
<h3 id="heading-pre-requisites">Pre-requisites</h3>
<p>1 - Ok to build this, you will need to get an OpenAI key. you can get on for free at <a target="_blank" href="https://openai.com/api/">https://openai.com/api/</a>. Just sign-in, click on Personal and then View API Keys and create a new one. Make sure to copy-paste it in a secure place.</p>
<p>2 - Download the csv file from My Github <a target="_blank" href="https://github.com/drzamoramora/datasets/blob/main/supers.csv">Datasets</a> Repo</p>
<p>3 - Open a jupyter notebook and install the following libraries</p>
<ul>
<li><p>openai</p>
</li>
<li><p>pandas</p>
</li>
<li><p>numpy</p>
</li>
</ul>
<h3 id="heading-coding-time">Coding Time!</h3>
<p>Alright, enough chat, let's get into the business here. The first step is to load the required libraries.</p>
<h4 id="heading-load-libraries">Load Libraries</h4>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> openai

<span class="hljs-keyword">from</span> openai.embeddings_utils <span class="hljs-keyword">import</span> get_embedding, cosine_similarity

openai.api_key = <span class="hljs-string">'put-your-api-key-here'</span>
</code></pre>
<p>In this snippet, we are loading all the utils we need as well as setting up the API Key.</p>
<h4 id="heading-create-the-combined-field-for-search">Create the "Combined" Field for Search</h4>
<p>We load the supers.csv into a pandas dataframe. We will search over the "history_text" and "powers_text" descriptions. To make this easier, we will merge both columns into a new one called "Combined". The following code achieves exactly this. We will be using only the first 50 super heroes for our testing.</p>
<pre><code class="lang-python">df = pd.read_csv(<span class="hljs-string">"data/supers.csv"</span>)
df = df.fillna(<span class="hljs-string">''</span>)

<span class="hljs-comment"># lets use the first 50 superheros. (because of the rate limit)</span>
df = df.head(<span class="hljs-number">50</span>)

df[<span class="hljs-string">"combined"</span>] = df[[<span class="hljs-string">"history_text"</span>, <span class="hljs-string">"powers_text"</span>]].apply(<span class="hljs-string">" "</span>.join, axis=<span class="hljs-number">1</span>)
</code></pre>
<h4 id="heading-create-the-embeddings">Create the Embeddings</h4>
<p>The "Combined" column plays an important role. We need to convert this text into an Embedding. The embedding is a vector representation of the tokens in the text according to the "text-embedding-ada-002" model. This means we will create a new pandas column with the name "Embedding" to store this representation. The code below loops over the data frame and creates an embedding out of each combined text row. Then each embedding is converted as numpy.array and added to the dataframe. Note that the model embeddings are created by making a remote call to OpenAI through the get_embedding(...) function, which has a rate limit of 60 calls/second unless you upgrade your subscription.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> df[<span class="hljs-string">"combined"</span>]:
    embedding = get_embedding(item, engine=<span class="hljs-string">"text-embedding-ada-002"</span>)
    embeddings.append(np.array(embedding))

df[<span class="hljs-string">"embedding"</span>] = embeddings
</code></pre>
<p>Now we have a new column called "embeddings" that will hold the model representation for each row. the only thing left to do here is to build a Search function that can calculate the cosine similarity between the search query and the existent embeddings. The most similar results should be the ones returned first.</p>
<h4 id="heading-search-function">Search Function</h4>
<p>This is where the magic happens. The search function converts a query such as "<em>helps batman</em>" to a vector embedding and then compares it to the rest of the dataset. The results are sorted by the similarity column calculated from the cosine function. Take a look.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">df, description, n=<span class="hljs-number">3</span></span>):</span>
    text_embedding = get_embedding(
        description,
        engine=<span class="hljs-string">"text-embedding-ada-002"</span>
    )
    df[<span class="hljs-string">"similarity"</span>] = df.embedding.apply(<span class="hljs-keyword">lambda</span> x: cosine_similarity(x, text_embedding))

    results = (
        df.sort_values(<span class="hljs-string">"similarity"</span>, ascending=<span class="hljs-literal">False</span>)
        .head(n)
    )

    <span class="hljs-keyword">return</span> results
</code></pre>
<h4 id="heading-searching">Searching</h4>
<p>Here comes the fun and final part. We now just look for information and we let the search(...) function make the magic. The n=3 means to show the top 3 results.</p>
<pre><code class="lang-python">results = search(df, <span class="hljs-string">"helps batman"</span>, n=<span class="hljs-number">3</span>)
</code></pre>
<p>Now we loop over the results with this code to see what came back.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> index, row <span class="hljs-keyword">in</span> results.iterrows():
    print(<span class="hljs-string">"---------------------- "</span>)
    print(row[<span class="hljs-string">"real_name"</span>], <span class="hljs-string">'[Similarity Score:'</span>, round(row[<span class="hljs-string">"similarity"</span>]*<span class="hljs-number">100</span>),<span class="hljs-string">"%]"</span>)
    print(<span class="hljs-string">" "</span>)
    print(<span class="hljs-string">"History:"</span>, row[<span class="hljs-string">"history_text"</span>][:<span class="hljs-number">200</span>])
    print(<span class="hljs-string">" "</span>)
    print(<span class="hljs-string">"Powers:"</span>, row[<span class="hljs-string">"powers_text"</span>][:<span class="hljs-number">200</span>])
</code></pre>
<p>These are the results from the search:</p>
<pre><code class="lang-json">---------------------- 
Alfred Pennyworth [Similarity Score: <span class="hljs-number">84</span> %]

History: Alfred CranePennyworth is the butler, mentor, surrogate father, and close friend of Bruce Wayne. Alfred has served the Wayne family since before Bruce was born. After Bruce was left orphaned from the 

Powers: Alfred is exceptionally intelligent, which extends to his considerable investigative, analytical, communications, computer operating, engineering, and medical skills, as well as those in ordinary hous
---------------------- 
Aaron Cash [Similarity Score: <span class="hljs-number">82</span> %]

History: Aaron Cash is the head of security at Arkham Asylum. He has a hook for a hand after his real hand was eaten by Killer Croc.

Powers: 
---------------------- 
Bruce Wayne [Similarity Score: <span class="hljs-number">82</span> %]

History: He was one of the many prisoners of Indian Hill to be transferred to another facility upstate on the orders of The Court. However, Fish Mooney hijacks the bus and drives it into Gotham City, where the

Powers:
</code></pre>
<p>As you can see, with a Similarity Score of 84%, <strong>Alfred Pennyworth</strong>, was the first result. For those who don't know, Alfred is Batman's butler.</p>
<p>Cheers!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674763653670/7dc87f17-792c-45ac-9a8b-e4a5f0cfba14.jpeg" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Online Love: Distance-based Couple Matching with Quota]]></title><description><![CDATA[Introduction
Greetings, friends; in this post, I will explain my solution for a variation of the Stable Matching problem, particularly for the case of couple matching. The idea is that given a set of Men (M) with, let's say, ten dudes and a set of Wo...]]></description><link>https://www.doczamora.com/online-love-distance-based-couple-matching-with-quota</link><guid isPermaLink="true">https://www.doczamora.com/online-love-distance-based-couple-matching-with-quota</guid><category><![CDATA[algorithms]]></category><category><![CDATA[Mathematics]]></category><category><![CDATA[Python]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Tue, 27 Dec 2022 21:25:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/3fd2b1528c94cfcee4dc552ba3fb52ab.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Greetings, friends; in this post, I will explain my solution for a variation of the Stable Matching problem, particularly for the case of couple matching. The idea is that given a set of Men (M) with, let's say, ten dudes and a set of Women (F) with 100 ladies, we will use a distance-based method (Euclidean Distance) to match every woman to every dude so that every dude has the same amount of ladies assigned to each one after a quota has been reached.</p>
<p>This exercise aims to replicate a little of Tinder's or Match's way of assigning you a person you might want to meet. We will make some assumptions. The first one is that there is at least one female for every male. The other one is that there might be more women in the data than men, so this will overflow. The algorithm in this post will assign many ladies to a single dude based on their matching score. Once a male has reached the assignment quota, the best matches will go to another male. The last assumption here is the direction of the assignments; we are assigning many females to a single male. Feel free to revert this if your heart feels this is wrong.</p>
<p>Ok, let's start. The first thing to do here is to create random data about the parties of interest. I have created a pandas data frame for each set with the following attributes: Age, Education, State, Children, and Income. You can add more if you want.</p>
<p>The following code will create 10 random Males and 100 random females. Each variable is encoded. This means that it uses a numeric representation of a particular category.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> warnings
warnings.filterwarnings(<span class="hljs-string">'ignore'</span>)

<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> randrange
<span class="hljs-keyword">import</span> math
</code></pre>
<h3 id="heading-create-the-fake-dataset">Create the Fake DataSet</h3>
<pre><code class="lang-python"><span class="hljs-comment"># 1: age 18 - 25</span>
<span class="hljs-comment"># 2: age 26 - 30</span>
<span class="hljs-comment"># 3: age 31 - 35</span>
<span class="hljs-comment"># 4: age 36 - 40</span>
<span class="hljs-comment"># 5: age 41 - 45</span>
<span class="hljs-comment"># 6: age 46 - 50</span>
<span class="hljs-comment"># 7: age 50+</span>

<span class="hljs-comment"># 1: edu none</span>
<span class="hljs-comment"># 2: edu elementary</span>
<span class="hljs-comment"># 3: edu highschool</span>
<span class="hljs-comment"># 4: edu college</span>

<span class="hljs-comment"># 1: state AL</span>
<span class="hljs-comment"># 2: state CO</span>
<span class="hljs-comment"># 3: state CT</span>
<span class="hljs-comment"># 4: state GA</span>

<span class="hljs-comment"># 1: income 20-50k</span>
<span class="hljs-comment"># 2: income 50-100k</span>
<span class="hljs-comment"># 3: income 100k-150k</span>
<span class="hljs-comment"># 4: income 150-200k</span>
<span class="hljs-comment"># 5: income 200k+</span>

males = pd.DataFrame()

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>,<span class="hljs-number">10</span>):
    males = males.append({<span class="hljs-string">'Name'</span>: <span class="hljs-string">'Male_'</span> + str(i+<span class="hljs-number">1</span>) , <span class="hljs-string">'Age'</span> : randrange(<span class="hljs-number">7</span>)+<span class="hljs-number">1</span>, <span class="hljs-string">'Education'</span> : randrange(<span class="hljs-number">4</span>)+<span class="hljs-number">1</span>, <span class="hljs-string">'State'</span> : randrange(<span class="hljs-number">4</span>)+<span class="hljs-number">1</span>, <span class="hljs-string">'Children'</span>: randrange(<span class="hljs-number">3</span>)+<span class="hljs-number">1</span>, <span class="hljs-string">'income'</span> : randrange(<span class="hljs-number">5</span>)+<span class="hljs-number">1</span>}, ignore_index=<span class="hljs-literal">True</span>)

male_names = males.Name
males = males.drop([<span class="hljs-string">'Name'</span>], axis = <span class="hljs-number">1</span>)

females = pd.DataFrame()
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>,<span class="hljs-number">100</span>):
    females = females.append({<span class="hljs-string">'Name'</span>: <span class="hljs-string">'Female_'</span> + str(i+<span class="hljs-number">1</span>) , <span class="hljs-string">'Age'</span> : randrange(<span class="hljs-number">7</span>)+<span class="hljs-number">1</span>, <span class="hljs-string">'Education'</span> : randrange(<span class="hljs-number">4</span>)+<span class="hljs-number">1</span>, <span class="hljs-string">'State'</span> : randrange(<span class="hljs-number">4</span>)+<span class="hljs-number">1</span>, <span class="hljs-string">'Children'</span>: randrange(<span class="hljs-number">3</span>)+<span class="hljs-number">1</span>, <span class="hljs-string">'income'</span> : randrange(<span class="hljs-number">5</span>)+<span class="hljs-number">1</span>}, ignore_index=<span class="hljs-literal">True</span>)

female_names = females.Name
females = females.drop([<span class="hljs-string">'Name'</span>], axis = <span class="hljs-number">1</span>)
</code></pre>
<p>The code above will generate the following grid of data. You can observe that each attribute is represented by a number from the encoding defined as comments. The same attributes are used for both Males and Females, as this is the way, later, to compare how similar a couple is. This is the list of the ten males with their features.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672176533605/ec5001cf-ea7b-4c3d-999a-b3e119d0eac9.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-the-main-algorithm">The Main Algorithm</h2>
<h3 id="heading-part-1-create-a-grid-with-euclidean-distances">Part 1 - Create a Grid with Euclidean Distances</h3>
<p>The first part of our journey to find a match is to compare each male to each female feature array and estimate how "similar" they are with a distance-based method. In our case, I chose to use the Euclidean Distance. If you want, select another technique like Cosine, Minkowski, or Chebychev.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Estimation of Euclidean Distance between Males and Females...</span>
male_matchings = []
<span class="hljs-keyword">for</span> index, m_row <span class="hljs-keyword">in</span> males.iterrows():
    male = m_row.to_numpy()
    matchings = []
    <span class="hljs-keyword">for</span> index, f_row <span class="hljs-keyword">in</span> females.iterrows():
        female = f_row.to_numpy()
        similarity = np.linalg.norm(male-female) <span class="hljs-comment"># euclidean distace</span>
        matchings.append(similarity)
    male_matchings.append(matchings)
</code></pre>
<p>The code snippet shows an O(N^2) nested-loop approach to compare each male with each woman with the "np.linalg.norm(male-female)" method from Numpy, which tells the Euclidean Distance between two arrays. The closer they are, the closer to zero the value is. The <strong><em>male_matchings</em></strong> is a list of lists that contains such distances.</p>
<h3 id="heading-part-2-sort-similarity-arrays">Part 2 - Sort Similarity Arrays</h3>
<p>Each row of the male_matchings list represents a man, and the sublist attached represents the distance obtained for each woman. Let's sort each sublist so that the best match is on top. The following code obtains each sublist, sorts it, and appends it to the <strong><em>matches_values</em></strong> list of lists. Now the <strong><em>matches_values</em></strong> contain the sorted representation of the male_matchings list of lists.</p>
<pre><code class="lang-python"><span class="hljs-comment"># re-sorting of matchings &amp; matrix of values and names</span>
matches = [] <span class="hljs-comment"># sorted collections</span>
matches_values = []
<span class="hljs-keyword">for</span> fem <span class="hljs-keyword">in</span> male_matchings:

    x = {}
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>, len(fem)):
        x[female_names[i]] = fem[i]

    sorted_x = sorted(x.items(), key=<span class="hljs-keyword">lambda</span> kv: kv[<span class="hljs-number">1</span>])
    matches.append([k[<span class="hljs-number">0</span>] <span class="hljs-keyword">for</span> k <span class="hljs-keyword">in</span> sorted_x])
    matches_values.append([k[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> k <span class="hljs-keyword">in</span> sorted_x])
</code></pre>
<h3 id="heading-part-3-assignments-based-on-quota">Part 3 - Assignments based on Quota</h3>
<p>We did some pre-work to start making some assignments. We estimated the euclidean distance between each pair and sorted them so that the most similar other was on top of their stack. Now, we must start assigning one to another but with certain conditions. Here is the algorithm:</p>
<p><strong><em>While there are Females available {</em></strong></p>
<ol>
<li><p>We will assign one lady to one man at a time. This means that "Anna" will be assigned to "Johnny," assuming "Anna" is his first option.</p>
</li>
<li><p>Once a lady has been assigned, her name is added to the taken_females array. This means that even if another dude has a good match with Anna, she is no longer available.</p>
</li>
<li><p>After Johnny gets a lady assigned, we must move down to the second male in the list and assign their first match if she is not assigned. We will continue like this until all males can get given. If the first lady in the list is unavailable, then the male gets nothing until the second iteration.</p>
</li>
<li><p>Quota validation: every male can only be matched with math.ceil((1/len(male_names)) * len(female_names)). This means that if there are 100 women and 10 men, only 10 ladies can be assigned per male. If the quota is reached for that dude, he will be skipped and will not get any more assignments.</p>
</li>
</ol>
<p><strong><em>}</em></strong></p>
<p>The following code shows how this is done:</p>
<pre><code class="lang-python"><span class="hljs-comment"># main algorithm.   </span>
assigments = pd.DataFrame()
taken_females = []
min_score = <span class="hljs-number">0</span>

quota = math.ceil((<span class="hljs-number">1</span>/len(male_names)) * len(female_names))
quotas = {}
<span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> male_names:
    quotas[name] = <span class="hljs-number">0</span>
print(<span class="hljs-string">"Max Quota per Male"</span>, quota)

j_max = len(matches[<span class="hljs-number">0</span>]) <span class="hljs-comment"># width of matrix (number of females)</span>
i_max = len(matches) <span class="hljs-comment"># height of matrix (number of males)</span>

<span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>,j_max):

    <span class="hljs-comment">#print("Iteration:", j+1)</span>

    current = pd.DataFrame({
        <span class="hljs-string">'males'</span> : male_names,
        <span class="hljs-string">'females'</span> : np.array(matches)[:,j].tolist(),
        <span class="hljs-string">'scores'</span> : np.array(matches_values)[:,j].tolist()
    }).sort_values(by=<span class="hljs-string">'scores'</span>, ascending=<span class="hljs-literal">True</span>)

    <span class="hljs-comment"># MAKE ASSIGMENTS based on best score for each column.</span>
    <span class="hljs-keyword">for</span> index, row <span class="hljs-keyword">in</span> current.iterrows():

        female_name = row[<span class="hljs-string">'females'</span>]
        male_name = row[<span class="hljs-string">'males'</span>]
        score = row[<span class="hljs-string">'scores'</span>]

        <span class="hljs-comment"># check quota before assigment...</span>
        <span class="hljs-keyword">if</span> quotas[male_name] &gt;= quota:
            <span class="hljs-keyword">continue</span>

        <span class="hljs-comment"># if the female is taken, then continue con next male...</span>
        <span class="hljs-keyword">if</span> female_name <span class="hljs-keyword">in</span> taken_females:
            <span class="hljs-keyword">continue</span>
        <span class="hljs-keyword">else</span>:
            assigments = assigments.append({<span class="hljs-string">'Male'</span>: male_name , <span class="hljs-string">'Female'</span> : female_name}, ignore_index=<span class="hljs-literal">True</span>)
            <span class="hljs-comment">#print(" --- ",male_name, "assigned to", female_name)</span>
            taken_females.append(female_name)
            min_score += score
            quotas[male_name] += <span class="hljs-number">1</span>

    <span class="hljs-comment"># convergence, all females taken</span>
    <span class="hljs-keyword">if</span> len(taken_females) == len(female_names):
        print(<span class="hljs-string">"All Females Assigned - Algorithm Converged at"</span>, round(min_score,<span class="hljs-number">2</span>))
        <span class="hljs-keyword">break</span>
</code></pre>
<p>The code above shows that each male gets ten ladies each. This is to emulate the app functionality where you get a match, and if you don't like it, then you swipe left and continue with the next one.</p>
<p>The following image shows the assigments.groupby(["Male"]).sum() command to show which females were assigned to each male.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672175803964/287a98f7-db32-44cd-a46d-2906519ef716.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-additional-comments">Additional Comments</h3>
<p>The quota concept was introduced to allow all males to get assigned. If the quota validation is removed from the code, then you can guarantee the best matches will happen, but you might leave one bro without a lady, and here, we don't do that.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672176278122/9dcc0f65-6fe0-4ecb-b1fc-a7bf349c4950.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Content-based Recommender System for Movies with Tensorflow]]></title><description><![CDATA[Introduction
A content-based recommender is a type of system that makes recommendations to users based on their preferences and considers product attributes. This sounds very much like the Amazon "if you liked that, maybe you might also like this..."...]]></description><link>https://www.doczamora.com/content-based-recommender-system-for-movies-with-tensorflow</link><guid isPermaLink="true">https://www.doczamora.com/content-based-recommender-system-for-movies-with-tensorflow</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[TensorFlow]]></category><category><![CDATA[product]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[tutorials]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Wed, 15 Jun 2022 05:20:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/1VV1MRafd7A/upload/v1655265801156/MvhfAcPdw.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>A content-based recommender is a type of system that makes recommendations to users based on their preferences and considers product attributes. This sounds very much like the Amazon "if you liked that, maybe you might also like this..." type of recommendation.</p>
<p>The idea is to recommend something the user has <em>never rated before</em>. When I say "rated" means it probably hasn't visited, rated, or clicked it before.</p>
<blockquote>
<p>In a real setting, you can change rates for visited, clicked, or watched. You might also find some other metric to describe the interest of the user in a certain product.</p>
</blockquote>
<p>The example below is a hello-world type of example where we are going to recommend movies to users. We will only have 4 users and 5 movies:'Star Wars', 'The Dark Knight', 'Shrek', 'The Incredibles', 'Bleu', and 'Memento'. Each movie is described by its genre. however we will use one-hot encoding for the genres: 'Action', 'Sci-Fi', 'Comedy', 'Cartoon', 'Drama'. </p>
<p>Let's start coding.  The first thing to do is to represent User ratings and Movie features as tensors (matrices). </p>
<p>Let's start by loading Tensorflow and Numpy.</p>
<pre><code><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> tensorflow <span class="hljs-keyword">as</span> tf
</code></pre><h3 id="heading-load-data">Load Data</h3>
<p>We have the following data from 4 users that rated some movies. We also have the metadata from 6 movies described by the genre. Let's keep some arrays with the user names and movie names for later use.</p>
<pre><code><span class="hljs-attr">users</span> = [<span class="hljs-string">'Juan'</span>, <span class="hljs-string">'Daniel'</span>,  <span class="hljs-string">'Ana'</span>, <span class="hljs-string">'Christian'</span>]

<span class="hljs-attr">movies</span> = [
    <span class="hljs-string">'Star Wars'</span>, <span class="hljs-string">'The Dark Knight'</span>, <span class="hljs-string">'Shrek'</span>,
    <span class="hljs-string">'The Incredibles'</span>, <span class="hljs-string">'Bleu'</span>, <span class="hljs-string">'Memento'</span>
]

<span class="hljs-attr">features</span> = [<span class="hljs-string">'Action'</span>, <span class="hljs-string">'Sci-Fi'</span>, <span class="hljs-string">'Comedy'</span>, <span class="hljs-string">'Cartoon'</span>, <span class="hljs-string">'Drama'</span>]

<span class="hljs-attr">num_users</span> = len(users)
<span class="hljs-attr">num_movies</span> = len(movies)
<span class="hljs-attr">num_feats</span> = len(features)
<span class="hljs-attr">num_recommendations</span> = <span class="hljs-number">2</span>
</code></pre><p>The following table shows the preferences shown by users for some of the movies. There are blank spaces as not all the users have watched all the movies.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655267134347/NyXyHhl-z.png" alt="image.png" /></p>
<p>The <strong>users_movies</strong> tensor contains the information from the table. Let's load this information manually.</p>
<pre><code><span class="hljs-string">users_movies</span> <span class="hljs-string">=</span> <span class="hljs-string">tf.constant([</span>
                [<span class="hljs-number">4</span>,  <span class="hljs-number">6</span>,  <span class="hljs-number">8</span>,  <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]<span class="hljs-string">,</span>
                [<span class="hljs-number">0</span>,  <span class="hljs-number">0</span>, <span class="hljs-number">10</span>,  <span class="hljs-number">0</span>, <span class="hljs-number">8</span>, <span class="hljs-number">3</span>]<span class="hljs-string">,</span>
                [<span class="hljs-number">0</span>,  <span class="hljs-number">6</span>,  <span class="hljs-number">0</span>,  <span class="hljs-number">0</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>]<span class="hljs-string">,</span>
                [<span class="hljs-number">10</span>, <span class="hljs-number">9</span>,  <span class="hljs-number">0</span>,  <span class="hljs-number">5</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>]<span class="hljs-string">],</span> <span class="hljs-string">dtype=tf.float32)</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655267352085/fHwlVb2z_.png" alt="image.png" /></p>
<p>Let's do the same thing with the <strong>movies_feats</strong>. The following tensor will contain the genre metadata for each movie as seen in the table above.</p>
<pre><code><span class="hljs-string">movies_feats</span> <span class="hljs-string">=</span> <span class="hljs-string">tf.constant([</span>
                [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>]<span class="hljs-string">,</span>
                [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]<span class="hljs-string">,</span>
                [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>]<span class="hljs-string">,</span>
                [<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>]<span class="hljs-string">,</span>
                [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>]<span class="hljs-string">,</span>
                [<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>]<span class="hljs-string">],</span> <span class="hljs-string">dtype=tf.float32)</span>
</code></pre><h3 id="heading-user-embeddings">User Embeddings</h3>
<p>Now that we have those tensors with user and movie data, we need to create the user embeddings. The user embeddings show the relationship between each user and the movies by performing matrix multiplication. We can easily achieve this with the tf.matmul (yes, for matrix multiplication) in TensorFlow.</p>
<pre><code>users_feats <span class="hljs-operator">=</span> tf.matmul(users_movies, movies_feats)
users_feats
</code></pre><p>This will print the following tensor:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655267793433/Ferebyz8U.png" alt="image.png" /></p>
<p>As we can see, this is basically telling us how important is each feature for each user. We must normalize each row so that each value adds to 1. The following code normalizes each row:</p>
<pre><code>users_feats <span class="hljs-operator">=</span> users_feats <span class="hljs-operator">/</span> tf.reduce_sum(users_feats, axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>, keepdims<span class="hljs-operator">=</span>True)
users_feats
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655267997210/mAToV_Skh.png" alt="image.png" /></p>
<p>The <strong>user_feats</strong> tensor now has normalized values for each user (row) and for each feature (column).</p>
<h3 id="heading-ranking-features-for-each-user">Ranking Features for Each User</h3>
<p>The <strong>user_feats</strong> tell us how important is each feature for each user. Let's print this so we can understand the preferences of each user by the calculated weights.</p>
<p>The <strong>top_users_features</strong> is a tensor that returns the sorted indices of the most important attributes for each row. We are basically sorting each row and returning the index for each attribute. We will later loop and print the name of each feature name. </p>
<p>We find the top-k values of each row with the "tf.nn.top_k" function form tensorflow.</p>
<pre><code>top_users_features <span class="hljs-operator">=</span> tf.nn.top_k(users_feats, num_feats)[<span class="hljs-number">1</span>]
top_users_features
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655268409053/tzuEhum0a.png" alt="image.png" /></p>
<p>The tensor above shows the indices of the features that are more relevant for each user. The following code prints, for every user, the name of what seems to be more relevant to them:</p>
<pre><code><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(num_users):
    feature_names = [features[<span class="hljs-type">int</span>(<span class="hljs-keyword">index</span>)] <span class="hljs-keyword">for</span> <span class="hljs-keyword">index</span> <span class="hljs-keyword">in</span> top_users_features[i]]
    print(<span class="hljs-string">'{}: {}'</span>.format(users[i], feature_names))
</code></pre><ul>
<li>Juan: ['Action', 'Sci-Fi', 'Comedy', 'Cartoon', 'Drama']</li>
<li>Daniel: ['Drama', 'Comedy', 'Cartoon', 'Action', 'Sci-Fi']</li>
<li>Ana: ['Action', 'Drama', 'Sci-Fi', 'Comedy', 'Cartoon']</li>
<li>Christian: ['Action', 'Sci-Fi', 'Drama', 'Comedy', 'Cartoon']</li>
</ul>
<p>So Juan and Christian prefer Action and Sci-Fi, and Daniel (and Ana) prefer Drama and Comedy. Please note that they all have different preferences and in different order as defined in the users_feats tensor.</p>
<h3 id="heading-find-similarity-between-users-and-movies">Find Similarity Between Users and Movies</h3>
<p>Now, we need to calculate the similarity between the user ratings and the movie features (already calculated in the users_feats tensor). The idea is to create the projected ratings for each movie and store them in a new tensor called <strong>users_ratings</strong>.</p>
<pre><code>users_ratings <span class="hljs-operator">=</span>  [tf.map_fn(lambda x: tf.tensordot(users_feats[i], x, axes <span class="hljs-operator">=</span> <span class="hljs-number">1</span>), 
                           tf.cast(movies_feats, tf.float32))
                  <span class="hljs-keyword">for</span> i in range(num_users)]
</code></pre><p>In this code, we are using dot-product as a similarity measure between the tensors to calculate the projected ratings. This tensor will now serve as the prediction for the entire dataset. The higher the dot-product, the more we will recommend the movie. The only problem with this is that we don't want to recommend movies the user has already seen, so we will remove the movie the user has already seen by applying a mask to the users_ratings tensor. </p>
<p>The first thing we will do is to create the tensor <strong>users_unseen_movies</strong> which will have a True if the movie has not been rated by the user and False otherwise.</p>
<pre><code>users_unseen_movies <span class="hljs-operator">=</span> tf.equal(users_movies, tf.zeros_like(users_movies))
users_unseen_movies
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655269204050/Sa1MfZylW.png" alt="image.png" /></p>
<p>The <strong>ignore_matrix</strong> is just a tensor the same size as the users_movies filled with zeros. This will serve as a base tensor to fill with only the probabilities of the unseen movies. </p>
<pre><code>ignore_matrix <span class="hljs-operator">=</span> tf.zeros_like(tf.cast(users_movies, tf.float32))
ignore_matrix
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655269390364/YJsUabNgT.png" alt="image.png" /></p>
<p>Now, the magic is created with the <strong>tf.where</strong> function from tensorflow, which is able to apply the mask to the users_ratings so that only the unseen movies are kept in the tensor. </p>
<pre><code>users_ratings_new <span class="hljs-operator">=</span> tf.where(
    users_unseen_movies,
    users_ratings,
    ignore_matrix)

users_ratings_new
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655269839178/CNSM2ysbQ.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655270071701/4DhRGTC1x.png" alt="image.png" /></p>
<p>As you can observe, now only the unsee movie probabilities are shown. These will be our movie recommendations! </p>
<h3 id="heading-recommendation-top-2-movies-from-the-usersratingsnew-tensor">Recommendation: Top 2 movies (from the users_ratings_new tensor)</h3>
<p>We can now calculate all of the users to 2 movies with the tf.nn.top_k function. The following code will return the top-k indices for each row of the users_ratings_new matrix. Remember that the users_ratings_new rows represent the users and the columns the movies. The following code obtains the tensor with the top movies for each user:</p>
<pre><code>top_movies <span class="hljs-operator">=</span> tf.nn.top_k(users_ratings_new, num_recommendations)[<span class="hljs-number">1</span>]
top_movies
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655269684114/I-LOp2U3W.png" alt="image.png" /></p>
<p>As we did previously, we can print the name of the user and the top-2 movies that are recommended for the user that it has never seen before!</p>
<pre><code><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(num_users):
    movie_names = [movies[<span class="hljs-keyword">index</span>] <span class="hljs-keyword">for</span> <span class="hljs-keyword">index</span> <span class="hljs-keyword">in</span> top_movies[i]]
    print(<span class="hljs-string">'{}: {}'</span>.format(users[i], movie_names))
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655269770398/CtaxaQY1f.png" alt="image.png" /></p>
<h4 id="heading-acknowledgments">Acknowledgments</h4>
<p>This post has been a reproduction of the code provided by the Google Cloud Platform Data Analyst Recommender Systems program.</p>
]]></content:encoded></item><item><title><![CDATA[Exploratory Research for Machine Learning]]></title><description><![CDATA[Introduction
When we research something, we look to gain knowledge and answers about things (if any). The idea is to follow a process (the scientific method) that will lead us to an outcome, but that process might be affected by the desired results a...]]></description><link>https://www.doczamora.com/exploratory-research-for-machine-learning</link><guid isPermaLink="true">https://www.doczamora.com/exploratory-research-for-machine-learning</guid><category><![CDATA[research]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[Deep Learning]]></category><category><![CDATA[Computer Science]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Wed, 08 Jun 2022 00:41:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/2EJCSULRwC8/upload/v1654648410177/FgpMfqfLR.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>When we research something, we look to gain knowledge and answers about things (if any). The idea is to follow a process (the scientific method) that will lead us to an outcome, but that process might be affected by the desired results and the nature of the problem itself.</p>
<p>While there is sufficient documentation, books, and articles about research methods for some well-depicted problems, these often point to research in medicine, psychology, economics, and natural and political sciences (among others). During my doctoral studies, I found that the books I had to review as part of the program had a strong focus on psychology. I found it challenging as I was trying to apply research on information systems, particularly for machine learning, which is a quantitative discipline. Although the books in the program covered practically everything in terms of methodologies, they still let me spin a bit on what to use if I want to create research on how to build a self-driving car or train a convolutional neural network to identify Covid in X-rays. </p>
<p>This post reviews the Exploratory Research previously used in machine learning research to understand how problems are framed and solved. I will also briefly introduce the method I used for my dissertation at the end of this post for sign language recognition. </p>
<h3 id="heading-exploratory-research">Exploratory Research</h3>
<p>Exploratory research looks to investigate questions that have not been previously studied in depth or are different from other problems in literature. For example, research titles such as "Generative adversarial nets" (Goodfellow, 2014) sound like a candidate topic to be assessed as exploratory. This ground-breaking research reveals how to train generative models using an adversarial process by training two neural networks simultaneously. If we look at the 2014 paper, it goes straight to the action, with virtually no clarification on methodology, research techniques, or anything in this space. This type of research does not mean there is no research question and methods. Still, the way it was written shows only the novelty, not the failed experiments and other original theories for the adversarial GANS apart from what has been included in the literature review.  </p>
<p>Tom Dietterich (2019) from Oregon State University recommends the following process to drive the exploratory research successfully. </p>
<blockquote>
<p>Exploratory research -&gt; Initial Solutions -&gt; Refinement &amp; Evaluation -&gt; Competing Solutions &amp; Comparative Evaluation -&gt; Mapping The Solution to Space -&gt; Engineering &amp; Technology Transfer.</p>
</blockquote>
<p>This process states an "initial solution" to a problem that can be refined, reduced, and evaluated to be compared to other solutions. This will lead the research to determine if the outcome is important enough for publication or if it needs additional refinement, or should it be stashed.   </p>
<h4 id="heading-initial-solutions">Initial Solutions</h4>
<p>The idea here is to provide the kick-start solution to the problem. It does not have to be pretty, but it will serve as the base model for improvement. This stage is essential as this helps to define a precedent for a base solution to a complex problem. A paper might be created at this stage even if the solution does not generalize well. For example, Bayesian networks (Pearl 1985) described simple message passing for tree-structured networks.</p>
<blockquote>
<p>Nothing stimulates good research like a bad paper about an interesting problem - Dietterich</p>
</blockquote>
<h4 id="heading-refinement-and-evaluation">Refinement and Evaluation</h4>
<p>This is the process where the initial solution is evaluated for improvement. The refinement process can affect the initial solution by proposing new metrics, algorithms, hyper parameters, optimization techniques, or more data. The idea is to see if this could be done better even if the new solution takes a 180-degree turn.    </p>
<h4 id="heading-competing-solutions-andamp-comparative-evaluation">Competing Solutions &amp; Comparative Evaluation</h4>
<p>In the previous step, the model or algorithm is compared against itself. We are looking to understand how this is compared against other methods or techniques available for similar purposes in this phase. </p>
<p>It is now always easy to perform the comparative evaluation when the research is proposing something completely new, as in the case of adversarial networks. But the analysis can also be put in perspective against other research efforts that look to solve the same problem, but not in the same way.</p>
<p>After Goodfellow's paper on adversarial gans, now it's easier to do this as many researchers are looking for progress, and improvements against each other can be used for benchmarks. </p>
<h4 id="heading-mappings-solutions-to-space">Mappings Solutions to Space</h4>
<p>This looks to identify the design space for a particular problem. What are the bounds, critical design decisions, and how is the algorithm compared to others? For example, the concept of learning and the training time changes drastically between KNN and logistic regression on foundational machine learning algorithms. The training time becomes a problem for KNN as the dataset size increases. But why? How does this affect the usage of the algorithm for particular issues? How can the issue be fixed? These are questions to revisit in this stage as time and space complexity are under evaluation.</p>
<h4 id="heading-engineering-andamp-technology-transfer">Engineering &amp; Technology Transfer</h4>
<p>At least in machine learning research, applied research is recommended, and a proof-by-construction will help demonstrate that the investigation is sound. Many research papers test over well-known datasets such as ImageNet, Fake News Detection Dataset, Boston Housing, Atari RL, or MNIST. Study replicability is essential as we often read articles to solve other problems and require code or parts of the approach used to solve the research problem. Writing a paper with publicly accessible data and a code-repository is one of the best things we can do for the scientific community that uses ML for their research efforts. </p>
<h3 id="heading-design-science">Design Science</h3>
<p>Design science research focuses on the development and performance of (designed) artifacts with the explicit intention of improving the functional performance of the artifact. Design science research is typically applied to categories of artifacts, including algorithms, human/computer interfaces, design methodologies (including process models), and languages. Its application is most notable in the Engineering and Computer Science disciplines, though it is not restricted to these and can be found in many disciplines and fields (Vaishnavi et al., 2019).</p>
<p>Design science is a research methodology that focuses on an artifact and looks for improvement iteratively. So, a machine learning model can be seen as an artifact, subject to the seven guidelines for the research:</p>
<ul>
<li><strong>Design as an artifact</strong>: Design-science research must produce a viable artifact in the form of a construct, a model, a method, or an instantiation. </li>
<li><strong>Problem relevance</strong>: The objective of design-science research is to develop technology-based solutions to important and relevant business problems. </li>
<li><strong>Design evaluation</strong>: The utility, quality, and efficacy of a design artifact must be rigorously demonstrated via well-executed evaluation methods. </li>
<li><strong>Research contributions</strong>: Effective design-science research must provide clear and verifiable contributions in the areas of the design artifact, design foundations, and/or design methodologies. </li>
<li><strong>Research rigor</strong>: Design-science research relies upon the application of rigorous methods in both the construction and evaluation of the design artifact. </li>
<li><strong>Design as a search process</strong>: The search for an effective artifact requires utilizing available means to reach desired ends while satisfying laws in the problem environment. </li>
<li><strong>Communication of research</strong>: Design-science research must be presented effectively both to technology-oriented as well as management-oriented audiences.</li>
</ul>
<p>Dietterich's exploratory research process can be merged with the Design Science methodology (they are highly compatible but not the same). Design science puts mathematical rigor and artifact validation as a key to improving the solution (research results), methods, constructs, and other design theories to construct new knowledge. The idea is that the exploratory analysis is performed in iterations. We can evaluate the effect of a particular change in the model or methods used on each cycle. </p>
<h4 id="heading-design-science-for-sign-language-recognition">Design Science for Sign Language Recognition</h4>
<p>I used design science for my dissertation "Video-Based Costa Rican Sign Language Recognition for Emergency Services" which proposes the process required to transform a video into text when a person is communicating in sign language (LESCO).</p>
<p>The entire project was envisioned as a collection of artifacts: from the raw video data, the algorithms to transform the data, to the machine learning models used to classify each sign into its textual meaning (label). </p>
<blockquote>
<p>Everything is measurable, therefore it can be improved.</p>
</blockquote>
<p>The valuable thing about design science is that we can plan the experiment and collect the information on each iteration. After every cycle, we observe what changed and rerun the experiment to see if there are any improvements (pretty much trial and error, which in synthesis is at the core of the experimental research paradigm). This can take us to a path for improvement where we are storytelling how we got into the eureka moment. </p>
<h3 id="heading-references">References</h3>
<p>Dietterich, T. (2019). Research Methods in Machine Learning. 46.</p>
<p>Hevner, A. R.; March, S. T.; Park, J. &amp; Ram, S. Design Science in Information Systems Research. MIS Quarterly, 2004, 28, 75-106. URL: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.103.1725&amp;rep=rep1&amp;type=pdf</p>
<p>Ian J. Goodfellow, Jean Pouget-Abadie, Mehdi Mirza, Bing Xu, David Warde-Farley, Sherjil Ozair, Aaron Courville, and Yoshua Bengio. 2014. Generative adversarial nets. In Proceedings of the 27th International Conference on Neural Information Processing Systems - Volume 2 (NIPS'14). MIT Press, Cambridge, MA, USA, 2672–2680.</p>
<p>Pearl, J. (1985) A model of self-activated memory for evidential reasoning, in Proceedings of the 7th Conference of the Cognitive Science Society, University of California, Irvine, CA, pp. 329–334.</p>
<p>Vaishnavi, V., Kuechler, W., and Petter, S. (2004/19). "Design Science Research in Information Systems" January 20, 2004; last updated June 30, 2019. URL: http://desrist.org/design-research-in-information-systems</p>
]]></content:encoded></item><item><title><![CDATA[Spurious Correlations in Machine Learning]]></title><description><![CDATA[Lucky Correlations
One of the challenges we face while designing machine learning solutions is picking the right prediction features. Deciding which elements are essential and which ones genuinely contribute to model performance becomes complicated a...]]></description><link>https://www.doczamora.com/spurious-correlations-in-machine-learning</link><guid isPermaLink="true">https://www.doczamora.com/spurious-correlations-in-machine-learning</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[Deep Learning]]></category><category><![CDATA[statistics]]></category><category><![CDATA[Blogging]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Tue, 31 May 2022 18:41:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/HXBECPqQXaE/upload/v1654022421786/ZSMUx_B45.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h4 id="heading-lucky-correlations">Lucky Correlations</h4>
<p>One of the challenges we face while designing machine learning solutions is picking the right prediction features. Deciding which elements are essential and which ones genuinely contribute to model performance becomes complicated as the number of features increases.</p>
<p>The infinite monkey theorem states that a monkey hitting keys at random on a typewriter keyboard for an infinite amount of time will almost surely type any given text, such as the complete works of William Shakespeare.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654021193318/mhUloL68x.png" alt="image.png" /></p>
<p>As absurd as the theorem sounds (which has been proved btw), has an important implication in machine learning. When there are too many features, there is the probability that the model can predict the response variable by pure luck, just like the monkey typing random stuff, because some variables result in being perfect predictors.</p>
<p>In statistics, a spurious correlation (or spuriousness) refers to a connection between two variables that appears to be causal but is not. With spurious correlation, any observed dependencies between variables are merely due to chance or related to some unseen confounder (Kenton, 2021).</p>
<p>Spuriousness then implicates the existence of variables in machine learning models that might be nearly-perfect predictors but by pure luck. To understand better the predictive capabilities of spurious relationships, let's look at the following example from <a target="_blank" href="https://tylervigen.com/spurious-correlations">Tyler Vigen</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654021268473/S7DVM3ZWP.png" alt="chart.png" /></p>
<p>Let's seriously consider the relationship from the chart above. If this is true, the US government should reduce the spending on science and technology to reduce the suicide rate. But that relationship is casual; it is just a coincidence. And this phenomenon can also happen within your machine learning model. There might be variables that perfectly predict the response (y) but by luck. This situation can also appear unnoticed as the dimensional space increases. </p>
<h4 id="heading-covariance-andamp-spurious-correlations">Covariance &amp; Spurious Correlations</h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654021354062/nlEfDxjaA.png" alt="image.png" /></p>
<p>Covariance is a measure of the joint variability of two random variables. This is, the changes in the X variable are aligned to changes in the Y variable. The issue with covariance is that the relationship is judged based on the linear relationship (as in the Pearson Correlation Coefficient). Two random variables might be perfectly correlated but with a non-linear relationship. This can happen in neural networks when an image classifier learns to identify a "moose" from images because it realizes that the moose images are always in snowy conditions. The classifier learns about the snow and forgets the moose. And because the dataset images with snow are the only ones with a moose, then the classifier predicts the moose perfectly every time, making us think that the classifier is doing a great job.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654021386325/F2jToSHaW.png" alt="image.png" /></p>
<p>If you want to know how to influence neural networks to perform the wrong predictions, please read:</p>
<ul>
<li><strong>Unsupervised Adversarial Defense through Tandem Deep Image Priors</strong> (https://www.researchgate.net/publication/347798137_Unsupervised_Adversarial_Defense_through_Tandem_Deep_Image_Priors/figures?lo=1)</li>
<li><strong>A Baseline for Detecting Misclassified and Out-of-Distribution Examples in Neural Networks</strong> (https://arxiv.org/pdf/1610.02136.pdf)</li>
<li><strong>Adversarial Examples in the Physical World </strong>(https://www.taylorfrancis.com/chapters/edit/10.1201/9781351251389-8/adversarial-examples-physical-world-alexey-kurakin-ian-goodfellow-samy-bengio)</li>
</ul>
<h4 id="heading-what-can-i-do">What can I do?</h4>
<ul>
<li>First, today's machine learning solutions are based on correlations, not causations. Many solutions work because of the correlations learned, even if they are full of nonsense. Keep this in mind. </li>
<li>Looking for the best features is an art more than science. When the model has way too many elements, they seem to contribute to the model's accuracy in the same way. Check for the curse of dimensionality. </li>
<li>Focus on data first. Make sure you collect good data (moose pictures in many shapes, angles, and seasons) and use cross-validation to validate the model performance. Good data is the critical ingredient for a good model. </li>
<li>Split the data into train/valid/test sets. The train set is used to make the model learn. The valid set is used to validate the model accuracy with cross validation. The test set is a randomly picked sample before the train and valid set were created. This set is important as it represents real-world data the model has never seen before.</li>
<li>Using the covariance matrix only helps spot linear relationships. Don't take this for granted.</li>
<li>Test manually. Collect images or new samples and use them to validate the model. Spurious relationships usually overfit the model. This means that if the classifier is making lucky predictions, it should not work with other external images.</li>
<li>Always start with a simple architecture and data model. The simpler it is, the easiest to spot the issues in the classifier. Neural networks that are too tall and wide are difficult to debug. </li>
<li>Don't hack the data to make the classifier work. A penguin detector based on penguin images from cartoon books might be convenient because of the reduced amount of colors. Still, it will certainly not generalize to authentic penguin images from the wild. </li>
<li>Test several algorithms. There might be a chance that a machine learning algorithm might overfit the data giving us the sensation that the classifier can learn beyond the training set. For example, don't just use decision trees; test random forests and compare the results.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Cats vs Dogs: Binary Classifier with PyTorch CNN]]></title><description><![CDATA[My base stack for deep learning is Tensorflow, but PyTorch has been growing exponentially. Therefore I am going to start exploring PyTorch more and more, so I decided to make some hello-world examples for me (and you) to be updated on how to do thing...]]></description><link>https://www.doczamora.com/cats-vs-dogs-binary-classifier-with-pytorch-cnn</link><guid isPermaLink="true">https://www.doczamora.com/cats-vs-dogs-binary-classifier-with-pytorch-cnn</guid><category><![CDATA[Python]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[pytorch]]></category><category><![CDATA[neural networks]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Thu, 26 May 2022 20:46:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/ouo1hbizWwo/upload/v1653593402806/u_7ULskLC.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>My base stack for deep learning is Tensorflow, but PyTorch has been growing <a target="_blank" href="https://www.doczamora.com/tensorflow-vs-pytorch">exponentially</a>. Therefore I am going to start exploring PyTorch more and more, so I decided to make some hello-world examples for me (and you) to be updated on how to do things with the Facebook/Meta approach for deep learning. </p>
<p>We will start our exploration by building a binary classifier for Cat and Dog pictures. The images were downloaded from the <a target="_blank" href="https://www.kaggle.com/competitions/dogs-vs-cats-redux-kernels-edition/data">Kaggle Dogs vs Cats Redux Edition competition</a>. There are 25,000 images of dogs and cats we will use to train our convolutional neural network.</p>
<p>If you are wondering how to get PyTorch installed, I used miniconda with the following commands to get the environment started.</p>
<pre><code><span class="hljs-comment"># install conda environment with pytorch support</span>
<span class="hljs-comment"># - conda create -n torch python=3.7</span>
<span class="hljs-comment"># - conda activate torch</span>
<span class="hljs-comment"># - conda install pytorch torchvision torchaudio cudatoolkit=11.0 -c pytorch</span>
</code></pre><h4 id="heading-import-libraries">Import Libraries</h4>
<pre><code><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> random
<span class="hljs-keyword">import</span> time

<span class="hljs-keyword">import</span> torch
<span class="hljs-keyword">import</span> torchvision
<span class="hljs-keyword">import</span> torch.nn <span class="hljs-keyword">as</span> nn
<span class="hljs-keyword">import</span> torchvision.datasets <span class="hljs-keyword">as</span> datasets
<span class="hljs-title">from</span> torchvision <span class="hljs-keyword">import</span> datasets, transforms
<span class="hljs-title">from</span> torch.utils.data <span class="hljs-keyword">import</span> Dataset, DataLoader
<span class="hljs-keyword">import</span> torch.nn.functional <span class="hljs-keyword">as</span> F

<span class="hljs-title">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split

<span class="hljs-title">from</span> <span class="hljs-type">PIL</span> <span class="hljs-keyword">import</span> Image
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
</code></pre><h4 id="heading-download-data-and-preprocess-images">Download Data and Preprocess Images</h4>
<p>Once you downloaded the data, put the training images in the data/train/ folder on your local computer. The following code will parse the train folder and will collect the path for each image and will save it into the img_files list:</p>
<pre><code>img_files = os.listdir(<span class="hljs-string">'data/train/'</span>)
img_files = list(filter(<span class="hljs-keyword">lambda</span> x: x != <span class="hljs-string">'train'</span>, img_files))
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">train_path</span>(<span class="hljs-params">p</span>):</span> <span class="hljs-keyword">return</span> <span class="hljs-string">f"data/train/<span class="hljs-subst">{p}</span>"</span>
img_files = list(map(train_path, img_files))

print(<span class="hljs-string">"total training images"</span>, len(img_files))
print(<span class="hljs-string">"First item"</span>, img_files[<span class="hljs-number">0</span>])
</code></pre><p>output:</p>
<ul>
<li>total training images 25000</li>
<li>First item data/train/cat.0.jpg</li>
</ul>
<p>Before we start transforming our data, let's split the dataset into train-test sets with the following code. </p>
<pre><code><span class="hljs-comment"># create train-test split</span>
random.shuffle(img_files)

train = img_files[:20000]
<span class="hljs-built_in">test</span> = img_files[20000:]

<span class="hljs-built_in">print</span>(<span class="hljs-string">"train size"</span>, len(train))
<span class="hljs-built_in">print</span>(<span class="hljs-string">"test size"</span>, len(<span class="hljs-built_in">test</span>))
</code></pre><p>output:</p>
<ul>
<li>train size 20000</li>
<li>test size 5000</li>
</ul>
<p>Now, we have to use each path to load the image, convert it to RGB, and also label the image based on the name. If the word "cat" is in the path, then the label will be 0, otherwise 1 for a dog. Additional transformation is needed for the image, so a transform object will be created to resize the image to 244x244 and normalize its values. The following class will receive a Dataset (from torch.utils.data) and will apply the transformation.</p>
<pre><code><span class="hljs-comment"># image normalization</span>
transform = transforms.Compose([
    transforms.Resize((<span class="hljs-number">224</span>, <span class="hljs-number">224</span>)),
    transforms.ToTensor(),
    transforms.Normalize((<span class="hljs-number">0</span>.<span class="hljs-number">5</span>,), (<span class="hljs-number">0</span>.<span class="hljs-number">5</span>,))
])

<span class="hljs-comment"># preprocessing of images</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CatDogDataset</span>(<span class="hljs-title">Dataset</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(<span class="hljs-keyword">self</span>, image_paths, transform)</span></span>:
        <span class="hljs-keyword">super</span>().__init_<span class="hljs-number">_</span>()
        <span class="hljs-keyword">self</span>.paths = image_paths
        <span class="hljs-keyword">self</span>.len = len(<span class="hljs-keyword">self</span>.paths)
        <span class="hljs-keyword">self</span>.transform = transform

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__len__</span><span class="hljs-params">(<span class="hljs-keyword">self</span>)</span></span>: <span class="hljs-keyword">return</span> <span class="hljs-keyword">self</span>.len

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__getitem__</span><span class="hljs-params">(<span class="hljs-keyword">self</span>, index)</span></span>: 
        path = <span class="hljs-keyword">self</span>.paths[index]
        image = Image.open(path).convert(<span class="hljs-string">'RGB'</span>)
        image = <span class="hljs-keyword">self</span>.transform(image)
        label = <span class="hljs-number">0</span> <span class="hljs-keyword">if</span> <span class="hljs-string">'cat'</span> <span class="hljs-keyword">in</span> path <span class="hljs-keyword">else</span> <span class="hljs-number">1</span>
        <span class="hljs-keyword">return</span> (image, label)
</code></pre><p>Ok, let's use the CatDogDataset class to transform the train and test sets and convert them into an iterable dataset that PyTorch can use to train the model.</p>
<pre><code># create train dataset
train_ds = CatDogDataset(train, transform)
train_dl = DataLoader(train_ds, batch_size=<span class="hljs-number">100</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-built_in">len</span>(train_ds), <span class="hljs-built_in">len</span>(train_dl))

# create test dataset
test_ds = CatDogDataset(test, transform)
test_dl = DataLoader(test_ds, batch_size=<span class="hljs-number">100</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-built_in">len</span>(test_ds), <span class="hljs-built_in">len</span>(test_dl))
</code></pre><p>output</p>
<ul>
<li>20000 200</li>
<li>5000 50</li>
</ul>
<h4 id="heading-convolutional-architecture">Convolutional Architecture</h4>
<p>PyTorch uses a pythonic approach to define the architecture of the neural network in contrast to how you usually do it with Keras. The following architecture is simple, contains 3 convolutional layers with the core neural network composed of 3 fully connected layers. This architecture is not optimal but serves the purpose of testing the model. I recommend you to change this architecture (increase layers, change depth, etc) to get different results. </p>
<pre><code><span class="hljs-comment"># Pytorch Convolutional Neural Network Model Architecture</span>
<span class="hljs-attribute">class</span> CatAndDogConvNet(nn.Module):

    <span class="hljs-attribute">def</span> __init__(self):
        <span class="hljs-attribute">super</span>().__init__()

        <span class="hljs-comment"># onvolutional layers (3,16,32)</span>
        <span class="hljs-attribute">self</span>.conv<span class="hljs-number">1</span> = nn.Conv<span class="hljs-number">2</span>d(in_channels = <span class="hljs-number">3</span>, out_channels = <span class="hljs-number">16</span>, kernel_size=(<span class="hljs-number">5</span>, <span class="hljs-number">5</span>), stride=<span class="hljs-number">2</span>, padding=<span class="hljs-number">1</span>)
        <span class="hljs-attribute">self</span>.conv<span class="hljs-number">2</span> = nn.Conv<span class="hljs-number">2</span>d(in_channels = <span class="hljs-number">16</span>, out_channels = <span class="hljs-number">32</span>, kernel_size=(<span class="hljs-number">5</span>, <span class="hljs-number">5</span>), stride=<span class="hljs-number">2</span>, padding=<span class="hljs-number">1</span>)
        <span class="hljs-attribute">self</span>.conv<span class="hljs-number">3</span> = nn.Conv<span class="hljs-number">2</span>d(in_channels = <span class="hljs-number">32</span>, out_channels = <span class="hljs-number">64</span>, kernel_size=(<span class="hljs-number">3</span>, <span class="hljs-number">3</span>), padding=<span class="hljs-number">1</span>)

        <span class="hljs-comment"># conected layers</span>
        <span class="hljs-attribute">self</span>.fc<span class="hljs-number">1</span> = nn.Linear(in_features= <span class="hljs-number">64</span> * <span class="hljs-number">6</span> * <span class="hljs-number">6</span>, out_features=<span class="hljs-number">500</span>)
        <span class="hljs-attribute">self</span>.fc<span class="hljs-number">2</span> = nn.Linear(in_features=<span class="hljs-number">500</span>, out_features=<span class="hljs-number">50</span>)
        <span class="hljs-attribute">self</span>.fc<span class="hljs-number">3</span> = nn.Linear(in_features=<span class="hljs-number">50</span>, out_features=<span class="hljs-number">2</span>)


    <span class="hljs-attribute">def</span> forward(self, X):

        <span class="hljs-attribute">X</span> = F.relu(self.conv<span class="hljs-number">1</span>(X))
        <span class="hljs-attribute">X</span> = F.max_pool<span class="hljs-number">2</span>d(X, <span class="hljs-number">2</span>)

        <span class="hljs-attribute">X</span> = F.relu(self.conv<span class="hljs-number">2</span>(X))
        <span class="hljs-attribute">X</span> = F.max_pool<span class="hljs-number">2</span>d(X, <span class="hljs-number">2</span>)

        <span class="hljs-attribute">X</span> = F.relu(self.conv<span class="hljs-number">3</span>(X))
        <span class="hljs-attribute">X</span> = F.max_pool<span class="hljs-number">2</span>d(X, <span class="hljs-number">2</span>)

        <span class="hljs-attribute">X</span> = X.view(X.shape[<span class="hljs-number">0</span>], -<span class="hljs-number">1</span>)
        <span class="hljs-attribute">X</span> = F.relu(self.fc<span class="hljs-number">1</span>(X))
        <span class="hljs-attribute">X</span> = F.relu(self.fc<span class="hljs-number">2</span>(X))
        <span class="hljs-attribute">X</span> = self.fc<span class="hljs-number">3</span>(X)

        <span class="hljs-attribute">return</span> X
</code></pre><h4 id="heading-model-traning">Model Traning</h4>
<p>Ok, we are all set to train our data against the CatAndDogConvNet model. The following code will do the hard work. Please note that the accuracy and loss functions are loaded from the PyTorch libraries but the performance metrics are calculated manually.</p>
<pre><code><span class="hljs-comment"># Create instance of the model</span>
model = CatAndDogConvNet()

losses = []
accuracies = []
epoches = 8
<span class="hljs-keyword">start</span> = time.time()
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr = <span class="hljs-number">0.001</span>)

<span class="hljs-comment"># Model Training...</span>
<span class="hljs-keyword">for</span> epoch <span class="hljs-keyword">in</span> <span class="hljs-keyword">range</span>(epoches):

    epoch_loss = <span class="hljs-number">0</span>
    epoch_accuracy = <span class="hljs-number">0</span>

    <span class="hljs-keyword">for</span> X, y <span class="hljs-keyword">in</span> train_dl:

        preds = <span class="hljs-keyword">model</span>(X)
        loss = loss_fn(preds, y)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        accuracy = ((preds.argmax(dim=<span class="hljs-number">1</span>) == y).float().mean())
        epoch_accuracy += accuracy
        epoch_loss += loss
        print(<span class="hljs-string">'.'</span>, <span class="hljs-keyword">end</span>=<span class="hljs-string">''</span>, <span class="hljs-keyword">flush</span>=<span class="hljs-literal">True</span>)

    epoch_accuracy = epoch_accuracy/<span class="hljs-keyword">len</span>(train_dl)
    accuracies.append(epoch_accuracy)
    epoch_loss = epoch_loss / <span class="hljs-keyword">len</span>(train_dl)
    losses.append(epoch_loss)

    print(<span class="hljs-string">"\n --- Epoch: {}, train loss: {:.4f}, train acc: {:.4f}, time: {}"</span>.format(epoch, epoch_loss, epoch_accuracy, time.time() - <span class="hljs-keyword">start</span>))

    <span class="hljs-comment"># test set accuracy</span>
    <span class="hljs-keyword">with</span> torch.no_grad():

        test_epoch_loss = <span class="hljs-number">0</span>
        test_epoch_accuracy = <span class="hljs-number">0</span>

        <span class="hljs-keyword">for</span> test_X, test_y <span class="hljs-keyword">in</span> test_dl:

            test_preds = <span class="hljs-keyword">model</span>(test_X)
            test_loss = loss_fn(test_preds, test_y)

            test_epoch_loss += test_loss            
            test_accuracy = ((test_preds.argmax(dim=<span class="hljs-number">1</span>) == test_y).float().mean())
            test_epoch_accuracy += test_accuracy

        test_epoch_accuracy = test_epoch_accuracy/<span class="hljs-keyword">len</span>(test_dl)
        test_epoch_loss = test_epoch_loss / <span class="hljs-keyword">len</span>(test_dl)

        print(<span class="hljs-string">"Epoch: {}, test loss: {:.4f}, test acc: {:.4f}, time: {}\n"</span>.format(epoch, test_epoch_loss, test_epoch_accuracy, time.time() - <span class="hljs-keyword">start</span>))
</code></pre><ul>
<li>Epoch: 7, train loss: 0.2084, train acc: 0.9138, time: 871.9559330940247</li>
<li>Epoch: 7, test loss: 0.5432, test accracy: 0.8340, time: 890.4497690200806</li>
</ul>
<p>As we can observe the model train accuracy reached 91% with 83% for the test set. Not bad, but this can be improved! </p>
<h4 id="heading-making-predictions">Making Predictions</h4>
<p>We will re-use the CatDogDataset to create the TestCatDogDataset a class that pretty much does the same thing, but returns the image object and the file id, as the /data/test/ folder contains a set of unlabeled images.</p>
<pre><code>test_files <span class="hljs-operator">=</span> os.listdir(<span class="hljs-string">'data/test/'</span>)
test_files <span class="hljs-operator">=</span> list(filter(lambda x: x <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-string">'test'</span>, test_files))
def test_path(p): <span class="hljs-keyword">return</span> f<span class="hljs-string">"data/test/{p}"</span>
test_files <span class="hljs-operator">=</span> list(map(test_path, test_files))

class TestCatDogDataset(Dataset):
    def __init__(<span class="hljs-built_in">self</span>, image_paths, transform):
        <span class="hljs-built_in">super</span>().__init__()
        <span class="hljs-built_in">self</span>.paths <span class="hljs-operator">=</span> image_paths
        <span class="hljs-built_in">self</span>.len <span class="hljs-operator">=</span> len(<span class="hljs-built_in">self</span>.paths)
        <span class="hljs-built_in">self</span>.transform <span class="hljs-operator">=</span> transform

    def __len__(<span class="hljs-built_in">self</span>): <span class="hljs-keyword">return</span> <span class="hljs-built_in">self</span>.len

    def __getitem__(<span class="hljs-built_in">self</span>, index): 
        path <span class="hljs-operator">=</span> <span class="hljs-built_in">self</span>.paths[index]
        image <span class="hljs-operator">=</span> Image.open(path).convert(<span class="hljs-string">'RGB'</span>)
        image <span class="hljs-operator">=</span> <span class="hljs-built_in">self</span>.transform(image)
        fileid <span class="hljs-operator">=</span> path.split(<span class="hljs-string">'/'</span>)[<span class="hljs-number">-1</span>].split(<span class="hljs-string">'.'</span>)[<span class="hljs-number">0</span>]
        <span class="hljs-keyword">return</span> (image, filed)

test_ds <span class="hljs-operator">=</span> TestCatDogDataset(test_files, transform)
test_dl <span class="hljs-operator">=</span> DataLoader(test_ds, batch_size<span class="hljs-operator">=</span><span class="hljs-number">100</span>)
len(test_ds), len(test_dl)
</code></pre><p>output:</p>
<ul>
<li>(12500, 125)</li>
</ul>
<p>Let's now make predictions for the entire unlabeled test set from the /data/test/ folder. We will store the probabilities of the image to be a dog P(Image|dog) in the dog_probs list:</p>
<pre><code>dog_probs <span class="hljs-operator">=</span> []

with torch.no_grad():
    <span class="hljs-keyword">for</span> X, fileid in test_dl:
        preds <span class="hljs-operator">=</span> model(X)
        preds_list <span class="hljs-operator">=</span> F.softmax(preds, dim<span class="hljs-operator">=</span><span class="hljs-number">1</span>)[:, <span class="hljs-number">1</span>].tolist()
        dog_probs <span class="hljs-operator">+</span><span class="hljs-operator">=</span> list(zip(list(fileid), preds_list))
</code></pre><p>Let's print the top 5 images to see what the algorithm predicted in unseen images:</p>
<p>%matplotlib inline</p>
<pre><code><span class="hljs-comment"># display some images</span>
<span class="hljs-attribute">for</span> img, probs in zip(test_files[:<span class="hljs-number">5</span>], dog_probs[:<span class="hljs-number">5</span>]):
    <span class="hljs-attribute">pil_im</span> = Image.open(img, 'r')
    <span class="hljs-attribute">label</span> = <span class="hljs-string">"dog"</span> if probs[<span class="hljs-number">1</span>] &gt; <span class="hljs-number">0</span>.<span class="hljs-number">5</span> else <span class="hljs-string">"cat"</span>
    <span class="hljs-attribute">title</span> = <span class="hljs-string">"prob of dog: "</span> + str(probs[<span class="hljs-number">1</span>]) + <span class="hljs-string">" Classified as: "</span> + label
    <span class="hljs-attribute">plt</span>.figure()
    <span class="hljs-attribute">plt</span>.imshow(pil_im)
    <span class="hljs-attribute">plt</span>.suptitle(title)
    <span class="hljs-attribute">plt</span>.show()
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653597653596/bMr_I9pNl.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653597668276/kOK1Ne3kL.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653597673652/RPiB0DmKN.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653597679207/29ieaHOzA.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653597684246/GqNVkArA9.png" alt="image.png" /></p>
<p>The classifier is not perfect and still making mistakes. How do we solve this? let's try another approach that has proved to be very effective in training convolutional neural networks to achieve state-of-art performance: <strong>transfer learning</strong>. I will replicate this same example using transfer learning in my next post to check the difference.</p>
<p>Kudos to <a target="_blank" href="https://www.kaggle.com/code/chriszou/dogs-vs-cats-pytorch-cnn-without-transfer-learning/notebook">chriszou</a>for the original code for this post.</p>
]]></content:encoded></item><item><title><![CDATA[AutoML with PyCaret for Hepatitis-C Prediction]]></title><description><![CDATA[Scientific Background
Hoffmann et al. (2018), in their paper "Using machine learning techniques to generate laboratory diagnostic pathways—a case study" challenged the use of expert rules in the interpretation of laboratory testing with machine learn...]]></description><link>https://www.doczamora.com/automl-with-pycaret-for-hepatitis-c-prediction</link><guid isPermaLink="true">https://www.doczamora.com/automl-with-pycaret-for-hepatitis-c-prediction</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Benchmark]]></category><category><![CDATA[Data Science]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Sat, 07 May 2022 15:19:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/-2Xvz8uRnfM/upload/v1651933186597/gjv7a97SX.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-scientific-background">Scientific Background</h3>
<p>Hoffmann et al. (2018), in their paper <a target="_blank" href="https://jlpm.amegroups.com/article/view/4401">"Using machine learning techniques to generate laboratory diagnostic pathways—a case study"</a> challenged the use of expert rules in the interpretation of laboratory testing with machine learning models. The idea behind using machine learning is to provide an alternative to laboratory diagnostics that can offer state-of-art detection capabilities for certain conditions. </p>
<p>Fortunately, the data from this paper is available at the <a target="_blank" href="https://archive.ics.uci.edu/ml/datasets/HCV+data">Machine Learning UCI Repository</a> from UC Irvine. This dataset is also available at Kaggle as <a target="_blank" href="https://www.kaggle.com/datasets/fedesoriano/hepatitis-c-dataset">CSV</a>, so I used the latter one. </p>
<p>The data was collected from 73 patients (52 males and 21 females), ages 19 to 75, with proven serological and histopathological diagnoses of hepatitis C. The data was labeled in several categories according to their hepatic activity index. This index was later used to transfer those groups into the machine learning classes.</p>
<h3 id="heading-the-data">The Data</h3>
<p>Each entry in the dataset is described by ten biochemical tests, gender, and age. the following list details which test indicators were used in the data collection process:</p>
<p><strong>Test Codes</strong></p>
<ul>
<li>albumin (ALB)</li>
<li>alkaline phosphatase (ALP)</li>
<li>alanine amino-transferase (ALT)</li>
<li>aspartate amino-transferase (AST)</li>
<li>bilirubin (BIL)</li>
<li>choline esterase (CHE)</li>
<li>LDL (CHOL)</li>
<li>creatinine (CREA)</li>
<li>gamma glutamyl transpeptidase) (GGT)</li>
<li>PROT</li>
</ul>
<p><strong>Additional attributes </strong></p>
<ul>
<li>age</li>
<li>sex</li>
</ul>
<p><strong>Response variable (y)</strong></p>
<ul>
<li>Category (diagnosis) (values: '0=Blood Donor', '0s=suspect Blood Donor', '1=Hepatitis', '2=Fibrosis', '3=Cirrhosis')</li>
</ul>
<h3 id="heading-analysis-with-pycaret">Analysis with PyCaret</h3>
<p>In the paper, the results using decision trees obtained the following results.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651934743473/XItPK6mns.png" alt="image.png" /></p>
<p>We are going to use the PyCaret AutoML capabilities to improve the accuracy over all the classes by using cross-validation. </p>
<h3 id="heading-code">Code</h3>
<p><strong>Imports</strong></p>
<pre><code><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-title">from</span> pycaret.classification <span class="hljs-keyword">import</span> *
</code></pre><p><strong>Load Data</strong></p>
<pre><code>data <span class="hljs-operator">=</span> pd.read_csv(<span class="hljs-string">"HepatitisCdata.csv"</span>)
data <span class="hljs-operator">=</span> data.drop(labels<span class="hljs-operator">=</span><span class="hljs-string">'Unnamed: 0'</span>, axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>)
data.head(<span class="hljs-number">10</span>)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651934895675/T9RfVY-8o.png" alt="image.png" /></p>
<p><strong>Data Preprocessing</strong></p>
<pre><code># pd.Series(<span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>], dtype=<span class="hljs-string">"category"</span>)
# [<span class="hljs-string">'0=Blood Donor'</span>, <span class="hljs-string">'0s=suspect Blood Donor'</span>, <span class="hljs-string">'1=Hepatitis'</span>, <span class="hljs-string">'2=Fibrosis'</span>, <span class="hljs-string">'3=Cirrhosis'</span>]

<span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>] = [<span class="hljs-number">0</span> <span class="hljs-keyword">if</span> x == <span class="hljs-string">"0=Blood Donor"</span> <span class="hljs-keyword">else</span> x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>]]
<span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>] = [<span class="hljs-number">1</span> <span class="hljs-keyword">if</span> x == <span class="hljs-string">"0s=suspect Blood Donor"</span> <span class="hljs-keyword">else</span> x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>]]
<span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>] = [<span class="hljs-number">2</span> <span class="hljs-keyword">if</span> x == <span class="hljs-string">"1=Hepatitis"</span> <span class="hljs-keyword">else</span> x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>]]
<span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>] = [<span class="hljs-number">3</span> <span class="hljs-keyword">if</span> x == <span class="hljs-string">"2=Fibrosis"</span> <span class="hljs-keyword">else</span> x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>]]
<span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>] = [<span class="hljs-number">4</span> <span class="hljs-keyword">if</span> x == <span class="hljs-string">"3=Cirrhosis"</span> <span class="hljs-keyword">else</span> x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-keyword">data</span>[<span class="hljs-string">"Category"</span>]]

# pd.Series(<span class="hljs-keyword">data</span>[<span class="hljs-string">"Sex"</span>], dtype=<span class="hljs-string">"category"</span>)
# [<span class="hljs-string">'f'</span>, <span class="hljs-string">'m'</span>]

<span class="hljs-keyword">data</span>[<span class="hljs-string">"Sex"</span>] = [<span class="hljs-number">0</span> <span class="hljs-keyword">if</span> x == <span class="hljs-string">"f"</span> <span class="hljs-keyword">else</span> <span class="hljs-number">1</span> <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-keyword">data</span>[<span class="hljs-string">"Sex"</span>]]
<span class="hljs-keyword">data</span>.head(<span class="hljs-number">10</span>)
</code></pre><p>The data looks much cleaner, and categorical columns were encoded accordingly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651934993899/kgPhH0aQ7.png" alt="image.png" /></p>
<p><strong>Magic with PyCaret</strong></p>
<p>PyCaret with minimal coding will perform a benchmark of a suite of machine learning algorithms, will estimate metrics to determine which is the best model and will also calculate many visualizations such as AUC/ROC curves. </p>
<pre><code><span class="hljs-comment"># pycaret setup</span>
<span class="hljs-attr">s</span> = setup(data, target = <span class="hljs-string">"Category"</span>)

<span class="hljs-comment"># model training and selection</span>
<span class="hljs-attr">best</span> = compare_models()
</code></pre><p>This code snippet automatically created the following table of results, showing which algorithms performed better, and the metrics they aced are highlighted in yellow. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651935256619/QZZ61IIzx.png" alt="image.png" /></p>
<p>The clear winner here is the GBC <a target="_blank" href="https://en.wikipedia.org/wiki/Gradient_boosting">Gradient Boosting Classifier</a> algorithm. </p>
<p><strong>Performance Metrics</strong></p>
<p>PyCaret with a single line of code can provide a set of analyses that can help us identify how the mode is performing, accuracy, F1-Score, sensitivity analysis, and many more. Here are some interesting visualizations provided by PyCaret.</p>
<pre><code><span class="hljs-selector-tag">evaluate_model</span>(best)
</code></pre><p>That's it! here are some analytics:</p>
<p><em>ROC/AUC Curve for GBC</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651935506463/yxK6hRaC4.png" alt="image.png" /></p>
<p><em>Confusion Matrix</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651935535288/VjtBcqwfT.png" alt="image.png" /></p>
<p><em>Precision-Recall Curve</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651935564411/pwLl5q9Zy.png" alt="image.png" /></p>
<p><em>Classification Report</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651935619179/Bqp5NBUcZ.png" alt="image.png" /></p>
<h3 id="heading-prediction-of-new-patients">Prediction of New Patients</h3>
<p>Before we start marking some predictions, PyCaret offers the save_model method to save the machine learning model as a pickle file. The following code shows how to save and load the model if you want later to use it in a web service.</p>
<p><em>Save Model</em></p>
<pre><code># save model <span class="hljs-keyword">to</span> disk "hepatitis_model.pkl"
save_model(best, "hepatitis_model")
</code></pre><p><em>Load Model</em></p>
<pre><code><span class="hljs-keyword">from</span> pycaret.classification <span class="hljs-keyword">import</span> <span class="hljs-title">load_model</span>

# <span class="hljs-title">load</span> <span class="hljs-title">model</span>
<span class="hljs-title">hepatitis_model</span> <span class="hljs-operator">=</span> <span class="hljs-title">load_model</span>(<span class="hljs-string">'hepatitis_model'</span>)
</code></pre><p><strong>Prediction of a new Patient</strong></p>
<p>We are simulating a new patient, and we are creating a new pandas data frame with the information needed. the following snippet shows how to submit a new patient for inference.</p>
<p><em>Create the Data Frame</em></p>
<pre><code><span class="hljs-string">patient_data</span> <span class="hljs-string">=</span> <span class="hljs-string">pd.DataFrame()</span>
<span class="hljs-string">patient_data</span> <span class="hljs-string">=</span> <span class="hljs-string">patient_data.append({</span>
    <span class="hljs-attr">'Age':</span> <span class="hljs-number">32.00</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'Sex':</span> <span class="hljs-number">1.00</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'ALB':</span> <span class="hljs-number">44.30</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'ALP':</span> <span class="hljs-number">52.30</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'ALT':</span> <span class="hljs-number">21.70</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'AST':</span> <span class="hljs-number">22.40</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'BIL':</span> <span class="hljs-number">17.20</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'CHE':</span> <span class="hljs-number">4.15</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'CHOL':</span> <span class="hljs-number">3.57</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'CREA':</span> <span class="hljs-number">78.00</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'GGT':</span> <span class="hljs-number">24.10</span><span class="hljs-string">,</span>
    <span class="hljs-attr">'PROT':</span> <span class="hljs-number">75.40</span>
<span class="hljs-string">},</span> <span class="hljs-string">ignore_index=True)</span>
</code></pre><p><em>Perform the Prediction</em></p>
<pre><code># <span class="hljs-keyword">perform</span> prediction
prediction = predict_model(hepatitis_model, data = patient_data)

print(<span class="hljs-string">'Patient was CLASSIFIED as:'</span>, classes[prediction.Label[<span class="hljs-number">0</span>]])
</code></pre><p>The outcome of this prediction is: <strong> Patient was CLASSIFIED as: Blood Donor</strong>.</p>
<p><strong>Summary</strong></p>
<p>The PyCaret POC demonstrated a 0.9395 accuracy and 0.9270 F1-Score for predicting the classes in the diabetes dataset. This is way much better than the results shown by Hoffmann et al. Although this is a promising result, this code is still a POC and should not be used for production purposes until further evaluation by medical experts (I am, unfortunately, the wrong type of doctor here for medical and clinical approval!)</p>
<h3 id="heading-download-the-code">Download the Code</h3>
<p>I uploaded the code a Gist <a target="_blank" href="https://gist.github.com/drzamoramora/090b4dfaf0e403ceb919a244ec1b2a18">Here!</a></p>
<p>if you liked this, remember to send some love back.</p>
<p><a href="https://www.buymeacoffee.com/doczamora" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" class="buycoffee" alt="Buy Me A Coffee." /></a></p>
]]></content:encoded></item><item><title><![CDATA[Counting Pipes: Automation with Computer Vision]]></title><description><![CDATA[While on the hardware store...
I made a quick visit to the hardware store to find some PVC tubes. While looking for them, I realized that every item in the warehouse must be counted, by someone I guess in a periodically way to refill when the reserve...]]></description><link>https://www.doczamora.com/counting-pipes-automation-with-computer-vision</link><guid isPermaLink="true">https://www.doczamora.com/counting-pipes-automation-with-computer-vision</guid><category><![CDATA[Computer Science]]></category><category><![CDATA[Computer Vision]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[automation]]></category><category><![CDATA[opencv]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Mon, 02 May 2022 05:36:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/S32zqWHnYwk/upload/v1651468027381/eM5tsTXUc.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-while-on-the-hardware-store">While on the hardware store...</h3>
<p>I made a quick visit to the hardware store to find some PVC tubes. While looking for them, I realized that every item in the warehouse must be counted, by someone I guess in a periodically way to refill when the reserve is running low (how boring). So, what if there is a camera in front of the racks counting things? This is exactly what I tried to do with an image I downloaded to check how we can use computer vision (OpenCV) to count for things.</p>
<p>While looking at the OpenCV documentation and samples online, I found that there are several techniques to identify geometric shapes from an image. Concretely, there is a method in OpenCV; <a target="_blank" href="https://docs.opencv.org/4.x/da/d53/tutorial_py_houghcircles.html">HoughCircles</a>, which is able to find circles by using the <a target="_blank" href="https://en.wikipedia.org/wiki/Hough_transform#:~:text=The%20Hough%20transform%20is%20a,shapes%20by%20a%20voting%20procedure.">Hough transform</a>.</p>
<p>The <strong>HoughCircles(...)</strong> method has the following <a target="_blank" href="https://docs.opencv.org/4.x/dd/d1a/group__imgproc__feature.html#ga47849c3be0d0406ad3ca45db65a25d2d">documentation</a>:</p>
<pre><code><span class="hljs-selector-tag">cv</span><span class="hljs-selector-class">.HoughCircles</span>(    <span class="hljs-selector-tag">image</span>, <span class="hljs-selector-tag">method</span>, <span class="hljs-selector-tag">dp</span>, <span class="hljs-selector-tag">minDist</span><span class="hljs-selector-attr">[, circles[, param1[, param2[, minRadius[, maxRadius]</span>]]]]    )
</code></pre><p>Parameters</p>
<ul>
<li><strong>image</strong>: 8-bit, single-channel, grayscale input image.</li>
<li><strong>circles</strong>: Output vector of found circles. Each vector is encoded as 3 or 4 element floating-point vector (x,y,radius) or (x,y,radius,votes) .</li>
<li><strong>method</strong>:    Detection method, see HoughModes. The available methods are HOUGH_GRADIENT and HOUGH_GRADIENT_ALT.</li>
<li><strong>dp</strong>    Inverse ratio of the accumulator resolution to the image resolution. For example, if dp=1 , the accumulator has the same resolution as the input image. If dp=2 , the accumulator has half as big width and height. For HOUGH_GRADIENT_ALT the recommended value is dp=1.5, unless some small very circles need to be detected.</li>
<li><strong>minDist</strong>:    Minimum distance between the centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is too large, some circles may be missed.</li>
<li><strong>param1</strong>:    First method-specific parameter. In case of HOUGH_GRADIENT and HOUGH_GRADIENT_ALT, it is the higher threshold of the two passed to the Canny edge detector (the lower one is twice smaller). Note that HOUGH_GRADIENT_ALT uses Scharr algorithm to compute image derivatives, so the threshold value shough normally be higher, such as 300 or normally exposed and contrasty images.</li>
<li><strong>param2</strong>:    Second method-specific parameter. In case of HOUGH_GRADIENT, it is the accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first. In the case of HOUGH_GRADIENT_ALT algorithm, this is the circle "perfectness" measure. The closer it to 1, the better shaped circles algorithm selects. In most cases 0.9 should be fine. If you want get better detection of small circles, you may decrease it to 0.85, 0.8 or even less. But then also try to limit the search range [minRadius, maxRadius] to avoid many false circles.</li>
<li><strong>minRadius</strong>:    Minimum circle radius.</li>
<li><strong>maxRadius</strong>:    Maximum circle radius. If &lt;= 0, uses the maximum image dimension. If &lt; 0, HOUGH_GRADIENT returns centers without finding the radius. HOUGH_GRADIENT_ALT always computes circle radiuses.</li>
</ul>
<h3 id="heading-proof-of-concept">Proof of Concept</h3>
<p>Well, lets try to use this method and adjust its parameters to identify circles in an image. The circles we want to identify are the ones that belongs to the end of the pipes. </p>
<pre><code><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> cv2 <span class="hljs-keyword">as</span> cv
<span class="hljs-title">from</span> matplotlib <span class="hljs-keyword">import</span> pyplot <span class="hljs-keyword">as</span> plt
</code></pre><h4 id="heading-load-the-image">Load the Image</h4>
<pre><code><span class="hljs-comment"># use matplotlib to print image in jupyter notebook</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">show</span>(<span class="hljs-params">img</span>):</span>
    plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">16</span>))
    plt.imshow(img, cmap=<span class="hljs-string">'gray'</span>)
    plt.show()
</code></pre><pre><code># <span class="hljs-keyword">load</span> the image <span class="hljs-keyword">in</span> <span class="hljs-keyword">full</span> color
img = cv.imread(<span class="hljs-string">'pipes.png'</span>, cv.IMREAD_COLOR)
<span class="hljs-keyword">show</span>(img)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651468571301/mjge54xPi.png" alt="descarga.png" /></p>
<p>So this is the original image with a bunch of pipes. I am not going to count them. Lets use the function to identify them.</p>
<h4 id="heading-preprocessing">Preprocessing</h4>
<p>The cv.HoughCircles() function requires the image to be in grayscale. Also, applying a gaussian blur is also a good idea to blend imperfections from the image that might cause false positives.</p>
<pre><code><span class="hljs-comment"># Convert to grayscale</span>
<span class="hljs-attribute">gray</span> = cv.cvtColor(img, cv.COLOR_BGR<span class="hljs-number">2</span>GRAY)

<span class="hljs-comment"># Apply blur with a 3x3 kernel</span>
<span class="hljs-attribute">gray_blurred</span> = cv.blur(gray, (<span class="hljs-number">3</span>, <span class="hljs-number">3</span>))

<span class="hljs-attribute">show</span>(gray_blurred)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651468756432/4pwsWCFcT.png" alt="descarga.png" /></p>
<p>Nice! now our image is lightly blurred and in grayscale. That's all the pre-processing we need.</p>
<h4 id="heading-apply-cvhoughcircles-to-the-grayblurred-image">Apply cv.HoughCircles to the gray_blurred Image</h4>
<pre><code><span class="hljs-comment"># Apply Hough transform on the blurred image.</span>
<span class="hljs-attribute">detected_circles</span> = cv.HoughCircles(gray_blurred, 
                   <span class="hljs-attribute">cv</span>.HOUGH_GRADIENT, <span class="hljs-number">1</span>, <span class="hljs-number">15</span>, param<span class="hljs-number">1</span> = <span class="hljs-number">100</span>,
               <span class="hljs-attribute">param2</span> = <span class="hljs-number">20</span>, minRadius = <span class="hljs-number">0</span>, maxRadius = <span class="hljs-number">20</span>)
</code></pre><p>detected_circles is list that contains all the circles identified in the image. Each circle is composed of 3 values in the list: a, b, and r. The a-b are the x-y location of the circle and r is the radius. The data looks something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651469156238/57EfgwH39.png" alt="descarga.png" /></p>
<p>Now its time to loop over each circle and draw the origin of the circle over the original image. This is done in the following cycle:</p>
<pre><code><span class="hljs-attribute">pipes_count</span> = <span class="hljs-number">0</span>

<span class="hljs-comment"># Draw circles that are detected.</span>
<span class="hljs-attribute">if</span> detected_circles is not None:

    <span class="hljs-comment"># Convert circle metadata to integers</span>
    <span class="hljs-attribute">detected_circles</span> = np.uint<span class="hljs-number">16</span>(np.around(detected_circles))

    <span class="hljs-attribute">for</span> points in detected_circles[<span class="hljs-number">0</span>, :]:
        <span class="hljs-attribute">a</span>, b, r = points[<span class="hljs-number">0</span>], points[<span class="hljs-number">1</span>], points[<span class="hljs-number">2</span>]

        <span class="hljs-comment"># Draw a small circle (of radius 1) to show the center.</span>
        <span class="hljs-attribute">cv</span>.circle(img, (a, b), <span class="hljs-number">1</span>, (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>), <span class="hljs-number">3</span>)

        <span class="hljs-comment"># count the number of pipes</span>
        <span class="hljs-attribute">pipes_count</span> += <span class="hljs-number">1</span>
</code></pre><p>I added also the variable pipes_count to count how many circles were detected. At the end this is the number we need.</p>
<p>The final image with the small blue circle drawn at the origin of each pipe looks like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651469357514/3eg6zO4kt.png" alt="descarga.png" /></p>
<h4 id="heading-how-many-pipes">How many pipes?</h4>
<p>Well, there are <strong>79 pipes</strong> in this image. </p>
<h4 id="heading-download-the-code">Download the Code</h4>
<p>The Gist is available <a target="_blank" href="https://gist.github.com/drzamoramora/0463f1902eb26493b18fdaead7a8c84e">here</a></p>
<p>Hope you like this!</p>
<p><a href="https://www.buymeacoffee.com/doczamora" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" class="buycoffee" alt="Buy Me A Coffee." /></a></p>
]]></content:encoded></item><item><title><![CDATA[Mediapipe: Drowsy Driver Detection]]></title><description><![CDATA[Introduction
In this post, we will use a cool project from Google; The Mediapipe, to build a code snippet that is able to identify if a person is drowsy. This could be applicable to monitor people while driving or while performing dangerous tasks tha...]]></description><link>https://www.doczamora.com/mediapipe-drowsy-driver-detection</link><guid isPermaLink="true">https://www.doczamora.com/mediapipe-drowsy-driver-detection</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[Computer Vision]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[tutorials]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Fri, 29 Apr 2022 07:59:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/7DWnTxE-XY0/upload/v1651184767708/sv3Rxh3ca.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>In this post, we will use a cool project from Google; The <a target="_blank" href="https://mediapipe.dev/">Mediapipe</a>, to build a code snippet that is able to identify if a person is drowsy. This could be applicable to monitor people while driving or while performing dangerous tasks that require being fully awake.</p>
<blockquote>
<p>MediaPipe offers cross-platform, customizable ML solutions for live and streaming media. Learn more about the Mediapipe project <a target="_blank" href="https://mediapipe.dev/">here</a></p>
</blockquote>
<p>The idea is simple: we will monitor your eyes. If your eyes are closed for some time, then we will show an alert. Now we have to make a list of the things we need to provide a solution. Here is the list of things:</p>
<ol>
<li><strong>Camera</strong>. We need a camera to monitor in real-time, the person's eyes to identify if he/she is falling asleep. For this exercise, we will use our PC or laptop webcam. the OpenCV library has already all the tools to capture each frame from a video stream in real-time.</li>
<li><strong>Capture Eyes Metadata</strong>. Fortunately, the Google Mediapipe library has a python wrapper (because it was originally accessible only in C++) that provides facial landmarks that we can use to capture the contour around the eyes.</li>
<li><strong>Determine if eyes are open or closed</strong>. The metadata captured from the Mediapipe library is an array of [x,y] positions of each landmark in the face (as seen in the image below). We need to filter them to get only the points around the right and left eyes. Once these arrays are available, we will estimate the height of each eye. We will make a condition that if an eye is half-opened during k frames, then we will raise an alert. We will use k = 20 in our example.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651185119175/lq14-0U1u.jpg" alt="faceMesh.jpg" /></p>
<p>Ok, now that we have the idea of how to solve this, let's start with the fun part. Time to build the prototype.</p>
<h3 id="heading-load-the-libraries">Load the Libraries</h3>
<p>Mediapipe is available with pip, so use <strong>pip install mediapipe</strong> to download the library.</p>
<pre><code><span class="hljs-keyword">import</span> cv2 <span class="hljs-keyword">as</span> cv
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> mediapipe <span class="hljs-keyword">as</span> mp
</code></pre><h3 id="heading-eye-height-function-openlenarr">Eye Height Function <em>open_len(arr)</em></h3>
<p>The Mediapipe will output the points around both eyes as a collection of [x,y] points. The idea is to identify the highest and lowest, y-values for each eye, so that we can use them to calculate how open each one is. The following function will take the array from Mediapipe and calculate the height of each eye as the difference between the max-min y values of the [x,y] point collection. </p>
<pre><code>def open_len(arr):
    y_arr <span class="hljs-operator">=</span> []

    <span class="hljs-keyword">for</span> <span class="hljs-keyword">_</span>,y in arr:
        y_arr.append(y)

    min_y <span class="hljs-operator">=</span> min(y_arr)
    max_y <span class="hljs-operator">=</span> max(y_arr)

    <span class="hljs-keyword">return</span> max_y <span class="hljs-operator">-</span> min_y
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651215331354/tcFY_GB45.PNG" alt="Capture.PNG" /></p>
<h3 id="heading-functional-prototype">Functional Prototype</h3>
<pre><code><span class="hljs-string">mp_face_mesh</span> <span class="hljs-string">=</span> <span class="hljs-string">mp.solutions.face_mesh</span>

<span class="hljs-comment"># A: location of the eye-landamarks in the facemesh collection</span>
<span class="hljs-string">RIGHT_EYE</span> <span class="hljs-string">=</span> [ <span class="hljs-number">362</span>, <span class="hljs-number">382</span>, <span class="hljs-number">381</span>, <span class="hljs-number">380</span>, <span class="hljs-number">374</span>, <span class="hljs-number">373</span>, <span class="hljs-number">390</span>, <span class="hljs-number">249</span>, <span class="hljs-number">263</span>, <span class="hljs-number">466</span>, <span class="hljs-number">388</span>, <span class="hljs-number">387</span>, <span class="hljs-number">386</span>, <span class="hljs-number">385</span>,<span class="hljs-number">384</span>, <span class="hljs-number">398</span> ]
<span class="hljs-string">LEFT_EYE</span> <span class="hljs-string">=</span> [ <span class="hljs-number">33</span>, <span class="hljs-number">7</span>, <span class="hljs-number">163</span>, <span class="hljs-number">144</span>, <span class="hljs-number">145</span>, <span class="hljs-number">153</span>, <span class="hljs-number">154</span>, <span class="hljs-number">155</span>, <span class="hljs-number">133</span>, <span class="hljs-number">173</span>, <span class="hljs-number">157</span>, <span class="hljs-number">158</span>, <span class="hljs-number">159</span>, <span class="hljs-number">160</span>, <span class="hljs-number">161</span> , <span class="hljs-number">246</span> ]

<span class="hljs-comment"># handle of the webcam</span>
<span class="hljs-string">cap</span> <span class="hljs-string">=</span> <span class="hljs-string">cv.VideoCapture(0)</span>

<span class="hljs-comment"># Mediapipe parametes</span>
<span class="hljs-string">with</span> <span class="hljs-string">mp_face_mesh.FaceMesh(</span>
    <span class="hljs-string">max_num_faces=1,</span>
    <span class="hljs-string">refine_landmarks=True,</span>
    <span class="hljs-string">min_detection_confidence=0.5,</span>
    <span class="hljs-string">min_tracking_confidence=0.5</span>
<span class="hljs-string">)</span> <span class="hljs-attr">as face_mesh:</span>

    <span class="hljs-comment"># B: count how many frames the user seems to be going to nap (half closed eyes)</span>
    <span class="hljs-string">drowsy_frames</span> <span class="hljs-string">=</span> <span class="hljs-number">0</span>

    <span class="hljs-comment"># C: max height of each eye</span>
    <span class="hljs-string">max_left</span> <span class="hljs-string">=</span> <span class="hljs-number">0</span>
    <span class="hljs-string">max_right</span> <span class="hljs-string">=</span> <span class="hljs-number">0</span>

    <span class="hljs-attr">while True:</span>

        <span class="hljs-comment"># get every frame from the web-cam</span>
        <span class="hljs-string">ret,</span> <span class="hljs-string">frame</span> <span class="hljs-string">=</span> <span class="hljs-string">cap.read()</span>
        <span class="hljs-attr">if not ret:</span>
            <span class="hljs-string">break</span>

        <span class="hljs-comment"># Get the current frame and collect the image information</span>
        <span class="hljs-string">frame</span> <span class="hljs-string">=</span> <span class="hljs-string">cv.flip(frame,</span> <span class="hljs-number">1</span><span class="hljs-string">)</span>
        <span class="hljs-string">rgb_frame</span> <span class="hljs-string">=</span> <span class="hljs-string">cv.cvtColor(frame,</span> <span class="hljs-string">cv.COLOR_BGR2RGB)</span>
        <span class="hljs-string">img_h,</span> <span class="hljs-string">img_w</span> <span class="hljs-string">=</span> <span class="hljs-string">frame.shape[:2]</span>

        <span class="hljs-comment"># D: collect the mediapipe results</span>
        <span class="hljs-string">results</span> <span class="hljs-string">=</span> <span class="hljs-string">face_mesh.process(rgb_frame)</span>

        <span class="hljs-comment"># E: if mediapipe was able to find any landmanrks in the frame...</span>
        <span class="hljs-attr">if results.multi_face_landmarks:</span>

            <span class="hljs-comment"># F: collect all [x,y] pairs of all facial landamarks</span>
            <span class="hljs-string">all_landmarks</span> <span class="hljs-string">=</span> <span class="hljs-string">np.array([np.multiply([p.x,</span> <span class="hljs-string">p.y],</span> [<span class="hljs-string">img_w</span>, <span class="hljs-string">img_h</span>]<span class="hljs-string">).astype(int)</span> <span class="hljs-string">for</span> <span class="hljs-string">p</span> <span class="hljs-string">in</span> <span class="hljs-string">results.multi_face_landmarks[0].landmark])</span>

            <span class="hljs-comment"># G: right and left eye landmarks</span>
            <span class="hljs-string">right_eye</span> <span class="hljs-string">=</span> <span class="hljs-string">all_landmarks[RIGHT_EYE]</span>
            <span class="hljs-string">left_eye</span> <span class="hljs-string">=</span> <span class="hljs-string">all_landmarks[LEFT_EYE]</span>

            <span class="hljs-comment"># H: draw only landmarks of the eyes over the image</span>
            <span class="hljs-string">cv.polylines(frame,</span> [<span class="hljs-string">left_eye</span>]<span class="hljs-string">,</span> <span class="hljs-literal">True</span><span class="hljs-string">,</span> <span class="hljs-string">(0,255,0),</span> <span class="hljs-number">1</span><span class="hljs-string">,</span> <span class="hljs-string">cv.LINE_AA)</span>
            <span class="hljs-string">cv.polylines(frame,</span> [<span class="hljs-string">right_eye</span>]<span class="hljs-string">,</span> <span class="hljs-literal">True</span><span class="hljs-string">,</span> <span class="hljs-string">(0,255,0),</span> <span class="hljs-number">1</span><span class="hljs-string">,</span> <span class="hljs-string">cv.LINE_AA)</span> 

            <span class="hljs-comment"># I: estimate eye-height for each eye</span>
            <span class="hljs-string">len_left</span> <span class="hljs-string">=</span> <span class="hljs-string">open_len(right_eye)</span>
            <span class="hljs-string">len_right</span> <span class="hljs-string">=</span> <span class="hljs-string">open_len(left_eye)</span>

            <span class="hljs-comment"># J: keep highest distance of eye-height for each eye</span>
            <span class="hljs-string">if</span> <span class="hljs-string">len_left</span> <span class="hljs-string">&gt;</span> <span class="hljs-attr">max_left:</span>
                <span class="hljs-string">max_left</span> <span class="hljs-string">=</span> <span class="hljs-string">len_left</span>

            <span class="hljs-string">if</span> <span class="hljs-string">len_right</span> <span class="hljs-string">&gt;</span> <span class="hljs-attr">max_right:</span>
                <span class="hljs-string">max_right</span> <span class="hljs-string">=</span> <span class="hljs-string">len_right</span>

            <span class="hljs-comment"># print on screen the eye-height for each eye</span>
            <span class="hljs-string">cv.putText(img=frame,</span> <span class="hljs-string">text='Max:</span> <span class="hljs-string">' + str(max_left)  + '</span> <span class="hljs-attr">Left Eye:</span> <span class="hljs-string">' + str(len_left), fontFace=0, org=(10, 30), fontScale=0.5, color=(0, 255, 0))
            cv.putText(img=frame, text='</span><span class="hljs-attr">Max:</span> <span class="hljs-string">' + str(max_right)  + '</span> <span class="hljs-attr">Right Eye:</span> <span class="hljs-string">' + str(len_right), fontFace=0, org=(10, 50), fontScale=0.5, color=(0, 255, 0))

            # K: condition: if eyes are half-open the count.
            if (len_left &lt;= int(max_left / 2) + 1 and len_right &lt;= int(max_right / 2) + 1):
                drowsy_frames += 1
            else:
                drowsy_frames = 0

            # L: if count is above k, that means the person has drowsy eyes for more than k frames.
            if (drowsy_frames &gt; 20):
                cv.putText(img=frame, text='</span><span class="hljs-string">ALERT',</span> <span class="hljs-string">fontFace=0,</span> <span class="hljs-string">org=(200,</span> <span class="hljs-number">300</span><span class="hljs-string">),</span> <span class="hljs-string">fontScale=3,</span> <span class="hljs-string">color=(0,</span> <span class="hljs-number">255</span><span class="hljs-string">,</span> <span class="hljs-number">0</span><span class="hljs-string">),</span> <span class="hljs-string">thickness</span> <span class="hljs-string">=</span> <span class="hljs-number">3</span><span class="hljs-string">)</span>


        <span class="hljs-string">cv.imshow('img',</span> <span class="hljs-string">frame)</span>
        <span class="hljs-string">key</span> <span class="hljs-string">=</span> <span class="hljs-string">cv.waitKey(1)</span>
        <span class="hljs-string">if</span> <span class="hljs-string">key</span> <span class="hljs-string">==</span> <span class="hljs-string">ord('q'):</span>
            <span class="hljs-string">break</span>

<span class="hljs-string">cap.release()</span>
<span class="hljs-string">cv.destroyAllWindows()</span>
</code></pre><h3 id="heading-code-sections-explained">Code Sections Explained</h3>
<ul>
<li><p><strong>A</strong>: RIGHT_EYE and LEFT_EYE are the arrays of the indexes of the points around the eyes in the face-landmark collection. We will use these indexes to filter the results from the mediapipe.</p>
</li>
<li><p><strong>B</strong>: drowsy_frames is the variable used to accumulate how many frames the user closed the eyes at least 50% of the height of the eye. </p>
</li>
<li><p><strong>C</strong>: max_left and max_right will capture the maximum height recorded for each eye while open.</p>
</li>
<li><p><strong>D</strong>: This is where the mediapipe uses the rgb_frame and searches for landmarks. This is basically the predict method of the mediapipe FaceMesh functionality.</p>
</li>
<li><p><strong>E</strong>: results.multi_face_landmarks contains all the landmarks found. So if any, let's do something, otherwise, ignore it.</p>
</li>
<li><p><strong>F</strong>: all_landmarks contain all face landmarks found in the image by media pipe. This includes all the face area, not only the eyes.</p>
</li>
<li><p><strong>G</strong>: we filter the all_landmarks array with the indexes from RIGHT_EYE and LEFT_EYE from section A. This will return two lists of the form [[x,y],[x,y],...,[x,y]] that contains only the points around the left and right eye.</p>
</li>
<li><p><strong>H</strong>: this is for debugging. We will use OpenCV polylines method to draw the lines around the eyes from the right_eye and left_eye landmarks captured in section G.</p>
</li>
<li><p><strong>I</strong>: Estimate the height of each eye.</p>
</li>
<li><p><strong>J</strong>: keep track of the max height of each eye.</p>
</li>
<li><p><strong>K</strong>: This is the drowsy condition. If eyes are half-open add 1 to the drowsy_frames counter. Otherwise, initialize the variable to 0 to start counting again.</p>
</li>
<li><p><strong>L</strong>: If the user has drowsy eyes for more than 20 frames, then show the ALERT text on the screen.</p>
</li>
</ul>
<h3 id="heading-this-is-the-way-of-mediapipe">This is the way... of mediapipe</h3>
<p><img src="https://doczamora-images.s3.us-east-2.amazonaws.com/DrowsyMediapipe.gif" /></p>
<h3 id="heading-get-the-full-code">Get the Full Code</h3>
<p>You can get the Gist <strong><a target="_blank" href="https://gist.github.com/drzamoramora/a1b1b3644ac09c6483e533d52f1aba57">here</a>!
</strong>
<a href="https://www.buymeacoffee.com/doczamora" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" class="buycoffee" alt="Buy Me A Coffee." /></a></p>
]]></content:encoded></item><item><title><![CDATA[Tensorflow vs PyTorch]]></title><description><![CDATA[This is something I have been asked frequently. Which should I learn? Are both required for a Data Scientist? Let's check the following benchmark I made:

Warning: This comparison is biased from my experience which is mostly with tensorflow, but ther...]]></description><link>https://www.doczamora.com/tensorflow-vs-pytorch</link><guid isPermaLink="true">https://www.doczamora.com/tensorflow-vs-pytorch</guid><category><![CDATA[TensorFlow]]></category><category><![CDATA[Python]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[Benchmark]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Mon, 25 Apr 2022 20:49:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/B87zMorEZRo/upload/v1650919713624/xW1i6Yo0U.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is something I have been asked frequently. Which should I learn? Are both required for a Data Scientist? Let's check the following benchmark I made:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650917780963/4P9a9J3c3.PNG" alt="Capture.PNG" /></p>
<p><strong>Warning</strong>: This comparison is biased from my experience which is mostly with tensorflow, but there are interesting conclusions. Althought they scored similarly, there are some aspects that might weigh a bit more, here they are.</p>
<ol>
<li><p>According ti <a target="_blank" href="https://www.assemblyai.com/blog/pytorch-vs-tensorflow-in-2022/">AssemblyAI</a>, Historically TF has been used as the defacto framework for deep learning, but the raise of popularity for PyTorch as grown exponentially. In 2017 almost 90% of the research papers used TF. In 2021 almost 80% of the new research are made with PyTorch.</p>
</li>
<li><p><a target="_blank" href="https://paperswithcode.com/trends">Papers with Code</a> Shows that most of the papers exposed are done with PyTorch.</p>
</li>
<li><p>Althoug Tensorflow 1 was first, it was difficult to use, giving other Libraries and Frameworks a chance to shine.</p>
</li>
<li><p>Companies like OpenAI have moved a lot of their internal efforts from TF to PyTorch. There are things like Reinforcement Learning that are still done in TF. </p>
</li>
<li><p>According to <a target="_blank" href="https://gradientflow.com/one-simple-chart-tensorflow-vs-pytorch-in-job-postings/">GradietFlow</a>, Tensorflow is the most popular framework in job postings, but I believe this is because of historical reasons. PyTorch grew 194% year-over-year in contrast to Tensorflow who grew just 23%.</p>
</li>
<li><p>Most of the models ready-to-use on HuggingFace are made in <a target="_blank" href="https://huggingface.co/">PyTorch</a>. </p>
</li>
<li><p>Tensorflow has some unique features such as TFLite for mobile devices and for Javascript, allowing you to train simple models on the web. PyTorch Mobile was released in 2019 for iOS and Android devices. PyTorchLive was Facebooks's response for javascript and react-native support. </p>
</li>
<li><p>Reinformcement Learning is more robust on the Tensorflow side. </p>
</li>
</ol>
<blockquote>
<p>I believe the final message is loud an clear. PyTorch is the future and it's becoming the new bad boy in town. Tensorflow is still widely used and supported. So, you better learn both as they will be competing. </p>
</blockquote>
<p>If you are just starting, I recommend start with Tensorflow and look for the alternative PyTorch code. </p>
<p><a href="https://www.buymeacoffee.com/doczamora" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee." /></a></p>
]]></content:encoded></item><item><title><![CDATA[Recommend Cereals with the Correlation Coefficient]]></title><description><![CDATA[Today's post is about how to recommend things. Concretely, we are going to perform a basic implementation of an item-to-item recommender by using the Correlation coefficient we explored in another post.
To explore this idea, we will be using a Cereal...]]></description><link>https://www.doczamora.com/recommend-cereals-with-the-correlation-coefficient</link><guid isPermaLink="true">https://www.doczamora.com/recommend-cereals-with-the-correlation-coefficient</guid><category><![CDATA[Tutorial]]></category><category><![CDATA[statistics]]></category><category><![CDATA[Applications]]></category><category><![CDATA[Machine Learning]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Wed, 20 Apr 2022 05:47:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/MajwKB0xAF0/upload/v1650432000428/tKmD--77r.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today's post is about how to recommend things. Concretely, we are going to perform a basic implementation of an item-to-item recommender by using the Correlation coefficient we explored in another <a target="_blank" href="https://www.doczamora.com/covariance-and-correlation-coefficient">post</a>.</p>
<p>To explore this idea, we will be using a Cereals dataset I downloaded from Kaggle. You can download the dataset from <a target="_blank" href="https://www.kaggle.com/datasets/crawford/80-cereals">here</a>.</p>
<p>The dataset contains about 77 different cereals with some interesting nutritional features such as calories, protein, fat, sodium, carbohydrates, sugars, vitamins, etc.</p>
<pre><code><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns

<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
</code></pre><p>Now, let's load the data and select only the nutritional attributes we want to use:</p>
<pre><code><span class="hljs-attr">data</span> = pd.read_csv(<span class="hljs-string">'data/cereals-products.csv'</span>)
<span class="hljs-attr">data</span> = data[[<span class="hljs-string">'name'</span>,<span class="hljs-string">'calories'</span>,<span class="hljs-string">'protein'</span>,<span class="hljs-string">'fat'</span>,<span class="hljs-string">'sodium'</span>, <span class="hljs-string">'fiber'</span>, <span class="hljs-string">'carbo'</span>, <span class="hljs-string">'sugars'</span>, <span class="hljs-string">'potass'</span>, <span class="hljs-string">'vitamins'</span>]]
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650432248266/fB-Fc9mVO.PNG" alt="Capture.PNG" /></p>
<p>As you can see, there are 77 different kinds of cereal, each one described by 10 features. The objective is to calculate a <em>metric </em> that can tell us how "similar" is one cereal to the other. That metric is the Pearson Correlation Coefficient.</p>
<p>Numpy has the <strong>corcoeff </strong> method that allows us to calculate the correlation coefficient of all cereals at once! We will use the data loaded to estimate the correlation between cereals. This will generate a correlation matrix with dimensions [77,77]. </p>
<p>To calculate the Pearson matrix, we just need the numerical attributes, so we will avoid putting the "name" column as this has no use, for now.</p>
<pre><code>pearson_matrix <span class="hljs-operator">=</span> np.corrcoef(data[data.columns[<span class="hljs-number">1</span>:]])
</code></pre><p>The pearson_matrix is a 77x77 matrix of the correlations between cereals. To visualize this, we will use the seaborn library with the following code.</p>
<pre><code>plt.figure(figsize <span class="hljs-operator">=</span> (<span class="hljs-number">16</span>,<span class="hljs-number">16</span>))

sns.heatmap(pearson_matrix, 
        xticklabels<span class="hljs-operator">=</span>data[<span class="hljs-string">"name"</span>],
        yticklabels<span class="hljs-operator">=</span>data[<span class="hljs-string">"name"</span>],
        fmt<span class="hljs-operator">=</span><span class="hljs-string">"d"</span>)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650432701873/_qWdJpTKT.png" alt="descarga.png" /></p>
<p>Let's remember that the correlation measures the level of the linear relationship between two lists. If the correlation is perfect, then it will be 1.</p>
<p>The pearson_matrix is all we need now to search for cereals that are similar. The idea is that if we choose <em>"Special K"</em>, for example, we look into the pearson_matrix for those cereals that have the highest correlations. Is that simple! All we need to do now, is create a method <em>"recommend"</em> which will search in the pearson_matrix the top-k most similar cereals.</p>
<p>The code looks like this:</p>
<pre><code>def recommend(cereal_name, top_k):
    cereal_names <span class="hljs-operator">=</span> data[<span class="hljs-string">"name"</span>]
    index <span class="hljs-operator">=</span> list(cereal_names).index(cereal_name)
    coeff <span class="hljs-operator">=</span> pearson_matrix[index]
    df <span class="hljs-operator">=</span> pd.DataFrame({<span class="hljs-string">'pearson'</span>:coeff, <span class="hljs-string">'name'</span> : cereal_names}).sort_values(<span class="hljs-string">'pearson'</span>, ascending<span class="hljs-operator">=</span>False)
    <span class="hljs-keyword">return</span> df.head(top_k)
</code></pre><p>This method returns the list of cereals names sorted by their respective pearson coefficient. </p>
<p>Let's search for <strong>"Special K"</strong> to get the top 10 most similar cereals:</p>
<pre><code><span class="hljs-selector-tag">recommend</span>(<span class="hljs-string">"Special K"</span>, <span class="hljs-number">10</span>)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650433078533/BPqo3vden.png" alt="image.png" /></p>
<p>What about "100% Bran"</p>
<pre><code><span class="hljs-selector-tag">recommend</span>(<span class="hljs-string">"100% Bran"</span>, <span class="hljs-number">10</span>)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650433169328/RJk106cih.png" alt="image.png" /></p>
<p><strong>Final Thoughts:</strong></p>
<ul>
<li>The correlation coefficient is used as a similarity measure to find other products that are mathematically similar, based on the data attributes.</li>
<li>If this recommender is used in a commercial setting, it should be used as tool to find replacement cereals or similar cereals in terms of nutritional values, not flavor. </li>
<li>The person matrix calculated here should be persisted somewhere so that this is not estimated on every call. If new products are added, the matrix should be generated again.</li>
<li>This technique shown here works also with other types of data such as categorical data or text. In the case of categorical data, variables should be one-hot encoded. If used with text, then the text should be converted into tokens.</li>
</ul>
<p><a href="https://www.buymeacoffee.com/doczamora" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee." /></a></p>
]]></content:encoded></item><item><title><![CDATA[Bootstrapping vs Cross-Validation]]></title><description><![CDATA[Boostraping
Bootstrapping is a resampling technique with replacement; that is, we can choose on every sample a subset of elements that might be repeated.  

The bootstrap method is a statistical technique for estimating quantities of a population by ...]]></description><link>https://www.doczamora.com/bootstrapping-vs-cross-validation</link><guid isPermaLink="true">https://www.doczamora.com/bootstrapping-vs-cross-validation</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[statistics]]></category><category><![CDATA[Data Science]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Sun, 17 Apr 2022 16:57:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/uOhBxB23Wao/upload/v1650214652142/YQU5SXCx_.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-boostraping">Boostraping</h3>
<p>Bootstrapping is a resampling technique with replacement; that is, we can choose on every sample a subset of elements that might be repeated.  </p>
<blockquote>
<p>The bootstrap method is a statistical technique for estimating quantities of a population by averaging estimates from multiple small data samples (Brownlee, 2018).</p>
</blockquote>
<p><strong>The Algorithm To Create One Sample</strong></p>
<pre><code>N <span class="hljs-operator">=</span> size of Dataset (population)
n <span class="hljs-operator">=</span> target size of sample
cn <span class="hljs-operator">=</span> current size of the sample
s <span class="hljs-operator">=</span> sample

While (cn <span class="hljs-operator">&lt;</span> n)
  Randomly select an item i <span class="hljs-keyword">from</span> the dataset D 
  Add the randomly selected item i to s. 
  cn+<span class="hljs-operator">+</span>
</code></pre><p>This creates subset s full of randomly selected samples from D. This process can be repeated k times. </p>
<h4 id="heading-boostraping-with-scikit-learn">Boostraping with Scikit-Learn</h4>
<p>In Scikit-Learn, we can get a random sample of a dataset D with the resample method. Let's select from a 4-row matrix 3 samples of two rows each.</p>
<pre><code><span class="hljs-string">import</span> <span class="hljs-string">numpy</span> <span class="hljs-string">as</span> <span class="hljs-string">np</span>
<span class="hljs-string">from</span> <span class="hljs-string">sklearn.utils</span> <span class="hljs-string">import</span> <span class="hljs-string">resample</span>

<span class="hljs-string">X</span> <span class="hljs-string">=</span> <span class="hljs-string">np.array([[1.,</span> <span class="hljs-number">0</span><span class="hljs-string">.],</span> [<span class="hljs-number">2</span><span class="hljs-string">.</span>, <span class="hljs-number">1</span><span class="hljs-string">.</span>]<span class="hljs-string">,</span> [<span class="hljs-number">0</span><span class="hljs-string">.</span>, <span class="hljs-number">0</span><span class="hljs-string">.</span>]<span class="hljs-string">,</span> [<span class="hljs-number">2</span>,<span class="hljs-number">4</span>]<span class="hljs-string">])</span>
</code></pre><p>array([[1., 0.],
       [2., 1.],
       [0., 0.],
       [2., 4.]])</p>
<pre><code><span class="hljs-selector-tag">resample</span>(X, n_samples=<span class="hljs-number">2</span>)
</code></pre><p>array([[1., 0.],
       [1., 0.]])</p>
<pre><code><span class="hljs-selector-tag">resample</span>(X, n_samples=<span class="hljs-number">2</span>)
</code></pre><p>array([[0., 0.],
       [2., 4.]])</p>
<pre><code><span class="hljs-selector-tag">resample</span>(X, n_samples=<span class="hljs-number">2</span>)
</code></pre><p>array([[2., 4.],
       [0., 0.]])</p>
<h3 id="heading-cross-validation">Cross-Validation</h3>
<p>Cross-validations is a very similar technique to Bootstrapping, with the difference that it selects its samples without replacement; that is, there are no repeated elements in every subset. Selecting k-samples with Cross-Validation is called K-Fold CrossValidation. Usually, on each cross-validation exercise, we define a portion of the selected sample to be the train and the other the test set (for example 70/30 or 80/20). The type of cross-validation that selects a test set with one single example is called LOOCV (leave one out cross-validation).</p>
<p>Subsetting a dataset using LOOCV is computationally expensive, so with usually use k-fold cross-validation with a k = {4, 5, 7, 10}</p>
<blockquote>
<p>In k-fold cross-validation, the original sample is randomly partitioned into k equal sized subsamples. Of the k subsamples, a single subsample is retained as the validation data for testing the model, and the remaining k − 1 subsamples are used as training data. The cross-validation process is then repeated k times, with each of the k subsamples used exactly once as the validation data. The k results can then be averaged to produce a single estimation.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650214098195/n7BMYHz8-.jpg" alt="1630394319812.jpg" /></p>
<h4 id="heading-cross-validation-with-scikit-learn">Cross-Validation with Scikit-Learn</h4>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">numpy</span> <span class="hljs-title"><span class="hljs-keyword">as</span></span> <span class="hljs-title">np</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-title">sklearn</span>.<span class="hljs-title">model_selection</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">KFold</span>

<span class="hljs-title">X</span> <span class="hljs-operator">=</span> <span class="hljs-title">np</span>.<span class="hljs-title">array</span>([[1, 2], [3, 4], [1, 2], [3, 4]])
<span class="hljs-title">y</span> <span class="hljs-operator">=</span> <span class="hljs-title">np</span>.<span class="hljs-title">array</span>([1, 2, 3, 4])
<span class="hljs-title">kf</span> <span class="hljs-operator">=</span> <span class="hljs-title">KFold</span>(<span class="hljs-title">n_splits</span><span class="hljs-operator">=</span>2)
<span class="hljs-title">kf</span>.<span class="hljs-title">get_n_splits</span>(<span class="hljs-title">X</span>)

<span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">train_index</span>, <span class="hljs-title">test_index</span> <span class="hljs-title">in</span> <span class="hljs-title">kf</span>.<span class="hljs-title">split</span>(<span class="hljs-title">X</span>):
    <span class="hljs-title">print</span>(<span class="hljs-string">"TRAIN:"</span>, <span class="hljs-title">train_index</span>, <span class="hljs-string">"TEST:"</span>, <span class="hljs-title">test_index</span>)
    <span class="hljs-title">X_train</span>, <span class="hljs-title">X_test</span> <span class="hljs-operator">=</span> <span class="hljs-title">X</span>[<span class="hljs-title">train_index</span>], <span class="hljs-title">X</span>[<span class="hljs-title">test_index</span>]
    <span class="hljs-title">y_train</span>, <span class="hljs-title">y_test</span> <span class="hljs-operator">=</span> <span class="hljs-title">y</span>[<span class="hljs-title">train_index</span>], <span class="hljs-title">y</span>[<span class="hljs-title">test_index</span>]
</code></pre><p>KFold(n_splits=2, random_state=None, shuffle=False)
TRAIN: [2 3] TEST: [0 1]
TRAIN: [0 1] TEST: [2 3]</p>
<h3 id="heading-so-bootstrapping-or-cross-validation">So Bootstrapping or Cross-Validation</h3>
<ol>
<li>Bootstrapping selects samples with replacements that can be as big as the dataset.</li>
<li>Cross-validation samples are smaller than the dataset.</li>
<li>Bootstrapping contains repeated elements in every subset. Bootstrapping relies on random sampling. </li>
<li>Cross-validation does not rely on random sampling, just splitting the dataset into k unique subsets.</li>
<li>Cross-validation is usually used to test an ML model's generalization capabilities.</li>
<li>Bootstrapping is used more for statistical tests, ensemble machine learning, and parameter estimation.</li>
</ol>
<p>If you are still not sure which one to use for testing your ML model, just go with cross-validation.</p>
<h3 id="heading-example-of-cross-validation-with-a-ml-model">Example of Cross-validation with a ML Model</h3>
<pre><code><span class="hljs-keyword">from</span> sklearn <span class="hljs-keyword">import</span> <span class="hljs-title">datasets</span>, <span class="hljs-title">linear_model</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-title">sklearn</span>.<span class="hljs-title">model_selection</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">cross_val_score</span>

<span class="hljs-title">diabetes</span> <span class="hljs-operator">=</span> <span class="hljs-title">datasets</span>.<span class="hljs-title">load_diabetes</span>()
<span class="hljs-title">X</span> <span class="hljs-operator">=</span> <span class="hljs-title">diabetes</span>.<span class="hljs-title">data</span>[:150]
<span class="hljs-title">y</span> <span class="hljs-operator">=</span> <span class="hljs-title">diabetes</span>.<span class="hljs-title">target</span>[:150]
<span class="hljs-title">lasso</span> <span class="hljs-operator">=</span> <span class="hljs-title">linear_model</span>.<span class="hljs-title">Lasso</span>()
<span class="hljs-title">print</span>(<span class="hljs-title">cross_val_score</span>(<span class="hljs-title">lasso</span>, <span class="hljs-title">X</span>, <span class="hljs-title">y</span>, <span class="hljs-title">cv</span><span class="hljs-operator">=</span>3))
</code></pre><p>[0.33150734 0.08022311 0.03531764]</p>
<p>In this example, we are applying Lasso to predict diabetes progression after one year. With k = 3, we obtained accuracy scores of 33%, 8%, and 35%. If we average them we can say that the cross-validation accuracy score is mean(33%, 8%, and 35%) = 25.3%.</p>
<p>Now, you can test this same code with another ML model such as Linear Regression OLS. If the new model has a better cross-validation accuracy score, then you can be certain that the new model performs better than the other one. Cross-validation is excellent for model selection.</p>
<p><a href="https://www.buymeacoffee.com/doczamora" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee." /></a></p>
]]></content:encoded></item><item><title><![CDATA[P-Value Intuition: Flipping Two Coins Example]]></title><description><![CDATA[To understand what a p-value is, I looked into some simple scenarios to explain this without having to get into probability density functions and distributions. StatQuest had a very nice idea of explaining this with coin flips. Let's check this out h...]]></description><link>https://www.doczamora.com/p-value-intuition-flipping-two-coins-example</link><guid isPermaLink="true">https://www.doczamora.com/p-value-intuition-flipping-two-coins-example</guid><category><![CDATA[statistics]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Mathematics]]></category><dc:creator><![CDATA[Dr. Juan Zamora-Mora]]></dc:creator><pubDate>Sat, 16 Apr 2022 02:45:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1650072769001/NVMyIhzim.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>To understand what a p-value is, I looked into some simple scenarios to explain this without having to get into probability density functions and distributions. StatQuest had a very nice idea of explaining this with coin flips. Let's check this out here.</p>
<h3 id="heading-probability-of-tossing-two-coins">Probability of Tossing two Coins</h3>
<p>First, we will flip two coins two times to explain the probability of getting something out of these scenarios. The following image explains all possible outcomes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650072511424/HIA9BHayl.png" alt="Flip Coins.png" /></p>
<p>As you can observe from the diagram we can get HH, TT, or [HT-TH] which are basically the same thing. We calculate the probability of these 3 outcomes, assuming each toss is independent. So the probability of getting a HH or TT is 0.25, but the probability of getting either HT or TH is 0.5.</p>
<h3 id="heading-what-is-the-p-value">What is the p-value?</h3>
<p>The p-value is not the coin flip probability. We have already calculated that.</p>
<blockquote>
<p>The p-value is the probability that <strong>random chance has generated the data</strong>, <strong>something of equal chance</strong> or <strong>rarer</strong>. With p-values, we look to understand the probability of how the data was generated.</p>
</blockquote>
<h3 id="heading-what-is-the-p-value-for-hh">What is the p-value for HH?</h3>
<p>The p-value is the sum of the probability of HH (which we already know is 0.25) + the probability of something of equal chance (in this case the probability of TT which is also 0.25) + the probability of a rarer event (which in this case is 0 because there is nothing rarer than what we have in the diagram)</p>
<p>p−value(HH)=p(HH)+p(TT)+0 p−value(HH)=0.25+0.25+0=0.5</p>
<p>So to recap, the probability of HH is 0.25 but the p-value of HH is 0.5.</p>
<h3 id="heading-so">So?</h3>
<p>Well, the p-value checks the probability that HH is generated by luck. The 0.5 means that HH is not special, it's a very common combination that is very plausible caused by luck. When a p-value is less than 0.05, we say that it is statistically significant, because it rejects the null hypothesis, which is that the observed event (in this case HH) was caused by luck or any other factor.</p>
<h3 id="heading-p-values-in-regression-or-ml-models">p-values in regression or ML models</h3>
<p>We can use p-values in machine learning models to understand the significance of predictors (variables) used for regression or classification. For example, we might use scipy to generate a regression model with OLS for some problems such as estimating the battery life of a Tesla car after x mileage. The OLS will make the linear regression model and calculate the p-values for each variable including the intercept.</p>
<p>When we observe a predictor if a p-value is lower than 0.05, we say that that variable is <strong>significant</strong> because the change in that predictor affects the response variable (y) not by luck. Then that p-value rejects the null hypothesis.</p>
<p><strong>Warning:</strong> We have to be careful with the curse of dimensionality and p-values. If our ML model has too many variables, this might cause the predictors to have a very low p-value making them significant when they are not. Reducing the number of dimensions and pruning the model from variables that make noise is a must when using p-values.</p>
<p>The following image shows an example print of the scipy OLS. You can see that every regressor has its p-values (p&gt;|t|) calculated and (almost) all of them are less than 0.05, which means they are statistically significant. Since SqFtLot has a 0.323 &gt; 0.05, we can think of removing this feature since its variability does not go along y.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650076842686/mqBu0dprP.png" alt="1*c5xhZH-NoxqesYcKRlflYw.png" /></p>
]]></content:encoded></item></channel></rss>