Shows the score curves when given different settings for the three types of scoring functions available in Elasticsearch.
Forked from anonymous/ES Function Score Visualization.markdown
Created
December 18, 2019 17:15
-
-
Save XjSv/91c8d49cf6fc48ef2a74363a89971560 to your computer and use it in GitHub Desktop.
ES Function Score Visualization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<form id="chart_control" style="display:none"> | |
<div> | |
<label for="offset">Offset (days):</label> | |
<input id="offset" type="number" min="0" max="365" step="1" /> | |
</div> | |
<div> | |
<label for="scale">Scale (days):</label> | |
<input id="scale" type="number" min="0" max="365" step="1" /> | |
</div> | |
<div class="break"> | |
<label for="decay">Decay:</label> | |
<input id="decay" type="number" min="0.000001" max="0.999999" step="0.000001" /> | |
</div> | |
<div> | |
<input type="submit" value="Update Graph" /> | |
</div> | |
</form> | |
<div class="break"> | |
<canvas id="chart" width="600" height="220"></canvas> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
( function( w ) { | |
var day_ms = 86400000; | |
var config = { | |
origin : 365 * day_ms, // 1971-01-01 | |
offset : 2419200000, // 28 days | |
scale : 4838400000, // 56 days | |
decay : 0.5 | |
}; | |
var scorer = { | |
_distance: function( val ) { | |
return Math.max( 0, Math.abs( val - config.origin ) - config.offset ); | |
}, | |
gauss: function( val ) { | |
var segma_sq = -1 * Math.pow( config.scale, 2 ) / ( 2 * Math.log( config.decay ) ); | |
return Math.exp( -1 * ( Math.pow( scorer._distance( val ), 2 ) / ( 2 * segma_sq ) ) ) | |
}, | |
exp: function( val ) { | |
var lambda = Math.log( config.decay ) / config.scale; | |
return Math.exp( lambda * scorer._distance( val ) ); | |
}, | |
linear: function( val ) { | |
var s = config.scale / ( 1 - config.decay ); | |
return Math.max( ( ( s - scorer._distance( val ) ) / s ), 0 ); | |
} | |
} | |
w.day_scorer = { | |
set_configs: function( offset_days, scale_days, decay ) { | |
config.offset = day_ms * offset_days; | |
config.scale = day_ms * scale_days; | |
config.decay = decay; | |
}, | |
get_configs: function() { | |
return { | |
offset : config.offset / day_ms, | |
scale : config.scale / day_ms, | |
decay : config.decay, | |
} | |
}, | |
// Calc scores for range of days defaults to a year | |
calc_days: function( first, last ) { | |
// Origin is always last day of range | |
config.origin = last * day_ms; | |
var s = { | |
gauss : [], | |
exp : [], | |
linear : [] | |
}; | |
for ( var d = first; d <= last; d++ ) { | |
s.gauss.push( scorer.gauss( d * day_ms ) ); | |
s.exp.push( scorer.exp( d * day_ms ) ); | |
s.linear.push( scorer.linear( d * day_ms ) ); | |
} | |
return s; | |
} | |
}; | |
} )( window ); | |
( function( w, d ) { | |
// Set default chart configs | |
Chart.defaults.global.responsive = true; | |
Chart.defaults.global.scaleOverride = true; | |
Chart.defaults.global.scaleSteps = 4; | |
Chart.defaults.global.scaleStepWidth = 0.25; | |
Chart.defaults.global.scaleStartValue = 0; | |
Chart.defaults.global.tooltipXOffset = 0; | |
Chart.defaults.global.multiTooltipTemplate = "<%= value.toFixed(3) %><%if (datasetLabel){%> - <%=datasetLabel%><%}%>"; | |
var first = 0, | |
last = 365; | |
var get_labels = function( all ) { | |
var months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]; | |
var labels = []; | |
for ( var day = first; day <= last; day++ ) { | |
var date = new Date( 86400000 * day ); | |
if ( all || date.getUTCDate() == 1 ) { | |
labels.push( months[ date.getUTCMonth() ] + ' ' + date.getUTCDate() ); | |
} else { | |
labels.push( '' ); | |
} | |
} | |
return labels; | |
}; | |
var get_filler = function() { | |
var filler = new Array( 1 + last - first ); | |
filler.fill( 0 ); | |
return filler; | |
}; | |
var update_chart = function() { | |
var scores = w.day_scorer.calc_days( first, last ); | |
var labels = get_labels( true ); | |
[ 'gauss', 'exp', 'linear' ].forEach( function( type, i ) { | |
scores[ type ].forEach( function( s, j ) { | |
graph.datasets[ i ].points[ j ].value = s; | |
graph.datasets[ i ].points[ j ].label = labels[ j ]; | |
} ); | |
} ); | |
graph.update() | |
} | |
var graph = null, | |
ctx = null, | |
data = { | |
labels: get_labels( false ), | |
datasets: [ | |
{ | |
label: "gauss", | |
fillColor: "rgba( 0, 135, 190, 0.05 )", | |
strokeColor: "rgba( 0, 135, 190, 1 )", | |
pointColor: "rgba( 0, 135, 190, 1)", | |
data: get_filler() | |
}, | |
{ | |
label: "exp", | |
fillColor: "rgba( 213, 78, 33, 0.05 )", | |
strokeColor: "rgba( 213, 78, 33, 1 )", | |
pointColor: "rgba( 213, 78, 33, 1 )", | |
data: get_filler() | |
}, | |
{ | |
label: "linear", | |
fillColor: "rgba( 168, 190, 206, 0.05 )", | |
strokeColor: "rgba( 168, 190, 206, 1 )", | |
pointColor: "rgba( 168, 190, 206, 1 )", | |
data: get_filler() | |
} | |
] | |
}, | |
options = { | |
scaleShowVerticalLines: false, | |
pointDot: false, | |
pointHitDetectionRadius: 1 | |
}, | |
ids = { | |
chart : '', | |
offset : '', | |
scale : '', | |
decay : '' | |
}; | |
w.decay_chart = { | |
init: function( chart_id, offset_id, scale_id, decay_id ) { | |
// Store IDs | |
ids = { | |
chart : chart_id, | |
offset : offset_id, | |
scale : scale_id, | |
decay : decay_id | |
} | |
// Set UI to default values | |
var configs = w.day_scorer.get_configs(); | |
d.getElementById( ids.offset ).value = configs.offset; | |
d.getElementById( ids.scale ).value = configs.scale; | |
d.getElementById( ids.decay ).value = configs.decay; | |
ctx = d.getElementById( ids.chart ).getContext( "2d" ); | |
graph = new Chart( ctx ).Line( data, options ); | |
update_chart(); | |
}, | |
update: function() { | |
// Check new values from UI | |
var valid = true; | |
[ ids.offset, ids.scale, ids.decay ].forEach( function( id ) { | |
var elem = d.getElementById( id ); | |
if ( false == elem.validity.valid ) { | |
valid = false; | |
if ( 'function' == typeof elem.reportValidity ) { | |
elem.reportValidity(); | |
} | |
elem.className = "invalid"; | |
} else { | |
elem.className = ""; | |
} | |
} ); | |
if ( !valid ) { | |
return; | |
} | |
w.day_scorer.set_configs( | |
parseInt( d.getElementById( ids.offset ).value ), | |
parseInt( d.getElementById( ids.scale ).value ), | |
parseFloat( d.getElementById( ids.decay ).value ) | |
); | |
update_chart(); | |
} | |
} | |
} )( window, document ); | |
window.onload = function() { | |
var elem = document.getElementById( 'chart_control' ); | |
elem.addEventListener( 'submit', function( event ) { | |
event.preventDefault(); | |
window.decay_chart.update(); | |
} ); | |
elem.style.display = ''; | |
window.decay_chart.init( 'chart', 'offset', 'scale', 'decay' ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.1.1/Chart.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; | |
font-size: 13px; | |
} | |
label, input { | |
margin-bottom: 0.25em; | |
width: 7em; | |
display: block; | |
float: left; | |
} | |
input[type="number"] { | |
text-align: right; | |
} | |
input[type="submit"] { | |
width: 10em; | |
} | |
form div { | |
width: 14em; | |
float: left; | |
} | |
div.break { | |
clear: left; | |
} | |
.invalid { | |
color: #d94f4f; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment