<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Viet Nguyen</title>
    <description>The latest articles on DEV Community by Viet Nguyen (@vnugent).</description>
    <link>https://dev.to/vnugent</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F469474%2F9a829cfc-886e-4b51-8252-780175caf6e4.jpeg</url>
      <title>DEV Community: Viet Nguyen</title>
      <link>https://dev.to/vnugent</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vnugent"/>
    <language>en</language>
    <item>
      <title>Are You a Connector?</title>
      <dc:creator>Viet Nguyen</dc:creator>
      <pubDate>Wed, 16 Sep 2020 09:37:29 +0000</pubDate>
      <link>https://dev.to/vnugent/are-you-a-connector-59l4</link>
      <guid>https://dev.to/vnugent/are-you-a-connector-59l4</guid>
      <description>&lt;h4&gt;
  
  
  TLDR; &lt;em&gt;“Connectors”&lt;/em&gt; are people who genuinely want to help others by connecting you to their network.
&lt;/h4&gt;

&lt;p&gt;How did you get that remote job or that awesome apartment in a highly competitive rental market?&lt;/p&gt;

&lt;p&gt;Looking back at my career trajectory I can see two patterns emerging, great opportunities came by either pure luck or by knowing someone outside of my immediate circle.&lt;/p&gt;

&lt;p&gt;In this post, I want to talk about the latter, the "outsider" network effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Backstory
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How I Became a Remote Developer since 2012
&lt;/h3&gt;

&lt;p&gt;I have lived in New York city for seven years. In the end I knew I was ready to move west to Oregon, literally speaking, to a greener place where I can live closer to the mountains.&lt;/p&gt;

&lt;p&gt;I started my job search, also asking people I knew well if they knew of anything.&lt;/p&gt;

&lt;p&gt;Most of my friends were living and working in the city. They had none to very few contacts at companies out west. Nothing.&lt;/p&gt;

&lt;p&gt;One day during a water cooler chat, someone mentioned Maria had left for another company where she's now happily &lt;em&gt;working full-time from home.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Maria and I were in the same department. We were working on different projects under different managers . Besides occasional small talks when we happened to share the elevator, there was little interaction between the two of us. It's safe to say we had very little in common.&lt;/p&gt;

&lt;p&gt;Two weeks later, I was able to get a hold of Maria via email, first to congratulate her on the new job, and also to inquire about the work-from-home part. Lo and behold, I learned that her company was still hiring. After several rounds of interviews, I got the job and joined a fully remote team.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Connector
&lt;/h2&gt;

&lt;p&gt;In his book “The Tipping Point”, Malcolm Gladwell calls people like Maria “connectors”.&lt;/p&gt;

&lt;p&gt;Connectors are uniquely important people. Due to their supportive nature they tend to have cultivated a large or diverse network. And the key importance here is: they are willing to introduce us to their network. According to Gladwell, people within our close circles are generally similar to us in terms of interests and social economic background. Therefore, we are likely aware of similar opportunities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DYxjEzBD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gqxtix5senfbjubyjfcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DYxjEzBD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gqxtix5senfbjubyjfcl.png" alt="Extended network"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For that reason, my groups of friends in New York while appeared to be diverse, in fact, had a lot in common with me. We enjoyed going to similar restaurants, discussing the same TV series, and sharing similar hobbies on the weekend.&lt;/p&gt;

&lt;p&gt;If they knew of a new opportunity, chances were it's going to be a position in tech in the city.&lt;/p&gt;

&lt;p&gt;Connectors, on the other hand, are outside of our immediate circles. There is little overlapping between their networks and ours. Connectors are exposed to potential opportunities that we and our friends are not aware of.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not All Networkings Are Equal
&lt;/h2&gt;

&lt;p&gt;Have you met someone at a party and they said, “Oh, you should definitely talk to X! I'll introduce you two.”&lt;/p&gt;

&lt;p&gt;When people offer to make an introduction, they see potential in you, or values in your ideas, and &lt;em&gt;are willing to take a reputation risk&lt;/em&gt; to connect you to their network, said Rob Fitzpatrick in his book for startup founders, &lt;em&gt;The Mom Test: How to Talk to Customers and Learn If Your Business is a Good Idea when Everyone is Lying to You.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Spot a Connector
&lt;/h2&gt;

&lt;p&gt;Connectors are not unicorns. They can be a friend of a friend or someone in your LinkedIn extended network. While you don't run into them very often, when you do, it's not too difficult to recognize one. They are the conduit to new potentials and resources beyond what are currently available in our immediate network.&lt;/p&gt;

&lt;p&gt;Last but not least, what is the best way to thank your connectors? I think besides thanking them directly, one of the best ways is to pay it forward and become a connector yourself.&lt;/p&gt;




