You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@predictionio.apache.org by do...@apache.org on 2016/10/08 05:22:01 UTC
[02/51] [abbrv] [partial] incubator-predictionio-site git commit:
Documentation based on
apache/incubator-predictionio#8d80086e4a69196a65628e4273705a3487838b93
http://git-wip-us.apache.org/repos/asf/incubator-predictionio-site/blob/a542290d/templates/recommendation/customize-data-prep/index.html
----------------------------------------------------------------------
diff --git a/templates/recommendation/customize-data-prep/index.html b/templates/recommendation/customize-data-prep/index.html
new file mode 100644
index 0000000..219e7be
--- /dev/null
+++ b/templates/recommendation/customize-data-prep/index.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html><html><head><title>Customizing Data Preparator (Recommendation)</title><meta charset="utf-8"/><meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><meta class="swiftype" name="title" data-type="string" content="Customizing Data Preparator (Recommendation)"/><link rel="canonical" href="https://docs.prediction.io/templates/recommendation/customize-data-prep/"/><link href="/images/favicon/normal-b330020a.png" rel="shortcut icon"/><link href="/images/favicon/apple-c0febcf2.png" rel="apple-touch-icon"/><link href="//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet"/><link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet"/><link href="/stylesheets/application-a2a2f408.css" rel="stylesheet" type="text/css"/><script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5
shiv.min.js"></script><script src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script><script src="//use.typekit.net/pqo0itb.js"></script><script>try{Typekit.load({ async: true });}catch(e){}</script></head><body><div id="global"><header><div class="container" id="header-wrapper"><div class="row"><div class="col-sm-12"><div id="logo-wrapper"><span id="drawer-toggle"></span><a href="#"></a><a href="http://predictionio.incubator.apache.org/"><img alt="PredictionIO" id="logo" src="/images/logos/logo-ee2b9bb3.png"/></a></div><div id="menu-wrapper"><div id="pill-wrapper"><a class="pill left" href="/gallery/template-gallery">TEMPLATES</a> <a class="pill right" href="//github.com/apache/incubator-predictionio/">OPEN SOURCE</a></div></div><img class="mobile-search-bar-toggler hidden-md hidden-lg" src="/images/icons/search-glass-704bd4ff.png"/></div></div></div></header><div id="search-bar-row-wrapper"><div class="container-fluid" id="search-bar-row"><div clas
s="row"><div class="col-md-9 col-sm-11 col-xs-11"><div class="hidden-md hidden-lg" id="mobile-page-heading-wrapper"><p>PredictionIO Docs</p><h4>Customizing Data Preparator (Recommendation)</h4></div><h4 class="hidden-sm hidden-xs">PredictionIO Docs</h4></div><div class="col-md-3 col-sm-1 col-xs-1 hidden-md hidden-lg"><img id="left-menu-indicator" src="/images/icons/down-arrow-dfe9f7fe.png"/></div><div class="col-md-3 col-sm-12 col-xs-12 swiftype-wrapper"><div class="swiftype"><form class="search-form"><img class="search-box-toggler hidden-xs hidden-sm" src="/images/icons/search-glass-704bd4ff.png"/><div class="search-box"><img src="/images/icons/search-glass-704bd4ff.png"/><input type="text" id="st-search-input" class="st-search-input" placeholder="Search Doc..."/></div><img class="swiftype-row-hider hidden-md hidden-lg" src="/images/icons/drawer-toggle-active-fcbef12a.png"/></form></div></div><div class="mobile-left-menu-toggler hidden-md hidden-lg"></div></div></div></div><div id=
"page" class="container-fluid"><div class="row"><div id="left-menu-wrapper" class="col-md-3"><nav id="nav-main"><ul><li class="level-1"><a class="expandible" href="/"><span>Apache PredictionIO (incubating) Documentation</span></a><ul><li class="level-2"><a class="final" href="/"><span>Welcome to Apache PredictionIO (incubating)</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Getting Started</span></a><ul><li class="level-2"><a class="final" href="/start/"><span>A Quick Intro</span></a></li><li class="level-2"><a class="final" href="/install/"><span>Installing Apache PredictionIO (incubating)</span></a></li><li class="level-2"><a class="final" href="/start/download/"><span>Downloading an Engine Template</span></a></li><li class="level-2"><a class="final" href="/start/deploy/"><span>Deploying Your First Engine</span></a></li><li class="level-2"><a class="final" href="/start/customize/"><span>Customizing the Engine</span></a></li></ul></li><li class="l
evel-1"><a class="expandible" href="#"><span>Integrating with Your App</span></a><ul><li class="level-2"><a class="final" href="/appintegration/"><span>App Integration Overview</span></a></li><li class="level-2"><a class="expandible" href="/sdk/"><span>List of SDKs</span></a><ul><li class="level-3"><a class="final" href="/sdk/java/"><span>Java & Android SDK</span></a></li><li class="level-3"><a class="final" href="/sdk/php/"><span>PHP SDK</span></a></li><li class="level-3"><a class="final" href="/sdk/python/"><span>Python SDK</span></a></li><li class="level-3"><a class="final" href="/sdk/ruby/"><span>Ruby SDK</span></a></li><li class="level-3"><a class="final" href="/sdk/community/"><span>Community Powered SDKs</span></a></li></ul></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Deploying an Engine</span></a><ul><li class="level-2"><a class="final" href="/deploy/"><span>Deploying as a Web Service</span></a></li><li class="level-2"><a class="final" href="/cli/#
engine-commands"><span>Engine Command-line Interface</span></a></li><li class="level-2"><a class="final" href="/deploy/monitoring/"><span>Monitoring Engine</span></a></li><li class="level-2"><a class="final" href="/deploy/engineparams/"><span>Setting Engine Parameters</span></a></li><li class="level-2"><a class="final" href="/deploy/enginevariants/"><span>Deploying Multiple Engine Variants</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Customizing an Engine</span></a><ul><li class="level-2"><a class="final" href="/customize/"><span>Learning DASE</span></a></li><li class="level-2"><a class="final" href="/customize/dase/"><span>Implement DASE</span></a></li><li class="level-2"><a class="final" href="/customize/troubleshooting/"><span>Troubleshooting Engine Development</span></a></li><li class="level-2"><a class="final" href="/api/current/#package"><span>Engine Scala APIs</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><spa
n>Collecting and Analyzing Data</span></a><ul><li class="level-2"><a class="final" href="/datacollection/"><span>Event Server Overview</span></a></li><li class="level-2"><a class="final" href="/cli/#event-server-commands"><span>Event Server Command-line Interface</span></a></li><li class="level-2"><a class="final" href="/datacollection/eventapi/"><span>Collecting Data with REST/SDKs</span></a></li><li class="level-2"><a class="final" href="/datacollection/eventmodel/"><span>Events Modeling</span></a></li><li class="level-2"><a class="final" href="/datacollection/webhooks/"><span>Unifying Multichannel Data with Webhooks</span></a></li><li class="level-2"><a class="final" href="/datacollection/channel/"><span>Channel</span></a></li><li class="level-2"><a class="final" href="/datacollection/batchimport/"><span>Importing Data in Batch</span></a></li><li class="level-2"><a class="final" href="/datacollection/analytics/"><span>Using Analytics Tools</span></a></li></ul></li><li class="leve
l-1"><a class="expandible" href="#"><span>Choosing an Algorithm(s)</span></a><ul><li class="level-2"><a class="final" href="/algorithm/"><span>Built-in Algorithm Libraries</span></a></li><li class="level-2"><a class="final" href="/algorithm/switch/"><span>Switching to Another Algorithm</span></a></li><li class="level-2"><a class="final" href="/algorithm/multiple/"><span>Combining Multiple Algorithms</span></a></li><li class="level-2"><a class="final" href="/algorithm/custom/"><span>Adding Your Own Algorithms</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>ML Tuning and Evaluation</span></a><ul><li class="level-2"><a class="final" href="/evaluation/"><span>Overview</span></a></li><li class="level-2"><a class="final" href="/evaluation/paramtuning/"><span>Hyperparameter Tuning</span></a></li><li class="level-2"><a class="final" href="/evaluation/evaluationdashboard/"><span>Evaluation Dashboard</span></a></li><li class="level-2"><a class="final" href="/
evaluation/metricchoose/"><span>Choosing Evaluation Metrics</span></a></li><li class="level-2"><a class="final" href="/evaluation/metricbuild/"><span>Building Evaluation Metrics</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>System Architecture</span></a><ul><li class="level-2"><a class="final" href="/system/"><span>Architecture Overview</span></a></li><li class="level-2"><a class="final" href="/system/anotherdatastore/"><span>Using Another Data Store</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Engine Template Gallery</span></a><ul><li class="level-2"><a class="final" href="/gallery/template-gallery/"><span>Browse</span></a></li><li class="level-2"><a class="final" href="/community/submit-template/"><span>Submit your Engine as a Template</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Demo Tutorials</span></a><ul><li class="level-2"><a class="final" href="/demo/tapster/"><span>
Comics Recommendation Demo</span></a></li><li class="level-2"><a class="final" href="/demo/community/"><span>Community Contributed Demo</span></a></li><li class="level-2"><a class="final" href="/demo/textclassification/"><span>Text Classification Engine Tutorial</span></a></li></ul></li><li class="level-1"><a class="expandible" href="/community/"><span>Getting Involved</span></a><ul><li class="level-2"><a class="final" href="/community/contribute-code/"><span>Contribute Code</span></a></li><li class="level-2"><a class="final" href="/community/contribute-documentation/"><span>Contribute Documentation</span></a></li><li class="level-2"><a class="final" href="/community/contribute-sdk/"><span>Contribute a SDK</span></a></li><li class="level-2"><a class="final" href="/community/contribute-webhook/"><span>Contribute a Webhook</span></a></li><li class="level-2"><a class="final" href="/community/projects/"><span>Community Projects</span></a></li></ul></li><li class="level-1"><a class="expa
ndible" href="#"><span>Getting Help</span></a><ul><li class="level-2"><a class="final" href="/resources/faq/"><span>FAQs</span></a></li><li class="level-2"><a class="final" href="/support/"><span>Support</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Resources</span></a><ul><li class="level-2"><a class="final" href="/resources/intellij/"><span>Developing Engines with IntelliJ IDEA</span></a></li><li class="level-2"><a class="final" href="/resources/upgrade/"><span>Upgrade Instructions</span></a></li><li class="level-2"><a class="final" href="/resources/glossary/"><span>Glossary</span></a></li></ul></li></ul></nav></div><div class="col-md-9 col-sm-12"><div class="content-header hidden-md hidden-lg"><div id="page-title"><h1>Customizing Data Preparator (Recommendation)</h1></div></div><div id="table-of-content-wrapper"><h5>On this page</h5><aside id="table-of-contents"><ul> <li> <a href="#the-data-preparator-component">The Data Preparator Component</a
> </li> <li> <a href="#modify-the-preparator">Modify the Preparator</a> </li> <li> <a href="#deploy-the-modified-engine">Deploy the Modified Engine</a> </li> <li> <a href="#adding-preparator-parameters">Adding Preparator Parameters</a> </li> </ul> </aside><hr/><a id="edit-page-link" href="https://github.com/apache/incubator-predictionio/tree/livedoc/docs/manual/source/templates/recommendation/customize-data-prep.html.md"><img src="/images/icons/edit-pencil-d6c1bb3d.png"/>Edit this page</a></div><div class="content-header hidden-sm hidden-xs"><div id="page-title"><h1>Customizing Data Preparator (Recommendation)</h1></div></div><div class="content"><p>Data Preparator is where pre-processing actions occurs. For example, one may want to remove some very popular items from the training data because she thinks that these items may not help finding individual person's tastes or one may have a black list of item that she wants to remove from the training data before feeding it to the al
gorithm.</p><p>This section assumes that you have created a <em>MyRecommendation</em> engine based on the <a href="/templates/recommendation/quickstart/">Recommendation Engine Template: QuickStart</a>. We will demonstrate how to add a filtering logic to exclude a list of items in the training data.</p><p>A sample black list file containing the items to be excluded is provided in <code>./data/sample_not_train_data.txt</code>.</p><p>A full end-to-end example can be found on <a href="https://github.com/apache/incubator-predictionio/tree/develop/examples/scala-parallel-recommendation/custom-prepartor">GitHub</a>.</p><h2 id='the-data-preparator-component' class='header-anchors'>The Data Preparator Component</h2><p>Recall <a href="/start/engines/">the DASE Architecture</a>, data is prepared by 2 components sequentially: <em>Data Source</em> and <em>Data Preparator</em>. <em>Data Source</em> reads data from the data store of Event Server and then <em>Data Preparator</em> prepares <code>RDD
[Rating]</code> for the ALS algorithm.</p><p>You may modify any component in an engine template to fit your needs. This example shows you how to add the filtering logics in Data Preparator.</p><h2 id='modify-the-preparator' class='header-anchors'>Modify the Preparator</h2><p>The Data Preparator component can be found in <code>src/main/scala/Preparator.scala</code> in the "MyRecommendation" directory. The unmodified version looks like the following:</p><div class="highlight scala"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7</pre></td><td class="code"><pre><span class="k">class</span> <span class="nc">Preparator</span>
+ <span class="k">extends</span> <span class="nc">PPreparator</span><span class="o">[</span><span class="kt">TrainingData</span>, <span class="kt">PreparedData</span><span class="o">]</span> <span class="o">{</span>
+
+ <span class="k">def</span> <span class="n">prepare</span><span class="o">(</span><span class="n">sc</span><span class="k">:</span> <span class="kt">SparkContext</span><span class="o">,</span> <span class="n">trainingData</span><span class="k">:</span> <span class="kt">TrainingData</span><span class="o">)</span><span class="k">:</span> <span class="kt">PreparedData</span> <span class="o">=</span> <span class="o">{</span>
+ <span class="k">new</span> <span class="nc">PreparedData</span><span class="o">(</span><span class="n">ratings</span> <span class="k">=</span> <span class="n">trainingData</span><span class="o">.</span><span class="n">ratings</span><span class="o">)</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <p>The <code>prepare</code> method simply passes the ratings from <code>TrainingData</code> to <code>PreparedData</code>.</p><p>You can modify the <code>prepare</code> method to read a black list of items from a file and remove them from <code>TrainingData</code>, so it becomes:</p><div class="highlight scala"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16</pre></td><td class="code"><pre><span class="k">import</span> <span class="nn">scala.io.Source</span> <span class="c1">// ADDED
+</span>
+<span class="k">class</span> <span class="nc">Preparator</span>
+ <span class="k">extends</span> <span class="nc">PPreparator</span><span class="o">[</span><span class="kt">TrainingData</span>, <span class="kt">PreparedData</span><span class="o">]</span> <span class="o">{</span>
+
+ <span class="k">def</span> <span class="n">prepare</span><span class="o">(</span><span class="n">sc</span><span class="k">:</span> <span class="kt">SparkContext</span><span class="o">,</span> <span class="n">trainingData</span><span class="k">:</span> <span class="kt">TrainingData</span><span class="o">)</span><span class="k">:</span> <span class="kt">PreparedData</span> <span class="o">=</span> <span class="o">{</span>
+ <span class="c1">// MODIFIED HERE
+</span> <span class="k">val</span> <span class="n">noTrainItems</span> <span class="k">=</span> <span class="nc">Source</span><span class="o">.</span><span class="n">fromFile</span><span class="o">(</span><span class="s">"./data/sample_not_train_data.txt"</span><span class="o">)</span>
+ <span class="o">.</span><span class="n">getLines</span><span class="o">.</span><span class="n">toSet</span>
+ <span class="c1">// exclude noTrainItems from original trainingData
+</span> <span class="k">val</span> <span class="n">ratings</span> <span class="k">=</span> <span class="n">trainingData</span><span class="o">.</span><span class="n">ratings</span><span class="o">.</span><span class="n">filter</span><span class="o">(</span> <span class="n">r</span> <span class="k">=></span>
+ <span class="o">!</span><span class="n">noTrainItems</span><span class="o">.</span><span class="n">contains</span><span class="o">(</span><span class="n">r</span><span class="o">.</span><span class="n">item</span><span class="o">)</span>
+ <span class="o">)</span>
+ <span class="k">new</span> <span class="nc">PreparedData</span><span class="o">(</span><span class="n">ratings</span><span class="o">)</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <blockquote> <p>We will show you how not to hardcode the path <code>./data/sample_not_train_data.txt</code> soon.</p></blockquote> <h2 id='deploy-the-modified-engine' class='header-anchors'>Deploy the Modified Engine</h2><p>Now you can deploy the modified engine as described in <a href="/templates/recommendation/quickstart/">Quick Start</a>.</p><p>Make sure the <code>appName</code> defined in the file <code>engine.json</code> matches your <em>App Name</em>:</p><div class="highlight shell"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7</pre></td><td class="code"><pre>...
+<span class="s2">"datasource"</span>: <span class="o">{</span>
+ <span class="s2">"params"</span> : <span class="o">{</span>
+ <span class="s2">"appName"</span>: <span class="s2">"YourAppName"</span>
+ <span class="o">}</span>
+<span class="o">}</span>,
+...
+</pre></td></tr></tbody></table> </div> <p>To build <em>MyRecommendation</em> and deploy it as a service:</p><div class="highlight shell"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3</pre></td><td class="code"><pre><span class="gp">$ </span>pio build
+<span class="gp">$ </span>pio train
+<span class="gp">$ </span>pio deploy
+</pre></td></tr></tbody></table> </div> <p>This will deploy an engine that binds to <a href="http://localhost:8000">http://localhost:8000</a>. You can visit that page in your web browser to check its status.</p><p>Now, You can try to retrieve predicted results. To recommend 4 movies to user whose ID is 1, send this JSON <code>{ "user": "1", "num": 4 }</code> to the deployed engine</p><div class="highlight shell"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1</pre></td><td class="code"><pre><span class="gp">$ </span>curl -H <span class="s2">"Content-Type: application/json"</span> -d <span class="s1">'{ "user": "1", "num": 4 }'</span> http://localhost:8000/queries.json
+</pre></td></tr></tbody></table> </div> <p>and it will return a JSON of recommended movies.</p><div class="highlight json"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7
+8</pre></td><td class="code"><pre><span class="p">{</span><span class="w">
+ </span><span class="s2">"itemScores"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"22"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">4.072304374729956</span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"62"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">4.058482414005789</span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"75"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">4.046063009943821</span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"68"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">3.8153661512945325</span><span class="p">}</span><span class="w">
+ </span><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></pre></td></tr></tbody></table> </div> <p>Congratulations! You have learned how to add customized logic to your Data Preparator!</p><h2 id='adding-preparator-parameters' class='header-anchors'>Adding Preparator Parameters</h2><p>Optionally, you may want to take the hardcoded path (<code>./data/sample_not_train_data.txt</code>) away from the source code.</p><p>PredictionIO offers <code>PreparatorParams</code> so you can read variable values from <code>engine.json</code> instead.</p><p>Modify <code>src/main/scala/Preparator.scala</code> again in the <em>MyRecommendation</em> directory to:</p><div class="highlight scala"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19</pre></td><td class="code"><pre><span class="k">import</span> <span class="nn">org.apache.predictionio.controller.Params</span> <span class="c1">// ADDED
+</span>
+ <span class="c1">// ADDED CustomPreparatorParams case class
+</span><span class="k">case</span> <span class="k">class</span> <span class="nc">CustomPreparatorParams</span><span class="o">(</span>
+ <span class="n">filepath</span><span class="k">:</span> <span class="kt">String</span>
+<span class="o">)</span> <span class="k">extends</span> <span class="nc">Params</span>
+
+<span class="k">class</span> <span class="nc">Preparator</span><span class="o">(</span><span class="n">pp</span><span class="k">:</span> <span class="kt">CustomPreparatorParams</span><span class="o">)</span> <span class="c1">// ADDED CustomPreparatorParams
+</span> <span class="k">extends</span> <span class="nc">PPreparator</span><span class="o">[</span><span class="kt">TrainingData</span>, <span class="kt">PreparedData</span><span class="o">]</span> <span class="o">{</span>
+
+ <span class="k">def</span> <span class="n">prepare</span><span class="o">(</span><span class="n">sc</span><span class="k">:</span> <span class="kt">SparkContext</span><span class="o">,</span> <span class="n">trainingData</span><span class="k">:</span> <span class="kt">TrainingData</span><span class="o">)</span><span class="k">:</span> <span class="kt">PreparedData</span> <span class="o">=</span> <span class="o">{</span>
+ <span class="k">val</span> <span class="n">noTrainItems</span> <span class="k">=</span> <span class="nc">Source</span><span class="o">.</span><span class="n">fromFile</span><span class="o">(</span><span class="n">pp</span><span class="o">.</span><span class="n">filepath</span><span class="o">).</span><span class="n">getLines</span><span class="o">.</span><span class="n">toSet</span> <span class="c1">//CHANGED
+</span> <span class="k">val</span> <span class="n">ratings</span> <span class="k">=</span> <span class="n">trainingData</span><span class="o">.</span><span class="n">ratings</span><span class="o">.</span><span class="n">filter</span><span class="o">(</span> <span class="n">r</span> <span class="k">=></span>
+ <span class="o">!</span><span class="n">noTrainItems</span><span class="o">.</span><span class="n">contains</span><span class="o">(</span><span class="n">r</span><span class="o">.</span><span class="n">item</span><span class="o">)</span>
+ <span class="o">)</span>
+ <span class="k">new</span> <span class="nc">PreparedData</span><span class="o">(</span><span class="n">ratings</span><span class="o">)</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+
+</pre></td></tr></tbody></table> </div> <p>In <code>engine.json</code>, you define the parameters <code>filepath</code> for the Data Preparator:</p><div class="highlight json"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7
+8
+9</pre></td><td class="code"><pre><span class="p">{</span><span class="w">
+ </span><span class="err">...</span><span class="w">
+ </span><span class="s2">"preparator"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
+ </span><span class="s2">"params"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
+ </span><span class="s2">"filepath"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./data/sample_not_train_data.txt"</span><span class="w">
+ </span><span class="p">}</span><span class="w">
+ </span><span class="p">},</span><span class="w">
+ </span><span class="err">...</span><span class="w">
+</span><span class="err">}</span><span class="w">
+</span></pre></td></tr></tbody></table> </div> <p>Try to build <em>MyRecommendation</em> and deploy it again:</p><div class="highlight shell"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3</pre></td><td class="code"><pre><span class="gp">$ </span>pio build
+<span class="gp">$ </span>pio train
+<span class="gp">$ </span>pio deploy
+</pre></td></tr></tbody></table> </div> <p>You can change the <code>filepath</code> value without re-building the code next time.</p><h4 id='<a-href="/templates/recommendation/customize-serving/">next:-customizing-serving</a>' class='header-anchors' ><a href="/templates/recommendation/customize-serving/">Next: Customizing Serving</a></h4></div></div></div></div><footer><div class="container"><div class="seperator"></div><div class="row"><div class="col-md-6 col-xs-6 footer-link-column"><div class="footer-link-column-row"><h4>Community</h4><ul><li><a href="//docs.prediction.io/install/" target="blank">Download</a></li><li><a href="//docs.prediction.io/" target="blank">Docs</a></li><li><a href="//github.com/apache/incubator-predictionio" target="blank">GitHub</a></li><li><a href="mailto:user-subscribe@predictionio.incubator.apache.org" target="blank">Subscribe to User Mailing List</a></li><li><a href="//stackoverflow.com/questions/tagged/predictionio" target="blank">Stackoverflow</a><
/li></ul></div></div><div class="col-md-6 col-xs-6 footer-link-column"><div class="footer-link-column-row"><h4>Contribute</h4><ul><li><a href="//predictionio.incubator.apache.org/community/contribute-code/" target="blank">Contribute</a></li><li><a href="//github.com/apache/incubator-predictionio" target="blank">Source Code</a></li><li><a href="//issues.apache.org/jira/browse/PIO" target="blank">Bug Tracker</a></li><li><a href="mailto:dev-subscribe@predictionio.incubator.apache.org" target="blank">Subscribe to Development Mailing List</a></li></ul></div></div></div></div><div id="footer-bottom"><div class="container"><div class="row"><div class="col-md-12"><div id="footer-logo-wrapper"><img alt="PredictionIO" src="/images/logos/logo-white-d1e9c6e6.png"/></div><div id="social-icons-wrapper"><a class="github-button" href="https://github.com/apache/incubator-predictionio" data-style="mega" data-count-href="/apache/incubator-predictionio/stargazers" data-count-api="/repos/apache/incubato
r-predictionio#stargazers_count" data-count-aria-label="# stargazers on GitHub" aria-label="Star apache/incubator-predictionio on GitHub">Star</a> <a class="github-button" href="https://github.com/apache/incubator-predictionio/fork" data-icon="octicon-git-branch" data-style="mega" data-count-href="/apache/incubator-predictionio/network" data-count-api="/repos/apache/incubator-predictionio#forks_count" data-count-aria-label="# forks on GitHub" aria-label="Fork apache/incubator-predictionio on GitHub">Fork</a> <script id="github-bjs" async="" defer="" src="https://buttons.github.io/buttons.js"></script><a href="//www.facebook.com/predictionio" target="blank"><img alt="PredictionIO on Twitter" src="/images/icons/twitter-ea9dc152.png"/></a> <a href="//twitter.com/predictionio" target="blank"><img alt="PredictionIO on Facebook" src="/images/icons/facebook-5c57939c.png"/></a> </div></div></div></div></div></footer></div><script>(function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||fun
ction(){
+(w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
+e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
+})(window,document,'script','//s.swiftypecdn.com/install/v1/st.js','_st');
+
+_st('install','HaUfpXXV87xoB_zzCQ45');</script><script src="/javascripts/application-280db181.js"></script></body></html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-predictionio-site/blob/a542290d/templates/recommendation/customize-data-prep/index.html.gz
----------------------------------------------------------------------
diff --git a/templates/recommendation/customize-data-prep/index.html.gz b/templates/recommendation/customize-data-prep/index.html.gz
new file mode 100644
index 0000000..c8b5d60
Binary files /dev/null and b/templates/recommendation/customize-data-prep/index.html.gz differ
http://git-wip-us.apache.org/repos/asf/incubator-predictionio-site/blob/a542290d/templates/recommendation/customize-serving/index.html
----------------------------------------------------------------------
diff --git a/templates/recommendation/customize-serving/index.html b/templates/recommendation/customize-serving/index.html
new file mode 100644
index 0000000..07b38b4
--- /dev/null
+++ b/templates/recommendation/customize-serving/index.html
@@ -0,0 +1,173 @@
+<!DOCTYPE html><html><head><title>Customizing Serving Component (Recommendation)</title><meta charset="utf-8"/><meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><meta class="swiftype" name="title" data-type="string" content="Customizing Serving Component (Recommendation)"/><link rel="canonical" href="https://docs.prediction.io/templates/recommendation/customize-serving/"/><link href="/images/favicon/normal-b330020a.png" rel="shortcut icon"/><link href="/images/favicon/apple-c0febcf2.png" rel="apple-touch-icon"/><link href="//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet"/><link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet"/><link href="/stylesheets/application-a2a2f408.css" rel="stylesheet" type="text/css"/><script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/htm
l5shiv.min.js"></script><script src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script><script src="//use.typekit.net/pqo0itb.js"></script><script>try{Typekit.load({ async: true });}catch(e){}</script></head><body><div id="global"><header><div class="container" id="header-wrapper"><div class="row"><div class="col-sm-12"><div id="logo-wrapper"><span id="drawer-toggle"></span><a href="#"></a><a href="http://predictionio.incubator.apache.org/"><img alt="PredictionIO" id="logo" src="/images/logos/logo-ee2b9bb3.png"/></a></div><div id="menu-wrapper"><div id="pill-wrapper"><a class="pill left" href="/gallery/template-gallery">TEMPLATES</a> <a class="pill right" href="//github.com/apache/incubator-predictionio/">OPEN SOURCE</a></div></div><img class="mobile-search-bar-toggler hidden-md hidden-lg" src="/images/icons/search-glass-704bd4ff.png"/></div></div></div></header><div id="search-bar-row-wrapper"><div class="container-fluid" id="search-bar-row"><div cl
ass="row"><div class="col-md-9 col-sm-11 col-xs-11"><div class="hidden-md hidden-lg" id="mobile-page-heading-wrapper"><p>PredictionIO Docs</p><h4>Customizing Serving Component (Recommendation)</h4></div><h4 class="hidden-sm hidden-xs">PredictionIO Docs</h4></div><div class="col-md-3 col-sm-1 col-xs-1 hidden-md hidden-lg"><img id="left-menu-indicator" src="/images/icons/down-arrow-dfe9f7fe.png"/></div><div class="col-md-3 col-sm-12 col-xs-12 swiftype-wrapper"><div class="swiftype"><form class="search-form"><img class="search-box-toggler hidden-xs hidden-sm" src="/images/icons/search-glass-704bd4ff.png"/><div class="search-box"><img src="/images/icons/search-glass-704bd4ff.png"/><input type="text" id="st-search-input" class="st-search-input" placeholder="Search Doc..."/></div><img class="swiftype-row-hider hidden-md hidden-lg" src="/images/icons/drawer-toggle-active-fcbef12a.png"/></form></div></div><div class="mobile-left-menu-toggler hidden-md hidden-lg"></div></div></div></div><div
id="page" class="container-fluid"><div class="row"><div id="left-menu-wrapper" class="col-md-3"><nav id="nav-main"><ul><li class="level-1"><a class="expandible" href="/"><span>Apache PredictionIO (incubating) Documentation</span></a><ul><li class="level-2"><a class="final" href="/"><span>Welcome to Apache PredictionIO (incubating)</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Getting Started</span></a><ul><li class="level-2"><a class="final" href="/start/"><span>A Quick Intro</span></a></li><li class="level-2"><a class="final" href="/install/"><span>Installing Apache PredictionIO (incubating)</span></a></li><li class="level-2"><a class="final" href="/start/download/"><span>Downloading an Engine Template</span></a></li><li class="level-2"><a class="final" href="/start/deploy/"><span>Deploying Your First Engine</span></a></li><li class="level-2"><a class="final" href="/start/customize/"><span>Customizing the Engine</span></a></li></ul></li><li clas
s="level-1"><a class="expandible" href="#"><span>Integrating with Your App</span></a><ul><li class="level-2"><a class="final" href="/appintegration/"><span>App Integration Overview</span></a></li><li class="level-2"><a class="expandible" href="/sdk/"><span>List of SDKs</span></a><ul><li class="level-3"><a class="final" href="/sdk/java/"><span>Java & Android SDK</span></a></li><li class="level-3"><a class="final" href="/sdk/php/"><span>PHP SDK</span></a></li><li class="level-3"><a class="final" href="/sdk/python/"><span>Python SDK</span></a></li><li class="level-3"><a class="final" href="/sdk/ruby/"><span>Ruby SDK</span></a></li><li class="level-3"><a class="final" href="/sdk/community/"><span>Community Powered SDKs</span></a></li></ul></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Deploying an Engine</span></a><ul><li class="level-2"><a class="final" href="/deploy/"><span>Deploying as a Web Service</span></a></li><li class="level-2"><a class="final" href="/c
li/#engine-commands"><span>Engine Command-line Interface</span></a></li><li class="level-2"><a class="final" href="/deploy/monitoring/"><span>Monitoring Engine</span></a></li><li class="level-2"><a class="final" href="/deploy/engineparams/"><span>Setting Engine Parameters</span></a></li><li class="level-2"><a class="final" href="/deploy/enginevariants/"><span>Deploying Multiple Engine Variants</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Customizing an Engine</span></a><ul><li class="level-2"><a class="final" href="/customize/"><span>Learning DASE</span></a></li><li class="level-2"><a class="final" href="/customize/dase/"><span>Implement DASE</span></a></li><li class="level-2"><a class="final" href="/customize/troubleshooting/"><span>Troubleshooting Engine Development</span></a></li><li class="level-2"><a class="final" href="/api/current/#package"><span>Engine Scala APIs</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#">
<span>Collecting and Analyzing Data</span></a><ul><li class="level-2"><a class="final" href="/datacollection/"><span>Event Server Overview</span></a></li><li class="level-2"><a class="final" href="/cli/#event-server-commands"><span>Event Server Command-line Interface</span></a></li><li class="level-2"><a class="final" href="/datacollection/eventapi/"><span>Collecting Data with REST/SDKs</span></a></li><li class="level-2"><a class="final" href="/datacollection/eventmodel/"><span>Events Modeling</span></a></li><li class="level-2"><a class="final" href="/datacollection/webhooks/"><span>Unifying Multichannel Data with Webhooks</span></a></li><li class="level-2"><a class="final" href="/datacollection/channel/"><span>Channel</span></a></li><li class="level-2"><a class="final" href="/datacollection/batchimport/"><span>Importing Data in Batch</span></a></li><li class="level-2"><a class="final" href="/datacollection/analytics/"><span>Using Analytics Tools</span></a></li></ul></li><li class="
level-1"><a class="expandible" href="#"><span>Choosing an Algorithm(s)</span></a><ul><li class="level-2"><a class="final" href="/algorithm/"><span>Built-in Algorithm Libraries</span></a></li><li class="level-2"><a class="final" href="/algorithm/switch/"><span>Switching to Another Algorithm</span></a></li><li class="level-2"><a class="final" href="/algorithm/multiple/"><span>Combining Multiple Algorithms</span></a></li><li class="level-2"><a class="final" href="/algorithm/custom/"><span>Adding Your Own Algorithms</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>ML Tuning and Evaluation</span></a><ul><li class="level-2"><a class="final" href="/evaluation/"><span>Overview</span></a></li><li class="level-2"><a class="final" href="/evaluation/paramtuning/"><span>Hyperparameter Tuning</span></a></li><li class="level-2"><a class="final" href="/evaluation/evaluationdashboard/"><span>Evaluation Dashboard</span></a></li><li class="level-2"><a class="final" hre
f="/evaluation/metricchoose/"><span>Choosing Evaluation Metrics</span></a></li><li class="level-2"><a class="final" href="/evaluation/metricbuild/"><span>Building Evaluation Metrics</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>System Architecture</span></a><ul><li class="level-2"><a class="final" href="/system/"><span>Architecture Overview</span></a></li><li class="level-2"><a class="final" href="/system/anotherdatastore/"><span>Using Another Data Store</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Engine Template Gallery</span></a><ul><li class="level-2"><a class="final" href="/gallery/template-gallery/"><span>Browse</span></a></li><li class="level-2"><a class="final" href="/community/submit-template/"><span>Submit your Engine as a Template</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Demo Tutorials</span></a><ul><li class="level-2"><a class="final" href="/demo/tapster/"><s
pan>Comics Recommendation Demo</span></a></li><li class="level-2"><a class="final" href="/demo/community/"><span>Community Contributed Demo</span></a></li><li class="level-2"><a class="final" href="/demo/textclassification/"><span>Text Classification Engine Tutorial</span></a></li></ul></li><li class="level-1"><a class="expandible" href="/community/"><span>Getting Involved</span></a><ul><li class="level-2"><a class="final" href="/community/contribute-code/"><span>Contribute Code</span></a></li><li class="level-2"><a class="final" href="/community/contribute-documentation/"><span>Contribute Documentation</span></a></li><li class="level-2"><a class="final" href="/community/contribute-sdk/"><span>Contribute a SDK</span></a></li><li class="level-2"><a class="final" href="/community/contribute-webhook/"><span>Contribute a Webhook</span></a></li><li class="level-2"><a class="final" href="/community/projects/"><span>Community Projects</span></a></li></ul></li><li class="level-1"><a class="
expandible" href="#"><span>Getting Help</span></a><ul><li class="level-2"><a class="final" href="/resources/faq/"><span>FAQs</span></a></li><li class="level-2"><a class="final" href="/support/"><span>Support</span></a></li></ul></li><li class="level-1"><a class="expandible" href="#"><span>Resources</span></a><ul><li class="level-2"><a class="final" href="/resources/intellij/"><span>Developing Engines with IntelliJ IDEA</span></a></li><li class="level-2"><a class="final" href="/resources/upgrade/"><span>Upgrade Instructions</span></a></li><li class="level-2"><a class="final" href="/resources/glossary/"><span>Glossary</span></a></li></ul></li></ul></nav></div><div class="col-md-9 col-sm-12"><div class="content-header hidden-md hidden-lg"><div id="page-title"><h1>Customizing Serving Component (Recommendation)</h1></div></div><div id="table-of-content-wrapper"><h5>On this page</h5><aside id="table-of-contents"><ul> <li> <a href="#the-serving-component">The Serving Component</a> </li> <l
i> <a href="#modify-the-serving-interface">Modify the Serving Interface</a> </li> <li> <a href="#deploy-the-modified-engine">Deploy the Modified Engine</a> </li> <li> <a href="#adding-serving-parameters">Adding Serving Parameters</a> </li> </ul> </aside><hr/><a id="edit-page-link" href="https://github.com/apache/incubator-predictionio/tree/livedoc/docs/manual/source/templates/recommendation/customize-serving.html.md"><img src="/images/icons/edit-pencil-d6c1bb3d.png"/>Edit this page</a></div><div class="content-header hidden-sm hidden-xs"><div id="page-title"><h1>Customizing Serving Component (Recommendation)</h1></div></div><div class="content"><p>Serving component is where post-processing occurs. For example, if you are recommending items to users, you may want to remove items that are not currently in stock from the list of recommendation.</p><p>This section is based on the <a href="/templates/recommendation/quickstart/">Recommendation Engine Template</a>.</p><p>A full end-to-end
example can be found on <a href="https://github.com/apache/incubator-predictionio/tree/develop/examples/scala-parallel-recommendation/custom-serving">GitHub</a>.</p> <h2 id='the-serving-component' class='header-anchors'>The Serving Component</h2><p>Recall <a href="/start/engines/">the DASE Architecture</a>, a PredictionIO engine has 4 main components: Data Source, Data Preparator, Algorithm, and Serving components. When a Query comes in, it is passed to the Algorithm component for making Predictions.</p><p>The Engine's serving component can be found in <code>src/main/scala/Serving.scala</code> in the <em>MyRecommendation</em> directory. By default, it looks like the following:</p><div class="highlight scala"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7
+8</pre></td><td class="code"><pre><span class="k">class</span> <span class="nc">Serving</span> <span class="k">extends</span> <span class="nc">LServing</span><span class="o">[</span><span class="kt">Query</span>, <span class="kt">PredictedResult</span><span class="o">]</span> <span class="o">{</span>
+
+ <span class="k">override</span>
+ <span class="k">def</span> <span class="n">serve</span><span class="o">(</span><span class="n">query</span><span class="k">:</span> <span class="kt">Query</span><span class="o">,</span>
+ <span class="n">predictedResults</span><span class="k">:</span> <span class="kt">Seq</span><span class="o">[</span><span class="kt">PredictedResult</span><span class="o">])</span><span class="k">:</span> <span class="kt">PredictedResult</span> <span class="o">=</span> <span class="o">{</span>
+ <span class="n">predictedResults</span><span class="o">.</span><span class="n">head</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <p>We will customize the Serving component to remove temporarily disabled items from the Prediction made by Algorithms.</p><h2 id='modify-the-serving-interface' class='header-anchors'>Modify the Serving Interface</h2><p>We will use a file to specify a list of disabled items. When the <code>serve</code> method is called, it loads the file and removes items in the disabled list from <code>PredictedResult</code>. The following code snippet illustrates the logic:</p><div class="highlight scala"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17</pre></td><td class="code"><pre><span class="k">import</span> <span class="nn">scala.io.Source</span> <span class="c1">// ADDED
+</span>
+<span class="k">class</span> <span class="nc">Serving</span> <span class="k">extends</span> <span class="nc">LServing</span><span class="o">[</span><span class="kt">Query</span>, <span class="kt">PredictedResult</span><span class="o">]</span> <span class="o">{</span>
+
+ <span class="k">override</span> <span class="k">def</span> <span class="n">serve</span><span class="o">(</span><span class="n">query</span><span class="k">:</span> <span class="kt">Query</span><span class="o">,</span> <span class="n">predictedResults</span><span class="k">:</span> <span class="kt">Seq</span><span class="o">[</span><span class="kt">PredictedResult</span><span class="o">])</span>
+ <span class="k">:</span> <span class="kt">PredictedResult</span> <span class="o">=</span> <span class="o">{</span>
+ <span class="c1">// Read the disabled item from file.
+</span> <span class="k">val</span> <span class="n">disabledProducts</span><span class="k">:</span> <span class="kt">Set</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span> <span class="k">=</span> <span class="nc">Source</span>
+ <span class="o">.</span><span class="n">fromFile</span><span class="o">(</span><span class="s">"./data/sample_disabled_items.txt"</span><span class="o">)</span>
+ <span class="o">.</span><span class="n">getLines</span>
+ <span class="o">.</span><span class="n">toSet</span>
+
+ <span class="k">val</span> <span class="n">itemScores</span> <span class="k">=</span> <span class="n">predictedResults</span><span class="o">.</span><span class="n">head</span><span class="o">.</span><span class="n">itemScores</span>
+ <span class="c1">// Remove items from the original predictedResult
+</span> <span class="nc">PredictedResult</span><span class="o">(</span><span class="n">itemScores</span><span class="o">.</span><span class="n">filter</span><span class="o">(</span><span class="n">ps</span> <span class="k">=></span> <span class="o">!</span><span class="n">disabledProducts</span><span class="o">(</span><span class="n">ps</span><span class="o">.</span><span class="n">item</span><span class="o">)))</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <div class="alert-message info"><p>We will show you how not to hardcode the path <code>./data/sample_disabled_items.txt</code> soon.</p></div><div class="alert-message warning"><p>This example code uses a local relative path. For remote deployment, it is recommended to use a globally accessible absolute path.</p></div><div class="alert-message danger"><p>This example is only for demonstration purpose. Reading from disk for every query leads to terrible system performance. Use a more efficient implementation for production deployment.</p></div><h2 id='deploy-the-modified-engine' class='header-anchors'>Deploy the Modified Engine</h2><p>Now you can deploy the modified engine as described in the <a href="/templates/recommendation/quickstart/">Quick Start</a> guide.</p><p>Make sure the <code>appId</code> defined in the file <code>engine.json</code> match your <em>App ID</em>:</p><div class="highlight shell"><table style="border-spacing: 0"><tbody><
tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7</pre></td><td class="code"><pre>...
+<span class="s2">"datasource"</span>: <span class="o">{</span>
+ <span class="s2">"params"</span>: <span class="o">{</span>
+ <span class="s2">"appId"</span>: 1
+ <span class="o">}</span>
+<span class="o">}</span>,
+...
+</pre></td></tr></tbody></table> </div> <p>To build <em>MyRecommendation</em> and deploy it as a service:</p><div class="highlight shell"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3</pre></td><td class="code"><pre><span class="gp">$ </span>pio build
+<span class="gp">$ </span>pio train
+<span class="gp">$ </span>pio deploy
+</pre></td></tr></tbody></table> </div> <p>This will deploy an engine that binds to <a href="http://localhost:8000">http://localhost:8000</a>. You can visit that page in your web browser to check its status.</p><p>Now, you can try to retrieve predicted results. To recommend 4 movies to user whose ID is 1, send this JSON <code>{ "user": "1", "num": 4 }</code> to the deployed engine</p><div class="highlight shell"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2</pre></td><td class="code"><pre><span class="gp">$ </span>curl -H <span class="s2">"Content-Type: application/json"</span> -d <span class="s1">'{ "user": "1", "num": 4 }'</span> <span class="se">\</span>
+ http://localhost:8000/queries.json
+</pre></td></tr></tbody></table> </div> <p>and it will return a JSON of recommended movies.</p><div class="highlight json"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7
+8</pre></td><td class="code"><pre><span class="p">{</span><span class="w">
+ </span><span class="s2">"itemScores"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"65"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">6.537168137254073</span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"69"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">6.391430405762495</span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"38"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">5.829957095096519</span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"11"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">5.5991291456974</span><span class="p">}</span><span class="w">
+ </span><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></pre></td></tr></tbody></table> </div> <p>Now, to verify the blacklisting logic, we add the item 69 (the second item) to the blacklisting file <code>data/sample_disabled_items.txt</code>. Rerun the <code>curl</code> query, and the change should take effect immediately as the disabled item list is reloaded every time the <code>serve</code> method is called.</p><div class="highlight shell"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3</pre></td><td class="code"><pre><span class="gp">$ </span><span class="nb">echo</span> <span class="s2">"69"</span> >> ./data/sample_disabled_items.txt
+<span class="gp">$ </span>curl -H <span class="s2">"Content-Type: application/json"</span> -d <span class="s1">'{ "user": "1", "num": 4 }'</span> <span class="se">\</span>
+ http://localhost:8000/queries.json
+</pre></td></tr></tbody></table> </div> <div class="highlight json"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7</pre></td><td class="code"><pre><span class="p">{</span><span class="w">
+ </span><span class="s2">"itemScores"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"65"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">6.537168137254073</span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"38"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">5.829957095096519</span><span class="p">},</span><span class="w">
+ </span><span class="p">{</span><span class="s2">"item"</span><span class="p">:</span><span class="w"> </span><span class="s2">"11"</span><span class="p">,</span><span class="w"> </span><span class="s2">"score"</span><span class="p">:</span><span class="w"> </span><span class="mf">5.5991291456974</span><span class="p">}</span><span class="w">
+ </span><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></pre></td></tr></tbody></table> </div> <p>Congratulations! You have learned how to add customized realtime blacklisting logic to your Serving component!</p><h2 id='adding-serving-parameters' class='header-anchors'>Adding Serving Parameters</h2><p>Optionally, you may want to take the hardcoded path (<code>./data/sample_disabled_items.txt</code>) away from the source code.</p><p>PredictionIO offers <code>ServingParams</code> so you can read variable values from <code>engine.json</code> instead. PredictionIO transforms the JSON object specified in <code>engine.json</code>'s <code>serving</code> field into the <code>ServingParams</code> class.</p><p>Modify <code>src/main/scala/Serving.scala</code> again in the <em>MyRecommendation</em> directory to:</p><div class="highlight scala"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22</pre></td><td class="code"><pre><span class="k">import</span> <span class="nn">scala.io.Source</span>
+
+<span class="k">import</span> <span class="nn">org.apache.predictionio.controller.Params</span> <span class="c1">// ADDED
+</span>
+<span class="c1">// ADDED ServingParams to specify the blacklisting file location.
+</span><span class="k">case</span> <span class="k">class</span> <span class="nc">ServingParams</span><span class="o">(</span><span class="n">filepath</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">extends</span> <span class="nc">Params</span>
+
+<span class="k">class</span> <span class="nc">Serving</span><span class="o">(</span><span class="k">val</span> <span class="n">params</span><span class="k">:</span> <span class="kt">ServingParams</span><span class="o">)</span>
+ <span class="k">extends</span> <span class="nc">LServing</span><span class="o">[</span><span class="kt">Query</span>, <span class="kt">PredictedResult</span><span class="o">]</span> <span class="o">{</span>
+
+ <span class="k">override</span>
+ <span class="k">def</span> <span class="n">serve</span><span class="o">(</span><span class="n">query</span><span class="k">:</span> <span class="kt">Query</span><span class="o">,</span> <span class="n">predictedResults</span><span class="k">:</span> <span class="kt">Seq</span><span class="o">[</span><span class="kt">PredictedResult</span><span class="o">])</span>
+ <span class="k">:</span> <span class="kt">PredictedResult</span> <span class="o">=</span> <span class="o">{</span>
+ <span class="k">val</span> <span class="n">disabledProducts</span><span class="k">:</span> <span class="kt">Set</span><span class="o">[</span><span class="kt">String</span><span class="o">]</span> <span class="k">=</span> <span class="nc">Source</span>
+ <span class="o">.</span><span class="n">fromFile</span><span class="o">(</span><span class="n">params</span><span class="o">.</span><span class="n">filepath</span><span class="o">)</span>
+ <span class="o">.</span><span class="n">getLines</span>
+ <span class="o">.</span><span class="n">toSet</span>
+
+ <span class="k">val</span> <span class="n">itemScores</span> <span class="k">=</span> <span class="n">predictedResults</span><span class="o">.</span><span class="n">head</span><span class="o">.</span><span class="n">itemScores</span>
+ <span class="nc">PredictedResult</span><span class="o">(</span><span class="n">itemScores</span><span class="o">.</span><span class="n">filter</span><span class="o">(</span><span class="n">ps</span> <span class="k">=></span> <span class="o">!</span><span class="n">disabledProducts</span><span class="o">(</span><span class="n">ps</span><span class="o">.</span><span class="n">item</span><span class="o">)))</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <p>In <code>engine.json</code>, you specify the parameter <code>serving</code> for the Serving component (the JSON4S library automatically extract the JSON object into a Scala class under the hood):</p><div class="highlight json"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3
+4
+5
+6
+7
+8
+9</pre></td><td class="code"><pre><span class="p">{</span><span class="w">
+ </span><span class="err">...</span><span class="w">
+ </span><span class="s2">"serving"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
+ </span><span class="s2">"params"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
+ </span><span class="s2">"filepath"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./data/sample_disabled_items.txt"</span><span class="w">
+ </span><span class="p">}</span><span class="w">
+ </span><span class="p">},</span><span class="w">
+ </span><span class="err">...</span><span class="w">
+</span><span class="err">}</span><span class="w">
+</span></pre></td></tr></tbody></table> </div> <p>Again, to build <em>MyRecommendation</em> and deploy it as a service:</p><div class="highlight shell"><table style="border-spacing: 0"><tbody><tr><td class="gutter gl" style="text-align: right"><pre class="lineno">1
+2
+3</pre></td><td class="code"><pre><span class="gp">$ </span>pio build
+<span class="gp">$ </span>pio train
+<span class="gp">$ </span>pio deploy
+</pre></td></tr></tbody></table> </div> <p>You can change the <code>filepath</code> value without re-building the code next time.</p><h4 id='<a-href="/templates/recommendation/blacklist-items/">next:-filter-recommended-items-by-blacklist-in-query</a>' class='header-anchors' ><a href="/templates/recommendation/blacklist-items/">Next: Filter Recommended Items by Blacklist in Query</a></h4></div></div></div></div><footer><div class="container"><div class="seperator"></div><div class="row"><div class="col-md-6 col-xs-6 footer-link-column"><div class="footer-link-column-row"><h4>Community</h4><ul><li><a href="//docs.prediction.io/install/" target="blank">Download</a></li><li><a href="//docs.prediction.io/" target="blank">Docs</a></li><li><a href="//github.com/apache/incubator-predictionio" target="blank">GitHub</a></li><li><a href="mailto:user-subscribe@predictionio.incubator.apache.org" target="blank">Subscribe to User Mailing List</a></li><li><a href="//stackoverflow.com/questions/tagg
ed/predictionio" target="blank">Stackoverflow</a></li></ul></div></div><div class="col-md-6 col-xs-6 footer-link-column"><div class="footer-link-column-row"><h4>Contribute</h4><ul><li><a href="//predictionio.incubator.apache.org/community/contribute-code/" target="blank">Contribute</a></li><li><a href="//github.com/apache/incubator-predictionio" target="blank">Source Code</a></li><li><a href="//issues.apache.org/jira/browse/PIO" target="blank">Bug Tracker</a></li><li><a href="mailto:dev-subscribe@predictionio.incubator.apache.org" target="blank">Subscribe to Development Mailing List</a></li></ul></div></div></div></div><div id="footer-bottom"><div class="container"><div class="row"><div class="col-md-12"><div id="footer-logo-wrapper"><img alt="PredictionIO" src="/images/logos/logo-white-d1e9c6e6.png"/></div><div id="social-icons-wrapper"><a class="github-button" href="https://github.com/apache/incubator-predictionio" data-style="mega" data-count-href="/apache/incubator-predictionio/
stargazers" data-count-api="/repos/apache/incubator-predictionio#stargazers_count" data-count-aria-label="# stargazers on GitHub" aria-label="Star apache/incubator-predictionio on GitHub">Star</a> <a class="github-button" href="https://github.com/apache/incubator-predictionio/fork" data-icon="octicon-git-branch" data-style="mega" data-count-href="/apache/incubator-predictionio/network" data-count-api="/repos/apache/incubator-predictionio#forks_count" data-count-aria-label="# forks on GitHub" aria-label="Fork apache/incubator-predictionio on GitHub">Fork</a> <script id="github-bjs" async="" defer="" src="https://buttons.github.io/buttons.js"></script><a href="//www.facebook.com/predictionio" target="blank"><img alt="PredictionIO on Twitter" src="/images/icons/twitter-ea9dc152.png"/></a> <a href="//twitter.com/predictionio" target="blank"><img alt="PredictionIO on Facebook" src="/images/icons/facebook-5c57939c.png"/></a> </div></div></div></div></div></footer></div><script>(function(w
,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
+(w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
+e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
+})(window,document,'script','//s.swiftypecdn.com/install/v1/st.js','_st');
+
+_st('install','HaUfpXXV87xoB_zzCQ45');</script><script src="/javascripts/application-280db181.js"></script></body></html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-predictionio-site/blob/a542290d/templates/recommendation/customize-serving/index.html.gz
----------------------------------------------------------------------
diff --git a/templates/recommendation/customize-serving/index.html.gz b/templates/recommendation/customize-serving/index.html.gz
new file mode 100644
index 0000000..2f126c6
Binary files /dev/null and b/templates/recommendation/customize-serving/index.html.gz differ