stMind

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

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

2.4 アイテムを推薦する

今回は、ユーザ間の類似性スコアとアイテム(作品)の評価点を用いて作品をランキング化して提示するサンプルを実装しました。getRecommendationsサブルーチンを追加しました。これまでとほとんど同じで、新たに使ったのはexists関数くらいか。。。データセットを外部から読み込むようにしたりとか新しいことをした方がいいような気がしてきました。

出来たもの
# personへ推薦するアイテムを返す
sub getRecommendations {
    my ($prefs, $person, $similarity) = @_;

    # ユーザ間の類似性スコアとアイテムの評価点から、対象ユーザが評価していないアイテムの評価値を計算
    # 評価値を全ユーザの類似性スコアを合計した値で割った重み付き平均を計算し、値の高い順にソートしてランキングを作成
    my %totals = ();
    my %simSums = ();
    foreach my $user (keys %$prefs) {
	next if ($user eq $person);
	# ユーザ間の類似性スコア算出
	my $score;
	$score = &$similarity($prefs, $person, $user);

	# 0以下のスコアは無視する
	next if ($score <= 0);

	# 対象ユーザが評価していないアイテムについて評価値を計算
	foreach my $item (keys %{ $prefs->{$user} }) {
	    if ((not exists $prefs->{$person}->{$item}) || ($prefs->{$person}->{$item} == 0)) {
		# 評価値
		$totals{$item} += $prefs->{$user}->{$item} * $score;
		# 類似性スコアの合計値
		$simSums{$item} += $score;		
	    }
	}
    }

    # 重み付き平均の算出
    my %li = ();    
    foreach my $item (keys %totals) {
	$li{$item} = $totals{$item} / $simSums{$item};
    }

    # 値の高い順にソートする
    my @rankings = ();
    foreach my $item (sort {$li{$b} <=> $li{$a}} keys %li) {
	my $h = {
	    $item => $li{$item}
	};
	push(@rankings, $h);
    }

    return @rankings;    
}

ユーザ名を指定すると、推薦するアイテムと指定したユーザのスコアの予想値が表示されます。

Enter person1 ==> Toby
Recommendations:
	The Night Listener	 : 3.3477895267131
	Lady in the Water	 : 2.83254991826416
	Just My Luck	 : 2.53098070376556

コード置き場

コードはgistにも置いてあります。
gist: 489178 - GitHub