這是一個b站使用推薦引擎推薦的案例:
0點贊1收藏2轉發
<select id="getAllUserPreference" resultType="com.imooc.bilibili.domain.UserPreference">
select
userId,
videoId,
sum(case operationType
when '0' then 6
when '1' then 2
when '2' then 2
else 0 end
) as `value`
from
t_video_operation
group by userId, videoId
</select>
public class UserPreference {
private Long id;
private Long userId;
private Long videoId;
private Float value;
private Date createTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getVideoId() {
return videoId;
}
public void setVideoId(Long videoId) {
this.videoId = videoId;
}
public Float getValue() {
return value;
}
public void setValue(Float value) {
this.value = value;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
/**
* 基於使用者的協同推薦
* @param userId 使用者id
*/
public List<Video> recommend(Long userId) throws TasteException {
List<UserPreference> list = videoDao.getAllUserPreference();
//建立資料模型
DataModel dataModel = this.createDataModel(list);
//獲取使用者相似程度
UserSimilarity similarity = new UncenteredCosineSimilarity(dataModel);
System.out.println(similarity.userSimilarity(11, 12));
//獲取使用者鄰居
UserNeighborhood userNeighborhood = new NearestNUserNeighborhood(2, similarity, dataModel);
long[] ar = userNeighborhood.getUserNeighborhood(userId);
//構建推薦器
Recommender recommender = new GenericUserBasedRecommender(dataModel, userNeighborhood, similarity);
//推薦影片
List<RecommendedItem> recommendedItems = recommender.recommend(userId, 5);
List<Long> itemIds = recommendedItems.stream().map(RecommendedItem::getItemID).collect(Collectors.toList());
return videoDao.batchGetVideosByIds(itemIds);
}
/**
* 基於內容的協同推薦
* @param userId 使用者id
* @param itemId 參考內容id(根據該內容進行相似內容推薦)
* @param howMany 需要推薦的數量
*/
public List<Video> recommendByItem(Long userId, Long itemId, int howMany) throws TasteException {
List<UserPreference> list = videoDao.getAllUserPreference();
//建立資料模型
DataModel dataModel = this.createDataModel(list);
//獲取內容相似程度
ItemSimilarity similarity = new UncenteredCosineSimilarity(dataModel);
GenericItemBasedRecommender genericItemBasedRecommender = new GenericItemBasedRecommender(dataModel, similarity);
// 物品推薦相擬度,計算兩個物品同時出現的次數,次數越多工的相擬度越高
List<Long> itemIds = genericItemBasedRecommender.recommendedBecause(userId, itemId, howMany)
.stream()
.map(RecommendedItem::getItemID)
.collect(Collectors.toList());
//推薦影片
return videoDao.batchGetVideosByIds(itemIds);
}
private DataModel createDataModel(List<UserPreference> userPreferenceList) {
FastByIDMap<PreferenceArray> fastByIdMap = new FastByIDMap<>();
Map<Long, List<UserPreference>> map = userPreferenceList.stream().collect(Collectors.groupingBy(UserPreference::getUserId));
Collection<List<UserPreference>> list = map.values();
for(List<UserPreference> userPreferences : list){
GenericPreference[] array = new GenericPreference[userPreferences.size()];
for(int i = 0; i < userPreferences.size(); i++){
UserPreference userPreference = userPreferences.get(i);
GenericPreference item = new GenericPreference(userPreference.getUserId(), userPreference.getVideoId(), userPreference.getValue());
array[i] = item;
}
fastByIdMap.put(array[0].getUserID(), new GenericUserPreferenceArray(Arrays.asList(array)));
}
return new GenericDataModel(fastByIdMap);
}