**基于 Apache Mahout 实现高效的协同过滤推荐电影**

基于 Apache Mahout 实现高效的协同过滤推荐电影
Apache Mahout 是 Apache Software Foundation (ASF) 旗下的一个开源项目,提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序,并且,在 Mahout 的最近版本中还加入了对 Apache Hadoop 的支持,使这些算法可以更高效的运行在云计算环境中。

Apache Mahout 中提供的一个协同过滤算法的高效实现,它是一个基于 Java 实现的可扩展的,高效的推荐引擎。
Mahout里面包含了系列数据挖掘算法,taste算法,分类,聚类,关联规则
demo电影影城项目就得用到Mahout的一些推荐算法,还有必要的搜索引擎,下面呢我就说一下我的电影推荐-Taste算法之Java应用(电影的推荐)

Preference
基于协同过滤的推荐引擎的输入是用户的历史偏好信息,在 Mahout 里它被建模为 Preference(接口),一个 Preference 就是一个简单的三元组 < 用户 ID, 物品 ID, 用户偏好 >,它的实现类是 GenericPreference,因为占用内存太大。因此不推荐使用,而它自身呢,,Mahout 在这方面做了一些优化,它创建了 PreferenceArray(接口类)保存一组用户偏好数据,为了优化性能,Mahout 给出了两个实现类,GenericUserPreferenceArray 和 GenericItemPreferenceArray。
下面呢是我的代码解释:

PreferenceArray prefsForUser3 = new GenericUserPreferenceArray(4);//4 这里可以是很大,但是呢别超内存就行了
 prefsForUser3.setUserID(1, 3L); 
 prefsForUser3.setItemID(1, 101L); 
 prefsForUser3.setValue(1, 5.0f);  
 prefsForUser3.setItemID(2, 102L); 
 prefsForUser3.setValue(2, 4.5f);

// 这样呢就建立好了一个user-----------》 这个用户信息:<3,101,5.0>    <3,102,4.5>ataModel**out 的推荐引擎实际接受的输入是 DataModel,它是对用户偏好数据的压缩表示,通过创建内存版 DataModel 的语句我们可以看出:
DataModel model = new GenericDataModel(FastByIDMap map)
DataModel 是用户喜好信息的抽象接口,它的具体实现支持从任意类型的数据源抽取用户喜好信息,具体实现包括内存版的 GenericDataModel,支持文件读取的 FileDataModel 和支持数据库读取的 JDBCDataModel

GenericDataModel代码:

FastByIDMap preferences = new FastByIDMap(); 
PreferenceArray prefsForUser1 = new GenericUserPreferenceArray(4);  
PreferenceArray prefsForUser2 = new GenericUserPreferenceArray(4);
PreferenceArray prefsForUser3 = new GenericUserPreferenceArray(4);
 prefsForUser2.setUserID(0, 1L); 
 prefsForUser2.setItemID(0, 101L); 
 prefsForUser2.setValue(0, 3.0f);  
 prefsForUser2.setItemID(1, 102L);  
 prefsForUser3.setValue(1, 4.5f);//用户id=1
 prefsForUser3.setUserID(1, 3L); 
 prefsForUser3.setItemID(1, 101L); 
 prefsForUser3.setValue(1, 5.0f);  
 prefsForUser3.setItemID(2, 102L); 
 prefsForUser3.setValue(2, 4.5f);//用户id=3
 prefsForUser1.setUserID(2, 2L); 
 prefsForUser1.setItemID(2, 101L); 
 prefsForUser1.setValue(2, 3.0f);  
 prefsForUser1.setItemID(3, 102L); 
 prefsForUser1.setValue(3, 4.5f);//用户id=2
 preferences.put(1L, prefsForUser3);
 System.out.println(preferences.get(1L));preferences.get(1L);
 preferences.put(2L, prefsForUser1);
 preferences.put(3L, prefsForUser2);        
  DataModel model = new GenericDataModel(preferences);
  DataModel model = new GenericDataModel(preferences); 
  这个训练模型方法可以接受,也很方便,虽然说内存比直接从数据库得出要快得多,但也占用了不少宝贵的内存资源。但是对于数据量很大的项目来说就不行了

FileDataModel:

