<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.0.0">Jekyll</generator><link href="https://tmayer.github.io/blog/feed.xml" rel="self" type="application/atom+xml" /><link href="https://tmayer.github.io/blog/" rel="alternate" type="text/html" /><updated>2020-07-26T04:56:01-05:00</updated><id>https://tmayer.github.io/blog/feed.xml</id><title type="html">Thomas Mayer</title><subtitle>NLP, ML, linguistics, visualizations, guitar and more.</subtitle><entry><title type="html">User and Item Based Filtering</title><link href="https://tmayer.github.io/blog/machinelearning/2020/06/21/user-item-based-filtering.html" rel="alternate" type="text/html" title="User and Item Based Filtering" /><published>2020-06-21T00:00:00-05:00</published><updated>2020-06-21T00:00:00-05:00</updated><id>https://tmayer.github.io/blog/machinelearning/2020/06/21/user-item-based-filtering</id><content type="html" xml:base="https://tmayer.github.io/blog/machinelearning/2020/06/21/user-item-based-filtering.html">&lt;!--
#################################################
### THIS FILE WAS AUTOGENERATED! DO NOT EDIT! ###
#################################################
# file to edit: _notebooks/2020-06-21-user-item-based-filtering.ipynb
--&gt;

&lt;div class=&quot;container&quot; id=&quot;notebook-container&quot;&gt;
        
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;Collaborative Filtering is a method in recommendation systems that searches for similar objects in order to create a ranked list of suggestions. In general, we distinguish between two different approaches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User-based filtering: we first identify the most similar users to the one for whom we want to give recommendations.&lt;/li&gt;
&lt;li&gt;Item-based filtering: we first search for the most similar items to the ones that are most relevant to the user (e.g., most liked by the user)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will look at both approaches and discuss their advantages. This blog post is very much inspired by Chapter 2 of Toby Segaran's classic book &quot;Programming Collective Intelligence&quot; (O'Reilly, 2007).&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h2 id=&quot;Data&quot;&gt;Data&lt;a class=&quot;anchor-link&quot; href=&quot;#Data&quot;&gt; &lt;/a&gt;&lt;/h2&gt;&lt;p&gt;For our discussion we need some recommendation data. There are several ways of expressing a user's preference, such as binary distinctions (booked a hotel vs. didn't book the hotel) or more explicit feedback in the form of graded reviews.&lt;/p&gt;
&lt;p&gt;We take the exemplary data below (taken from Segaran's book) and compute the recommendations using the Pandas library.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Lisa Rose&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Lady in the Water&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Snakes on a Plane&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;Just My Luck&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Superman Returns&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;You, Me and Dupree&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;The Night Listener&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
     &lt;span class=&quot;s1&quot;&gt;&amp;#39;Gene Seymour&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Lady in the Water&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Snakes on a Plane&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;Just My Luck&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Superman Returns&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;The Night Listener&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;You, Me and Dupree&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
     &lt;span class=&quot;s1&quot;&gt;&amp;#39;Michael Phillips&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Lady in the Water&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Snakes on a Plane&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;Superman Returns&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;The Night Listener&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
     &lt;span class=&quot;s1&quot;&gt;&amp;#39;Claudia Puig&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Snakes on a Plane&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Just My Luck&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;The Night Listener&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Superman Returns&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;You, Me and Dupree&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
     &lt;span class=&quot;s1&quot;&gt;&amp;#39;Mick LaSalle&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Lady in the Water&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Snakes on a Plane&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;Just My Luck&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Superman Returns&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;The Night Listener&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;You, Me and Dupree&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
     &lt;span class=&quot;s1&quot;&gt;&amp;#39;Jack Matthews&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Lady in the Water&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Snakes on a Plane&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;The Night Listener&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Superman Returns&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;You, Me and Dupree&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
     &lt;span class=&quot;s1&quot;&gt;&amp;#39;Toby&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Snakes on a Plane&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;4.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;You, Me and Dupree&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Superman Returns&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pd&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;


&lt;div class=&quot;output_html rendered_html output_subarea output_execute_result&quot;&gt;
&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Lady in the Water&lt;/th&gt;
      &lt;th&gt;Snakes on a Plane&lt;/th&gt;
      &lt;th&gt;Just My Luck&lt;/th&gt;
      &lt;th&gt;Superman Returns&lt;/th&gt;
      &lt;th&gt;You, Me and Dupree&lt;/th&gt;
      &lt;th&gt;The Night Listener&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;Lisa Rose&lt;/th&gt;
      &lt;td&gt;2.5&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;2.5&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Gene Seymour&lt;/th&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Michael Phillips&lt;/th&gt;
      &lt;td&gt;2.5&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;4.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Claudia Puig&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;4.0&lt;/td&gt;
      &lt;td&gt;2.5&lt;/td&gt;
      &lt;td&gt;4.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Mick LaSalle&lt;/th&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;4.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Jack Matthews&lt;/th&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;4.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Toby&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;4.5&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;4.0&lt;/td&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;The data frame shows our toy data set as an input for recommendations. Usually, the matrix is much bigger and way more sparse. Yet, it illustrates the fact that some users (such as Toby) haven't rated (and thus might not have seen) all the movies. We would like to get a ranking of the missing movies so that we can recommend the movie which most likely fits to their preferences.&lt;/p&gt;
&lt;p&gt;In the collaborative filtering approach (be it user or item based), there are the two main steps to get to this ranking (here illustrated with the user-based approach for our movie toy data set):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Define a similarity between objects (either users or items). This step is different from user and item based recommenders and gives them their respective names. In the user-based approach, the similarity is defined in terms of how the users rated the movies. If users give the same or a very similar rating to the same movie, they are considered more similar than if they give very different ratings. We will see below how we can quantify this to arrive at a similarity matrix between users.&lt;/li&gt;
&lt;li&gt;The second step takes the previously defined similarity metric and uses it to compute a weighted average to obtain the final recommendation scores. Once we identified a similarity among users, we will check all the missing movies and weigh the ratings that the other users gave depending on their similarity to the user at hand. &lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;User-based-Filtering&quot;&gt;User-based Filtering&lt;a class=&quot;anchor-link&quot; href=&quot;#User-based-Filtering&quot;&gt; &lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Now we want to go through the different steps for user-based filtering and compute the similarities and rankings.&lt;/p&gt;
&lt;h2 id=&quot;Step-1:-Identify-similar-users&quot;&gt;Step 1: Identify similar users&lt;a class=&quot;anchor-link&quot; href=&quot;#Step-1:-Identify-similar-users&quot;&gt; &lt;/a&gt;&lt;/h2&gt;&lt;p&gt;There are multiple ways to define the similarity among users based on the ratings they gave to the movies. However, there is one particular method that is easy to understand and visualize: the &lt;strong&gt;Euclidean Distance&lt;/strong&gt; score.&lt;/p&gt;
&lt;p&gt;For the sake of simplicity, let's reduce the number of movies in our dataset to two:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Snakes on a Plane&lt;/li&gt;
&lt;li&gt;You, Me and Dupree&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The ratings for the two movies constitute the features on which the users can be compared. A two-dimenstional visualization would look like this:&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Euclidean distance example&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;plt&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xkcd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;xaxis&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;You, Me and Dupree&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;yaxis&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Snakes on a Plane&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xaxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yaxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;scatter&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xaxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;yaxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xlim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ylim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# annotate the labels&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;xval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xaxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yaxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Lisa Rose&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# make sure that labels don&amp;#39;t overlap&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;yval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;annotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_png output_subarea &quot;&gt;
&lt;img src=&quot;data:image/png;base64,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QKxYsUIIIURkZKR46623hBBC/P777wKA2LJlixBCiB07dgidTieaN28uRo0aJXr16iX0er0YPHjwZf2bXA1yc3NFbGysuP7668WSJUtE165dRVZWVqXXFBcXi5iYGHHrrbeKWbNmic6dOwsAol27dkIIIRYvXizUarXo06ePmDx5smjYsKG0jn7zzTeFwWCQpmWxWETdunXFwIEDL6jF5/MJnU4npkyZIj132223CQBi586d0nP9+/cXqampwufziYkTJwq9Xi8mTZokxo0bJ6KjowUA8f3330uvHzVqlLjllluq/P5hYWHi3XfflR47HA6hUqnEypUrped+/vlnAUDs3r1bCFFxbIDRaBT9+/cXw4cPF02aNBHR0dHi119/FUJUHCugVqvFmTNnhM/nE6mpqUKj0Yjly5cLIYRYsmSJ0Gq1okePHmLQoEEiIyNDGI3Gq+IYlUB6X7WPITh69CiGDh0KjUYDlUqFRYsWYdGiRdLv58+fX+nozaosX74cy5cvx/r16/8ytfiHO/48bORPu/6hSr+qLqcZHR0tpST//lOif7ratWujR48eyMzMBAAkJSVh7ty5aNq0qXQcgFarxZAhQ6TT7wYNGoS2bdtK05g2bRrS09OxbNkyHD9+HKNHj8aYMWMAAPfeey/q1KkjvTYtLQ2LFy+ucsvsmmuuQb169fDCCy8gISEB1113HQYOHIg77rgD3bp1g1arxRdffIGlS5fi119/xdNPPw273Y6TJ09CrVZj9erVWLZsGdauXYvdu3cjLS0Nr732Gvr27Stt2Y0ZMwZxcXH47LPPEB4ejnfffRd79+5FUVERAGDixInS/tyUlBSMHj1augjPrbfeisOHD+Odd97BsWPHkJKSgk8//VT2ue//BMnJydi6dStGjx6NgQMHIiIiAmvXrq30mri4OOzYsQOvv/46duzYgdtuuw0zZszA888/D5/Ph0GDBiEtLQ2LFi3C9u3b0adPH2m9ftddd0mjD0DFluf777+PX3/9tcp67rzzTvTq1Ut6/NRTT2HLli2Vjv8aNGgQ9u7dC6/Xi+eeew7169fH119/DZPJhNWrV2PlypWVRoObNWuGhg0bVvl5Xbt2lZYDoOLfwEsvvVTpLLjMzEzcc8890jEvK1euxMcff4zNmzfDbDbjgQcewP333y9dv+Oxxx7DkSNHkJqaCgB4+umn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
&quot; /&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;As you can see, Claudia Puig and Lisa Rose are pretty close to each other (actually, they overlap as they have exactly the same values for both features) while Toby and Gene Seymour are most dissimilar. Although the two-dimensional plot nicely shows the differences between users for these two movies, there are two problems:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;there are more than two movies, hence we need a higher dimensional plot (which would be hard to visualize)&lt;/li&gt;
&lt;li&gt;it is hard to compare all the users to each other; it would be preferable to have a single (similarity or distance) score.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To this end, we compute the Euclidean distance score. It is best explained in the two-dimensional case above, however, it can easily be extended to higher dimensional cases. As we all learned in high-school geometry, you can compute the distance of two points in a two-dimensional space if you compute the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;compute the distance between the points on each axis and square it&lt;/li&gt;
&lt;li&gt;take the sum of the distances from all axes&lt;/li&gt;
&lt;li&gt;take the square root of the total sum&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Since this defines a distance function, yet we need a similarity score we just use the Euclidean score, add 1 to it (so not to run into any division-by-zero error) and invert it. The final function looks as follows. Note that we didn't take the square root (to get the same results as in Segaran's book). The square root doesn't change anything in the order of the similarities/distances and thus can be ignored for our purposes.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;euclidean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;eucl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eucl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;In Pandas, there is a very convenient way to get the pairwise results for a function like the &lt;code&gt;euclidean()&lt;/code&gt; above for a data frame by using the &lt;code&gt;corr()&lt;/code&gt; method and specify your own method (in this case just giving the function name &lt;code&gt;euclidean&lt;/code&gt; as the parameter &lt;code&gt;method&lt;/code&gt;). You just have to decide for which items in our data frame the correlation 
should be computed, for the users or the movies. In our case, we're interested in the users, that's why 
we have to transpose the data frame first (by using the &lt;code&gt;.T&lt;/code&gt; shortcut, i.e., &lt;code&gt;critics.T&lt;/code&gt;) before applying the correlation method.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;corr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;euclidean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;


