DataModel
datamodel里边存放所有userids,itemids,preference values,提供访问接口
基于内存的DataModel
GenericDataModel
一个最简单实现是GenericDataModel,数据源都来自于内存
GenericDataModel包含下面四个属性:
private final long[] userIDs;
private final FastByIDMap<PreferenceArray> preferenceFromUsers;
private final long[] itemIDs;
private final FastByIDMap<PreferenceArray> preferenceForItems;
FileDataModel
逗号分隔的就可以,格式为user ID, item ID, preference value
tab分隔的也行,文件还可以被压缩,推荐使用压缩过的数据,可以大量节省空间
空行和前面带#号的行都会被视为注释,还可以加入timestamp
当数据量太大的时候,最好选择其它model,比如jdbc的model
查看代码,实际上FileDataModel也使用了GenericDataModel来存储Preference数据
数据更新
当文件更新时,可以通过调用refresh函数更新recommender
DataModel dataModel = new FileDataModel(new File("input.csv");
Recommender recommender = new SlopeOneRecommender(dataModel);
...
recommender.refresh(null);
更新时候不用调用DataModel的refresh函数,recommender会自己调用依赖的这些对象的更新函数
更新数据时,不是更新所有的file内容,实际上变化数据量很小,可以通过update file的方式来更新,例如主文件是foo.txt.gz,更新文件可以是foo1.txt.gz,foo2.txt.gz等,update文件内容举例如下:
1,108,3.0
1,103,
第一行是加入user1对item108的preference value 3.0,第二行是去掉user1对item103的评价
基于数据库的Data Model
数据量太大的时候就不能都放在内存了,可以放置在关系数据库中
相对基于内存Data Model,基于数据库Data Model会慢很多
MySQLJDBCDataModel
jdbc data model主要使用的就是MySQLJDBCDataModel
数据源可以缺省配置,也可以通过JNDI配置,当然也可以通过程序配置。例如:
MysqlDataSource dataSource = new MysqlDataSource ();
dataSource.setServerName("my_database_host");
dataSource.setUser("my_user");
dataSource.setPassword("my_password");
dataSource.setDatabaseName("my_database_name");
JDBCDataModel dataModel = new MySQLJDBCDataModel(
dataSource, "my_prefs_table", "my_user_column",
"my_item_column", "my_pref_value_column");
使用MySQLJDBCDataModel时候,下面几个措施可以有效提升性能(mahout in action 2012第34页):
1.user id和item id应该是非空的,并且要建立索引
2.user id和item id要联合起来做为主键
3.long型对应mysql的bigint,float对应mysql的float
4.查看MySQLJDBCDataModel的javadoc,里边有介绍如何通过参数调整方式提高性能
没有Preference value的情况处理
比如用户浏览文章,只有用户和文章的关系,没有评分
这类preference的名称叫Booleanpreferences,值包括:like,dislike,nothing at all