http://git-wip-us.apache.org/repos/asf/incubator-predictionio-site/blob/dd18a676/templates/classification/reading-custom-properties/index.html
----------------------------------------------------------------------
diff --git a/templates/classification/reading-custom-properties/index.html 
b/templates/classification/reading-custom-properties/index.html
new file mode 100644
index 0000000..1551f72
--- /dev/null
+++ b/templates/classification/reading-custom-properties/index.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html><html><head><title>Reading Custom Properties 
(Classification)</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="Reading Custom Properties 
(Classification)"/><link rel="canonical" 
href="https://predictionio.incubator.apache.org/templates/classification/reading-custom-properties/"/><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-3a3867f7.css" 
rel="stylesheet" type="text/css"/><script 
src="//cdnjs.cloudflare.com/ajax/libs/html
 5shiv/3.7.2/html5shiv.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-b
 ar-row"><div class="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>Reading Custom Properties (Classification)</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="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="fina
 l" href="/batchpredict/"><span>Batch Predictions</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>Co
 llecting 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="/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="/algorith
 m/"><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/met
 ricbuild/"><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>PredictionIO Official 
Templates</span></a><ul><li class="level-2"><a class="final" 
href="/templates/"><span>Intro</span></a></li><li class="level-2"><a 
class="expandible" href="#"><span>Recommendation</span></a><ul><li 
class="level-3"><a class="final" 
href="/templates/recommendation/quickstart/"><span>Quick 
Start</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/dase/"><span>DASE</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/recommendation/evaluation/"><span>Evaluation 
Explained</span></a></li><
 li class="level-3"><a class="final" 
href="/templates/recommendation/how-to/"><span>How-To</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/recommendation/reading-custom-events/"><span>Read Custom 
Events</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/customize-data-prep/"><span>Customize Data 
Preparator</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/customize-serving/"><span>Customize 
Serving</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/training-with-implicit-preference/"><span>Train 
with Implicit Preference</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/blacklist-items/"><span>Filter Recommended 
Items by Blacklist in Query</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/batch-evaluator/"><span>Batch Persistable 
Evaluator</span></a></li></ul></li><li class="level-2"><a class="expan
 dible" href="#"><span>E-Commerce Recommendation</span></a><ul><li 
class="level-3"><a class="final" 
href="/templates/ecommercerecommendation/quickstart/"><span>Quick 
Start</span></a></li><li class="level-3"><a class="final" 
href="/templates/ecommercerecommendation/dase/"><span>DASE</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/ecommercerecommendation/how-to/"><span>How-To</span></a></li><li
 class="level-3"><a class="final" 
href="/templates/ecommercerecommendation/train-with-rate-event/"><span>Train 
with Rate Event</span></a></li><li class="level-3"><a class="final" 
href="/templates/ecommercerecommendation/adjust-score/"><span>Adjust 
Score</span></a></li></ul></li><li class="level-2"><a class="expandible" 
href="#"><span>Similar Product</span></a><ul><li class="level-3"><a 
class="final" href="/templates/similarproduct/quickstart/"><span>Quick 
Start</span></a></li><li class="level-3"><a class="final" 
href="/templates/similarproduct/dase/"><span>DASE</span></a></li
 ><li class="level-3"><a class="final" 
 >href="/templates/similarproduct/how-to/"><span>How-To</span></a></li><li 
 >class="level-3"><a class="final" 
 >href="/templates/similarproduct/multi-events-multi-algos/"><span>Multiple 
 >Events and Multiple Algorithms</span></a></li><li class="level-3"><a 
 >class="final" 
 >href="/templates/similarproduct/return-item-properties/"><span>Returns Item 
 >Properties</span></a></li><li class="level-3"><a class="final" 
 >href="/templates/similarproduct/train-with-rate-event/"><span>Train with Rate 
 >Event</span></a></li><li class="level-3"><a class="final" 
 >href="/templates/similarproduct/rid-user-set-event/"><span>Get Rid of Events 
 >for Users</span></a></li><li class="level-3"><a class="final" 
 >href="/templates/similarproduct/recommended-user/"><span>Recommend 
 >Users</span></a></li></ul></li><li class="level-2"><a class="expandible" 
 >href="#"><span>Classification</span></a><ul><li class="level-3"><a 
 >class="final" href="/templates/classification/quickstart/"><span>Quick Star
 t</span></a></li><li class="level-3"><a class="final" 
href="/templates/classification/dase/"><span>DASE</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/classification/how-to/"><span>How-To</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/classification/add-algorithm/"><span>Use Alternative 
Algorithm</span></a></li><li class="level-3"><a class="final active" 
href="/templates/classification/reading-custom-properties/"><span>Read Custom 
Properties</span></a></li></ul></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 cl
 ass="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="/cli/"><span>Command-line Interface</span></a></li><li class="level-2"><a 
class="final" href="/resources/release/"><span>Release 
Cadence</span></a></li><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><li 
class="level-1"><a class="expandible" href="#"><span>Apache Software 
Foundation</span></a><ul><li class="level-2"><a class="final" href="https:/
 /www.apache.org/"><span>Apache Homepage</span></a></li><li class="level-2"><a 
class="final" 
href="https://www.apache.org/licenses/";><span>License</span></a></li><li 
class="level-2"><a class="final" 
href="https://www.apache.org/foundation/sponsorship.html";><span>Sponsorship</span></a></li><li
 class="level-2"><a class="final" 
href="https://www.apache.org/foundation/thanks.html";><span>Thanks</span></a></li><li
 class="level-2"><a class="final" 
href="https://www.apache.org/security/";><span>Security</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="breadcrumbs" class="hidden-sm hidden xs"><ul><li><a 
href="#">PredictionIO Official Templates</a><span 
class="spacer">&gt;</span></li><li><a href="#">Classification</a><span 
class="spacer">&gt;</span></li><li><span class="last">Read Custom 
Properties</span></li></ul></div><div id="page-title"><h1>Reading Custom 
Properties (Classification)</h1></div></div><div id="ta
 ble-of-content-wrapper"><a id="edit-page-link" 
href="https://github.com/apache/incubator-predictionio/tree/livedoc/docs/manual/source/templates/classification/reading-custom-properties.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="breadcrumbs" 
class="hidden-sm hidden xs"><ul><li><a href="#">PredictionIO Official 
Templates</a><span class="spacer">&gt;</span></li><li><a 
href="#">Classification</a><span class="spacer">&gt;</span></li><li><span 
class="last">Read Custom Properties</span></li></ul></div><div 
id="page-title"><h1>Reading Custom Properties 
(Classification)</h1></div></div><div class="content"> <p>By default, the 
classification template reads 4 properties of a user entity: &quot;attr0&quot;, 
&quot;attr1&quot;, &quot;attr2&quot; and &quot;plan&quot;. You can modify the 
<a href="/templates/classification/dase/#data">default DataSource</a> to read 
your custom properties or different En
 tity Type.</p><p>In this example, we modify DataSource to read properties 