&lt;div class=&quot;output_html rendered_html output_subarea output_execute_result&quot;&gt;
&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Lisa Rose&lt;/th&gt;
      &lt;th&gt;Gene Seymour&lt;/th&gt;
      &lt;th&gt;Michael Phillips&lt;/th&gt;
      &lt;th&gt;Claudia Puig&lt;/th&gt;
      &lt;th&gt;Mick LaSalle&lt;/th&gt;
      &lt;th&gt;Jack Matthews&lt;/th&gt;
      &lt;th&gt;Toby&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;Lisa Rose&lt;/th&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.148148&lt;/td&gt;
      &lt;td&gt;0.444444&lt;/td&gt;
      &lt;td&gt;0.285714&lt;/td&gt;
      &lt;td&gt;0.333333&lt;/td&gt;
      &lt;td&gt;0.210526&lt;/td&gt;
      &lt;td&gt;0.222222&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Gene Seymour&lt;/th&gt;
      &lt;td&gt;0.148148&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.210526&lt;/td&gt;
      &lt;td&gt;0.133333&lt;/td&gt;
      &lt;td&gt;0.129032&lt;/td&gt;
      &lt;td&gt;0.800000&lt;/td&gt;
      &lt;td&gt;0.108108&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Michael Phillips&lt;/th&gt;
      &lt;td&gt;0.444444&lt;/td&gt;
      &lt;td&gt;0.210526&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.571429&lt;/td&gt;
      &lt;td&gt;0.285714&lt;/td&gt;
      &lt;td&gt;0.181818&lt;/td&gt;
      &lt;td&gt;0.285714&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Claudia Puig&lt;/th&gt;
      &lt;td&gt;0.285714&lt;/td&gt;
      &lt;td&gt;0.133333&lt;/td&gt;
      &lt;td&gt;0.571429&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.173913&lt;/td&gt;
      &lt;td&gt;0.181818&lt;/td&gt;
      &lt;td&gt;0.235294&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Mick LaSalle&lt;/th&gt;
      &lt;td&gt;0.333333&lt;/td&gt;
      &lt;td&gt;0.129032&lt;/td&gt;
      &lt;td&gt;0.285714&lt;/td&gt;
      &lt;td&gt;0.173913&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.137931&lt;/td&gt;
      &lt;td&gt;0.307692&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Jack Matthews&lt;/th&gt;
      &lt;td&gt;0.210526&lt;/td&gt;
      &lt;td&gt;0.800000&lt;/td&gt;
      &lt;td&gt;0.181818&lt;/td&gt;
      &lt;td&gt;0.181818&lt;/td&gt;
      &lt;td&gt;0.137931&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.117647&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Toby&lt;/th&gt;
      &lt;td&gt;0.222222&lt;/td&gt;
      &lt;td&gt;0.108108&lt;/td&gt;
      &lt;td&gt;0.285714&lt;/td&gt;
      &lt;td&gt;0.235294&lt;/td&gt;
      &lt;td&gt;0.307692&lt;/td&gt;
      &lt;td&gt;0.117647&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;As can be seen in the resulting matrix, some users are more similar to each other than others. For example, users Gene Seymour and Jack Matthews are pretty close to each other (0.8). In fact, except for &quot;Snakes on a Plane&quot; they gave the exact same ratings to all movies that they both watched.&lt;/p&gt;
