http://blog.csdn.net/feitongxunke
这一章主要介绍- 在Mahout里面表示和访问推荐程序的相关数据时所用的关键类。
- Mahout中用于访问数据的关键抽象:DataModel。
- 当用户和物品的数据没有评分和偏好值时,也就是布尔偏好,这个时候需要做的处理。
1.偏好数据表示
1.1Preference对象
一个Prefernence对象表示一个用户对一个物品的偏好,是(用户ID,物品ID,偏好值)的抽象。最有可能实现的是:
new GenericPreference(123, 456, 3.0f) //分别代表(用户ID,物品ID,偏好值)
1.2PrefernenceArray及其实现
如果要实现一组Prefernence,不能使用Collection or Prefernence[],因为这时候十分的占用内存。针对这种情况Mahout提供了PreferenceArray接口,表示一个偏好的聚合。这里可以举个例子:
GenericUserPrefernenceArray表示的是与某个用户关联的所有偏好。其内部包含一个单一用户ID,一个物品ID数组,以及一个偏好值数组。
PreferenceArray user1Prefs = new GenericUserPreferenceArray(2);
user1Prefs.setUserID(0, 1L);//设置用户ID
user1Prefs.setItemID(0, 101L);
user1Prefs.setValue(0, 2.0f);
user1Prefs.setItemID(1, 102L);
user1Prefs.setValue(1, 3.0f);
Preference pref = user1Prefs.get(1);//提取物品102的偏好值
1.3FastByIDMap和FastIDSet
在Mahout里面有许多Map和Set的数据结构,但是这个和Java里面的集合有些不同。
- FastByIDMap处理散列冲突是使用线性探测而不是链表法
- key和member都是使用long类型
- Set的内部没有使用Map
- FastByIDMap可以作为高速缓存,超过这个大小时,若要新加入条目则会把不常用的移走。
2.内存级DataModel
2.1GenericDataModel
它简单地将偏好作为输入,采用FastByIDMap的形式,将用户ID映射到这些用户的数据所在的PreferenceArray上。
FastByIDMap<PreferenceArray> preferences = new FastByIDMap<PreferenceArray>();
PreferenceArray prefsForUser1 = new GenericUserPreferenceArray(10);
prefsForUser1.setUserID(0, 1L);
prefsForUser1.setItemID(0, 101L);//增加偏好
prefsForUser1.setValue(0, 3.0f);
prefsForUser1.setItemID(1, 102L);
prefsForUser1.setValue(1, 4.5f);
preferences.put(1L, prefsForUser1);//在输入中附上用户1的偏好
DataModel model = new GenericDataModel(preferences);
3.无偏好值的处理
有时候我们会遇到没有评分的时候,只知道用户和物品是否关联,这时候称之为布尔型偏好。关于布尔型偏好的时候,书中举了个例子需要使用布尔型偏好的情况。一个人只对古典音乐感兴趣,对古典音乐家A给了很低的评分,给了古典音乐家B很高的评分,这个时候通过评分不能说明他对古典音乐是否感兴趣,但是如果这个时候转换成布尔型就可以了。
当使用无偏好值内存会得到大大节省,这个时候使用GenericBooleanPrefDataModel,这个将关联存为FastIDSet,没有偏好值。
给段代码看看:
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.eval.IRStatistics;
import org.apache.mahout.cf.taste.eval.RecommenderBuilder;
import org.apache.mahout.cf.taste.eval.RecommenderIRStatsEvaluator;
import org.apache.mahout.cf.taste.impl.eval.GenericRecommenderIRStatsEvaluator;
import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
import org.apache.mahout.cf.taste.impl.model.file.*;
import org.apache.mahout.cf.taste.impl.neighborhood.*;
import org.apache.mahout.cf.taste.impl.recommender.*;
import org.apache.mahout.cf.taste.impl.similarity.*;
import org.apache.mahout.cf.taste.model.*;
import org.apache.mahout.cf.taste.neighborhood.*;
import org.apache.mahout.cf.taste.recommender.*;
import org.apache.mahout.cf.taste.similarity.*;
import org.apache.mahout.common.RandomUtils;
import java.io.*;
class RecommenderIntro {
public static void main(String[] args) throws Exception {
RandomUtils.useTestSeed();
DataModel model = new GenericBooleanPrefDataModel(GenericBooleanPrefDataModel.toDataMap(new FileDataModel(new File("/Users/ericxk/Downloads/ml-100k/ua.base"))));
RecommenderIRStatsEvaluator evaluator = new GenericRecommenderIRStatsEvaluator();
RecommenderBuilder recommenderBuilder = new RecommenderBuilder() {
public Recommender buildRecommender(DataModel model)throws TasteException {
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
UserNeighborhood neighborhood =new NearestNUserNeighborhood(2, similarity, model);
return new GenericUserBasedRecommender(model, neighborhood, similarity);
}
};
IRStatistics stats = evaluator.evaluate(recommenderBuilder, null, model, null, 2, GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD, 1.0);
System.out.println(stats.getPrecision());
System.out.println(stats.getRecall());
}
}
最后文中讨论了用LogLikelihoodSimilarity代替PearsonCorrelationSimilarity,以及如果有缺失值的情况,关于这些后面章节会深入讨论。