KTV歌曲推荐-逻辑回归-用户性别预测
前言
上一篇写了推荐系统最古老的的一种算法叫协同过滤,古老并不是不好用,其实还是很好用的一种算法,随着时代的进步,出现了神经网络和因子分解等更优秀的算法解决不同的问题。 这里主要说一下逻辑回归,逻辑回归主要用于打分的预估。我这里没有打分的数据所以用性别代替。 这里的例子就是用歌曲列表预判用户性别。
什么是逻辑回归
逻辑回归的资料比较多,我比较推荐大家看刷一下bilibili上李宏毅老师的视频,这里我只说一些需要注意的点。
网络结构
逻辑回归可以理解为一种单层神经网络,网络结构如图:
激活函数选择
逻辑回归一般选sigmoid或者softmax
- 图的上半部分就是二元逻辑回归激活函数是sigmoid
- 图的下半部分是多元逻辑回归没有激活函数直接接了一个softmax
别问我啥是sigmoid啥是softmax,问就是百度。
损失函数选择
损失函数逻辑回归常用的有三种(其实有很多不止三种,自己查API喽):
- binary_crossentropy
- categorical_crossentropy
- sparse_categorical_crossentrop 这里其实用binary更合适,但是我这里选的categorical_crossentropy,因为我懒得改了,而且我后面会做其他功能
梯度下降选择
梯度下降方式有很多,我这里选择随机梯度下降,sgd其实我觉得adam更合适,看大家心情了。至于为啥
数据准备
这次的数据是1万条KTV唱歌数据,别问我数据哪来的。问就是别人给的。
X是用户唱歌数据的one-hot
Y是用户的性别one-hot
下面是真正的技术
代码实现
- 数据拆分为 80%训练 20%测试
- 这里虽然只有两类但是还是用了softmax,不影响
- 训练工具是keras
数据获取
下面代码都干了些啥呢,主要是两个matrix。
一个是用户唱歌的onehot->song_hot_matrix。
一个是用户性别的onehot->decades_hot_matrix。 代码不重要,主要看字。
import elasticsearch import elasticsearch.helpers import re import numpy as np import operator import datetime es_client = elasticsearch.Elasticsearch(hosts=["localhost:9200"]) def trim_song_name(song_name): """ 处理歌名,过滤掉无用内容和空白 """ song_name = song_name.strip() song_name = re.sub("【.*?】", "", song_name) song_name = re.sub("(.*?)", "", song_name) return song_name def trim_address_name(address_name): """ 处理地址 """ return str(address_name).strip() def get_data(size=0): """ 获取uid=>作品名list的字典 """ cur_size=0 song_dic = {} user_address_dic = {} user_decades_dic = {} search_result = elasticsearch.helpers.scan( es_client, index="ktv_user_info", doc_type="ktv_works", scroll="10m", query={ "query":{ "range": { "birthday": { "gt": 63072662400 } } } } ) for hit_item in search_result: cur_size += 1 if size>0 and cur_size>size: break user_info = hit_item["_source"] item = get_work_info(hit_item["_id"]) if item is None: continue work_list = item['item_list'] if len(work_list)<2: continue if user_info['gender']==0: continue if user_info['gender']==1: user_info['gender']="男" if user_info['gender']==2: user_info['gender']="女" song_dic[item['uid']] = [trim_song_name(item['songname']) for item in work_list] user_decades_dic[item['uid']] = user_info['gender'] user_address_dic[item['uid']] = trim_address_name(user_info['address']) return (song_dic, user_address_dic, user_decades_dic) def get_user_info(uid): """ 获取用户信息 """ ret = es_client.get( index="ktv_user_info", doc_type="ktv_works", id=uid ) return ret['_source'] def get_work_info(uid): """ 获取用户信息 """ try: ret = es_client.get( index="ktv_works", doc_type="ktv_works", id=uid ) return ret['_source'] except Exception as ex: return None def get_uniq_song_sort_list(song_dict): """ 合并重复歌曲并按歌曲名排序 """ return sorted(list(set(np.concatenate(list(song_dict.values())).tolist()))) from sklearn import preprocessing %run label_encoder.ipynb user_count = 4000 song_count = 0 # 获得用户唱歌数据 song_dict, user_address_dict, user_decades_dict = get_data(user_count) # 歌曲字典 song_label_encoder = LabelEncoder() song_label_encoder.fit_dict(song_dict, "", True) song_hot_matrix = song_label_encoder.encode_hot_dict(song_dict, True) user_decades_encoder = LabelEncoder() user_decades_encoder.fit_dict(user_decades_dict) decades_hot_matrix = user_decades_encoder.encode_hot_dict(user_decades_dict, False)
song_hot_matrix
uid | 洗刷刷 | 麻雀 | 你的答案 |
---|---|---|---|
0 | 0 | 1 | 0 |
1 | 1 | 1 | 0 |
2 | 1 | 0 | 0 |
3 | 0 | 0 | 0 |
decades_hot_matrix
uid | 男 | 女 |
---|---|---|
0 | 1 | 0 |
1 | 0 | 1 |
2 | 1 | 0 |
3 | 0 | 1 |
模型训练
import numpy as np from keras.models import Sequential from keras.layers import Dense, Activation, Embedding,Flatten import matplotlib.pyplot as plt from keras.utils import np_utils from sklearn import datasets from sklearn.model_selection import train_test_split n_class=user_decades_encoder.get_class_count() song_count=song_label_encoder.get_class_count() print(n_class) print(song_count) # 拆分训练数据和测试数据 train_X,test_X, train_y, test_y = train_test_split(song_hot_matrix, decades_hot_matrix, test_size = 0.2, random_state = 0) train_count = np.shape(train_X)[0] # 构建神经网络模型 model = Sequential() model.add(Dense(input_dim=8, units=n_class)) model.add(Activation('softmax')) # 选定loss函数和优化器 model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy']) # 训练过程 print('Training -----------') for step in range(train_count): scores = model.train_on_batch(train_X, train_y) if step % 50 == 0: print("训练样本 %d 个, 损失: %f, 准确率: %f" % (step, scores[0], scores[1]*100)) print('finish!')
准确率测试集评估
数据训练完了用拆分出来的20%数据测试一下:
# 准确率评估 from sklearn.metrics import classification_report scores = model.evaluate(test_X, test_y, verbose=0) print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100)) Y_test = np.argmax(test_y, axis=1) y_pred = model.predict_classes(test_X) print(classification_report(Y_test, y_pred))
输出:
accuracy: 78.43% precision recall f1-score support 0 0.72 0.90 0.80 220 1 0.88 0.68 0.77 239 accuracy 0.78 459 macro avg 0.80 0.79 0.78 459 weighted avg 0.80 0.78 0.78 459
人工测试
然后让小伙伴们一起来玩耍,嗯准确率100%,完美!
def pred(song_list=[]): blong_hot_matrix = song_label_encoder.encode_hot_dict({"bblong":song_list}, True) y_pred = model.predict_classes(blong_hot_matrix) return user_decades_encoder.decode_list(y_pred) # # 男A # print(pred(["一路向北", "暗香", "菊花台"])) # # 男B # print(pred(["不要说话", "平凡之路", "李白"])) # # 女A # print(pred(["知足", "被风吹过的夏天", "龙卷风"])) # # 男C # print(pred(["情人","再见","无赖","离人","你的样子"])) # # 男D # print(pred(["小情歌","我好想你","无与伦比的美丽"])) # # 男E # print(pred(["忐忑","最炫民族风","小苹果"]))
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Google地图官方API-在地图上绘图(自定义符号)
符号介绍当您想在标记上使用基于矢量的图标或将图像添加到折线时,符号非常有用 。 标记支持栅格图像和矢量图像的使用。请参阅有关自定义标记图标的文档 。A 是可以显示在或对象上的基于矢量的图像 。符号的形状由使用SVG路径符号的路径定义 。虽然是唯一必需的属性,但该 对象支持多种属性,使您可以自定义视觉外观,例如笔触和填充的颜色和粗细。请参阅下面的属性列表。 SymbolMarkerPolylinepathSymbol 通过SymbolPath 该类可以使用几个预定义的符号。请参阅下面的列表。 符号的属性请注意,a的默认行为Symbol取决于它出现在标记还是折线上而略有不同。这些差异在下面的属性列表中描述。 A Symbol支持以下属性: path(必填)是定义符号形状的路径。您可以在其中使用预定义的路径之一,也可以使用 SVG路径符号定义自定义路径 。注意:折线上的矢量路径必须适合22x22px的正方形。如果路径中包括该正方形以外的点,则必须将符号的属性调整为分数值(例如0.2),以使生成的缩放点适合正方形。 google.maps.SymbolPathscaleanchor设置符号相对...
- 下一篇
IDC云计算报告:阿里云全球前三,增速超亚马逊微软
据市场研究机构IDC数据,阿里云全球市场份额进一步上涨,紧随亚马逊、微软,增速为市场前五中最快。自2017年来,全球云计算市场形成3A格局(亚马逊AWS、微软Azure和阿里云),市场逐步向头部聚集,目前3A占据市场近七成份额。 历史数据显示,过去6年阿里云全球市场份额迅速增长,成为全球第三大云计算服务商。期间,亚马逊、微软、阿里云市场份额不断攀升,IBM逐年下滑,谷歌从2016年上榜后,逐渐上升至第五。 同时,3A阵营的增速持续领跑市场,其中阿里云增速最快,而全球前五名之外的云服务商大多跑输大盘,落后于整体行业增长。因此,市场份额不断向头部云服务商聚集,截止2019年6月,3A占据市场近七成份额。 据另一权威研究机构Gartner,阿里云在全球市场排名第三,市场份额不断上升。就市场整体而言,份额依旧向头部厂商进一步集中,亚马逊的市场份额见顶回撤,微软和阿里云份额均有增长。 分析师认为,阿里云研发投入近乎激进,建立起全球最丰富技术产品矩阵,带来强劲增长。据普华永道统计,阿里巴巴技术研发投入为中国上市公司之首。2017年,阿里巴巴宣布成立达摩院,3年投入1000亿进行核心基础技术研发,为...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2全家桶,快速入门学习开发网站教程
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Hadoop3单机部署,实现最简伪集群