&lt;p&gt;On the other hand, users Gene Seymour and Toby are most dissimilar (with a distance score of 0.108). This is due to the fact that they have only three movies that they both gave ratings to and those three movies have comparatively big differences.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Jack Matthews&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Gene Seymour&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Toby&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;


&lt;div class=&quot;output_html rendered_html output_subarea output_execute_result&quot;&gt;
&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Lady in the Water&lt;/th&gt;
      &lt;th&gt;Snakes on a Plane&lt;/th&gt;
      &lt;th&gt;Just My Luck&lt;/th&gt;
      &lt;th&gt;Superman Returns&lt;/th&gt;
      &lt;th&gt;You, Me and Dupree&lt;/th&gt;
      &lt;th&gt;The Night Listener&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;Jack Matthews&lt;/th&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;4.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Gene Seymour&lt;/th&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
      &lt;td&gt;5.0&lt;/td&gt;
      &lt;td&gt;3.5&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Toby&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;4.5&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;4.0&lt;/td&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h2 id=&quot;Ranking-the-critics&quot;&gt;Ranking the critics&lt;a class=&quot;anchor-link&quot; href=&quot;#Ranking-the-critics&quot;&gt; &lt;/a&gt;&lt;/h2&gt;&lt;p&gt;With the Euclidean similarity matrix we can compute a ranking of critics for each user. To this end, we define the function &lt;code&gt;top_matches&lt;/code&gt; that makes use of the &lt;code&gt;corr()&lt;/code&gt; method of data frames for the similary scores. To get a proper similarity ranking, we first identify all users other than the one under investigation and return a Pandas Series that is created by indexing the similarity matrix for the respective user. Finally, the series is sorted in reverse order to return the top similar users.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;top_matches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;euclidean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;other_people&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;columns&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;corr_persons&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;corr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;corr_persons&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other_people&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ascending&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;The most similar user to Toby is Mick LaSalle, showing a similarity value of 0.307, whereas the least similar is Gene Seymour (as discussed above).&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top_matches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Toby&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;Mick LaSalle        0.307692
Michael Phillips    0.285714
Claudia Puig        0.235294
Lisa Rose           0.222222
Jack Matthews       0.117647
Gene Seymour        0.108108
Name: Toby, dtype: float64&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h2 id=&quot;Step-2:-Recommending-Items&quot;&gt;Step 2: Recommending Items&lt;a class=&quot;anchor-link&quot; href=&quot;#Step-2:-Recommending-Items&quot;&gt; &lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Having defined the similarity of users, we can move to the second step: how to compute the actual recommendations for user Toby. For this, we first select those movies in our toy dataset that Toby hasn't ranked yet (assuming he hasn't watched them either). These missing movies are the basis for our recommendations. All we need to do now is rank them in the appropriate order so that the movie that we assume he would rate highest comes up first in our ranking.&lt;/p&gt;
&lt;p&gt;This begs the question how we make the predictions. The basic idea is pretty simple: we take the ratings from other users for the missing movies and compute the weighted average of the rankings for each movie. But where do we take the weights from? It's very easy. We take advantage of the similarities that we worked out above. Thus, the final score for each movie (for user Toby) is calculated by taking the sum of the rating times the similarity (to Toby) for each movie divided by the overall sum of the similarities.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;$ score_{movie} = \frac{\sum_{i=1}^{users} sim_{user_i, Toby} * rating_{user_i, movie}}{\sum_{i=1}^{users} sim_{user_i, Toby}}$&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;In Pandas, we can use the &lt;code&gt;isnull()&lt;/code&gt; method on the Series to identify all the missing movies for the user. We then index into the ratings data frame, extracting only those cells with similar users and missing films. For the actual computation of the scores we need two objects:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the subset of the cells from the original data frame of ratings giving the similar users and the missing movies (&lt;code&gt;cores&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;the filtered user similarities where all negatively correlated users to Toby have been discarded (&lt;code&gt;sims&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_recommendations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;missing_films&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isnull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;person_similarities&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;top_matches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;person_similarities&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person_similarities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person_similarities&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;movies_scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person_similarities&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;missing_films&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;movies_scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person_similarities&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sims&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_recommendations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Toby&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;


&lt;div class=&quot;output_html rendered_html output_subarea output_execute_result&quot;&gt;
&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Lady in the Water&lt;/th&gt;
      &lt;th&gt;Just My Luck&lt;/th&gt;
      &lt;th&gt;The Night Listener&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;Mick LaSalle&lt;/th&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Michael Phillips&lt;/th&gt;
      &lt;td&gt;2.5&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;4.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Claudia Puig&lt;/th&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;4.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Lisa Rose&lt;/th&gt;
      &lt;td&gt;2.5&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Jack Matthews&lt;/th&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Gene Seymour&lt;/th&gt;
      &lt;td&gt;3.0&lt;/td&gt;
      &lt;td&gt;1.5&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sims&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;Mick LaSalle        0.307692
Michael Phillips    0.285714
Claudia Puig        0.235294
Lisa Rose           0.222222
Jack Matthews       0.117647
Gene Seymour        0.108108
Name: Toby, dtype: float64&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;With these two objects we can first compute the numerator of the final score by taking the ratings for the missing movies and multiply them by the respective user's similarity to Toby.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;films_overview&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sims&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;films_overview&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;


&lt;div class=&quot;output_html rendered_html output_subarea output_execute_result&quot;&gt;
&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Mick LaSalle&lt;/th&gt;
      &lt;th&gt;Michael Phillips&lt;/th&gt;
      &lt;th&gt;Claudia Puig&lt;/th&gt;
      &lt;th&gt;Lisa Rose&lt;/th&gt;
      &lt;th&gt;Jack Matthews&lt;/th&gt;
      &lt;th&gt;Gene Seymour&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;Lady in the Water&lt;/th&gt;
      &lt;td&gt;0.923077&lt;/td&gt;
      &lt;td&gt;0.714286&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;0.555556&lt;/td&gt;
      &lt;td&gt;0.352941&lt;/td&gt;
      &lt;td&gt;0.324324&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Just My Luck&lt;/th&gt;
      &lt;td&gt;0.615385&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;0.705882&lt;/td&gt;
      &lt;td&gt;0.666667&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;0.162162&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;The Night Listener&lt;/th&gt;
      &lt;td&gt;0.923077&lt;/td&gt;
      &lt;td&gt;1.142857&lt;/td&gt;
      &lt;td&gt;1.058824&lt;/td&gt;
      &lt;td&gt;0.666667&lt;/td&gt;
      &lt;td&gt;0.352941&lt;/td&gt;
      &lt;td&gt;0.324324&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;After that, we can easily get the sum of these weighted scores for each movie.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;films_overview&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;Lady in the Water     2.870184
Just My Luck          2.150096
The Night Listener    4.468690
dtype: float64&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;All that is left now is to compute the denominator. For this, we take the non-null ratings as a mask for the similarities. The reason for this step is to remove individual similarities from the totals if the user didn't rate the respective movie. Pandas's weak typing comes in handy at this step. The boolean return values of the &lt;code&gt;notnull()&lt;/code&gt; method are turned into integers (0 for &lt;code&gt;False&lt;/code&gt;), which nullify the factor for the respective user. At the end, we obtain a similarity total for each movie.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;totals&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;notnull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sims&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;totals&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;Lady in the Water     1.041384
Just My Luck          0.873317
The Night Listener    1.276678
dtype: float64&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;Finally, we can compute the actual predicted movie ratings for user Toby by taking the sums of the weighted scores and dividing them by the totals. In our toy example, the movie 'The Night Listener' gets the highest rating with 3.35 and would thus be our first choice for a recommendation to Toby.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;films_overview&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;totals&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;recs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;Just My Luck          2.461988
Lady in the Water     2.756124
The Night Listener    3.500248
dtype: float64&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h1 id=&quot;Item-based-Filtering&quot;&gt;Item-based Filtering&lt;a class=&quot;anchor-link&quot; href=&quot;#Item-based-Filtering&quot;&gt; &lt;/a&gt;&lt;/h1&gt;&lt;p&gt;So far, we've looked at the user similarities first to reduce the search space for our recommendations. However, this comes with a downside when your matrix of ratings includes a large number of users and shows a lot of sparsity, thus making it hard to compute similarities among users when there is little to no overlap.&lt;/p&gt;
&lt;p&gt;An alternative approach, called item-based filtering, tries to remedy these problems by dispensing with the user similarity step and searching for similar items right away (hence the name). With our toy dataframe this is very easy as we only need to apply the &lt;code&gt;corr()&lt;/code&gt; method again, this time on the items and not on the users:&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;corr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;euclidean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;