**基于 Apache Mahout 实现高效的协同过滤推荐电影**_第1张图片

DataModel model =new FileDataModel(new File(“E:/work2/movies/src/main/java/text.txt”));//绝对路径

   新建一个数据测试文件text.txt内容有三列,分别是用户ID,商品ID,兴趣打分。
     用文件训练出的模型可以说相比内存版,剩下了内存,和数据库版省了时间,但是如果数据量一旦超过G,就没效率的概念了吧

MySQLJDBCDataModel:

mahout也给了一个数据库版的接口,Mahout 提供一个默认的 MySQL 的支持,它对用户偏好数据的存放有以下简单的要求:

  1. 用户 ID 列需要是 BIGINT 而且非空
  2. 物品 ID 列需要是 BIGINT 而且非空
  3. 用户偏好列需要是 FLOAT
MysqlDataSource dataSource = new MysqlDataSource(); 
 dataSource.setServerName("my_user"); 
 dataSource.setUser("my_password"); 
 dataSource.setPassword("my_database_host"); 
 JDBCDataModel dataModel = new MySQLJDBCDataModel(dataSource, "my_prefs_table", 
 "my_user_column", "my_item_column", "my_pref_value_column");

1、首先呢建立一个项目,导包,如果是web项目呢直接用maven。
2、建立自己中意的model;在这里我用SSm

FileDataMo@RequestMapping("/allmovies")


@RequestMapping("/allmovies")
public String allmovies(HttpSession session) throws Exception{
/**
 *  这是taste算法
 *  求出这个id的推荐itemid
 */
  List taste = new TasteItemId().taste();
  for (RecommendedItem recommendedItem : taste) {
System.out.println(recommendedItem.getItemID());//打印itemid
}   
        return "main";

    }
/**
*算法区
**/
DataModel  model =new FileDataModel(new File("E:/work2/movies/src/main/java/text.txt"));
        UserSimilarity similarity =new PearsonCorrelationSimilarity(model);  //根据模型创建相似度
            UserNeighborhood neighborhood =new NearestNUserNeighborhood(2,similarity,model);  
            Recommender recommender= new GenericUserBasedRecommender(model,neighborhood,similarity);  
            List recommendations =recommender.recommend(1L, 2);//给用户1推荐两个itemid
            /**
            *实时从数据库获取list并写入文件
            */
@WebListener
public class TasteIndexListener implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void contextInitialized(ServletContextEvent e) {
        ServletContext ctx = e.getServletContext();
        WebApplicationContext wctx = WebApplicationContextUtils.getWebApplicationContext(ctx);
        final MainFindMoiesSerivceImp mms = wctx.getBean(MainFindMoiesSerivceImp.class);
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                List ta = mms.findTaste();
                //进行字符串拼接
                List list=new ArrayList();
                for (Taste taste : ta) {                
                    StringBuffer buf=new StringBuffer();
                    buf.append(taste.getUserId());
                    buf.append(",");
                    buf.append(taste.getMoveId());
                    buf.append(",");
                    buf.append(taste.getValue());
                    String string = buf.toString();
                    list.add(string);
                }
                new TasteIo(list);//返回的是一个只带有一个元素的内容list
            }
        }, 20000,50000);//刷新间隔和时间

    }
/**
*文件流写入list ,不要写进对象,因为文件格式一定要规范
*/
package inverse.movies.utils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
public class TasteIo {
/**
* @param list传入要写入文件内容的集合
*/
public TasteIo(List list) {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(new File("E:/work2/movies/src/main/java/text.txt")));
for(String str : list)
{
// 写文件
bw.write(str, 0, str.length());
// 刷新流
bw.flush();
// 换行
bw.newLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭文件流
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

后台输出的结果:

17/08/11 10:24:55 INFO file.FileDataModel: Creating FileDataModel for file E:\work2\movies\src\main\java\text.txt
17/08/11 10:24:55 INFO file.FileDataModel: Reading file info...
17/08/11 10:24:55 INFO file.FileDataModel: Read lines: 21
17/08/11 10:24:55 INFO model.GenericDataModel: Processed 5 users
104
106

你可能感兴趣的:(小白成长之mahou,taste算法实现)