&lt;h4&gt;
  
  
  Mt. Hood, Oregon (photo by &lt;a href="https://unsplash.com/@aows"&gt;adrian&lt;/a&gt;)
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jiIpnsAO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nta3ddnrenz2n7a2becr.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jiIpnsAO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nta3ddnrenz2n7a2becr.jpeg" alt="Snow covered Mt. Hood"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Cover photo by &lt;a href="https://unsplash.com/@noahmatteo"&gt;Noah&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
      <category>career</category>
    </item>
    <item>
      <title>Building a Rock Climbing Route Recommendation Engine</title>
      <dc:creator>Viet Nguyen</dc:creator>
      <pubDate>Tue, 15 Sep 2020 12:27:05 +0000</pubDate>
      <link>https://dev.to/vnugent/building-a-rock-climbing-route-recommendation-engine-3mdj</link>
      <guid>https://dev.to/vnugent/building-a-rock-climbing-route-recommendation-engine-3mdj</guid>
      <description>&lt;p&gt;“I'm going to Vegas to spend more time in the mountains.” Said no one ever unless you're a rock climber.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Climber's guide to building recommendation engine in Python
&lt;/h2&gt;

&lt;h1&gt;
  
  
  Part I - Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Recommendation engines&lt;/strong&gt; or &lt;strong&gt;recommendation systems&lt;/strong&gt; are everywhere you turn, from music, movie and product recommendations, to what kind of current events and news shown to us.&lt;/p&gt;

&lt;p&gt;Would it be cool if rock climbers ourselves can build a climb recommendation engine to discover similar and interesting climbs?&lt;/p&gt;

&lt;p&gt;After reading this tutorial you can build one of such engine yourself in Python.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Jupyter notebook for this tutorial is &lt;a href="https://github.com/OpenBeta/openbeta-tutorials"&gt;available on Github&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before we start, let’s review four common ways to build a recommendation engine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Popularity-based recommenders&lt;/strong&gt;: The simplest of all. You make a list of items based on some criteria such as video view count or song play count. Twitter trending topics or Reddit comments are good examples of this approach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content-based recommenders&lt;/strong&gt;: This type of system takes one item as an input and suggests similar items based on a set of characteristics. For example, given a movie, the recommendation engine finds similar movies based on genre, directors and actors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborative-filtering recommenders&lt;/strong&gt;: You may have seen “People who did X also did Y” suggestions when browsing Amazon. Based on past behaviors or preferences of other users, the engine can predict similar choices.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g4fUypv---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/q1xxv7t7eccy3gt5cpse.png" alt="Alt Text"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid recommenders&lt;/strong&gt;: Lastly, there are no reasons why we can’t combine two or more of the above recommenders. In fact, hybrid recommenders are commonly used in real-world applications as research has shown they can produce more accurate suggestions. Spotify’s New music recommendations is one good example of this approach. For example, first we take the list of this month’s popular songs (popularity-based recommender) and suggest only songs that are similar by genre and artists (content-based recommender).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this tutorial we are going to build a Collaborative-filtering recommendation engine.&lt;/p&gt;

&lt;h3&gt;
  
  
  About The Dataset
&lt;/h3&gt;

&lt;p&gt;The dataset contains 84,786 ratings from 7,950 users on 3,161 climbs in Nevada, USA where the well-known Red Rock Canyon climbing area is located. The reason Nevada was chosen was simply because I have climbed there for several seasons.&lt;/p&gt;

&lt;p&gt;User ratings were extracted from MountainProject.com with user IDs anonymized.&lt;/p&gt;

