処理の流れと各処理におけるデータ形式
前回の繰り返しになりますが、
今回利用するデータも協調フィルタリングと同様にAmazon review data setです。このデータは以前紹介した場所から、
アイテム間の相関を協調フィルタリングではユーザの数で計算しましたが、
図1にMapReduceの各段階で使われる<key value>を示します。
![図1 協調フィルタリングおよびコンテンツベースの処理における<key value> 図1 協調フィルタリングおよびコンテンツベースの処理における<key value>](/assets/images/dev/serial/01/recommend_hadoop/0007/thumb/TH800_001.jpg)
ユーザidもアイテムidもプログラムにとっては英数字の文字列なので、
#!/usr/bin/perl
use strict;
use utf8;
my $term;
while (<STDIN>) {
chomp $_;
my @string = split ( /\t/, $_);
my @string2 = ();
my $text = $string[7];
unless ( defined $text ) { next; }
if ( $text eq '' ) { next; }
my $item_id = $string[1];
if ( $item_id eq '' ) { next; }
else {
#英大文字を英小文字に変換
$text =~ tr/A-Z/a-z/;
#レビュー本文を連続する英字を単語として分割し、リスト化する
@string2 = split ( /[^a-z]+/, $text);
}
#単語の重複をリストから除く
my %count;
@string2 = grep(!$count{$_}++, @string2);
foreach $term ( @string2 ) {
#空白文字、文字長が3未満の単語を除く
if ( $term eq "" or length($term) < 3 ) { next; }
print ($term . "\t" . $item_id . "\n" );
}
}
今回使うデータがアイテムごとのレビュー本文なので、
また、
今回のデータは英文ですが、
今回は英文ということで、
stop wordsを取り除く
レビュー本文には”
この単語は一般にstop wordsと呼ばれ、
- Text Fixer - web resources
- URL:http://
www. textfixer. com/ resources/ common-english-words. txt
stop wordsをMapperで処理する方法は三通りほどあります。
- Mapperの中にリストとして埋め込んで参照に使う。
- stop wordsのリストをhadoop streamingで他のMapperおよびReducerのスクリプトと同様に各ノードに配布して、
第一段階のMapperから読み込んで処理する。 - stop wordsのリストをHDFSに置き、
第一段階のMapperから読み込んで処理する。
リスト2に上記の3.の方針で実装したMapperを示します。
#!/usr/bin/perl
use strict;
use utf8;
my $term;
my %stw;
my @stwl;
#HDFS内からstop_word_list.txtの読み込み
open (IN, "hadoop dfs -cat /user/gihyo/amazon_gihyo_stw/stop_word_list.txt |");
while (<IN>) {
chomp $_;
@stwl = split (/,/);
}
close IN;
#stop wordへのフラグを立てる
foreach ( @stwl ) {
$stw{$_} = 1;
}
while (<STDIN>) {
chomp $_;
my @string = split ( /\t/, $_);
my @string2 = ();
my $text = $string[7];
unless ( defined $text ) { next; }
if ( $text eq '' ) { next; }
my $item_id = $string[1];
if ( $item_id eq '' ) { next; }
else {
$text =~ tr/A-Z/a-z/;
@string2 = split ( /[^a-z]+/, $text);
}
my %count;
@string2 = grep(!$count{$_}++, @string2);
foreach $term ( @string2 ) {
#空白文字、stop word及び文字長が3未満の単語を除く
if ( $term eq "" or defined $stw{$term} or length($term) < 3 ) { next; }
print ($term . "\t" . $item_id . "\n" );
}
}
協調フィルタリングでも、
まだまだ足りない?
stop wordsを除外することで、
ミススペリングや記号等、
データが増えるに従って、
次回はこの処理を情報検索の観点から見てみます。
この場を借りて宣伝させていただきます。
皆様のお越しを心よりお待ち申し上げております。