図は、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 件のコメント:
コメントを投稿