&lt;div class=&quot;output_html rendered_html output_subarea output_execute_result&quot;&gt;
&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Lady in the Water&lt;/th&gt;
      &lt;th&gt;Snakes on a Plane&lt;/th&gt;
      &lt;th&gt;Just My Luck&lt;/th&gt;
      &lt;th&gt;Superman Returns&lt;/th&gt;
      &lt;th&gt;You, Me and Dupree&lt;/th&gt;
      &lt;th&gt;The Night Listener&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;Lady in the Water&lt;/th&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.222222&lt;/td&gt;
      &lt;td&gt;0.222222&lt;/td&gt;
      &lt;td&gt;0.090909&lt;/td&gt;
      &lt;td&gt;0.400000&lt;/td&gt;
      &lt;td&gt;0.285714&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Snakes on a Plane&lt;/th&gt;
      &lt;td&gt;0.222222&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.105263&lt;/td&gt;
      &lt;td&gt;0.166667&lt;/td&gt;
      &lt;td&gt;0.051282&lt;/td&gt;
      &lt;td&gt;0.181818&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Just My Luck&lt;/th&gt;
      &lt;td&gt;0.222222&lt;/td&gt;
      &lt;td&gt;0.105263&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.064516&lt;/td&gt;
      &lt;td&gt;0.181818&lt;/td&gt;
      &lt;td&gt;0.153846&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Superman Returns&lt;/th&gt;
      &lt;td&gt;0.090909&lt;/td&gt;
      &lt;td&gt;0.166667&lt;/td&gt;
      &lt;td&gt;0.064516&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.053333&lt;/td&gt;
      &lt;td&gt;0.102564&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;You, Me and Dupree&lt;/th&gt;
      &lt;td&gt;0.400000&lt;/td&gt;
      &lt;td&gt;0.051282&lt;/td&gt;
      &lt;td&gt;0.181818&lt;/td&gt;
      &lt;td&gt;0.053333&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
      &lt;td&gt;0.148148&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;The Night Listener&lt;/th&gt;
      &lt;td&gt;0.285714&lt;/td&gt;
      &lt;td&gt;0.181818&lt;/td&gt;
      &lt;td&gt;0.153846&lt;/td&gt;
      &lt;td&gt;0.102564&lt;/td&gt;
      &lt;td&gt;0.148148&lt;/td&gt;
      &lt;td&gt;1.000000&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;Again, the same principles apply that we mentioned above for the user similarities. A score close to 1 indicates that the movies are very similar. For example, the movies 'Snakes on a Plane' and 'Lady in the Water' seem to be alike based on the users's ratings whereas 'Just my Luck' and 'Lady in the Water' are quite dissimilar.&lt;/p&gt;
&lt;p&gt;To compute the final recommendation scores all we need to do is to identify the missing movies of a given user (Toby) and compute a weighted average of their similarity to all movies the user has already rated together with their similarity to the missing movies.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_item_recommendations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;pearson&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;missing_films&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isnull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;movie_similarities&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;corr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;movie_similarities&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;movie_similarities&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;movie_similarities&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;missing_films&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;missing_films&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;person_ratings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;missing_films&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;movie_similarities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person_ratings&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_item_recommendations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Toby&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;euclidean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ms&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;


&lt;div class=&quot;output_html rendered_html output_subarea output_execute_result&quot;&gt;
&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Lady in the Water&lt;/th&gt;
      &lt;th&gt;Just My Luck&lt;/th&gt;
      &lt;th&gt;The Night Listener&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;Snakes on a Plane&lt;/th&gt;
      &lt;td&gt;0.222222&lt;/td&gt;
      &lt;td&gt;0.105263&lt;/td&gt;
      &lt;td&gt;0.181818&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Superman Returns&lt;/th&gt;
      &lt;td&gt;0.090909&lt;/td&gt;
      &lt;td&gt;0.064516&lt;/td&gt;
      &lt;td&gt;0.102564&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;You, Me and Dupree&lt;/th&gt;
      &lt;td&gt;0.400000&lt;/td&gt;
      &lt;td&gt;0.181818&lt;/td&gt;
      &lt;td&gt;0.148148&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pr&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;Snakes on a Plane     4.5
Superman Returns      4.0
You, Me and Dupree    1.0
Name: Toby, dtype: float64&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;p&gt;Like above, we now take the missing movies and weigh them with the similarities that we defined above. The result is an item-based recommendation score that indicates which movies we should recommend next to the user (in this case Toby).&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ms&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;Lady in the Water     1.763636
Just My Luck          0.913567
The Night Listener    1.376586
dtype: float64&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item_recos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ms&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ms&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;item_recos&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;Lady in the Water     2.473088
Just My Luck          2.598332
The Night Listener    3.182635
dtype: float64&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h1 id=&quot;User-or-Item-based-Filtering?&quot;&gt;User or Item-based Filtering?&lt;a class=&quot;anchor-link&quot; href=&quot;#User-or-Item-based-Filtering?&quot;&gt; &lt;/a&gt;&lt;/h1&gt;&lt;p&gt;As shown above, user and item-based filtering mainly differ in the first step: we either have to compute similarities for users or times first. With a very large database, item-based filtering is to be preferred as it is significantly faster to compare the items for users to identify the similarities than to compare a given user to all other users&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><author><name></name></author><summary type="html"></summary></entry><entry><title type="html">Softmax Explained</title><link href="https://tmayer.github.io/blog/deeplearning/2020/05/02/softmax-explained.html" rel="alternate" type="text/html" title="Softmax Explained" /><published>2020-05-02T00:00:00-05:00</published><updated>2020-05-02T00:00:00-05:00</updated><id>https://tmayer.github.io/blog/deeplearning/2020/05/02/softmax-explained</id><content type="html" xml:base="https://tmayer.github.io/blog/deeplearning/2020/05/02/softmax-explained.html">&lt;!--
#################################################
### THIS FILE WAS AUTOGENERATED! DO NOT EDIT! ###
#################################################
# file to edit: _notebooks/2020-05-02-softmax-explained.ipynb
--&gt;

