図は、2章の「推薦を行う」のユークリッド距離とピアソン相関の辺りに載っているグラフだけど、散布図の様子と2種類の類似性スコアの違いを、評者の組み合わせを選択して確認できるようにしてみた。
(function(ch02Plot01, $, undefined) {
var critics = {
'Lisa': {'Lady': 2.5, 'Snakes': 3.5, 'Luck': 3.0, 'Superman': 3.5, 'Dupree': 2.5, 'Listener': 3.0},
'Gene': {'Lady': 3.0, 'Snakes': 3.5, 'Luck': 1.5, 'Superman': 5.0, 'Listener': 3.0, 'Dupree': 3.5},
'Michael': {'Lady': 2.5, 'Snakes': 3.0, 'Superman': 3.5, 'Listener': 4.0},
'Claudia': {'Snakes': 3.5, 'Luck': 3.0, 'Listener': 4.5, 'Superman': 4.0, 'Dupree': 2.5},
'Mick': {'Lady': 3.0, 'Snakes': 4.0, 'Luck': 2.0, 'Superman': 3.0, 'Listener': 3.0, 'Dupree': 2.0},
'Jack': {'Lady': 3.0, 'Snakes': 4.0, 'Listener': 3.0, 'Superman': 5.0, 'Dupree': 3.5},
'Toby': {'Snakes':4.5,'Dupree':1.0,'Superman':4.0}};
var $this = ch02Plot01;
var ox = 40;
var oy = 390;
var size = 64;
$this.drawLine = function(ctx, x1, y1, x2, y2) {
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
};
$this.drawAxis = function() {
var ctx = $('#pci-ch02-plot').get(0).getContext('2d');
ctx.beginPath();
$this.drawLine(ctx, ox, oy, ox, oy-(size*11/2));
$this.drawLine(ctx, ox, oy, ox+(size*11/2), oy);
_.each(_.range(1, 6), function(e){
console.log($this);
$this.drawLine(ctx, ox-2, oy-e*size, ox+2, oy-e*size);
$this.drawLine(ctx, ox+e*size, oy+2, ox+e*size, oy-2);
ctx.font = "bold 10px Gorgia";
ctx.fillStyle = 'white';
ctx.fillText(e, ox+e*size-5, oy + 15);
ctx.fillText(e, ox-15, oy-e*size+5);
});
ctx.strokeStyle = 'white';
ctx.stroke();
console.log(ox + ":" + oy);
};
function plot(critic1, critic2) {
var pv = critics[critic1];
var ph = critics[critic2];
var duplications = {};
var watchedByBoth = _.intersection(_.keys(pv), _.keys(ph));
var ctx = $('#pci-ch02-plot').get(0).getContext('2d');
ctx.clearRect(ox+1, oy-(size*11/2), size*11/2, size*11/2);
ctx.font = "12px Gorgia";
_.each(watchedByBoth, function(title) {
var pos = [ph[title], pv[title]];
var dupLevel = duplications[pos];
if (!dupLevel) dupLevel = 0;
var cx = ox+ph[title]*size;
var cy = oy-pv[title]*size;
duplications[pos] = dupLevel + 1;
ctx.beginPath();
ctx.arc(cx, cy, 2, 2*Math.PI, false);
ctx.stroke();
var metrix = ctx.measureText(title);
ctx.fillText(title, cx-metrix.width/2, cy-5-dupLevel*13);
});
}
$this.onSelectionChanged = function() {
var $radio = $(this);
var ctx = $('#pci-ch02-plot').get(0).getContext('2d');
var fullName = $radio.next().text();
if ($radio.attr('name') == 'critic1') {
ctx.clearRect(0, 0, 100, oy-size*11/2);
ctx.font = "bold 12px Gorgia";
ctx.fillText(fullName, 10, oy-size*11/2-10);
}
if ($radio.attr('name') == 'critic2') {
ctx.clearRect(ox, oy+16, 1400, 100);
ctx.font = "bold 12px Gorgia";
var metrix = ctx.measureText(fullName);
ctx.fillText(fullName, ox+size*11/2-metrix.width, oy+30);
}
var critic1 = $('input:radio:checked[name="critic1"]').attr('value');
var critic2 = $('input:radio:checked[name="critic2"]').attr('value');
if (critic1 && critic2) {
plot(critic1, critic2);
calcSimilarity(critic1, critic2);
}
};
function calcSimilarity(critic1, critic2) {
var pv = critics[critic1];
var ph = critics[critic2];
var watchedByBoth = _.intersection(_.keys(pv), _.keys(ph));
if (watchedByBoth==[]) {
console.log(0);
} else {
var m = _.chain(watchedByBoth)
.map(function(title){
var a = pv[title];
var b = ph[title];
return [a, b, a*a, b*b, a*b, (a-b)*(a-b)];})
.reduce(function(acc, cur) {
return [acc[0]+cur[0], acc[1]+cur[1], acc[2]+cur[2], acc[3]+cur[3], acc[4]+cur[4], acc[5]+cur[5]];
}, [0, 0, 0, 0, 0, 0])
.value();
var n = watchedByBoth.length;
var sum1 = m[0];
var sum2 = m[1];
var sum1Sq = m[2];
var sum2Sq = m[3];
var pSum = m[4];
var diffSq = m[5];
var num = pSum - sum1*sum2/n;
var den = Math.pow((sum1Sq-sum1*sum1/n)*(sum2Sq-sum2*sum2/n), 0.5);
if (den != 0) {
$('#peason').text(num/den);
} else { $('#peason').text(0); }
$('#eucrid').text(1/(1+diffSq));
}
}
} (window.ch02Plot01 = window.ch02Plot01 || {}, jQuery));
$(function() {
ch02Plot01.drawAxis();
$('input:radio').change(ch02Plot01.onSelectionChanged);
$('input:radio#Lisa1').prop('checked', true).trigger('change');
$('input:radio#Gene2').prop('checked', true).trigger('change');
});
| Eucrid Distance: | |
| Peason Correlation: | |
|
|
|
技術的には、Canvas と、jQuery と underscore.js を使ってみた。
underscore.js は初めて使ってみたが悪くない。
0 件のコメント:
コメントを投稿