stMind

about Arsenal, Arsene Wenger, Tech, Computer vision and Machine learning

perl de 集合知プログラミング(2)

ピアソン相関係数による類似性判定

2.3.2節のピアソン相関によるスコアを実装してみました。相関係数の計算は、集合知プログラミングの付録にある数式ではなく、Wikipediaにある以下の数式を使って求めました。

相関係数

 r = \frac{ \displaystyle\sum_{i=1}^{n} (x_i - \bar{x})(y_i - \bar{y}) }{ \sqrt{ \displaystyle\sum_{i=1}^{n} (x_i - \bar{x})^{2} } \sqrt{ \displaystyle\sum_{i=1}^{n} (x_i - \bar{y})^{2} } }

出来たもの


ユークリッド距離の時と同じように、ピアソン相関を計算するサブルーチンを作成しました。今回は殆どつまることなく動くコードが実装できました。サブルーチンは以下のようになりました。

# person1とperson2のピアソン相関係数を返す
sub sim_pearson {
    my ($prefs, $person1, $person2) = @_;

    # 二人共評価しているアイテムのリストを得る
    my %si = ();
    foreach my $item (keys %{ $prefs->{$person1} }) {
	if ( $prefs->{$person2}->{$item} ) {
	    $si{$item} = 1;
	}
    }

    # 共に評価しているものが一つもなければ0を返す
    my $n = keys %si;
    if ($n == 0) { return 0; }
    
    # person1とperson2の評価の平均を求める
    my $p1ave = 0.0;
    my $p2ave = 0.0;
    foreach my $item (keys %si) {
	$p1ave += $prefs->{$person1}->{$item};
	$p2ave += $prefs->{$person2}->{$item};
    }
    $p1ave = $p1ave / $n;
    $p2ave = $p2ave / $n;

    # 偏差の二乗和、偏差積の和を求める
    my $Sp1p1 = 0.0;
    my $Sp2p2 = 0.0;
    my $Sp1p2 = 0.0;
    foreach my $item (keys %si) {
	$Sp1p1 += (($prefs->{$person1}->{$item} - $p1ave)**2);
	$Sp2p2 += (($prefs->{$person2}->{$item} - $p2ave)**2);
	$Sp1p2 += (($prefs->{$person1}->{$item} - $p1ave) * 
		    ($prefs->{$person2}->{$item} - $p2ave));
    }

    # 相関係数を求める
    my $r = $Sp1p2 / sqrt( $Sp1p1 * $Sp2p2 );
}

相関を知りたいユーザを標準入力から与えるとスコアが計算されます。

Enter person1 ==> Lisa Rose
Enter person2 ==> Gene Seymour
Similarity Score == 0.39605901719067

以上で、本の通りに類似性スコアを求めることが出来ました。