&lt;p&gt;Let’s load our data into a Pandas dataframe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt; 

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./openbeta-ratings-nevada.zip"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;compression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"zip"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eWGiLVbZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e3f9o25dzaj8ntsakk7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eWGiLVbZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e3f9o25dzaj8ntsakk7k.png" alt="Nevada dataset preview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Popular Climbs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One basic metric we can look at is how climbs are ranked by popularity by counting the number of ratings they received.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aggregate climbs and count number of ratings
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'route_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;])[&lt;/span&gt;&lt;span class="s"&gt;'ratings'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EaUQ2lG7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/y720yucwpd9hzd1k0mgq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EaUQ2lG7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/y720yucwpd9hzd1k0mgq.png" alt="Popular climbs - unsorted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sort the result by count and only show the top 20.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;popular&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'route_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;])[&lt;/span&gt;&lt;span class="s"&gt;'ratings'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'count'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="n"&gt;popular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--glnhH1E0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1dk9vgr2rip940jkn8l4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--glnhH1E0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1dk9vgr2rip940jkn8l4.png" alt="Top 20 popular climbs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There we have it! A list of popular climbs in Red Rocks. If you have visited the area before, you would definitely recognize those names.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gcztL11e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gj0jhrbm9hgowuxd4w43.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gcztL11e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gj0jhrbm9hgowuxd4w43.jpg" alt="Rappelling Sour Mash (5.10a) in Black Velvet Canyon"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  Understand Collaborative Filtering
&lt;/h3&gt;

&lt;p&gt;In Collaborative Filtering we find “like-minded” climbers based on ratings or preferences they have given to climbing routes.&lt;/p&gt;

&lt;p&gt;Let’s consider two multi-pitch climbs, &lt;em&gt;The Nightcrawler&lt;/em&gt; and &lt;em&gt;The Dragon&lt;/em&gt; that received 4-star ratings from climber Tamara. If you have also given high ratings to them, we can say two climbers have high similarity score. For the sake of this example, if Tamara gives another climb 3 or 4 stars, chances are, you will also like the climb and vice versa.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qv1cPC0g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9ubw5on86i1dyxzr1oxt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qv1cPC0g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9ubw5on86i1dyxzr1oxt.png" alt="User ratings for 2 climbs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is the principle idea behind Collaborative filtering!&lt;/em&gt; Intuitive and simple, right? In fact, you can calculate this similarity score by hand or with the help of a Python library. The higher the number, the more “like-minded” the two climbers.&lt;/p&gt;

&lt;p&gt;Believe it or not, the table above can be represented in Python as a 2-D array (matrix). We’ll use &lt;em&gt;Cosine similarity&lt;/em&gt;, a common and simple method to calculate similarity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Be sure to install sklearn library with pip or pipenv 
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sklearn.metrics.pairwise&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt; 

&lt;span class="n"&gt;tamara&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; 
&lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; 

&lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tamara&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="c1"&gt;# Result = [[0.98994949]]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can also calculate cosine similarity for more than two routes. Let’s say Tamara disliked Cat in the Hat and gave it 1-star.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YtF1TY5R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tc0im5wbnqiiwaq2tbpy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YtF1TY5R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tc0im5wbnqiiwaq2tbpy.png" alt="User ratings for 3 climbs"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sklearn.metrics.pairwise&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt;

&lt;span class="n"&gt;tamara&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; 
&lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; 

&lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tamara&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Result = [[0.94947403]]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Cosine similarity drops from 0.98994949 to 0.94947403.&lt;/p&gt;

&lt;p&gt;Now you see, we can extend the above logic to take into account other thousand climbs and user ratings. The math will, of course, get complicated as the size of the matrix increases. Take a deep breath as if you’re 1 meter above the last bolt! We are going to use &lt;a href="http://surpriselib.com"&gt;Surprise&lt;/a&gt;, a Python machine learning library, to help us build our recommendation engine.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Cosine similarity&lt;/em&gt; is just one of many ways to find similar items. Surprise recommendation library supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cosine similarity&lt;/li&gt;
&lt;li&gt;Pearson’s correlation coefficients&lt;/li&gt;
&lt;li&gt;Mean Square Difference&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Part II - Building Recommendation Engine
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Load the data file
&lt;/h2&gt;

&lt;p&gt;This step is a repeat of previous section for continuity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt; 
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./openbeta-ratings-nevada.zip"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;compression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"zip"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eWGiLVbZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e3f9o25dzaj8ntsakk7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eWGiLVbZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e3f9o25dzaj8ntsakk7k.png" alt="Nevada dataset preview"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Create a prediction model
&lt;/h2&gt;

&lt;p&gt;In this example, we use &lt;em&gt;K-Nearest Neighbors&lt;/em&gt; algorithm to build our prediction model. Essentially, the code does cosine similarity calculation like what we’ve just done previously, but it’s working hard on the dataset and also ranking climbs by similarity scores.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;surprise&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Dataset&lt;/span&gt; 
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;surprise&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Reader&lt;/span&gt; 
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;surprise&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;accuracy&lt;/span&gt; 
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;surprise&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;KNNBasic&lt;/span&gt; 
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;surprise.model_selection&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;train_test_split&lt;/span&gt; 
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;surprise.model_selection&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;KFold&lt;/span&gt; 

&lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rating_scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 

&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_from_df&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'route_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'ratings'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="n"&gt;sim_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'cosine'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'user_based'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'min_support'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="n"&gt;algo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;KNNBasic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sim_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sim_options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="n"&gt;kf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;KFold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_splits&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;trainset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testset&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;kf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; 
   &lt;span class="c1"&gt;# train and test algorithm 
&lt;/span&gt;   &lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trainset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
   &lt;span class="n"&gt;predictions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

   &lt;span class="c1"&gt;# compute and print Root Mean Squared Error
&lt;/span&gt;   &lt;span class="n"&gt;accuracy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rmse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predictions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Computing the cosine similarity matrix... 
Done computing similarity matrix. RMSE: 0.7172 
Computing the cosine similarity matrix... 
Done computing similarity matrix. RMSE: 0.7057 
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Understanding Train Set and Test Set&lt;/strong&gt;&lt;br&gt;
You may be wondering about RMSE values (root-mean-square-errors) and why there is a For loop and the need to split the dataset into train set and test set?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Consider our previous rating example. In a perfect world, the recommendation engine can predict with high accuracy if Tamara gives another route a high rating, you will also like that route.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YtF1TY5R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tc0im5wbnqiiwaq2tbpy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YtF1TY5R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tc0im5wbnqiiwaq2tbpy.png" alt="User ratings for 3 climbs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to measure prediction accuracy, the algorithm splits the dataset into multiple smaller sets in which it “pretends” it doesn’t know some of ratings climbers have given, and compare actual ratings vs predicted values. &lt;em&gt;RSME is the measure of the deviation.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Train set&lt;/strong&gt;: a subset of the dataset used to calculate similarity and perform prediction or “train” the prediction model.&lt;br&gt;
&lt;strong&gt;Test set&lt;/strong&gt;: a subset of the dataset where you apply the prediction model from the train set and test prediction accuracy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;strong&gt;Test set 1&lt;/strong&gt; — Compare 3 (actual) with predicted value.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VzSk6qex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dx1aesx0f2sn3td6cjcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VzSk6qex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dx1aesx0f2sn3td6cjcl.png" alt='Test set 1 - one rating by you is "covered"'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test set 2&lt;/strong&gt; — Compare 4 (actual) with predicted value.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V9Igs2Ud--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vbk7pw7l4u293av7orzp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V9Igs2Ud--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vbk7pw7l4u293av7orzp.png" alt='Test set 2 - another rating is "covered"'&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Make Recommendations
&lt;/h2&gt;

&lt;p&gt;It’s time to answer the great question, climbers who liked &lt;a href="https://www.mountainproject.com/route/105732422/epinephrine"&gt;Epinephrine&lt;/a&gt; also liked …&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;climb_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Epinephrine"&lt;/span&gt; 
&lt;span class="c1"&gt;# look up route_id from human-readable name 
&lt;/span&gt;&lt;span class="n"&gt;route_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;climb_name&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;'route_id'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"People who climbed '{}' also climbed"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;climb_name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 

&lt;span class="c1"&gt;# get similar climbs 
&lt;/span&gt;&lt;span class="n"&gt;prediction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_neighbors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;trainset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_inner_iid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;route_id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prediction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;People who climbed 'Epinephrine' also climbed [263, 506, 238, 75, 8, 511, 1024, 233, 173, 418, 550, 1050, 478, 2, 379, 596, 1491, 221, 730, 261, 30, 410, 109, 313, 264, 148, 659, 68, 223, 1131, 1283, 428, 272, 354, 496, 143, 737, 1152, 835, 17, 356, 368, 545, 89, 23, 74, 281, 480, 509, 278]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Domain Id vs Surprise Internal Id&lt;/strong&gt;&lt;br&gt;
For efficiency, the prediction algorithm converts our dataset into another data structure (most likely into some sort of matrix), and work with the data by their internal IDs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Surprise library provides two helper functions to convert one to another.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;trainset.to_inner_iid(route_i)&lt;/code&gt; — Convert domain-specific Id to internal Id.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;trainset.to_raw_iid(id)&lt;/code&gt; — Convert internal Id back to domain-specific Id.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Convert the list of recommended climbs to human-readable names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# convert Surprise internal Id to MP Id 
&lt;/span&gt;&lt;span class="n"&gt;recs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;trainset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_raw_iid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;asarray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pred&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 

&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recs&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; 

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pivot_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'route_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'grade'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;aggfunc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'ratings'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5HzlcXVh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tyihjryqsc58flprmg5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5HzlcXVh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tyihjryqsc58flprmg5p.png" alt="Predictions for Epinephrine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Off Belay
&lt;/h1&gt;

&lt;p&gt;That’s it. We have just built a simple climb recommendation engine for Red Rock Canyon with the help of Python Surprise lib. You can further fine-tune the engine by suggesting climbs by difficulty and type (trad vs sport). That’s a topic for a future article. Have fun and be safe!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you like this tutorial and want to see more like this, make sure to give it a ♥ Thanks!&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jupyter notebook for this tutorial is &lt;a href="https://github.com/OpenBeta/openbeta-tutorials"&gt;available on Github&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5&gt;
  
  
  The author and friends climbing The Dragon (5.11a)
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lezMEBah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tlu17vpsarsfrk24940r.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lezMEBah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tlu17vpsarsfrk24940r.jpg" alt="Climbers on the Dragon"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