&lt;div class=&quot;container&quot; id=&quot;notebook-container&quot;&gt;
        
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h2 id=&quot;Problem&quot;&gt;Problem&lt;a class=&quot;anchor-link&quot; href=&quot;#Problem&quot;&gt; &lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Given a bunch of numbers each representing a value for a given item you want to transform them into a metric to identify the highest value with the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the resulting metric should normalize all values, that is the sum of all values should be 1&lt;/li&gt;
&lt;li&gt;the metric should favor only one item among the numbers (the one with the highest original value), thus boosting it to make it stand apart more clearly&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Use-case&quot;&gt;Use case&lt;a class=&quot;anchor-link&quot; href=&quot;#Use-case&quot;&gt; &lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Activation function in the last layer of a classification network. Each item stands for a certain class and only one class is to be selected. In the previous layer any kind of activation can result (normally between 0 and infinity) but we want to have a normalized output at the end that tells us which class has been activated.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h2 id=&quot;Two-step-approach&quot;&gt;Two-step approach&lt;a class=&quot;anchor-link&quot; href=&quot;#Two-step-approach&quot;&gt; &lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Make all values positive (and boost higher values)&lt;/li&gt;
&lt;li&gt;Normalize all values so that they sum to 1.&lt;/li&gt;
&lt;/ol&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;original_values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;original_values&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;array([ 0.02614146,  1.45368858, -0.36014279,  0.81388848, -0.28236045,
       -1.2516738 ,  0.7559367 ,  1.185065  , -0.96293044,  0.65885819])&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h4 id=&quot;Step-1:-Make-everything-positive-while-keeping-the-order-of-elements-constant-(monotonicity)&quot;&gt;Step 1: Make everything positive while keeping the order of elements constant (monotonicity)&lt;a class=&quot;anchor-link&quot; href=&quot;#Step-1:-Make-everything-positive-while-keeping-the-order-of-elements-constant-(monotonicity)&quot;&gt; &lt;/a&gt;&lt;/h4&gt;&lt;p&gt;There are various ways of doing it, but a very convenient one is to use each value as the power of exp&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;original_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;array([1.02648614, 4.2788684 , 0.69757671, 2.25666596, 0.75400185,
       0.28602565, 2.12960538, 3.27089941, 0.38177248, 1.93258444])&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# check if the ranks in both arrays are still the same (order is preserved)&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy.testing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assert_array_equal&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assert_array_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argsort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argsort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# check if all values are positive&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h4 id=&quot;Step-2:-Normalize-the-values-to-lie-between-0-and-1.-The-sum-of-all-values-should-be-1&quot;&gt;Step 2: Normalize the values to lie between 0 and 1. The sum of all values should be 1&lt;a class=&quot;anchor-link&quot; href=&quot;#Step-2:-Normalize-the-values-to-lie-between-0-and-1.-The-sum-of-all-values-should-be-1&quot;&gt; &lt;/a&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;array([0.06033013, 0.25148384, 0.04099899, 0.13263203, 0.04431529,
       0.01681071, 0.12516425, 0.19224203, 0.02243808, 0.11358465])&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# check if all values are between 0 and 1&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;softmax_values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;softmax_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;softmax_values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# check if the values sum up to 1&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy.testing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assert_almost_equal&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assert_almost_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;softmax_values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Plot the original_values versus the softmax values. &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# We sort both arrays in increasing order. You can see that the &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# line for the softmax_values is slightly steeper, &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# thus indicating the boost of higher values.&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;plt&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xkcd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ax1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ax2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ax1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;original_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ax1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Original values&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ax2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;softmax_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ax2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Softmax values&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_png output_subarea &quot;&gt;
&lt;img src=&quot;data:image/png;base64,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r2+BnHrqqfKMGTPkeDye66LkVDQalQH51VdfVZ5btGiRXFZWlsNSdR7RAjmM7du3s2fPHi677LJmz59wwglIkkRlZWWOSpY7U6ZMwW63A01n3g8++CA6nY7JkyfnuGS5sXv3bubOncvtt9/OqFGjcl2cnPr0009Zv349999/PytWrGDLli25LlLO6PV6+vXrx1/+8hd8Ph87duzghRdeYNiwYbkuWqcQw3gPY9++faxZs4YLL7yw2foDkiTR2NjYo1ffa00sFmPp0qV89NFHzJo1i9NPPz3XRepykiTxwgsvIEkSV1xxBX6/nw8//JBzzjmnR897dCQNDQ0EAgEikYiyLoher2fChAndYknrrrZlyxZeeuklZeGp4uJizjzzTEwmU66LlnUigRwFZLGkbU6JJW07n1jStnOIJW2zQCxpK5a0FUvaiiVtxZK2h+qyJW3//ve/8+CDD2K321m7di2hUIhHHnmEzz77jEsuuYT//d//bVPFdCWxpG37iSVtxZK2YklbsaTtEf/OTBPIwoULufPOO1m2bBnnnnsuc+bM4Y033mDatGksW7aM1atXKwvKdDeSJB3ypZbFkrZdrqctaXs0EEvado7esqTtQw89xJ133onf7z9sH07GCWT79u0MGzaMDz/8kFGjRtGnTx+effZZrrrqKgYPHswll1zC73//+6z/Adkwb948nnzyyV695KggCEJbzZs3j8cff/yIV1AyPhUYOnQoI0eOZNGiRaxcuRJZlpk5cyYqlQqHw0EgEMhaobPN7/djNptzXQxBEIQulUxJLH5/K7saQu36vN/vJz8//4ivt6ktedddd/HBBx/wox/9iJNPPpmCggI8Hg+VlZXdepxzQ0MDTqcz18UQBEHoMnWBKJc/+zlPrKziV0u+QpLaPuC2tdjZpiFGs2fPZtiwYXz++edceOGFAKxatYri4uJufat+Y2MjBQUFuS6GIAhCl9i038dP/76eGn+UojwDd583ErW67X0krcXONo9RPe644zjuuOOU300mE6tXr+7WZ/ihUKjFZpggCEJP8cbX+7jjn5uIJFJM7O/g/66YgCvP2K5ttRY723QJa8+ePVx55ZX87ne/U0bBvPLKK0yZMqXVMeq5FAwGe+UdwoIg9B7JlMQD71Zw08sbiCRS/M9x5bxwzfHtTh7QeuxsUwvkxhtvZO/evbz11lsU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
&quot; /&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h2 id=&quot;Usage-in-Deep-Learning-frameworks&quot;&gt;Usage in Deep Learning frameworks&lt;a class=&quot;anchor-link&quot; href=&quot;#Usage-in-Deep-Learning-frameworks&quot;&gt; &lt;/a&gt;&lt;/h2&gt;&lt;p&gt;All Deep Learning frameworks have softmax functions. Here we show the Keras and PyTorch versions.&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;keras&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;keras&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backend&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;keras_result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keras&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;activations&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;softmax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;variable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;original_values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reshape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flatten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;

&lt;div class=&quot;output_subarea output_stream output_stderr output_text&quot;&gt;
&lt;pre&gt;Using TensorFlow backend.
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Since Keras&amp;#39;s softmax function uses a different approach, &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# the precision of the results varies&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy.testing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assert_array_almost_equal&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assert_array_almost_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keras_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;softmax_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pytorch_result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;functional&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;softmax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;original_values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reshape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flatten&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pytorch_result&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;output_wrapper&quot;&gt;
&lt;div class=&quot;output&quot;&gt;

&lt;div class=&quot;output_area&quot;&gt;



&lt;div class=&quot;output_text output_subarea output_execute_result&quot;&gt;
&lt;pre&gt;array([0.06033013, 0.25148384, 0.04099899, 0.13263203, 0.04431529,
       0.01681071, 0.12516425, 0.19224203, 0.02243808, 0.11358465])&lt;/pre&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

    
    
&lt;div class=&quot;cell border-box-sizing code_cell rendered&quot;&gt;
&lt;div class=&quot;input&quot;&gt;

&lt;div class=&quot;inner_cell&quot;&gt;
    &lt;div class=&quot;input_area&quot;&gt;
&lt;div class=&quot; highlight hl-ipython3&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assert_array_almost_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pytorch_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;softmax_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
    

