private double calculatePearsonSimilarity(Map<Integer, Double> ratings1, Map<Integer, Double> ratings2) { // 计算平均评分 double avgRating1 = calculateAverageRating(ratings1); double avgRating2 = calculateAverageRating(ratings2); double numerator = 0.0; double denominator1 = 0.0; double denominator2 = 0.0; for (int itemId : ratings1.keySet()) { if (ratings2.containsKey(itemId)) { double rating1 = ratings1.get(itemId); double rating2 = ratings2.get(itemId); numerator += (rating1 - avgRating1) * (rating2 - avgRating2); denominator1 += Math.pow(rating1 - avgRating1, 2); denominator2 += Math.pow(rating2 - avgRating2, 2); } }
时间: 2024-02-15 09:26:50 浏览: 53
这段代码定义了一个名为`calculatePearsonSimilarity`的方法,它接受两个Map类型的参数`ratings1`和`ratings2`,这两个Map对象分别表示两个用户对各个物品的评分。该方法计算这两个用户之间的皮尔逊相关系数作为相似度度量。
具体实现中,该方法首先计算这两个用户的平均评分。然后,它遍历这两个Map中的所有物品ID,对于这两个用户都评价过的物品,计算它们的评分差与平均评分之差的乘积,并将结果累加到变量`numerator`中。同时,它还计算了每个用户评分与平均评分之差的平方,并将结果分别累加到变量`denominator1`和`denominator2`中。在循环结束后,它将`numerator`除以`denominator1`和`denominator2`的平方根的乘积,得到皮尔逊相关系数,并将其作为方法的返回值。
相关问题
基于springboot的电影售票及管理系统,设计一个基于用户的协同过滤算法。根据用户对购买电影票的评分进行推荐。后端使用的是springboot和mybatisplus。1:说明算法思路:。2:写出算法的详细代码,以及代码的详细注解。
1. 算法思路:
协同过滤算法是一种基于用户行为的推荐算法,通过分析用户的历史行为,找到相似的用户或者物品,然后根据这些相似的用户或物品的评分数据,预测出当前用户对某个物品的评分。本次设计的电影售票及管理系统,可以采用基于用户的协同过滤算法,根据用户对购买电影票的评分进行推荐。
具体实现思路如下:
1)获取所有用户对电影的评分数据。
2)计算所有用户之间的相似度,可以采用皮尔逊相关系数或者余弦相似度等算法。
3)选取与当前用户最相似的K个用户。
4)根据这K个用户对某个电影的评分数据,预测当前用户对该电影的评分。
5)推荐给当前用户评分最高的N部电影。
2. 详细代码及注解如下:
```java
@Service
public class RecommendService {
@Autowired
private MybatisPlusDao mybatisPlusDao;
/**
* 基于用户的协同过滤算法推荐电影
* @param userId 当前用户ID
* @param k 相似用户数量
* @param n 推荐电影数量
* @return 推荐电影列表
*/
public List<Movie> recommendMovies(int userId, int k, int n) {
List<Movie> result = new ArrayList<>();
// 获取所有用户对电影的评分数据
List<UserMovieRating> allRatings = mybatisPlusDao.getAllRatings();
// 计算当前用户与其他用户之间的相似度
Map<Integer, Double> similarityMap = calculateSimilarity(userId, allRatings);
// 找到与当前用户相似度最高的K个用户
List<Integer> similarUserIds = findKSimilarUsers(similarityMap, k);
// 遍历这K个用户,找到他们评分最高的N部电影,加入推荐列表
for (Integer id : similarUserIds) {
List<UserMovieRating> ratings = mybatisPlusDao.getRatingsByUserId(id);
Collections.sort(ratings, new Comparator<UserMovieRating>() {
@Override
public int compare(UserMovieRating o1, UserMovieRating o2) {
return o2.getRating() - o1.getRating();
}
});
for (UserMovieRating rating : ratings) {
if (result.size() >= n) {
break;
}
if (!hasRated(userId, rating.getMovieId(), allRatings)) {
result.add(mybatisPlusDao.getMovieById(rating.getMovieId()));
}
}
}
return result;
}
/**
* 计算当前用户与其他用户之间的相似度
* @param userId 当前用户ID
* @param allRatings 所有用户对电影的评分数据
* @return 相似度Map,key为用户ID,value为相似度
*/
private Map<Integer, Double> calculateSimilarity(int userId, List<UserMovieRating> allRatings) {
Map<Integer, Double> similarityMap = new HashMap<>();
Map<Integer, List<UserMovieRating>> ratingMap = new HashMap<>();
// 将所有用户的评分数据按用户ID分类,方便计算相似度
for (UserMovieRating rating : allRatings) {
if (!ratingMap.containsKey(rating.getUserId())) {
ratingMap.put(rating.getUserId(), new ArrayList<>());
}
ratingMap.get(rating.getUserId()).add(rating);
}
// 计算当前用户与其他用户之间的相似度
for (Integer id : ratingMap.keySet()) {
if (id == userId) {
continue;
}
List<UserMovieRating> ratings1 = ratingMap.get(userId);
List<UserMovieRating> ratings2 = ratingMap.get(id);
double similarity = calculateSimilarity(ratings1, ratings2);
similarityMap.put(id, similarity);
}
return similarityMap;
}
/**
* 计算两个用户之间的相似度
* @param ratings1 用户1的评分数据
* @param ratings2 用户2的评分数据
* @return 相似度
*/
private double calculateSimilarity(List<UserMovieRating> ratings1, List<UserMovieRating> ratings2) {
double sum1 = 0.0, sum2 = 0.0, sum3 = 0.0;
Map<Integer, UserMovieRating> map = new HashMap<>();
for (UserMovieRating rating : ratings1) {
sum1 += rating.getRating();
map.put(rating.getMovieId(), rating);
}
for (UserMovieRating rating : ratings2) {
sum2 += rating.getRating();
if (map.containsKey(rating.getMovieId())) {
sum3 += (rating.getRating() - map.get(rating.getMovieId()).getRating()) * (rating.getRating() - map.get(rating.getMovieId()).getRating());
}
}
double avg1 = sum1 / ratings1.size();
double avg2 = sum2 / ratings2.size();
if (sum3 == 0) {
return 0;
}
double result = sum3 / Math.sqrt((ratings1.size() * avg1 - sum1) * (ratings2.size() * avg2 - sum2));
return result;
}
/**
* 找到与当前用户相似度最高的K个用户
* @param similarityMap 相似度Map
* @param k 相似用户数量
* @return 相似用户ID列表
*/
private List<Integer> findKSimilarUsers(Map<Integer, Double> similarityMap, int k) {
List<Integer> result = new ArrayList<>();
List<Map.Entry<Integer, Double>> list = new ArrayList<>(similarityMap.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Integer, Double>>() {
@Override
public int compare(Map.Entry<Integer, Double> o1, Map.Entry<Integer, Double> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
for (int i = 0; i < k; i++) {
result.add(list.get(i).getKey());
}
return result;
}
/**
* 判断用户是否已经评价过该电影
* @param userId 用户ID
* @param movieId 电影ID
* @param allRatings 所有用户对电影的评分数据
* @return 是否已经评价过该电影
*/
private boolean hasRated(int userId, int movieId, List<UserMovieRating> allRatings) {
for (UserMovieRating rating : allRatings) {
if (rating.getUserId() == userId && rating.getMovieId() == movieId) {
return true;
}
}
return false;
}
}
```
注解说明:
1)calculateSimilarity方法用于计算两个用户之间的相似度,采用的是皮尔逊相关系数算法。
2)findKSimilarUsers方法用于找到与当前用户相似度最高的K个用户。
3)hasRated方法用于判断用户是否已经评价过该电影。
4)recommendMovies方法是整个推荐算法的入口,先获取所有用户对电影的评分数据,然后计算当前用户与其他用户之间的相似度,找到与当前用户相似度最高的K个用户,遍历这K个用户,找到他们评分最高的N部电影,最后返回推荐电影列表。
在eclipse中编辑一个代码,实现对电影评分的分析
好的,以下是一个使用Java实现的对电影评分的分析代码:
```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MovieRatingAnalyzer {
// 电影评分数据
private static Map<String, List<Integer>> movieRatings = new HashMap<>();
// 初始化数据
static {
List<Integer> ratings1 = new ArrayList<>();
ratings1.add(5); ratings1.add(4); ratings1.add(4); ratings1.add(5); ratings1.add(5);
movieRatings.put("电影1", ratings1);
List<Integer> ratings2 = new ArrayList<>();
ratings2.add(3); ratings2.add(4); ratings2.add(3); ratings2.add(4); ratings2.add(5);
movieRatings.put("电影2", ratings2);
List<Integer> ratings3 = new ArrayList<>();
ratings3.add(4); ratings3.add(5); ratings3.add(4); ratings3.add(4); ratings3.add(3);
movieRatings.put("电影3", ratings3);
}
// 计算平均分
public static double getAverageRating(String movieName) {
List<Integer> ratings = movieRatings.get(movieName);
double sum = 0;
for (int rating : ratings) {
sum += rating;
}
return sum / ratings.size();
}
// 计算标准差
public static double getStandardDeviation(String movieName) {
List<Integer> ratings = movieRatings.get(movieName);
double avg = getAverageRating(movieName);
double sum = 0;
for (int rating : ratings) {
sum += Math.pow(rating - avg, 2);
}
return Math.sqrt(sum / ratings.size());
}
// 计算所有电影的平均分和标准差
public static Map<String, List<Double>> getAllMovieStatistics() {
Map<String, List<Double>> movieStatistics = new HashMap<>();
for (String movieName : movieRatings.keySet()) {
double avg = getAverageRating(movieName);
double std = getStandardDeviation(movieName);
List<Double> stats = new ArrayList<>();
stats.add(avg); stats.add(std);
movieStatistics.put(movieName, stats);
}
return movieStatistics;
}
// 打印所有电影的统计信息
public static void printAllMovieStatistics() {
Map<String, List<Double>> movieStatistics = getAllMovieStatistics();
for (String movieName : movieStatistics.keySet()) {
List<Double> stats = movieStatistics.get(movieName);
System.out.println(movieName + "的平均分为:" + stats.get(0) + ",标准差为:" + stats.get(1));
}
}
// 获取评分排名前N的电影
public static List<String> getTopMovies(int n) {
List<String> movieNames = new ArrayList<>(movieRatings.keySet());
Collections.sort(movieNames, new Comparator<String>() {
@Override
public int compare(String m1, String m2) {
return Double.compare(getAverageRating(m2), getAverageRating(m1));
}
});
return movieNames.subList(0, Math.min(n, movieNames.size()));
}
// 测试代码
public static void main(String[] args) {
printAllMovieStatistics();
System.out.println("评分排名前3的电影为:" + getTopMovies(3));
}
}
```
以上代码实现了以下功能:
1. 计算指定电影的平均分和标准差
2. 计算所有电影的平均分和标准差
3. 获取评分排名前N的电影
在测试代码中,我们打印了所有电影的统计信息,并且获取了评分排名前3的电影。您可以根据实际需求进行修改和扩展。
阅读全文