Mahout 是否提供了一种确定内容之间相似性的方法?
我想生成基于内容的推荐作为 Web 应用程序的一部分。我知道 Mahout 擅长获取用户评分矩阵并根据它们生成推荐,但我对协作(基于评分)推荐不感兴趣。我想对两段文本的匹配程度进行评分,然后推荐与我在用户个人资料中为用户存储的文本最匹配的项目......
我已经阅读了 Mahout 的文档,看起来它主要促进了协作(基于评级)的推荐,而不是基于内容的推荐......这是真的吗?
Mahout 是否提供了一种确定内容之间相似性的方法?
我想生成基于内容的推荐作为 Web 应用程序的一部分。我知道 Mahout 擅长获取用户评分矩阵并根据它们生成推荐,但我对协作(基于评分)推荐不感兴趣。我想对两段文本的匹配程度进行评分,然后推荐与我在用户个人资料中为用户存储的文本最匹配的项目......
我已经阅读了 Mahout 的文档,看起来它主要促进了协作(基于评级)的推荐,而不是基于内容的推荐......这是真的吗?
这并不完全正确。Mahout 没有基于内容的推荐器,但它确实具有基于内容计算项目之间相似性的算法。最流行的一种是 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
在哪里:
步骤 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>
. 以下是为我完成这项工作的两个简单函数:
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
是项目相似性文件的文件夹。最后,这只不过是基于项目的推荐。
希望这可以帮到你