标签:
从本质上来说,这是一个分类问题,类似于通过邮件内容来推测垃圾邮件,通过用户的相关信息来推测用户是否会拖欠贷款,而通过用户的APP安装列表来推测用户的性别也是一个类似的问题。
对于贝叶斯算法来说,我们首先需要一个训练集数据,这个训练集是一个已经打好标签的数据。而要对一堆的数据打标签,人工来做是不太合适的,在这里需要结合人类与计算机各自的优势,来半自动化的识别出比较明显的有性别倾向的APP的列表,再通过这些(有性别标识的)APP在用户的安装列表中所占的比例来判定出性别特征比较明显的用户,并为这些用户打上性别的标签,而这些用户以及其安装的APP列表就成为我们最终使用的贝叶斯算法的训练数据。
首先,受益于某些APP的命名以及其功能明显的性别倾向性,或者说得益于男女之间的差异,我们能够分别为男女各自定义一组APP名的关键词用来区别男女的用户。比如,对于女性来说,类似于“美丽说”,“美颜相机”,“蘑菇街”,“可爱”之类的关键词就比较能代表其女性的性别倾向性;而类似于“美女”,“体育”,“足球篮球”,“汽车”,“赛车”等关键字又是男性比较有代表性APP关键字。所以最终,我们形成了类似于下面的一组数据,这组数据由人工来完成:
性感美女 男性应用 Sexy 男性应用 汽车 男性应用 体育足球篮球 男性应用 足球 男性应用 篮球 男性应用 男人必玩 男性应用 战斗 男性应用 赛车 男性应用 快播 男性应用 配件 男性应用 暴力 男性应用 坦克 男性应用 美图秀秀 女性应用 大姨妈经期 女性应用 化妆美容 女性应用 美颜 女性应用 宝宝 女性应用 儿童 女性应用 美丽说 女性应用 美柚 女性应用 蘑菇街 女性应用 可爱 女性应用
curl -XPUT localhost:9200/appgender -d '{ "settings" : { "analysis" : { "analyzer" : { "ik" : { "tokenizer" : "ik" } } } }, "mappings" : { "appgender" : { "dynamic" : true, "properties" : { "appname" : { "type" : "string", "analyzer" : "ik" }, "genre": { "type": "string", "index": "not_analyzed" } } } } }'
#coding=utf-8 from elasticsearch import Elasticsearch if __name__ == '__main__': es = Elasticsearch() with open('data/gender_app_feature.tsv') as appgenre: for line in appgenre: appname, genre = line.strip().split('\t') es.index(index="appgender", doc_type="appgender", body={"appname": appname, "genre": genre})
GO锁屏 1975242 360省电王 2142434 录音机 2169688 天天爱消除 2450275 系统更新 2517301 Messaging 2533345 今日头条 2625085 墨迹天气 2762610 同花顺 3076707 QQ空间 3131907 漏洞修复 3255717 拨号盘 3609291 开心消消乐 3638686
第一列是APP名,第二列是APP的用户数,或者出现次数。而匹配工作也非常简单:
#coding=utf-8 import sys reload(sys) sys.setdefaultencoding('utf-8') from elasticsearch import Elasticsearch if __name__ == '__main__': es = Elasticsearch() with open('data/applist.log') as f: for line in f: line = line.replace('?', '') if line.strip(): t = line.strip().split(' ') if len(t) == 2: appname, num = t try: num = int(num) if num < 5: continue # print 'Processing: [%s], and its type is [%s]' % (appname, type(appname)) r = es.search(index='appgender', doc_type='appgender', body={'query': {'match': {'appname': appname}}}) hits = r['hits']['hits'] if hits: hit = hits[0] matched_app = hit['_source']['appname'] matched_genre = hit['_source']['genre'] hit_score = hit['_score'] record = u'%s\t%s\t%s\t%d\t%s' % (appname, matched_app, matched_genre, num, hit_score) print record.encode('utf-8') except Exception, e: sys.stderr.write(str(e) + '\n')
玩库赚流量 男人必玩 男性应用 14423 0.17464119 儿童拖拖乐游戏 儿童 女性应用 14699 0.34928238 4D极速沙滩赛车 赛车 男性应用 15583 0.34928238 宝宝树时光 宝宝 女性应用 16620 0.5457385 PPTV第1体育 体育足球篮球 男性应用 25234 0.17464119 汽车报价-汽车之家出品 汽车 男性应用 51951 0.34928238 汽车在线 汽车 男性应用 68215 1.03399 魔秀桌面 美图秀秀 女性应用 88965 0.34108657 球探体育比分 体育足球篮球 男性应用 90670 0.17464119 新浪体育 体育足球篮球 男性应用 102179 0.516995 美丽说 美丽说 女性应用 108899 2.873763 ......
0052c56f854f363e72a66b4c174e4050 女性应用 搜索 0052c56f854f363e72a66b4c174e4050 女性应用 美图秀秀 0056c01c656c00093a39be1ea783d060 女性应用 腾讯新闻 0056c01c656c00093a39be1ea783d060 女性应用 微信 0056c01c656c00093a39be1ea783d060 女性应用 快乐炸金花 0056c01c656c00093a39be1ea783d060 女性应用 欢乐斗地主 0056c01c656c00093a39be1ea783d060 女性应用 欢乐斗牛 0056c01c656c00093a39be1ea783d060 女性应用 百度 0056c01c656c00093a39be1ea783d060 女性应用 蘑菇街 0056c01c656c00093a39be1ea783d060 女性应用 金山电池医生 005cdf6d9f672ba5cbec4574586a942d 男性应用 快播 0088d4af42a65f864fc356405c73d39c 男性应用 牛仔美女 0088d4af42a65f864fc356405c73d39c 男性应用 美女刮刮乐 008a882683313fc6f64429a6396fed9c 女性应用 爱游戏 008a882683313fc6f64429a6396fed9c 女性应用 蘑菇街 00981a6f972fca3d1eccc942015054d2 女性应用 美图秀秀 00a17e719a86d8f11d534de346e0fcce 女性应用 微信 00a17e719a86d8f11d534de346e0fcce 女性应用 美图秀秀 00a953e662ef896ecde30a9a76e57e96 男性应用 天天基金网
第一列是用户的标识,第二列是根据“男女应用比重”所确定出的本用户的性别,而第三列就是这个用户展开后的全部应用。
#coding=utf-8 from collections import defaultdict TRAIN_DATA_FILE = 'data/genderapplist.log' if __name__ == '__main__': gender_dist = defaultdict(set) app_dist = defaultdict(lambda: defaultdict(int)) app_cond_male_prob = defaultdict(float) app_cond_female_prob = defaultdict(float) with open(TRAIN_DATA_FILE) as train_data: for line in train_data: line = line.strip() cells = line.split('\t') if len(cells) == 3: imei, gender, appname = cells gender = 'female' if gender == '女性应用' else 'male' gender_dist[gender].add(imei) app_dist[gender][appname] += 1 # calculate P(male) pmale = float(len(gender_dist['male'])) / (len(gender_dist['male']) + len(gender_dist['female'])) for appname in app_dist['male']: app_cond_male_prob[appname] = float(app_dist['male'].get(appname)) / len(gender_dist['male']) for appname in app_dist['female']: app_cond_female_prob[appname] = float(app_dist['female'].get(appname)) / len(gender_dist['female']) def gender_prob(applist): male_prob = pmale female_prob = (1 - pmale) for appname in applist: #print app_cond_male_prob.get(appname, 0.5) male_prob = male_prob * app_cond_male_prob.get(appname, 0.5) female_prob = female_prob * app_cond_female_prob.get(appname, 0.5) #print '-----------', male_prob, female_prob print 'user male probability %f' % (male_prob / (male_prob + female_prob)) print male_prob, female_prob appsamples = ["蘑菇街",'搜索', '腾讯新闻', '微信', '快乐炸金花', '欢乐斗地主', '欢乐斗牛', '百度', '金山电池医生',] gender_prob(appsamples) for appname in appsamples: print '%s\t%f\t%f' % (appname, app_cond_male_prob.get(appname), app_cond_female_prob.get(appname))
1. 我们的输入是一个用户的APP列表,输出是这个用户为男性的可能性
2. 输入类似于X = ("美图秀秀",‘搜索‘, ‘腾讯新闻‘, ‘微信‘, ‘快乐炸金花‘, ‘欢乐斗地主‘, ‘欢乐斗牛‘, ‘百度‘, ‘蘑菇街‘, ‘金山电池医生‘),而我们输出就是P(male|X)这样的条件概率。
3. 完整的贝叶斯公式为 P(male|X) = P(male) * P(X|male) / P(X),其中P(male)是男性的概率;P(male|X)是安装了这一堆APP的情况下此用户是男性的概率;P(X)是着堆APP被安装的概率。 但是对于一组固定的X来说,P(X)是个常量,我们可以不计算它。
4. 由于P(X)不用计算,我们必须分别计算出P(male) * P(X|male)和P(female) * P(X|female)
5. 由于训练数据集中P(appx|male)=0的情况,可以使用贝叶斯m估计的方法处理
通过以上的方法,最终就可以通过一个用户的APP的安装列表信息,估计这个用户的性别可能性。
如有表述疏漏,欢迎批评指正。
版权声明:本文为博主原创文章,未经博主允许不得转载。
使用朴素贝叶斯算法,通过用户安装的APP列表来推测用户的性别
标签:
原文地址:http://blog.csdn.net/cnweike/article/details/47167411