&lt;div class=&quot;cell border-box-sizing text_cell rendered&quot;&gt;&lt;div class=&quot;inner_cell&quot;&gt;
&lt;div class=&quot;text_cell_render border-box-sizing rendered_html&quot;&gt;
&lt;h2 id=&quot;Caveat&quot;&gt;Caveat&lt;a class=&quot;anchor-link&quot; href=&quot;#Caveat&quot;&gt; &lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Since softmax boosts the item with the highest value (winner takes it all), you shouldn't be using softmax whenever you want to have more than one element in the output (e.g., in multi-label classification scenarios).&lt;/p&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><author><name></name></author><summary type="html"></summary></entry><entry><title type="html">Guitar Fretboard Explorer</title><link href="https://tmayer.github.io/blog/visualization/d3js/dialectology/2019/12/19/guitar-fretboard-explorer.html" rel="alternate" type="text/html" title="Guitar Fretboard Explorer" /><published>2019-12-19T00:00:00-06:00</published><updated>2019-12-19T00:00:00-06:00</updated><id>https://tmayer.github.io/blog/visualization/d3js/dialectology/2019/12/19/guitar-fretboard-explorer</id><content type="html" xml:base="https://tmayer.github.io/blog/visualization/d3js/dialectology/2019/12/19/guitar-fretboard-explorer.html">&lt;p&gt;&lt;img src=&quot;/blog/images/fretboard-vis.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://guitar.th-mayer.de/fretboard/&quot; target=&quot;_blank&quot;&gt;Guitar Fretboard Explorer&lt;/a&gt; 
helps you to navigate through the standard tuning guitar fretboard. By hovering
over the strings on particular frets you see all similar natural notes together
with their corresponding notes in the score. In addition, the explorer also highlights certain
patterns on the fretboard to help memorize the relative note positions.&lt;/p&gt;

&lt;p&gt;Score rendered with &lt;a href=&quot;http://www.vexflow.com/&quot; target=&quot;_blank&quot;&gt;VexFlow&lt;/a&gt;. 
Fretboard visualization adapted from &lt;a href=&quot;https://github.com/txels/fretboard&quot; target=&quot;_blank&quot;&gt;https://github.com/txels/fretboard&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><summary type="html"></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://tmayer.github.io/blog/images/fretboard-vis.png" /><media:content medium="image" url="https://tmayer.github.io/blog/images/fretboard-vis.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Phoible Visualization</title><link href="https://tmayer.github.io/blog/visualization/d3js/typology/2014/05/18/phoible-vis.html" rel="alternate" type="text/html" title="Phoible Visualization" /><published>2014-05-18T00:00:00-05:00</published><updated>2014-05-18T00:00:00-05:00</updated><id>https://tmayer.github.io/blog/visualization/d3js/typology/2014/05/18/phoible-vis</id><content type="html" xml:base="https://tmayer.github.io/blog/visualization/d3js/typology/2014/05/18/phoible-vis.html">&lt;p&gt;&lt;img src=&quot;/blog/images/phoible-vis.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://tmayer.github.io/PhoibleVis/&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;PHOIBLE Explorer&lt;/b&gt;&lt;/a&gt; shows the values for all &lt;a href=&quot;http://phoible.org&quot; target=&quot;_blank&quot;&gt;&lt;i class=&quot;fa fa-external-link&quot;&gt;&lt;/i&gt; PHOIBLE&lt;/a&gt;
phonemes by combining the geolocation of the respective languages with their genealogy in
a &lt;a href=&quot;http://www.cc.gatech.edu/gvu/ii/sunburst/&quot; target=&quot;_blank&quot;&gt;&lt;i class=&quot;fa fa-external-link&quot;&gt;&lt;/i&gt; sunburst visualization&lt;/a&gt;
(Stasko and Zhang 2000). The map and the sunburst is enhanced with interactive functionalities.
You can select a region in the world map to get only those languages spoken in that area
displayed in the sunburst. The sunburst itself is zoomable. If you click on a segment, only
the languages of the respective subfamily are displayed.&lt;/p&gt;

&lt;p&gt;All data for the &lt;b&gt;PHOIBLE Explorer&lt;/b&gt; (including the genealogical information) has been taken from PHOIBLE (Moran et al. 2014). The macro areas are adapted from Dryer (1992).&lt;/p&gt;

