文档章节

KTV歌曲推荐-深入浅出协同过滤

sharpcx
 sharpcx
发布于 11/14 12:05
字数 1209
阅读 2379
收藏 59

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

前言

推荐算法有很多,最基础的就是协同过滤,前段时间对KTV数据比较感兴趣,大家去唱歌也只是唱熟悉的歌,那是不是有办法给大家一些建议拓展一下唱歌的宽度呢。KTV推荐可能要考虑很多因素,比如唱歌者的音域,年龄,地区,喜好,等等。第一版算法暂时只从item base的角度出发去给用户推荐。由于是个人兴趣,所以没有模型反馈迭代的过程,有兴趣的可以自己实现。

协同过滤算法

协同过滤又叫行为相似召回,其实就是基于共现的一种相似度计算。 Item Base的协同过滤算法有几个关键概念:

相似度计算

相似度计算有很多种:共现相似度,欧几里得距离,皮尔逊相关系数,等等这里使用的是共现相似度,公式如下:

其中N(i)为喜欢i歌曲的用户数,同样N(j)为喜欢j歌曲的用户数,分子为同时喜欢i,j的用户数。该公式为改良公式,分子中加入了N(j)对相似度进行惩罚。这里不细讲。

ItemBase和UserBase

UserBase

寻找兴趣相似的用户,然后将偏好相同的用户的歌曲推荐给被推荐用户,表中发现A和C用户都喜欢i和k歌曲所以两个用户相似,所以将C用户的歌曲l推荐给A用户。如果用共现的方式去表述就是。这里细节计算的时候会涉及到用户打分和相似用户数据排序汇总。我这里都是概述。

用户/歌曲 歌曲i 歌曲j 歌曲k 歌曲l
用户A 1 1 推荐
用户B 1
用户C 1 1 1

ItemBase

与UserBase类似,计算相似的时候使用的是歌曲矩阵找到相似的歌曲,然后根据用户历史数据进行推荐,大概原理如下表。表中发现i,k歌曲同事被A,B两个用户喜欢,所以i,k相似,如果C用户喜欢i歌曲那么他应该也喜欢相似的k歌曲.

用户/歌曲 歌曲i 歌曲j 歌曲k
用户A 1 1
用户B 1 1 1
用户C 1 推荐

这里使用的是ItemBase

算法实现

得到用户对歌曲的one hot矩阵

  • 将歌曲去重,按歌名排序
  • 得到歌曲和索引的转换字典

计算得到歌曲对歌曲的共现度矩阵

  • 计算共现矩阵

  • 计算单个歌曲的出现次数

  • 计算共现率值公式计算共现度

推荐

如果用户喜欢i歌曲则

得到推荐歌曲为k歌曲

代码实现

获取数据

import elasticsearch
import elasticsearch.helpers
import re
import numpy as np
import operator

def trim_song_name(song_name):
    """
    处理歌名,过滤掉无用内容和空白
    """
    song_name = song_name.strip()
    song_name = re.sub("-?【.*?】", "", song_name)
    song_name = re.sub("-?(.*?)", "", song_name)
    song_name = re.sub("-?(.*?)", "", song_name)
    return song_name

def get_data(size=0):
    """
    获取uid=>作品名list的字典
    """
    cur_size=0
    ret = {}
    
    es_client = elasticsearch.Elasticsearch()
    search_result = elasticsearch.helpers.scan(
        es_client, 
        index="ktv_works", 
        doc_type="ktv_works", 
        scroll="10m",
        query={}
    )

    all_songs_list = []
    all_songs_set = set()
    for hit_item in search_result:
        cur_size += 1
        if size>0 and cur_size>size:
            break
            
        item = hit_item['_source']
        work_list = item['item_list']
        ret[item['uid']] = [trim_song_name(item['songname']) for item in work_list]
        
    return ret

def get_uniq_song_sort_list(song_dict):
    """
    合并重复歌曲并按歌曲名排序
    """
    return sorted(list(set(np.concatenate(list(song_dict.values())).tolist())))
    

相似度计算

import math

# 共现数矩阵
col_show_count_matrix = np.zeros((song_count, song_count))
one_trik_matrix = np.zeros(song_count)
for i in range(song_count):
    for j in range(song_count):
        if i>j: # 对角矩阵只计算一半的矩阵
            one_trik_matrix = np.zeros(song_count)
            one_trik_matrix[i] = 1
            one_trik_matrix[j] = 1
            
            ret_m = user_song_one_hot_matrix.dot(one_trik_matrix.T)
            col_show_value = len([ix for ix in ret_m if ix==2])
            col_show_count_matrix[i,j] = col_show_value
            col_show_count_matrix[j,i] = col_show_value

# 相似度矩阵
col_show_rate_matrix = np.zeros((song_count, song_count))

# 歌曲count N(i)矩阵
song_count_matrix = np.zeros(song_count)
for i in range(song_count):
    song_col = user_song_one_hot_matrix[:,i]
    song_count_matrix[i] = len([ix for ix in song_col if ix>=1])

