Java点餐小程序实现个性化推荐菜品

1、业务数据表说明

顾客与订单是一对多的关系;订单与菜品是多对多的关系,所以还有一张关系表menu_order_;

2、从数据库查询并构建训练集

现在需要从这四张表联合查询查出 每一个顾客的下单菜品的数量。

1)存着每个顾客的下单菜品的菜品id和此菜品的下单次数。

2)先查出所有顾客customers,再查出每一个顾客的下单菜品的菜品id和此菜品的下单次数,写出到文件中(filename1是不带评分的数据,即userId-dishId;而filename2是userId-dishId-value)。

@PostConstruct
public void getUserItems() {
    try (Writer w1 = new BufferedWriter(new FileWriter(filename1));
         Writer w2 = new BufferedWriter(new FileWriter(filename2))) {
        // 查询所有用户
        List<Customer> customers = customerMapper.selectList(null);
        // 查询所有用户的下单菜品记录
        for (Customer customer : customers) {
            List<DishNumber> dishNumbers = orderMapper.getUserOrderDishes(customer.getCId());
            if (dishNumbers.size() == 0)
                continue;

            for (DishNumber d : dishNumbers) {
                w1.write(customer.getId() + "," + d.getDId() + "\n");
                w2.write(customer.getId() + "," + d.getDId() + "," + d.getValue() + "\n");
            }
        }
        w1.flush();
        w2.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

getUserDishes的sql语句:根据cId查询结果。

<select id="getUserOrderDishes" resultType="com.firstGroup.restaurant.model.vo.DishNumber">
        select d.id dId, count(*) value
        from menu_order_ mo, order_ o, customer c, dish d
        where o.c_id=c.c_id and mo.o_id=o.o_id and d.d_id=mo.d_id and o.c_id = #{cId}
        group by d.d_id
</select>

3)生成的训练集(数据时随意测试的,没有参考性)

数据说明:顾客id=1:下单菜品id=1,61次;菜品id=2,1次;菜品id=3,1次

 filename1;               filename2

             

3、使用Mahout实现基于用户的协调过滤推荐算法

 1)有用户评分的:

/*
 * @Author Haojie
 * @Description 有评分的基于用户的协同过滤推荐算法
 * @Param
 * @return
 **/
private List<Dish> userCFWithoutRecommend(String cId, Integer number) throws Exception {

    // 建立数据模型,包含用户评分
    DataModel dm = new GenericDataModel(
            GenericDataModel
                    .toDataMap(new FileDataModel(new File(filename2))));

    // 使用曼哈顿距离计算类似度
    UserSimilarity us = new EuclideanDistanceSimilarity(dm);

    //指定NearestNUserNeighborhood做为近邻算法
    UserNeighborhood unb = new NearestNUserNeighborhood(10, us, dm);

    // 构建包含用户评分的UserCF推荐器
    Recommender re = new GenericUserBasedRecommender(dm, unb, us);

    // 返回推荐结果,为cId用户推荐number个商品
    Integer id = customerMapper.selectById(cId).getId();
    List<RecommendedItem> list = re.recommend(id, number);
    List<Dish> dishes = new ArrayList<>();
    System.out.println("根据用户cId=" + cId + ", userId=" + id + "的点餐习惯,推荐的前" + number + "个菜品的id和推荐度如下:");

    for (RecommendedItem recommendedItem : list) {
        System.out.println(recommendedItem.getItemID() + " : " + recommendedItem.getValue());
        dishes.add(dishMapper.selectOne(new LambdaQueryWrapper<Dish>().eq(Dish::getId,
                recommendedItem.getItemID())));
    }
    return dishes;
}

 2)无用户评分的:

/*
 * @Author Haojie
 * @Description 无评分的基于用户的协同过滤推荐算法
 * @Param
 * @return
 **/
private List<Dish> userCFWithoutScoreRecommend(String cId, Integer number) throws Exception {

    // 建立数据模型,不包含用户评分
    DataModel dm = new GenericDataModel(
            GenericDataModel
                    .toDataMap(new FileDataModel(new File(filename1))));

    // 使用曼哈顿距离计算类似度
    UserSimilarity us = new CityBlockSimilarity(dm);

    //指定NearestNUserNeighborhood做为近邻算法
    UserNeighborhood unb = new NearestNUserNeighborhood(5, us, dm);

    // 构建不包含用户评分的UserCF推荐器
    Recommender re = new GenericBooleanPrefUserBasedRecommender(dm, unb, us);

    // 返回推荐结果,为cId用户推荐number个商品
    Integer id = customerMapper.selectById(cId).getId();
    List<RecommendedItem> list = re.recommend(id, number);
    List<Dish> dishes = new ArrayList<>();
    System.out.println("根据用户cId=" + cId + ", userId=" + id + "的点餐习惯,推荐的前" + number + "个菜品的id和推荐度如下:");

    for (RecommendedItem recommendedItem : list) {
        System.out.println(recommendedItem.getItemID() + " : " + recommendedItem.getValue());
        dishes.add(dishMapper.selectOne(new LambdaQueryWrapper<Dish>().eq(Dish::getId,
                recommendedItem.getItemID())));
    }
    return dishes;
}

最终都可以返回推荐的菜品数据。

问题

实现起来非常简单,但是有非常大的问题,那就是训练的数据只有id和评分,数据太少了;应该是整个菜品的属性,菜品分类,用户属性等等都拿去训练才比较合理。

参考:

1、Mahout实践,协同过滤算法介绍:

Java实现算法推荐:Mahout实践 - JavaShuo

2、具体实战:

Mahout推荐算法编程实践-demo说明 - JavaShuo

3、其他参考

012_流式计算系统(Mahout协同过滤) (bbsmax.com)

  • 0
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目完整可用,配合压缩包内数据库可直接运行使用。 eclipse+mysql5.7+jdk1.8 功能:推荐引擎利用特殊的信息过滤(IF,Information Filtering)技术,将不同的内容(例如电影、音乐、书籍、新闻、图片、网页等)推荐给可能感兴趣的用户。通常情况下,推荐引擎的实现是通过将用户的个人喜好与特定的参考特征进行比较,并试图预测用户对一些未评分项目的喜好程度。参考特征的选取可能是从项目本身的信息中提取的,或是基于用户所在的社会或社团环境。 根据如何抽取参考特征,我们可以将推荐引擎分为以下四大类: • 基于内容的推荐引擎:它将计算得到并推荐给用户一些与该用户已选择过的项目相似的内容。例如,当你在网上购书时,你总是购买与历史相关的书籍,那么基于内容的推荐引擎就会给你推荐一些热门的历史方面的书籍。 • 基于协同过滤的推荐引擎:它将推荐给用户一些与该用户味相似的其他用户喜欢的内容。例如,当你在网上买衣服时,基于协同过滤的推荐引擎会根据你的历史购买记录或是浏览记录,分析出你的穿衣位,并找到与你味相似的一些用户,将他们浏览和购买的衣服推荐给你。 • 基于关联规则的推荐引擎:它将推荐给用户一些采用关联规则发现算法计算出的内容。关联规则的发现算法有很多,如 Apriori、AprioriTid、DHP、FP-tree 等。 • 混合推荐引擎:结合以上各种,得到一个更加全面的推荐效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值