&lt;p&gt;If you use the &lt;b&gt;PHOIBLE Explorer&lt;/b&gt; in your research, please cite the third paper in the References section (Mayer et al. 2014). The &lt;b&gt;PHOIBLE Explorer&lt;/b&gt; is based on the &lt;em&gt;WALS Sunburst Explorer&lt;/em&gt; (&lt;a href=&quot;http://th-mayer.de/wals/&quot; target=&quot;_blank&quot;&gt;http://th-mayer.de/wals/&lt;/a&gt;) and the &lt;em&gt;World’s Languages Explorer&lt;/em&gt;
by Christian Rohrdantz, Michael Hund, Thomas Mayer, Bernhard Wälchli and Daniel A. Keim
(Rohrdantz et al. 2012).&lt;/p&gt;

&lt;p&gt;The &lt;b&gt;PHOIBLE Explorer&lt;/b&gt; is implemented in JavaScript using the D3 library (Bostock et al. 2011).&lt;/p&gt;

&lt;p&gt;The visualization has been funded by the DFG project
&lt;a href=&quot;http://paralleltext.info&quot; target=&quot;_blank&quot;&gt;“Algorithmic corpus-based approaches to typological
comparison”&lt;/a&gt; at the &lt;a href=&quot;http://www.uni-marburg.de&quot; target=&quot;_blank&quot;&gt;Philipps-Universität Marburg&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;bibliography&quot;&gt;Bibliography&lt;/h1&gt;

&lt;p&gt;Bostock, Michael, Vadim Ogievetsky and Jeffrey Heer. 2011. D3: Data-driven documents. &lt;i&gt;IEEE Transactions on Visualization &amp;amp; Computer Graphics&lt;/i&gt; (Proc. InfoVis), 17(12), 2301–2309.&lt;/p&gt;

&lt;p&gt;Dryer, Matthew S. 1992. The Greenbergian word order correlations. &lt;i&gt;Language&lt;/i&gt;, 68(1), 81-138.&lt;/p&gt;

&lt;p&gt;Mayer, Thomas, Bernhard Wälchli, Christian Rohrdantz and Michael Hund. 2014. From the extraction of continuous features in parallel texts to visual analytics of heterogeneous areal-typological datasets. In Nolan, Brian and Carlos Pascual-Periñán (eds.), &lt;em&gt;Language processing and grammars: The role of functionally oriented computational models&lt;/em&gt; (SLCS) (Serie: Studies in Language). Amsterdam: John Benjamins, 13-38.&lt;/p&gt;

&lt;p&gt;Moran, Steven, Daniel McCloy and Richard Wright (eds.) 2014. 
PHOIBLE Online. 
Leipzig: Max Planck Institute for Evolutionary Anthropology. 
(Available online at http://phoible.org, Accessed on 2014-09-30.)&lt;/p&gt;

&lt;p&gt;Rohrdantz, Christian, Michael Hund, Thomas Mayer, Bernhard Wälchli and Daniel A. Keim. 2012.
The World’s Languages Explorer: Visual analysis of language features in genealogical and areal
contexts. In &lt;i&gt;Computer Graphic Forum&lt;/i&gt;, 31(3), 935–944.
[&lt;a href=&quot;http://onlinelibrary.wiley.com/doi/10.1111/j.1467-8659.2012.03086.x/abstract&quot; target=&quot;_blank&quot;&gt;&lt;i class=&quot;fa fa-external-link&quot;&gt;&lt;/i&gt; link&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Stasko, John and Eugene Zhang. 2000. Focus+context display and navigation techniques for
enhancing radial, space-filling hierarchy visualizations. In &lt;i&gt;Proceedings of the IEEE Symposium on Information Visualization&lt;/i&gt;, 57–65. Los Alamitos CA: IEEE Computer Society.&lt;/p&gt;</content><author><name></name></author><summary type="html"></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://tmayer.github.io/blog/images/phoible-vis.png" /><media:content medium="image" url="https://tmayer.github.io/blog/images/phoible-vis.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">PhonMatrix</title><link href="https://tmayer.github.io/blog/visualization/d3js/typology/2014/03/13/phonmatrix.html" rel="alternate" type="text/html" title="PhonMatrix" /><published>2014-03-13T00:00:00-05:00</published><updated>2014-03-13T00:00:00-05:00</updated><id>https://tmayer.github.io/blog/visualization/d3js/typology/2014/03/13/phonmatrix</id><content type="html" xml:base="https://tmayer.github.io/blog/visualization/d3js/typology/2014/03/13/phonmatrix.html">&lt;p&gt;Visualizing phonological patterns such as vowel harmony and similar place avoidance from language data. The application can be accessed here: &lt;a href=&quot;http://phonmatrix.herokuapp.com/&quot; target=&quot;_blank&quot;&gt;http://phonmatrix.herokuapp.com/&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;description&quot;&gt;Description&lt;/h1&gt;

&lt;p&gt;PhonMatrix is a web-based visualization tool that statistically analyzes sound co-occurrences within words and displays the result in a symmetric sound matrix.&lt;/p&gt;

&lt;p&gt;In the first step, the user has to upload the text file containing the word list that serves as the input to the analysis process. Text files have to be encoded in UTF-8 and list only one word per line. For a meaningful analysis the words should be given in some phonemic transcription (e.g., using IPA).&lt;/p&gt;

&lt;p&gt;In the second step, the user can make changes to the automatic classification of symbols into vowels and consonants and exclude infrequent symbols from further consideration.&lt;/p&gt;

&lt;p&gt;In the third step, the results of the statistical analysis of the co-occurrence counts are displayed in a quadratic matrix of sounds. The rows and columns of the matrix represent the individual sounds that are relevant for the selected context (e.g., vowels in the context of VCV sequences). The rows thereby stand for the first members of the relevant sound pairs, whereas the columns contain the sec- ond members. Each cell of the matrix then shows the result for the pair of sounds in the respective row and column.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/phonmatrix.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The final result is a visualization of the co-occurrence matrix with rows and columns sorted according to the similarity of the sound vectors and statistical values represented as colors in the matrix cells. The visualization features a number of interactive components that facilitate the detection of potential patterns in the results by the user.&lt;/p&gt;

&lt;p&gt;The code is available on &lt;a href=&quot;https://github.com/tmayer/phonmatrix&quot; target=&quot;_blank&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;bibliography&quot;&gt;Bibliography&lt;/h1&gt;

&lt;p&gt;Mayer, Thomas and Christian Rohrdantz. 2013. PhonMatrix: Visualizing co-occurrence constraints in sounds. In Proceedings of the ACL 2013 System Demonstration.&lt;/p&gt;

&lt;p&gt;Mayer, Thomas, Christian Rohrdantz, Frans Plank, Peter Bak, Miriam Butt, Daniel A. Keim. 2010. Consonant co-occurrence in stems across languages: Automatic analysis and visualization of a phonotactic constraint. In Proceedings of the ACL 2010 Workshop on NLP and Linguistics: Finding the Common Ground (NLPLING 2010), 70–78.&lt;/p&gt;

&lt;p&gt;Mayer, Thomas, Christian Rohrdantz, Miriam Butt, Frans Plank and Daniel A. Keim. 2010. Visualizing Vowel Harmony. Journal of Linguistic Issues in Language Technology (LiLT), Vol. 4 Issue 2, 1–33.&lt;/p&gt;

&lt;p&gt;Rohrdantz, Christian, Thomas Mayer, Miriam Butt, Frans Plank and Daniel A. Keim. 2010. Comparative visual analysis of cross-linguistic features. In Proceedings of the International Symposium on Visual Analytics Science and Technology (EuroVAST 2010), 27–32.&lt;/p&gt;</content><author><name></name></author><summary type="html">Visualizing phonological patterns such as vowel harmony and similar place avoidance from language data. The application can be accessed here: http://phonmatrix.herokuapp.com/.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://tmayer.github.io/blog/images/phonmatrix.gif" /><media:content medium="image" url="https://tmayer.github.io/blog/images/phonmatrix.gif" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Hessen Dialekterkenner</title><link href="https://tmayer.github.io/blog/visualization/d3js/dialectology/2014/02/11/hessen-dialekterkenner.html" rel="alternate" type="text/html" title="Hessen Dialekterkenner" /><published>2014-02-11T00:00:00-06:00</published><updated>2014-02-11T00:00:00-06:00</updated><id>https://tmayer.github.io/blog/visualization/d3js/dialectology/2014/02/11/hessen-dialekterkenner</id><content type="html" xml:base="https://tmayer.github.io/blog/visualization/d3js/dialectology/2014/02/11/hessen-dialekterkenner.html">&lt;p&gt;&lt;img src=&quot;/blog/images/hessen-dialekterkenner.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Beantworten Sie 7 Fragen zu syntaktischen Dialektvarianten und ermitteln Sie, 
in welchem Gebiet in Hessen Ihr Dialekt gesprochen wird. Die interaktive 
Visualisierung finden Sie &lt;a href=&quot;http://th-mayer.de/syhd/&quot; target=&quot;_blank&quot;&gt;
hier&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;information&quot;&gt;Information&lt;/h1&gt;

&lt;p&gt;© 2012-2014 Michael Cysouw, Jürg Fleischer, Stephanie Leser, Thomas
Mayer&lt;br /&gt;
&lt;a href=&quot;http://www.hmwk.hessen.de/irj/HMWK_Internet?cid=a2396939885f8c8c0a3ba39bda517cbd&quot; target=&quot;_blank&quot;&gt;
Landesprogramm LOEWE&lt;/a&gt;&lt;br /&gt; &lt;a href=&quot;http://www.syhd.info/&quot; target=&quot;_blank&quot;&gt;Syntax hessischer
Dialekte (SyHD)&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://paralleltext.info&quot; target=&quot;_blank&quot;&gt;
DFG-Projekt “Algorithmic corpus-based approaches to typological comparison”&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Der Dialekterkenner wurde mit Hilfe der JavaScript-Bibliotheken
&lt;a href=&quot;http://d3js.org&quot; target=&quot;_blank&quot;&gt;D3.js&lt;/a&gt; und
&lt;a href=&quot;https://github.com/mbostock/topojson&quot; target=&quot;_blank&quot;&gt;TopoJSON&lt;/a&gt;
erstellt.
Das Cartogram wird mit &lt;a href=&quot;http://stamen.com/studio/shawn&quot; target=&quot;_blank&quot;&gt;
Shawn Allens&lt;/a&gt; D3-kompatibler Implementierung des
&lt;a href=&quot;http://lambert.nico.free.fr/tp/biblio/Dougeniketal1985.pdf&quot; target=&quot;_blank&quot;&gt;&lt;i&gt;Continuous Area Cartograms&lt;/i&gt;
Algorithmus&lt;/a&gt; von Dougenik et al. (1985) erzeugt. Die Voronoi-Tesselation wurde
mit Hilfe des R-Pakets &lt;a href=&quot;http://www.spatstat.org&quot; target=&quot;_blank&quot;&gt;Spatstat&lt;/a&gt; erzeugt.&lt;/p&gt;</content><author><name></name></author><summary type="html"></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://tmayer.github.io/blog/images/hessen-dialekterkenner.png" /><media:content medium="image" url="https://tmayer.github.io/blog/images/hessen-dialekterkenner.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Cartogram of the World’s Languages</title><link href="https://tmayer.github.io/blog/visualization/d3js/typology/2013/11/13/cartogram-languages-world.html" rel="alternate" type="text/html" title="Cartogram of the World's Languages" /><published>2013-11-13T00:00:00-06:00</published><updated>2013-11-13T00:00:00-06:00</updated><id>https://tmayer.github.io/blog/visualization/d3js/typology/2013/11/13/cartogram-languages-world</id><content type="html" xml:base="https://tmayer.github.io/blog/visualization/d3js/typology/2013/11/13/cartogram-languages-world.html">&lt;p&gt;&lt;img src=&quot;/blog/images/cartogram.jpg&quot; alt=&quot;&quot; title=&quot;Cartogram screenshot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The interactive cartogram can be accessed &lt;a href=&quot;http://th-mayer.de/cartogram&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The size of each country is scaled by
the number of languages that are spoken in its territory. 
Each language in the sample is only attributed to one country.
The sample contains &lt;a href=&quot;http://th-mayer.de/data/nrlangs_dahl.txt&quot;&gt;7,293
languages&lt;/a&gt;. Each language is plotted with a small blue dot on the map if the
“Show language locations” option is selected. If you mouse over the (distorted) world map,
you see the number of languages for the respective countries. The cartogram of the world’s languages is adapted from
&lt;a href=&quot;http://prag.ma/code/d3-cartogram/&quot;&gt;the cartogram example by Shawn Allen&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><summary type="html"></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://tmayer.github.io/blog/images/cartogram.jpg" /><media:content medium="image" url="https://tmayer.github.io/blog/images/cartogram.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The WALS Sunburst Explorer</title><link href="https://tmayer.github.io/blog/visualization/d3js/typology/2013/04/13/wals-sunburst-explorer.html" rel="alternate" type="text/html" title="The WALS Sunburst Explorer" /><published>2013-04-13T00:00:00-05:00</published><updated>2013-04-13T00:00:00-05:00</updated><id>https://tmayer.github.io/blog/visualization/d3js/typology/2013/04/13/wals-sunburst-explorer</id><content type="html" xml:base="https://tmayer.github.io/blog/visualization/d3js/typology/2013/04/13/wals-sunburst-explorer.html">&lt;p&gt;&lt;img src=&quot;/blog/images/WALS-sunburst.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;a href=&quot;http://th-mayer.de/wals/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; to open the interactive visualization.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;WALS Sunburst Explorer&lt;/em&gt; shows the values for all &lt;a href=&quot;http://wals.info&quot; target=&quot;_blank&quot;&gt;&lt;i class=&quot;fa fa-external-link&quot;&gt;&lt;/i&gt; WALS&lt;/a&gt;
features by combining the geolocation of the respective languages with their genealogy in
a &lt;a href=&quot;http://www.cc.gatech.edu/gvu/ii/sunburst/&quot; target=&quot;_blank&quot;&gt;&lt;i class=&quot;fa fa-external-link&quot;&gt;&lt;/i&gt; sunburst visualization&lt;/a&gt;
(Stasko and Zhang 2000). The map and the sunburst is enhanced with interactive functionalities.
You can select a region in the world map to get only those languages spoken in that area
displayed in the sunburst. The sunburst itself is zoomable. If you click on a segment, only
the languages of the respective subfamily are displayed.&lt;/p&gt;

&lt;p&gt;All data for the &lt;b&gt;WALS Sunburst Explorer&lt;/b&gt; (including the genealogical information) has been taken from WALS Online (Dryer and Haspelmath 2013). WALS Online data export created 2013-10-29 23:06:51.451389 from &lt;a href=&quot;http://wals.info/&quot; target=&quot;_blank&quot;&gt;&lt;i class=&quot;fa fa-external-link&quot;&gt;&lt;/i&gt; http://wals.info/&lt;/a&gt;. The macro areas are adapted from Dryer (1992).&lt;/p&gt;

&lt;p&gt;If you use the &lt;b&gt;WALS Sunburst Explorer&lt;/b&gt; in your research, please cite the fourth paper in the References section (Mayer et al. 2014). The &lt;b&gt;WALS Sunburst Explorer&lt;/b&gt; is based on the &lt;em&gt;World’s Languages Explorer&lt;/em&gt;
by Christian Rohrdantz, Michael Hund, Thomas Mayer, Bernhard Wälchli and Daniel A. Keim
(Rohrdantz et al. 2012).&lt;/p&gt;

&lt;p&gt;The &lt;b&gt;WALS Sunburst Explorer&lt;/b&gt; is implemented in JavaScript using the D3 library (Bostock et al. 2011). The ordinal scale is taken from &lt;a href=&quot;http://colorbrewer2.org/&quot; target=&quot;_blank&quot;&gt;&lt;i class=&quot;fa fa-external-link&quot;&gt;&lt;/i&gt; Cynthia Brewer’s colorbrewer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This work has been funded by the DFG project
&lt;a href=&quot;http://paralleltext.info&quot; target=&quot;_blank&quot;&gt;“Algorithmic corpus-based approaches to typological
comparison”&lt;/a&gt; at the &lt;a href=&quot;http://www.uni-marburg.de&quot; target=&quot;_blank&quot;&gt;Philipps-Universität Marburg&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;bibliography&quot;&gt;Bibliography&lt;/h1&gt;

&lt;p&gt;Bostock, Michael, Vadim Ogievetsky and Jeffrey Heer. 2011. D3: Data-driven documents. &lt;i&gt;IEEE Transactions on Visualization &amp;amp; Computer Graphics&lt;/i&gt; (Proc. InfoVis), 17(12), 2301–2309.&lt;/p&gt;

&lt;p&gt;Dryer, Matthew S. 1992. The Greenbergian word order correlations. &lt;i&gt;Language&lt;/i&gt;, 68(1), 81-138.&lt;/p&gt;

&lt;p&gt;Dryer, Matthew S. and Martin Haspelmath (eds.). 2013. The World Atlas of Language Structures Online. Leipzig: Max Planck Institute for Evolutionary Anthropology. (Available online at &lt;a href=&quot;http://wals.info/&quot;&gt;&lt;i class=&quot;fa fa-external-link&quot;&gt;&lt;/i&gt; http://wals.info/&lt;/a&gt;, Accessed on 2014-08-13.)&lt;/p&gt;

&lt;p&gt;Mayer, Thomas, Bernhard Wälchli, Christian Rohrdantz and Michael Hund. 2014. From the extraction of continuous features in parallel texts to visual analytics of heterogeneous areal-typological datasets. In Nolan, Brian and Carlos Pascual-Periñán (eds.), &lt;em&gt;Language processing and grammars: The role of functionally oriented computational models&lt;/em&gt; (SLCS) (Serie: Studies in Language). Amsterdam: John Benjamins, 13-38.&lt;/p&gt;

&lt;p&gt;Rohrdantz, Christian, Michael Hund, Thomas Mayer, Bernhard Wälchli and Daniel A. Keim. 2012.
The World’s Languages Explorer: Visual analysis of language features in genealogical and areal
contexts. In &lt;i&gt;Computer Graphic Forum&lt;/i&gt;, 31(3), 935–944.
[&lt;a href=&quot;http://onlinelibrary.wiley.com/doi/10.1111/j.1467-8659.2012.03086.x/abstract&quot; target=&quot;_blank&quot;&gt;&lt;i class=&quot;fa fa-external-link&quot;&gt;&lt;/i&gt; link&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Stasko, John and Eugene Zhang. 2000. Focus+context display and navigation techniques for
enhancing radial, space-filling hierarchy visualizations. In &lt;i&gt;Proceedings of the IEEE Symposium on Information Visualization&lt;/i&gt;, 57–65. Los Alamitos CA: IEEE Computer Society.&lt;/p&gt;</content><author><name></name></author><summary type="html"></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://tmayer.github.io/blog/images/WALS-sunburst.png" /><media:content medium="image" url="https://tmayer.github.io/blog/images/WALS-sunburst.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>