それは完全に真実ではありません。Mahout にはコンテンツ ベースのレコメンダーはありませんが、コンテンツに基づいてアイテム間の類似性を計算するためのアルゴリズムがあります。最も人気のあるものの 1 つは、TF-IDF とコサイン類似度です。ただし、計算はオンザフライではなく、オフラインで行われます。コンテンツに基づいてペアごとの類似性をより高速に計算するには、hadoop が必要です。これから書く手順は MAHOUT 0.8 用です。0.9で変更されたかどうかはわかりません。
ステップ 1. テキスト ドキュメントを seq ファイルに変換する必要があります。MAHOUT-0.8 ではこのコマンドを失いましたが、0.9 では次のようになります (MAHOUT のバージョンを確認してください)。
$MAHOUT_HOME/bin/mahout seqdirectory
--input <PARENT DIR WHERE DOCS ARE LOCATED> --output <OUTPUT DIRECTORY>
<-c <CHARSET NAME OF THE INPUT DOCUMENTS> {UTF-8|cp1252|ascii...}>
<-chunk <MAX SIZE OF EACH CHUNK in Megabytes> 64>
<-prefix <PREFIX TO ADD TO THE DOCUMENT ID>>
ステップ 2. 次のように、シーケンス ファイルをスパース ベクトルに変換する必要があります。
$MAHOUT_HOME/bin/mahout seq2sparse \
-i <SEQ INPUT DIR> \
-o <VECTORS OUTPUT DIR> \
-ow -chunk 100 \
-wt tfidf \
-x 90 \
-seq \
-ml 50 \
-md 3 \
-n 2 \
-nv \
-Dmapred.map.tasks=1000 -Dmapred.reduce.tasks=1000
どこ:
- チャンクは、ファイルのサイズです。
- x辞書ファイルの一部と見なされる用語の最大数。-x 未満の場合は、ストップ ワードと見なされます。
- wtは重み付けスキームです。
- md用語が辞書ファイルの一部とみなされるドキュメントの最小数。頻度の低い用語は無視されます。
- n Lp 空間で使用する正規化値。正規化の詳細な説明は、セクション 8.4 に記載されています。デフォルトのスキームは、重みを正規化しないことです。2 は、クラスタリングと類似度で使用している余弦距離に適しています。
- nv を使用して名前付きベクトルを取得し、さらにデータ ファイルを検査しやすくします。
ステップ 3. ベクトルから行列を作成します。
$MAHOUT_HOME/bin/mahout rowid -i <VECTORS OUTPUT DIR>/tfidf-vectors/part-r-00000 -o <MATRIX OUTPUT DIR>
ステップ 4. 上記のマトリックスの各行について、同様のドキュメントのコレクションを作成します。これにより、コレクション内の各ドキュメントに最も類似した 50 個のドキュメントが生成されます。
$MAHOUT_HOME/bin/mahout rowsimilarity -i <MATRIX OUTPUT DIR>/matrix -o <SIMILARITY OUTPUT DIR> -r <NUM OF COLUMNS FROM THE OUTPUT IN STEP 3> --similarityClassname SIMILARITY_COSINE -m 50 -ess -Dmapred.map.tasks=1000 -Dmapred.reduce.tasks=1000
これにより、コンテンツに基づいた上位 50 個のファイルを使用して、各アイテム間の類似性を持つファイルが生成されます。
ここで、推奨プロセスで使用するには、リソースの量に応じて、ファイルを読み取るか、データベースにロードする必要があります。を使用してメインメモリにロードしましCollection<GenericItemSimilarity.ItemItemSimilarity>
た。これが私のために仕事をした2つの簡単な機能です:
public static Collection<GenericItemSimilarity.ItemItemSimilarity> correlationMatrix(final File folder, TIntLongHashMap docIndex) throws IOException{
Collection<GenericItemSimilarity.ItemItemSimilarity> corrMatrix =
new ArrayList<GenericItemSimilarity.ItemItemSimilarity>();
ItemItemSimilarity itemItemCorrelation = null;
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
int n=0;
for (final File fileEntry : folder.listFiles()) {
if (fileEntry.isFile()) {
if(fileEntry.getName().startsWith("part-r")){
SequenceFile.Reader reader = new SequenceFile.Reader(fs, new Path(fileEntry.getAbsolutePath()), conf);
IntWritable key = new IntWritable();
VectorWritable value = new VectorWritable();
while (reader.next(key, value)) {
long itemID1 = docIndex.get(Integer.parseInt(key.toString()));
Iterator<Element> it = value.get().nonZeroes().iterator();
while(it.hasNext()){
Element next = it.next();
long itemID2 = docIndex.get(next.index());
double similarity = next.get();
//System.out.println(itemID1+ " : "+itemID2+" : "+similarity);
if (similarity < -1.0) {
similarity = -1.0;
} else if (similarity > 1.0) {
similarity = 1.0;
}
itemItemCorrelation = new GenericItemSimilarity.ItemItemSimilarity(itemID1, itemID2, similarity);
corrMatrix.add(itemItemCorrelation);
}
}
reader.close();
n++;
logger.info("File "+fileEntry.getName()+" readed ("+n+"/"+folder.listFiles().length+")");
}
}
}
return corrMatrix;
}
public static TIntLongHashMap getDocIndex(String docIndex) throws IOException{
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
TIntLongHashMap map = new TIntLongHashMap();
SequenceFile.Reader docIndexReader = new SequenceFile.Reader(fs, new Path(docIndex), conf);
IntWritable key = new IntWritable();
Text value = new Text();
while (docIndexReader.next(key, value)) {
map.put(key.get(), Long.parseLong(value.toString()));
}
return map;
}
最後に、推奨クラスでこれを呼び出します。
TIntLongHashMap docIndex = ItemPairwiseSimilarityUtil.getDocIndex(filename);
TLongObjectHashMap<TLongDoubleHashMap> correlationMatrix = ItemPairwiseSimilarityUtil.correlatedItems(folder, docIndex);
filename
docIndex ファイル名はどこfolder
にあり、アイテム類似性ファイルのフォルダーはどこにありますか。結局のところ、これはアイテムベースのレコメンデーションにすぎません。
これがあなたを助けることを願っています