# 相似度矩阵计算
for i in range(song_count):
    for j in range(song_count):
        if i>j: # 对角矩阵只计算一半的矩阵
            # 相似度计算 N(i)nN(j)/sqart(N(i)*N(j))
            rate_value = col_show_count_matrix[i,j]/math.sqrt(song_count_matrix[i]*song_count_matrix[j])
            col_show_rate_matrix[i,j] = rate_value
            col_show_rate_matrix[j,i] = rate_value

推荐

import operator

def get_songs_from_recommand(col_recommand_matrix):
    return [(int_to_song[k],r_value) for k,r_value in enumerate(col_recommand_matrix) if r_value>0]

input_song = "十年"
# 构造被推荐矩阵
one_trik_matrix = np.zeros(song_count)
one_trik_matrix[song_to_int[input_song]] = 1

col_recommand_matrix = col_show_rate_matrix.dot(one_trik_matrix.T)
recommand_array = get_songs_from_recommand(col_recommand_matrix)
sorted_x = sorted(recommand_array, key=lambda k:k[1], reverse=True)

# 获取推荐结果
print(sorted_x)


结果

[('三生三世', 0.5773502691896258), ('下个路口见', 0.5773502691896258), ('不分手的恋爱', 0.5773502691896258),...]

© 著作权归作者所有

sharpcx
粉丝 6
博文 7
码字总数 4542
作品 0
海淀
程序员
私信 提问
加载中

评论(6)

OSCharles
OSCharles
看到公式就头疼,他不认识我,我也不认识他
sharpcx
sharpcx 博主
其实,我也是,哈哈哈哈,我写的公式是简化的了,我还没加归一化和其他因素进去
码农小胖哥
码农小胖哥
写的很好
sharpcx
sharpcx 博主
谢谢
巴拉迪维
巴拉迪维
绝世好文
sharpcx
sharpcx 博主
谢谢
Netty进阶篇之简单版websocket发消息(7)

序言:简单开发前端发送消息,后端接收消息并返回。 1、故事牵引 今天通过一个故事来讲解netty,主要讲client和server端和下面的主要实现类。 客户要去ktv唱歌,进入ktv之前,门口会有招待服...

木九天
07/23
36
0
卡拉OK娱乐软件--Ultrastar Deluxe

Ultrastar Deluxe 是一个卡拉OK娱乐软件,类似于PS2 上的Singstar,于5月12日发布了首个适用于Ubuntu的二进制deb包。该软件可以在你唱歌的时候对你的波形与原歌声进行比较,从而评出一个分数...

匿名
2009/07/01
4.8K
0
点歌APP软件开发,点歌系统APP开发

ktv点歌系统开发难不难 随着科技的发展,智能手机的用户规模不断扩大,移动互联时代的来临,使得传统的营销模式已经无法满足KTV行业经营的需求,使得用户的消费、浏览习惯开始向移动端转移。...

APP开发东方智启
03/16
0
0
在线卡拉OK系统

昨天平安夜,和老婆一起参加朋友组织的聚会,参加的很多人都露了一把厨艺,虽然等吃饭很长时间,不过吃的非常开心。饭后大家唱歌,就在聚会的地方,一台电脑连着投影仪和网络,也许是客户端软...

goofegg
2010/02/20
341
0
《利用深度学习改进基于内容和混合音乐推荐》论文阅读

https://blog.csdn.net/u011239443/article/details/79984751 论文地址: https://www.smcnus.org/wp-content/uploads/2013/09/deepmr.pdf 摘要 现有的基于内容的音乐推荐系统通常采用两阶段......

u011239443
2018/04/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

web前端入门到实战:图解原生dialog标签(非常详细)

在html5中,新增了很多语义化的标签。如footer、header之类的,今天的主角是dialog标签 顾名思义,就是用来定义对话框的。目前只有Chrome和Safari支持该标签,所以用的不多,不过确实挺好用的...

梦想编程
24分钟前
3
0
一些php常用函数积累

本文链接<?php// id: ecffe70d3af54df9bad97b61918ace7d global $ct_path, $ct_log_path;$log_path = "test_php.txt";// 是否先log到buffer,再通过CT_flush()一次性写入文件$......

一字见心
25分钟前
3
0
IntelliJ idea中 注释代码折叠

visual studio中有#region 可以折叠代码,IntelliJ idea 中也有类似功能 //region 描述代码//endregion

format
25分钟前
4
0
oracle表中更改主键

一、数据表有主键但无主键约束名 先删除之前的主键,后添加主键 ,执行SQL: a. alter table 表名 drop primary key; b. alter table 表名 add primary key(想要更改的字段名称); 二、数据表...

_Somuns
27分钟前
3
0
jQuery AJAX提交表单

我有一个名称为orderproductForm的表单,输入的数量不确定。 我想做某种jQuery.get或ajax或类似的事情,它将通过Ajax调用页面,并发送所有形式为orderproductForm的输入。 我想一种方法是做类...

技术盛宴
32分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部