KTV歌曲推荐-深入浅出协同过滤
前言
推荐算法有很多,最基础的就是协同过滤,前段时间对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),...]
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Rancher 2.3实现K8S一键式升级!再也不用同步升级Rancher啦!
在Rancher 2.3之前,Rancher的新版本总是随着Kubernetes的新版本一起发布,如果你想要使用最新版本的Kubernetes,那么你需要先升级Rancher才能使用。Rancher 2.3改变了这一模式——现在,可以为可用的Kubernetes版本更新元数据存储,从而使Rancher服务器的升级过程与Kubernetes集群的升级过程解耦。 Kubernetes 版本控制 关于发行版的版本控制在Kubernetes文档中已经有详细的介绍,值得一提的是,每个Kubernetes的版本都遵循X.Y.Z的格式: X=主要版本 Y=次要版本 Z=修复版本(补丁版本) Kubernetes社区大致每三个月会发布一个次要版本(1.14->1.15),这些发行的版本会更新许多所需功能以及改进。尽管被标记为“次要版本”,但这些版本依旧十分重要! 补丁版本(1.15.1->1.15.2)的更新会更加频繁并且十分重要,因为它们包含了及其重要的安全性和适用于最新次要版本的bug修复。它们解决了: 安全漏洞 修复影响大部分用户无法解决的问题 基于Kubernetes的客户和产品拦...
- 下一篇
IntelliJ IDEA 2019.3 Beta 2 已经发布!
我们正接近发布日期,今天我们准备为您提供IntelliJ IDEA 2019.3的第二个Beta! IntelliJ IDEA Ultimate Beta构建是免费使用的,但它们会在构建日期的30天内过期。 我们正在对即将到来的IntelliJ IDEA 2019.3进行最后润色,并且此版本进行了一些显着更改。 首先,只是为了防止您措手不及,GitHub Pull Requests的时间表不会包含在此即将发布的版本中。我们将继续增强对GitHub Pull Requests的支持,并计划在我们的未来版本之一中提供它。 说到“版本控制”子系统中的更改,现在在合并,变基或“自动选择”操作期间发生冲突时,IDE将使您能够查看有关显示在“版本控制”子系统右侧窗格和左侧窗格中的更改的更多信息。合并对话框。只需单击“显示详细信息”链接。 另外,即将发布的IntelliJ IDEA版本将允许您与队友共享调试器渲染器。现在,JetBrains批注库包含Debug.Renderer批注,您可以使用它在源代码中直接指定渲染器。 立即尝试IntelliJ IDEA 2019.3 Beta2!并且不要忘记与我...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7设置SWAP分区,小内存服务器的救世主