&quot;featureA&quot;, &quot;featureB&quot;, &quot;featureC&quot;, 
&quot;featureD&quot; and &quot;label&quot; for entity type &quot;item&quot;. 
You can find the complete modified source code <a 
href="https://github.com/apache/incubator-predictionio/tree/develop/examples/scala-parallel-classification/reading-custom-properties";>here</a>.</p>
 <blockquote> <blockquote> <p>Note: you also need import events with these 
properties accordingly.</p></blockquote> </blockquote> <p>Modify the 
<code>readTraining()</code> and <code>readEval()</code> in 
DataSource.scala:</p> <ul> <li>modify the <code>entityType</code> 
parameter</li> <li>modify the list of properties names in the 
<code>required</code> parameter</li> <li>modify how to create the 
<code>LabeledPoint</code> object using the entity properties</li> </ul> <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
+23
+24
+25
+26
+27
+28
+29
+30
+31</pre></td><td class="code"><pre>  <span class="k">def</span> <span 
class="n">readTraining</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="k">:</span> 
<span class="kt">TrainingData</span> <span class="o">=</span> <span 
class="o">{</span>
+    <span class="o">...</span>
+    <span class="k">val</span> <span class="n">labeledPoints</span><span 
class="k">:</span> <span class="kt">RDD</span><span class="o">[</span><span 
class="kt">LabeledPoint</span><span class="o">]</span> <span class="k">=</span> 
<span class="nc">PEventStore</span><span class="o">.</span><span 
class="n">aggregateProperties</span><span class="o">(</span>
+      <span class="n">appName</span> <span class="k">=</span> <span 
class="n">dsp</span><span class="o">.</span><span class="n">appName</span><span 
class="o">,</span>
+      <span class="n">entityType</span> <span class="k">=</span> <span 
class="s">"item"</span><span class="o">,</span> <span class="c1">// MODIFIED
+</span>      <span class="c1">// only keep entities with these required 
properties defined
+</span>      <span class="n">required</span> <span class="k">=</span> <span 
class="nc">Some</span><span class="o">(</span><span class="nc">List</span><span 
class="o">(</span> <span class="c1">// MODIFIED
+</span>        <span class="s">"featureA"</span><span class="o">,</span> <span 
class="s">"featureB"</span><span class="o">,</span> <span 
class="s">"featureC"</span><span class="o">,</span> <span 
class="s">"featureD"</span><span class="o">,</span> <span 
class="s">"label"</span><span class="o">)))(</span><span 
class="n">sc</span><span class="o">)</span>
+      <span class="c1">// aggregateProperties() returns RDD pair of
+</span>      <span class="c1">// entity ID and its aggregated properties
+</span>      <span class="o">.</span><span class="n">map</span> <span 
class="o">{</span> <span class="k">case</span> <span class="o">(</span><span 
class="n">entityId</span><span class="o">,</span> <span 
class="n">properties</span><span class="o">)</span> <span class="k">=&gt;</span>
+        <span class="k">try</span> <span class="o">{</span>
+          <span class="c1">// MODIFIED
+</span>          <span class="nc">LabeledPoint</span><span 
class="o">(</span><span class="n">properties</span><span 
class="o">.</span><span class="n">get</span><span class="o">[</span><span 
class="kt">Double</span><span class="o">](</span><span 
class="s">"label"</span><span class="o">),</span>
+            <span class="nc">Vectors</span><span class="o">.</span><span 
class="n">dense</span><span class="o">(</span><span 
class="nc">Array</span><span class="o">(</span>
+              <span class="n">properties</span><span class="o">.</span><span 
class="n">get</span><span class="o">[</span><span class="kt">Double</span><span 
class="o">](</span><span class="s">"featureA"</span><span class="o">),</span>
+              <span class="n">properties</span><span class="o">.</span><span 
class="n">get</span><span class="o">[</span><span class="kt">Double</span><span 
class="o">](</span><span class="s">"featureB"</span><span class="o">),</span>
+              <span class="n">properties</span><span class="o">.</span><span 
class="n">get</span><span class="o">[</span><span class="kt">Double</span><span 
class="o">](</span><span class="s">"featureC"</span><span class="o">),</span>
+              <span class="n">properties</span><span class="o">.</span><span 
class="n">get</span><span class="o">[</span><span class="kt">Double</span><span 
class="o">](</span><span class="s">"featureD"</span><span class="o">)</span>
+            <span class="o">))</span>
+          <span class="o">)</span>
+        <span class="o">}</span> <span class="k">catch</span> <span 
class="o">{</span>
+          <span class="k">case</span> <span class="n">e</span><span 
class="k">:</span> <span class="kt">Exception</span> <span 
class="o">=&gt;</span> <span class="o">{</span>
+            <span class="n">logger</span><span class="o">.</span><span 
class="n">error</span><span class="o">(</span><span class="n">s</span><span 
class="s">"Failed to get properties ${properties} of"</span> <span 
class="o">+</span>
+              <span class="n">s</span><span class="s">" ${entityId}. 
Exception: ${e}."</span><span class="o">)</span>
+            <span class="k">throw</span> <span class="n">e</span>
+          <span class="o">}</span>
+        <span class="o">}</span>
+      <span class="o">}.</span><span class="n">cache</span><span 
class="o">()</span>
+    <span class="o">...</span>
+  <span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <p>Lastly, redefine the Query class 
parameters to take in four double values: featureA, featureB, featureC, and 
featureD. Now, to send a query, the field names must be changed 
accordingly:</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">'{ "featureA":2, "featureB":0, "featureC":0, "featureD":0 }'</span> 
http://localhost:8000/queries.json
+</pre></td></tr></tbody></table> </div> <p>That&#39;s it! Now your 
classification engine is using different properties as training 
data.</p></div></div></div></div><footer><div class="container"><div 
class="seperator"></div><div class="row"><div class="col-md-6 
footer-link-column"><div 
class="footer-link-column-row"><h4>Community</h4><ul><li><a 
href="//predictionio.incubator.apache.org/install/" 
target="blank">Download</a></li><li><a 
href="//predictionio.incubator.apache.org/" target="blank">Docs</a></li><li><a 
href="//github.com/apache/incubator-predictionio" 
target="blank">GitHub</a></li><li><a 
href="mailto:[email protected]"; 
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 
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:[email protected]"; 
target="blank">Subscribe to Development Mailing 
List</a></li></ul></div></div></div><div class="row"><div class="col-md-12 
footer-link-column"><a class="pull-right" 
href="http://incubator.apache.org/projects/predictionio.html";><img alt="Apache 
Incubator" src="/images/logos/apache_incubator-6954bd16.png"/></a><span>Apache 
PredictionIO is an effort undergoing incubation at The Apache Software 
Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of 
all newly accepted projects until a further review indicates that the 
infrastructure, communications, and decision making process have stabilized in 
a manner consistent with other successful ASF projects. While incubation sta
 tus is not necessarily a reflection of the completeness or stability of the 
code, it does indicate that the project has yet to be fully endorsed by the 
ASF.</span></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#fork
 s_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="https://twitter.com/predictionio"; target="blank"><img alt="PredictionIO 
on Twitter" src="/images/icons/twitter-ea9dc152.png"/></a> <a 
href="https://www.facebook.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-a6acb1f5.js"></script></body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-site/blob/dd18a676/templates/classification/reading-custom-properties/index.html.gz
----------------------------------------------------------------------
diff --git a/templates/classification/reading-custom-properties/index.html.gz 
b/templates/classification/reading-custom-properties/index.html.gz
new file mode 100644
index 0000000..2be724a
Binary files /dev/null and 
b/templates/classification/reading-custom-properties/index.html.gz differ

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-site/blob/dd18a676/templates/complementarypurchase/dase/index.html
----------------------------------------------------------------------
diff --git a/templates/complementarypurchase/dase/index.html 
b/templates/complementarypurchase/dase/index.html
new file mode 100644
index 0000000..14008fe
--- /dev/null
+++ b/templates/complementarypurchase/dase/index.html
@@ -0,0 +1,416 @@
+<!DOCTYPE html><html><head><title>DASE Components Explained (Complementary 
Purchase)</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="DASE Components Explained 
(Complementary Purchase)"/><link rel="canonical" 
href="https://predictionio.incubator.apache.org/templates/complementarypurchase/dase/"/><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-3a3867f7.css" 
rel="stylesheet" type="text/css"/><script 
src="//cdnjs.cloudflare.com/ajax/libs/ht
 ml5shiv/3.7.2/html5shiv.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 class="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>DASE Components Explained (Complementary Purchase)</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="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 c
 lass="final" href="/batchpredict/"><span>Batch Predictions</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="/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" 
href="/evaluation/metricchoose/"><span>Choosing Evaluation 
Metrics</span></a></li><li class="level-2"><a class="final" href="/eval
 uation/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>PredictionIO Official 
Templates</span></a><ul><li class="level-2"><a class="final" 
href="/templates/"><span>Intro</span></a></li><li class="level-2"><a 
class="expandible" href="#"><span>Recommendation</span></a><ul><li 
class="level-3"><a class="final" 
href="/templates/recommendation/quickstart/"><span>Quick 
Start</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/dase/"><span>DASE</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/recommendation/evaluation/"><span>Evaluation Explained</span>
 </a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/how-to/"><span>How-To</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/recommendation/reading-custom-events/"><span>Read Custom 
Events</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/customize-data-prep/"><span>Customize Data 
Preparator</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/customize-serving/"><span>Customize 
Serving</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/training-with-implicit-preference/"><span>Train 
with Implicit Preference</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/blacklist-items/"><span>Filter Recommended 
Items by Blacklist in Query</span></a></li><li class="level-3"><a class="final" 
href="/templates/recommendation/batch-evaluator/"><span>Batch Persistable 
Evaluator</span></a></li></ul></li><li class="level-2"><a cl
 ass="expandible" href="#"><span>E-Commerce Recommendation</span></a><ul><li 
class="level-3"><a class="final" 
href="/templates/ecommercerecommendation/quickstart/"><span>Quick 
Start</span></a></li><li class="level-3"><a class="final" 
href="/templates/ecommercerecommendation/dase/"><span>DASE</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/ecommercerecommendation/how-to/"><span>How-To</span></a></li><li
 class="level-3"><a class="final" 
href="/templates/ecommercerecommendation/train-with-rate-event/"><span>Train 
with Rate Event</span></a></li><li class="level-3"><a class="final" 
href="/templates/ecommercerecommendation/adjust-score/"><span>Adjust 
Score</span></a></li></ul></li><li class="level-2"><a class="expandible" 
href="#"><span>Similar Product</span></a><ul><li class="level-3"><a 
class="final" href="/templates/similarproduct/quickstart/"><span>Quick 
Start</span></a></li><li class="level-3"><a class="final" 
href="/templates/similarproduct/dase/"><span>DASE</spa
 n></a></li><li class="level-3"><a class="final" 
href="/templates/similarproduct/how-to/"><span>How-To</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/similarproduct/multi-events-multi-algos/"><span>Multiple 
Events and Multiple Algorithms</span></a></li><li class="level-3"><a 
class="final" 
href="/templates/similarproduct/return-item-properties/"><span>Returns Item 
Properties</span></a></li><li class="level-3"><a class="final" 
href="/templates/similarproduct/train-with-rate-event/"><span>Train with Rate 
Event</span></a></li><li class="level-3"><a class="final" 
href="/templates/similarproduct/rid-user-set-event/"><span>Get Rid of Events 
for Users</span></a></li><li class="level-3"><a class="final" 
href="/templates/similarproduct/recommended-user/"><span>Recommend 
Users</span></a></li></ul></li><li class="level-2"><a class="expandible" 
href="#"><span>Classification</span></a><ul><li class="level-3"><a 
class="final" href="/templates/classification/quickstart/"><span>
 Quick Start</span></a></li><li class="level-3"><a class="final" 
href="/templates/classification/dase/"><span>DASE</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/classification/how-to/"><span>How-To</span></a></li><li 
class="level-3"><a class="final" 
href="/templates/classification/add-algorithm/"><span>Use Alternative 
Algorithm</span></a></li><li class="level-3"><a class="final" 
href="/templates/classification/reading-custom-properties/"><span>Read Custom 
Properties</span></a></li></ul></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/taps
 ter/"><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="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="/cli/"><span>Command-line Interface</span></a></li><li class="level-2"><a 
class="final" href="/resources/release/"><span>Release 
Cadence</span></a></li><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><li 
class="level-1"><a class="expandible" href="#"><span>Apache Software 
Foundation</span></a><ul><li class="level-2"><a class="final" href="http
 s://www.apache.org/"><span>Apache Homepage</span></a></li><li 
class="level-2"><a class="final" 
href="https://www.apache.org/licenses/";><span>License</span></a></li><li 
class="level-2"><a class="final" 
href="https://www.apache.org/foundation/sponsorship.html";><span>Sponsorship</span></a></li><li
 class="level-2"><a class="final" 
href="https://www.apache.org/foundation/thanks.html";><span>Thanks</span></a></li><li
 class="level-2"><a class="final" 
href="https://www.apache.org/security/";><span>Security</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>DASE Components Explained (Complementary 
Purchase)</h1></div></div><div id="table-of-content-wrapper"><h5>On this 
page</h5><aside id="table-of-contents"><ul> <li> <a 
href="#the-engine-design">The Engine Design</a> </li> <li> <a 
href="#data">Data</a> </li> <li> <a href="#algorithm">Algorithm</a> </li> <li> 
<a href="#serving">Serving</a> </li> </ul
 > </aside><hr/><a id="edit-page-link" 
 > href="https://github.com/apache/incubator-predictionio/tree/livedoc/docs/manual/source/templates/complementarypurchase/dase.html.md.erb";><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>DASE 
 > Components Explained (Complementary Purchase)</h1></div></div><div 
 > class="content"> <p>PredictionIO&#39;s DASE architecture brings the 
 > separation-of-concerns design principle to predictive engine development. 
 > DASE stands for the following components of an engine:</p> <ul> 
 > <li><strong>D</strong>ata - includes Data Source and Data Preparator</li> 
 > <li><strong>A</strong>lgorithm(s)</li> <li><strong>S</strong>erving</li> 
 > <li><strong>E</strong>valuator</li> </ul> <p><p>Let&#39;s look at the code 
 > and see how you can customize the engine you built from the Complementary 
 > Purchase Engine Template.</p><div class="alert-message note"><p>Evaluator 
 > will not be covered in thi
 s tutorial.</p></div></p><h2 id='the-engine-design' class='header-anchors'>The 
Engine Design</h2><p>As you can see from the Quick Start, 
<em>MyComplementaryPurchase</em> takes a JSON prediction query, e.g. <code>{ 
&quot;items&quot; : [&quot;s2i1&quot;], &quot;num&quot; : 3 }</code>, and 
return a JSON predicted result. In 
MyComplementaryPurchase/src/main/scala/<strong><em>Engine.scala</em></strong>, 
the <code>Query</code> case class defines the format of such 
<strong>query</strong>:</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</pre></td><td class="code"><pre><span class="k">case</span> <span 
class="k">class</span> <span class="nc">Query</span><span 
class="o">(</span><span class="n">items</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="n">num</span><span class="k">:</span> <span class="kt">Int</span><span 
class="o">)</span>
+  <span class="k">extends</span> <span class="nc">Serializable</span>
+</pre></td></tr></tbody></table> </div> <p>The <code>PredictedResult</code> 
case class defines the format of <strong>predicted result</strong>, such 
as</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
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21</pre></td><td class="code"><pre><span class="p">{</span><span class="w">
+  </span><span class="s2">"rules"</span><span class="p">:[</span><span 
class="w">
+    </span><span class="p">{</span><span class="w">
+      </span><span class="s2">"cond"</span><span class="p">:[</span><span 
class="s2">"s2i1"</span><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="s2">"item"</span><span class="p">:</span><span 
class="s2">"s2i2"</span><span class="p">,</span><span class="w">
+          </span><span class="s2">"support"</span><span 
class="p">:</span><span class="mf">0.2</span><span class="p">,</span><span 
class="w">
+          </span><span class="s2">"confidence"</span><span 
class="p">:</span><span class="mf">0.9090909090909091</span><span 
class="p">,</span><span class="w">
+          </span><span class="s2">"lift"</span><span class="p">:</span><span 
class="mf">3.787878787878788</span><span class="w">
+        </span><span class="p">},</span><span class="w">
+        </span><span class="p">{</span><span class="w">
+          </span><span class="s2">"item"</span><span class="p">:</span><span 
class="s2">"s2i3"</span><span class="p">,</span><span class="w">
+          </span><span class="s2">"support"</span><span 
class="p">:</span><span class="mf">0.14</span><span class="p">,</span><span 
class="w">
+          </span><span class="s2">"confidence"</span><span 
class="p">:</span><span class="mf">0.6363636363636364</span><span 
class="p">,</span><span class="w">
+          </span><span class="s2">"lift"</span><span class="p">:</span><span 
class="mf">3.535353535353535</span><span class="w">
+        </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><span class="p">]</span><span class="w">
+</span><span class="p">}</span><span class="w">
+</span></pre></td></tr></tbody></table> </div> <p>with:</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</pre></td><td class="code"><pre><span class="k">case</span> <span 
class="k">class</span> <span class="nc">PredictedResult</span><span 
class="o">(</span><span class="n">rules</span><span class="k">:</span> <span 
class="kt">Array</span><span class="o">[</span><span 
class="kt">Rule</span><span class="o">])</span>
+  <span class="k">extends</span> <span class="nc">Serializable</span>
+
+<span class="k">case</span> <span class="k">class</span> <span 
class="nc">Rule</span><span class="o">(</span><span class="n">cond</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="n">itemScores</span><span class="k">:</span> <span 
class="kt">Array</span><span class="o">[</span><span 
class="kt">ItemScore</span><span class="o">])</span>
+  <span class="k">extends</span> <span class="nc">Serializable</span>
+
+<span class="k">case</span> <span class="k">class</span> <span 
class="nc">ItemScore</span><span class="o">(</span>
+  <span class="n">item</span><span class="k">:</span> <span 
class="kt">String</span><span class="o">,</span> <span 
class="n">support</span><span class="k">:</span> <span 
class="kt">Double</span><span class="o">,</span> <span 
class="n">confidence</span><span class="k">:</span> <span 
class="kt">Double</span><span class="o">,</span> <span 
class="n">lift</span><span class="k">:</span> <span class="kt">Double</span>
+<span class="o">)</span> <span class="k">extends</span> <span 
class="nc">Serializable</span>
+</pre></td></tr></tbody></table> </div> <p>Finally, 
<code>ComplementaryPurchaseEngine</code> is the <em>Engine Factory</em> that 
defines the components this engine will use: Data Source, Data Preparator, 
Algorithm(s) and Serving components.</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</pre></td><td class="code"><pre><span class="k">object</span> <span 
class="nc">ComplementaryPurchaseEngine</span> <span class="k">extends</span> 
<span class="nc">IEngineFactory</span> <span class="o">{</span>
+  <span class="k">def</span> <span class="n">apply</span><span 
class="o">()</span> <span class="k">=</span> <span class="o">{</span>
+    <span class="k">new</span> <span class="nc">Engine</span><span 
class="o">(</span>
+      <span class="n">classOf</span><span class="o">[</span><span 
class="kt">DataSource</span><span class="o">],</span>
+      <span class="n">classOf</span><span class="o">[</span><span 
class="kt">Preparator</span><span class="o">],</span>
+      <span class="nc">Map</span><span class="o">(</span><span 
class="s">"algo"</span> <span class="o">-&gt;</span> <span 
class="n">classOf</span><span class="o">[</span><span 
class="kt">Algorithm</span><span class="o">]),</span>
+      <span class="n">classOf</span><span class="o">[</span><span 
class="kt">Serving</span><span class="o">])</span>
+  <span class="o">}</span>
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <p>Each DASE component of the 
<code>ComplementaryPurchaseEngine</code> will be explained below.</p><h2 
id='data' class='header-anchors'>Data</h2><p>In the DASE architecture, data is 
prepared by 2 components sequentially: <em>DataSource</em> and 
<em>DataPreparator</em>. They take data from the data store and prepare them 
for Algorithm.</p><h3 id='data-source' class='header-anchors'>Data 
Source</h3><p>In 
MyComplementaryPurchase/src/main/scala/<strong><em>DataSource.scala</em></strong>,
 the <code>readTraining</code> method of class <code>DataSource</code> reads 
and selects data from the <em>Event Store</em> (data store of the <em>Event 
Server</em>). It returns <code>TrainingData</code>.</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
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35</pre></td><td class="code"><pre><span class="k">case</span> <span 
class="k">class</span> <span class="nc">DataSourceParams</span><span 
class="o">(</span><span class="n">appName</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">DataSource</span><span 
class="o">(</span><span class="k">val</span> <span class="n">dsp</span><span 
class="k">:</span> <span class="kt">DataSourceParams</span><span 
class="o">)</span>
+  <span class="k">extends</span> <span class="nc">PDataSource</span><span 
class="o">[</span><span class="kt">TrainingData</span>,
+      <span class="kt">EmptyEvaluationInfo</span>, <span 
class="kt">Query</span>, <span class="kt">EmptyActualResult</span><span 
class="o">]</span> <span class="o">{</span>
+
+  <span class="nd">@transient</span> <span class="k">lazy</span> <span 
class="k">val</span> <span class="n">logger</span> <span class="k">=</span> 
<span class="nc">Logger</span><span class="o">[</span><span 
class="kt">this.</span><span class="k">type</span><span class="o">]</span>
+
+  <span class="k">override</span>
+  <span class="k">def</span> <span class="n">readTraining</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="k">:</span> 
<span class="kt">TrainingData</span> <span class="o">=</span> <span 
class="o">{</span>
+
+    <span class="c1">// get all "user" "buy" "item" events
+</span>    <span class="k">val</span> <span class="n">buyEvents</span><span 
class="k">:</span> <span class="kt">RDD</span><span class="o">[</span><span 
class="kt">BuyEvent</span><span class="o">]</span> <span class="k">=</span> 
<span class="nc">PEventStore</span><span class="o">.</span><span 
class="n">find</span><span class="o">(</span>
+      <span class="n">appName</span> <span class="k">=</span> <span 
class="n">dsp</span><span class="o">.</span><span class="n">appName</span><span 
class="o">,</span>
+      <span class="n">entityType</span> <span class="k">=</span> <span 
class="nc">Some</span><span class="o">(</span><span 
class="s">"user"</span><span class="o">),</span>
+      <span class="n">eventNames</span> <span class="k">=</span> <span 
class="nc">Some</span><span class="o">(</span><span class="nc">List</span><span 
class="o">(</span><span class="s">"buy"</span><span class="o">)),</span>
+      <span class="n">targetEntityType</span> <span class="k">=</span> <span 
class="nc">Some</span><span class="o">(</span><span class="nc">Some</span><span 
class="o">(</span><span class="s">"item"</span><span class="o">)))(</span><span 
class="n">sc</span><span class="o">)</span>
+      <span class="o">.</span><span class="n">map</span> <span 
class="o">{</span> <span class="n">event</span> <span class="k">=&gt;</span>
+        <span class="k">try</span> <span class="o">{</span>
+          <span class="k">new</span> <span class="nc">BuyEvent</span><span 
class="o">(</span>
+            <span class="n">user</span> <span class="k">=</span> <span 
class="n">event</span><span class="o">.</span><span 
class="n">entityId</span><span class="o">,</span>
+            <span class="n">item</span> <span class="k">=</span> <span 
class="n">event</span><span class="o">.</span><span 
class="n">targetEntityId</span><span class="o">.</span><span 
class="n">get</span><span class="o">,</span>
+            <span class="n">t</span> <span class="k">=</span> <span 
class="n">event</span><span class="o">.</span><span 
class="n">eventTime</span><span class="o">.</span><span 
class="n">getMillis</span>
+          <span class="o">)</span>
+        <span class="o">}</span> <span class="k">catch</span> <span 
class="o">{</span>
+          <span class="k">case</span> <span class="n">e</span><span 
class="k">:</span> <span class="kt">Exception</span> <span 
class="o">=&gt;</span> <span class="o">{</span>
+            <span class="n">logger</span><span class="o">.</span><span 
class="n">error</span><span class="o">(</span><span class="n">s</span><span 
class="s">"Cannot convert ${event} to BuyEvent. ${e}"</span><span 
class="o">)</span>
+            <span class="k">throw</span> <span class="n">e</span>
+          <span class="o">}</span>
+        <span class="o">}</span>
+      <span class="o">}.</span><span class="n">cache</span><span 
class="o">()</span>
+
+    <span class="k">new</span> <span class="nc">TrainingData</span><span 
class="o">(</span><span class="n">buyEvents</span><span class="o">)</span>
+  <span class="o">}</span>
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <p>PredictionIO automatically loads 
the parameters of <em>datasource</em> specified in 
MyComplementaryPurchase/<strong><em>engine.json</em></strong>, including 
<em>appName</em>, to <code>dsp</code>.</p><p>In 
<strong><em>engine.json</em></strong>:</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
+8
+9</pre></td><td class="code"><pre><span class="o">{</span>
+  ...
+  <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">"MyApp1"</span>
+    <span class="o">}</span>
+  <span class="o">}</span>,
+  ...
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <p>In <code>readTraining()</code>, 
<code>PEventStore</code> is an object which provides function to access data 
that is collected by PredictionIO Event Server.</p><p>This Complementary 
Purchase Engine Template requires &quot;buy&quot; 
events.</p><p><code>PEventStore.find(...)</code> specifies the events that you 
want to read. In this case, &quot;user buy item&quot; events are read and then 
each is mapped to a <code>BuyEvent</code> object.</p><p><code>BuyEvent</code> 
case class is defined as:</p><div class="highlight scala"><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="k">case</span> <span class="k">class</span> <span 
class="nc">BuyEvent</span><span class="o">(</span><span 
class="n">user</span><span class="k">:</span> <span 
class="kt">String</span><span class="o">,</span> <span 
class="n">item</span><span class="k">:</span> <span clas
 s="kt">String</span><span class="o">,</span> <span class="n">t</span><span 
class="k">:</span> <span class="kt">Long</span><span class="o">)</span>
+</pre></td></tr></tbody></table> </div> <p><code>TrainingData</code> contains 
an RDD of <code>BuyEvent</code> objects. The class definition of 
<code>TrainingData</code> is:</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</pre></td><td class="code"><pre><span class="k">class</span> <span 
class="nc">TrainingData</span><span class="o">(</span>
+  <span class="k">val</span> <span class="n">buyEvents</span><span 
class="k">:</span> <span class="kt">RDD</span><span class="o">[</span><span 
class="kt">BuyEvent</span><span class="o">]</span>
+<span class="o">)</span> <span class="k">extends</span> <span 
class="nc">Serializable</span> <span class="o">{</span> <span 
class="o">...</span> <span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <p>PredictionIO then passes the 
returned <code>TrainingData</code> object to <em>Data Preparator</em>.</p><div 
class="alert-message note"><p>You could modify the DataSource to read other 
event other than the default <strong>buy</strong>.</p></div><h3 
id='data-preparator' class='header-anchors'>Data Preparator</h3><p>In 
MyComplementaryPurchase/src/main/scala/<strong><em>Preparator.scala</em></strong>,
 the <code>prepare</code> method of class <code>Preparator</code> takes 
<code>TrainingData</code> as its input and performs any necessary feature 
selection and data processing tasks. At the end, it returns 
<code>PreparedData</code> which should contain the data <em>Algorithm</em> 
needs.</p><p>By default, <code>prepare</code> simply copies the unprocessed 
<code>TrainingData</code> data to <code>PreparedData</code>:</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</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="nd">@transient</span> <span class="k">lazy</span> <span 
class="k">val</span> <span class="n">logger</span> <span class="k">=</span> 
<span class="nc">Logger</span><span class="o">[</span><span 
class="kt">this.</span><span class="k">type</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">td</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">buyEvents</span> <span class="k">=</span> 
<span class="n">td</span><span class="o">.</span><span 
class="n">buyEvents</span><span class="o">)</span>
+  <span class="o">}</span>
+<span class="o">}</span>
+
+<span class="k">class</span> <span class="nc">PreparedData</span><span 
class="o">(</span>
+  <span class="k">val</span> <span class="n">buyEvents</span><span 
class="k">:</span> <span class="kt">RDD</span><span class="o">[</span><span 
class="kt">BuyEvent</span><span class="o">]</span>
+<span class="o">)</span> <span class="k">extends</span> <span 
class="nc">Serializable</span>
+</pre></td></tr></tbody></table> </div> <p>PredictionIO passes the returned 
<code>PreparedData</code> object to Algorithm&#39;s <code>train</code> 
function.</p><h2 id='algorithm' class='header-anchors'>Algorithm</h2><p>In 
MyComplementaryPurchase/src/main/scala/<strong><em>ALSAlgorithm.scala</em></strong>,
 the two methods of the algorithm class are <code>train</code> and 
<code>predict</code>. <code>train</code> is responsible for training the 
predictive model; <code>predict</code> is responsible for using this model to 
make prediction.</p><p>The default algorithm is based on concept of <a 
href="http://en.wikipedia.org/wiki/Association_rule_learning";>Association Rule 
Learning</a> to find interesting association rules (A implies B) that indicates 
additional item (B) may be bought together given a list of items (A). A is the 
<em>condition</em> and B is the <em>consequence</em>.</p><h3 
id='algorithm-parameters' class='header-anchors'>Algorithm 
parameters</h3><p>The Algorithm takes the fo
 llowing parameters, as defined by the <code>AlgorithmParams</code> case 
class:</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</pre></td><td class="code"><pre><span class="k">case</span> <span 
class="k">class</span> <span class="nc">AlgorithmParams</span><span 
class="o">(</span>
+  <span class="n">basketWindow</span><span class="k">:</span> <span 
class="kt">Int</span><span class="o">,</span> <span class="c1">// in seconds
+</span>  <span class="n">maxRuleLength</span><span class="k">:</span> <span 
class="kt">Int</span><span class="o">,</span>
+  <span class="n">minSupport</span><span class="k">:</span> <span 
class="kt">Double</span><span class="o">,</span>
+  <span class="n">minConfidence</span><span class="k">:</span> <span 
class="kt">Double</span><span class="o">,</span>
+  <span class="n">minLift</span><span class="k">:</span> <span 
class="kt">Double</span><span class="o">,</span>
+  <span class="n">minBasketSize</span><span class="k">:</span> <span 
class="kt">Int</span><span class="o">,</span>
+  <span class="n">maxNumRulesPerCond</span><span class="k">:</span> <span 
class="kt">Int</span> <span class="c1">// max number of rules per condition
+</span>  <span class="o">)</span> <span class="k">extends</span> <span 
class="nc">Params</span>
+
+</pre></td></tr></tbody></table> </div> <p>Parameter description:</p> <ul> 
<li><strong>basketWindow</strong>: The buy event is considered as the same 
basket as previous one if the time difference is within this window (in unit of 
seconds). For example, if it&#39;s set to 120, it means that if the user buys 
item B within 2 minutes of previous purchase (item A), then the item set [A, B] 
is considered as the same basket. The purchase of this <em>basket</em> is 
referred as one <em>transaction</em>.</li> <li><strong>maxRuleLength</strong>: 
The maximum length of the association rule length. Must be at least 2. For 
example, rule of &quot;A implies B&quot; has length of 2 while rule &quot;A, B 
implies C&quot; has a length of 3. Increasing this number will incrase the 
training time significantly because more combinations are considered.</li> 
<li><strong>minSupport</strong>: The minimum required <em>support</em> for the 
item set to be considered as rule (valid range is 0 to 1). It&#39;s the p
 ercentage of the item set appearing among all transcations. This is used to 
filter out infrequent item set. For example, setting to 0.1 means that the item 
set must appear in 10 % of all transactions.</li> 
<li><strong>minConfidence</strong>: The minimum <em>confidence</em> required 
for the rules (valid range is 0 to 1). The confidence indicates the probability 
of the condition and conseuquence appear in the same transaction. For example, 
if A appears in 30 transactions and the item set [A, B] appears in 20 
transactions, then the rule &quot;A implies B&quot; has confidence of 
0.66.</li> <li><strong>minLift</strong>: The minimum <em>lift</em> required for 
the rule. It should be set to 1 to find high quality rule. It&#39;s the 
confidence of the rule divided by the support of the consequence. It is used to 
filter out rules that the consequence is very frequent anyway regardless of the 
condition.</li> <li><strong>minBasketSize</strong>: The minimum number of items 
in basket to be conside
 red by algorithm. This value must be at least 2.</li> 
<li><strong>maxNumRulesPerCond</strong>: Maximum number of rules generated per 
condition and stored in the model. By default, the top rules are sorted by 
<em>lift</em> score.</li> </ul> <div class="alert-message info"><p>If you 
import your own data and the engine doesn&#39;t return any results, it could be 
caused by the following reasons: (1) the algorithm parameter constraint is too 
high and the algo couldn&#39;t find rules that satisfy the condition. you could 
try setting the following param to 0: <strong>minSupport</strong>, 
<strong>minConfidence</strong>, <strong>minLift</strong> and then see if 
anything returned (regardless of recommendation quality), and then adjust the 
parameter accordingly. (2) the complementary purchase engine requires buy event 
with correct eventTime. If you import data without specifying eventTime, the 
SDK will use current time because it assumes the event happens in real time 
(which is not the case if
  you import as batch offline), resulting in that all buy events are treated as 
one big transcation while they should be treated as multiple 
transcations.</p></div><p>The values of these parameters can be specified in 
<em>algorithms</em> of 
MyComplementaryPurchase/<strong><em>engine.json</em></strong>:</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
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18</pre></td><td class="code"><pre><span class="o">{</span>
+  ...
+  <span class="s2">"algorithms"</span>: <span class="o">[</span>
+    <span class="o">{</span>
+      <span class="s2">"name"</span>: <span class="s2">"algo"</span>,
+      <span class="s2">"params"</span>: <span class="o">{</span>
+        <span class="s2">"basketWindow"</span> : 120,
+        <span class="s2">"maxRuleLength"</span> : 2,
+        <span class="s2">"minSupport"</span>: 0.1,
+        <span class="s2">"minConfidence"</span>: 0.6,
+        <span class="s2">"minLift"</span> : 1.0,
+        <span class="s2">"minBasketSize"</span> : 2,
+        <span class="s2">"maxNumRulesPerCond"</span>: 5
+      <span class="o">}</span>
+    <span class="o">}</span>
+  <span class="o">]</span>
+  ...
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <p>PredictionIO will automatically 
loads these values into the constructor of the <code>Algorithm</code> 
class.</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</pre></td><td class="code"><pre><span class="k">class</span> <span 
class="nc">Algorithm</span><span class="o">(</span><span class="k">val</span> 
<span class="n">ap</span><span class="k">:</span> <span 
class="kt">AlgorithmParams</span><span class="o">)</span>
+  <span class="k">extends</span> <span class="n">P2LAlgorithm</span><span 
class="o">[</span><span class="kt">PreparedData</span>, <span 
class="kt">Model</span>, <span class="kt">Query</span>, <span 
class="kt">PredictedResult</span><span class="o">]</span> <span 
class="o">{</span>
+    <span class="o">...</span>
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <h3 id='train(...)' 
class='header-anchors'>train(...)</h3><p><code>train</code> is called when you 
run <strong>pio train</strong> to train a predictive model. The algorithm first 
find all basket transcations, generates and filters the association rules based 
on the algorithm parameters:</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
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38</pre></td><td class="code"><pre>
+  <span class="k">def</span> <span class="n">train</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">pd</span><span class="k">:</span> <span 
class="kt">PreparedData</span><span class="o">)</span><span class="k">:</span> 
<span class="kt">Model</span> <span class="o">=</span> <span class="o">{</span>
+    <span class="k">val</span> <span class="n">windowMillis</span> <span 
class="k">=</span> <span class="n">ap</span><span class="o">.</span><span 
class="n">basketWindow</span> <span class="o">*</span> <span 
class="mi">1000</span>
+
+    <span class="o">...</span>
+
+    <span class="k">val</span> <span class="n">transactions</span><span 
class="k">:</span> <span class="kt">RDD</span><span class="o">[</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="o">...</span>
+
+    <span class="k">val</span> <span class="n">totalTransaction</span> <span 
class="k">=</span> <span class="n">transactions</span><span 
class="o">.</span><span class="n">count</span><span class="o">()</span>
+    <span class="k">val</span> <span class="n">minSupportCount</span> <span 
class="k">=</span> <span class="n">ap</span><span class="o">.</span><span 
class="n">minSupport</span> <span class="o">*</span> <span 
class="n">totalTransaction</span>
+
+    <span class="o">...</span>
+
+    <span class="c1">// generate item sets
+</span>    <span class="k">val</span> <span class="n">itemSets</span><span 
class="k">:</span> <span class="kt">RDD</span><span class="o">[</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="n">transactions</span>
+      <span class="o">.</span><span class="n">flatMap</span> <span 
class="o">{</span> <span class="n">tran</span> <span class="k">=&gt;</span>
+        <span class="o">(</span><span class="mi">1</span> <span 
class="n">to</span> <span class="n">ap</span><span class="o">.</span><span 
class="n">maxRuleLength</span><span class="o">).</span><span 
class="n">flatMap</span><span class="o">(</span><span class="n">n</span> <span 
class="k">=&gt;</span> <span class="n">tran</span><span class="o">.</span><span 
class="n">subsets</span><span class="o">(</span><span class="n">n</span><span 
class="o">))</span>
+      <span class="o">}</span>
+
+    <span class="o">...</span>
+
+    <span class="k">val</span> <span class="n">itemSetCount</span><span 
class="k">:</span> <span class="kt">RDD</span><span class="o">[(</span><span 
class="kt">Set</span><span class="o">[</span><span 
class="kt">String</span><span class="o">]</span>, <span 
class="kt">Int</span><span class="o">)]</span> <span class="k">=</span> <span 
class="o">...</span>
+
+    <span class="o">...</span>
+
+    <span class="k">val</span> <span class="n">rules</span><span 
class="k">:</span> <span class="kt">RDD</span><span class="o">[(</span><span 
class="kt">Set</span><span class="o">[</span><span 
class="kt">String</span><span class="o">]</span>, <span 
class="kt">RuleScore</span><span class="o">)]</span> <span class="k">=</span> 
<span class="o">...</span>
+
+    <span class="k">val</span> <span class="n">sortedRules</span> <span 
class="k">=</span> <span class="n">rules</span><span class="o">.</span><span 
class="n">groupByKey</span>
+      <span class="o">.</span><span class="n">mapValues</span><span 
class="o">(</span><span class="n">iter</span> <span class="k">=&gt;</span>
+        <span class="n">iter</span><span class="o">.</span><span 
class="n">toVector</span>
+          <span class="o">.</span><span class="n">sortBy</span><span 
class="o">(</span><span class="k">_</span><span class="o">.</span><span 
class="n">lift</span><span class="o">)(</span><span 
class="nc">Ordering</span><span class="o">.</span><span 
class="nc">Double</span><span class="o">.</span><span 
class="n">reverse</span><span class="o">)</span>
+          <span class="o">.</span><span class="n">take</span><span 
class="o">(</span><span class="n">ap</span><span class="o">.</span><span 
class="n">maxNumRulesPerCond</span><span class="o">)</span>
+        <span class="o">)</span>
+      <span class="o">.</span><span class="n">collectAsMap</span><span 
class="o">.</span><span class="n">toMap</span>
+
+    <span class="k">new</span> <span class="nc">Model</span><span 
class="o">(</span><span class="n">sortedRules</span><span class="o">)</span>
+  <span class="o">}</span>
+
+</pre></td></tr></tbody></table> </div> <p>PredictionIO will automatically 
store the returned model after training, i.e. the <code>Model</code> 
object.</p><p>The <code>Model</code> stores the top rules for each 
condition:</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</pre></td><td class="code"><pre><span class="k">class</span> <span 
class="nc">Model</span><span class="o">(</span>
+  <span class="k">val</span> <span class="n">rules</span><span 
class="k">:</span> <span class="kt">Map</span><span class="o">[</span><span 
class="kt">Set</span><span class="o">[</span><span 
class="kt">String</span><span class="o">]</span>, <span 
class="kt">Vector</span><span class="o">[</span><span 
class="kt">RuleScore</span><span class="o">]]</span>
+<span class="o">)</span> <span class="k">extends</span> <span 
class="nc">Serializable</span> <span class="o">{</span>
+  <span class="o">...</span>
+<span class="o">}</span>
+</pre></td></tr></tbody></table> </div> <h3 id='predict(...)' 
class='header-anchors'>predict(...)</h3><p><code>predict</code> is called when 
you send a JSON query to <a 
href="http://localhost:8000/queries.json";>http://localhost:8000/queries.json</a>.
 PredictionIO converts the query, such as <code>{ &quot;items&quot; : 
[&quot;s2i1&quot;], &quot;num&quot; : 3 }</code> to the <code>Query</code> 
class you defined previously in <code>Engine.scala</code>.</p><p>The 
<code>predict()</code> function does the following:</p> <ol> <li>find all 
possible subset of the items in query</li> <li>use the subsets as condition to 
look up the model and return the rules for each condition.</li> </ol> <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
+23
+24
+25</pre></td><td class="code"><pre>
+  <span class="o">...</span>
+
+  <span class="k">def</span> <span class="n">predict</span><span 
class="o">(</span><span class="n">model</span><span class="k">:</span> <span 
class="kt">Model</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="k">:</span> <span 
class="kt">PredictedResult</span> <span class="o">=</span> <span 
class="o">{</span>
+    <span class="k">val</span> <span class="n">conds</span> <span 
class="k">=</span> <span class="o">(</span><span class="mi">1</span> <span 
class="n">to</span> <span class="n">maxCondLength</span><span 
class="o">).</span><span class="n">flatMap</span><span class="o">(</span><span 
class="n">n</span> <span class="k">=&gt;</span> <span 
class="n">query</span><span class="o">.</span><span class="n">items</span><span 
class="o">.</span><span class="n">subsets</span><span class="o">(</span><span 
class="n">n</span><span class="o">))</span>
+
+    <span class="k">val</span> <span class="n">rules</span> <span 
class="k">=</span> <span class="n">conds</span><span class="o">.</span><span 
class="n">map</span> <span class="o">{</span> <span class="n">cond</span> <span 
class="k">=&gt;</span>
+      <span class="n">model</span><span class="o">.</span><span 
class="n">rules</span><span class="o">.</span><span class="n">get</span><span 
class="o">(</span><span class="n">cond</span><span class="o">).</span><span 
class="n">map</span><span class="o">{</span> <span class="n">vec</span> <span 
class="k">=&gt;</span>
+        <span class="k">val</span> <span class="n">itemScores</span> <span 
class="k">=</span> <span class="n">vec</span><span class="o">.</span><span 
class="n">take</span><span class="o">(</span><span class="n">query</span><span 
class="o">.</span><span class="n">num</span><span class="o">).</span><span 
class="n">map</span> <span class="o">{</span> <span class="n">rs</span> <span 
class="k">=&gt;</span>
+          <span class="k">new</span> <span class="nc">ItemScore</span><span 
class="o">(</span>
+            <span class="n">item</span> <span class="k">=</span> <span 
class="n">rs</span><span class="o">.</span><span class="n">conseq</span><span 
class="o">,</span>
+            <span class="n">support</span> <span class="k">=</span> <span 
class="n">rs</span><span class="o">.</span><span class="n">support</span><span 
class="o">,</span>
+            <span class="n">confidence</span> <span class="k">=</span> <span 
class="n">rs</span><span class="o">.</span><span 
class="n">confidence</span><span class="o">,</span>
+            <span class="n">lift</span> <span class="k">=</span> <span 
class="n">rs</span><span class="o">.</span><span class="n">lift</span>
+          <span class="o">)</span>
+        <span class="o">}.</span><span class="n">toArray</span>
+        <span class="nc">Rule</span><span class="o">(</span><span 
class="n">cond</span> <span class="k">=</span> <span class="n">cond</span><span 
class="o">,</span> <span class="n">itemScores</span> <span class="k">=</span> 
<span class="n">itemScores</span><span class="o">)</span>
+      <span class="o">}</span>
+    <span class="o">}.</span><span class="n">flatten</span><span 
class="o">.</span><span class="n">toArray</span>
+
+    <span class="k">new</span> <span class="nc">PredictedResult</span><span 
class="o">(</span><span class="n">rules</span><span class="o">)</span>
+  <span class="o">}</span>
+
+  <span class="o">...</span>
+
+</pre></td></tr></tbody></table> </div> <p>PredictionIO passes the returned 
<code>PredictedResult</code> object to <em>Serving</em>.</p><h2 id='serving' 
class='header-anchors'>Serving</h2><p>The <code>serve</code> method of class 
<code>Serving</code> processes predicted result. It is also responsible for 
combining multiple predicted results into one if you have more than one 
predictive model. <em>Serving</em> then returns the final predicted result. 
PredictionIO will convert it to a JSON response automatically.</p><p>In 
MyComplementaryPurchase/src/main/scala/<strong><em>Serving.scala</em></strong>,</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</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="nd">@transient</span> <span class="k">lazy</span> <span 
class="k">val</span> <span class="n">logger</span> <span class="k">=</span> 
<span class="nc">Logger</span><span class="o">[</span><span 
class="kt">this.</span><span class="k">type</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>When you send a JSON query to <a 
href="http://localhost:8000/queries.json";>http://localhost:8000/queries.json</a>,
 <code>PredictedResult</code> from all models will be passed to 
<code>serve</code> as a sequence, i.e. 
<code>Seq[PredictedResult]</code>.</p><div class="alert-message note"><p>An 
engine can train multiple models if you specify more than one Algorithm 
component in <code>object ComplementaryPurchaseEngine</code> inside 
<strong><em>Engine.scala</em></strong> and the corresponding parameters in 
<strong><em>engine.json</em></strong>. Since only one <code>Algorithm</code> is 
implemented by default, this <code>Seq</code> contains one 
element.</p></div></div></div></div></div><footer><div class="container"><div 
class="seperator"></div><div class="row"><div class="col-md-6 
footer-link-column"><div 
class="footer-link-column-row"><h4>Community</h4><ul><li><a 
href="//predictionio.incubator.apache.org/install/" 
target="blank">Download</a></l
 i><li><a href="//predictionio.incubator.apache.org/" 
target="blank">Docs</a></li><li><a 
href="//github.com/apache/incubator-predictionio" 
target="blank">GitHub</a></li><li><a 
href="mailto:[email protected]"; 
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 
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:[email protected]"; 
target="blank">Subscribe to Development Mailing 
List</a></li></ul></div></div></div><div class="row"><div class="col-md-12 
footer-
 link-column"><a class="pull-right" 
href="http://incubator.apache.org/projects/predictionio.html";><img alt="Apache 
Incubator" src="/images/logos/apache_incubator-6954bd16.png"/></a><span>Apache 
PredictionIO is an effort undergoing incubation at The Apache Software 
Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of 
all newly accepted projects until a further review indicates that the 
infrastructure, communications, and decision making process have stabilized in 
a manner consistent with other successful ASF projects. While incubation status 
is not necessarily a reflection of the completeness or stability of the code, 
it does indicate that the project has yet to be fully endorsed by the 
ASF.</span></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="https://twitter.com/predictionio"; target="blank"><img alt="PredictionIO 
on Twitter" src="/images/icons/twitter-ea9dc152.png"/></a> <a 
href="https://www.facebook.com/predictionio"; target="blank"><img alt="Pred
 ictionIO 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-a6acb1f5.js"></script></body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-site/blob/dd18a676/templates/complementarypurchase/dase/index.html.gz
----------------------------------------------------------------------
diff --git a/templates/complementarypurchase/dase/index.html.gz 
b/templates/complementarypurchase/dase/index.html.gz
new file mode 100644
index 0000000..9f9efbc
Binary files /dev/null and b/templates/complementarypurchase/dase/index.html.gz 
differ


Reply via email to