机器学习技术,可根据用户喜欢的Facebook网站估算用户的年龄


25

我有一个来自Facebook应用程序的数据库,我正在尝试使用机器学习根据用户喜欢的Facebook网站估算其年龄。

我的数据库具有三个关键特征:

  • 我的训练集中的年龄分布(总共12,000个用户)偏向年轻用户(即,我有1157个27岁的用户和23个65岁的用户);

  • 许多站点的点赞者不超过5个(我过滤掉了少于5个点赞的FB站点)。

  • 功能比示例更多。

因此,我的问题是:您建议采取什么策略准备数据以进行进一步分析?我应该执行某种降维吗?在这种情况下,哪种ML方法最合适?

我主要使用Python,因此非常感谢Python特定的提示。


1
当您说“功能多于示例”时,我认为您是指喜欢的网站的唯一数量是>> num个用户。网站的根域也是如此吗?也就是说,它们是网站中的youtube.com还是cnn.com网址数量,还是已经存在于域名中?我倾向于通过将URL折叠到域根目录(而不是特定页面)来减少维度。
cwharland 2014年

感谢您的回答。功能(唯一喜欢的站点)数量为32k,样本(用户)数量为12k。功能是Facebook Pages,因此无需阻止URL。用户可能不喜欢facebook.com/cnn。我喜欢尝试根据用户共享的链接估算用户年龄的想法,但:)
Wojciech Walczak 2014年

啊,我看错了喜欢的网站的描述。感谢您的澄清。
cwharland 2014年

Answers:


16

首先要考虑的是k-NN。这里的想法是,您有一个用户/项目矩阵,对于某些用户,您有一个报告的年龄。用户项目矩阵中某人的年龄可能由项目空间中某些最接近邻居的平均年龄或中位数年龄等因素很好地确定。

因此,您将每个用户表示为项目空间中的向量,找到k个最近的邻居,并为所讨论的向量分配一些最接近邻居年龄的摘要统计信息。您可以在距离截止点上选择k,或更实际地是,通过迭代地将年龄分配给火车并选择k,以最小化该分配中的误差。

如果维数是个问题,则可以通过选择单个值分解来选择m个向量来捕获整个组中最大的方差,从而轻松地对此设置进行归约。

在所有情况下,由于每个特征都是二进制的,因此余弦相似度似乎是您选择的距离度量标准。

鉴于您的特征空间关注范围很窄(同一动作的所有变体,喜欢),因此我需要对其他方法(回归,RF等)进行更多的思考,我认为用户/项目方法可能是最好的。

请注意,如果您自己报告的年龄是自我报告的,则可能需要更正其中的一些。Facebook上的人倾向于报告其出生十年的年龄。绘制出生日期(从年龄推算)的直方图,看看您是否在70年代,80年代,90年代等几十年出现峰值。


嗨,您的答案与我的实际策略非常相似。我sklearn.neighbors.KNeighborsRegressor在SVD缩减空间上使用了余弦度量(在应用SVD之后,平均估计误差从〜6年降至〜4)。我数据库中的用户年龄在18-65岁之间(较老的用户已被过滤掉),因此有48种可能的类别。我想知道kNN的类是否不是太多,是否应该将其视为回归或分类问题(我认为两者均适用)。
Wojciech Walczak 2014年

有趣的是,我可以使用每类随机森林分别适合多个类,然后以各种方式组合每个模型的结果。在这种情况下,您甚至可以考虑使用kNN为每个用户的年龄分配先验概率,然后遍历每个基于类别的模型,使用这些分数更新每个类别的先验概率,并从这些后代中选择最可能的类别。听起来有点复杂,但最糟糕的是您会拥有kNN精度。
cwharland 2014年

7

我最近在Python中做了一个类似的项目(使用FB之类的数据来预测意见),并通过以下基本过程获得了良好的结果:

  1. 通过逐行迭代记录(以逗号分隔)来读取训练集中(n = N),并使用计数器来识别最受欢迎的页面
  2. 对于K个最受欢迎的页面(我使用了大约5000个页面,但可以使用不同的值),请使用pandas.DataFrame.isin来测试训练集中的每个人是否喜欢每个页面,然后制作一个N x K数据帧结果(我将其称为xdata_train)
  3. 创建一个包含与xdata_train相同索引的所有结果变量(在我的情况下,根据您的年龄)的系列(我将其称为ydata_train)
  4. 通过scikit-learn设置随机森林分类器,以基于xdata_train预测ydata_train
  5. 使用scikit-learn的交叉验证测试来调整参数并提高准确性(调整受欢迎页面的数量,树的数量,最小叶尺寸等)
  6. 输出随机森林分类器和带泡菜的最受欢迎页面的列表(如果您一次完成所有操作,请保留在内存中)
  7. 加载其余数据,加载流行页面列表(如有必要),然后重复步骤2以生成xdata_new
  8. 加载随机森林分类器(如果需要),并使用它来预测xdata_new数据的值
  9. 将预测的分数输出为新的CSV或您选择的其他输出格式

在您的情况下,您需要将分类器换成回归器(因此请参见此处:http : //scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html),但其他过程相同应该工作没多大麻烦。

另外,您应该知道Python中随机森林的最神奇的功能:即时并行化!我们中那些最初在R中执行此操作然后又移到另一个位置的人总是感到惊讶,特别是当您在具有几十个内核的机器上工作时(请参阅此处:http : //blog.yhathq.com/posts/comparing- python-and-r.html中的random-forests)。

最后,请注意,如果您拥有有关朋友以及个人本身的数据,这将是网络分析的理想应用程序。如果您可以分析用户的朋友的年龄,则该用户的年龄几乎肯定会在其朋友中位数的一两年之内,尤其是如果用户的年龄足够小,可以在仍处于社交网络中建立自己的朋友网络时学校(因为大多数将是同学)。这种预测可能会胜过您从建模中得到的任何预测-这是教科书中的示例,其中每次正确的数据>正确的模型。

祝好运!


2
使用排名前5000位的网站的一个有趣方面是,它们可能不擅长按年龄段细分用户。排名靠前的站点是每个人都可以访问的站点。因此,他们不擅长细分用户,因为所有可能的分类(年龄)都与这些网站有关。这与tf-idf的idf部分类似。idf有助于滤除“每个人都具有此功能”的噪音。访问次数最多的网站如何随您的RF在您的可变重要性图中成为特征?
cwharland

1
好点子。一个简单的解决方法是将训练数据集分层为J个年龄段(例如13-16、17-20、21-24等),并获取每个组的首页(K / J)。这样可以确保您对每个组都有重要的代表。各个组之间肯定会有一些重叠,因此,如果您真的很挑剔,则可能希望每个组都占据唯一的(K / J)唯一页面,但是我认为这可能会过大。
Therriault

5

另一个建议是测试逻辑回归。作为一项额外的奖励,模型的权重(系数)将使您了解哪些站点是按年龄区分的。

Sklearn提供了sklearn.linear_model.LogisticRegression程序包,该程序包还可以处理稀疏数据。

如评论中所述,在当前情况下,输入变量比示例更多,您需要对模型进行正则化(使用sklearn.linear_model.LogisticRegression使用penalty='l1'参数)。


1
我认为,使用LR,您将必须为年龄段制作多个模型。如何比较两个针对不同年龄段的模型,这些模型预测用户的包含概率相同?
cwharland 2014年

1
请注意,当变量多于观察值时,LR会失败;如果不满足模型的假设,则LR的效果会很差。要使用它,降维必须是第一步。
2014年

1
@cwharland,您不应认为响应变量是分类的,因为它本质上是连续的,并且因问题定义而离散。对其进行绝对分类将意味着告诉算法,预测年龄16(实际上是17岁)与预测30(实际上是17岁)时一样严重。 30比17)被认为很大。在这种情况下,使用逻辑回归来预测连续值,而不是估计后验概率。
damienfrancois 2014年

@ChristopherLouden没错,逻辑回归的原始版本不适合“大p小n”情况,我应该提到正则化在当前情况下很重要。我更新我的答案。但是L1正规化的LR是一种功能选择,因此我认为不需要初步的FS步骤。
damienfrancois 2014年

@damienfrancois:我绝对同意。我只是有点担心,在这种情况下,LR会严厉惩罚中间值。鉴于您对极端年龄值不特别感兴趣,似乎没有动力映射到S形曲线。也许我误解了用法。
cwharland 2014年

4

D. Nguyen等人的一些研究尝试根据推特的推文来预测推特用户的年龄。也许您发现它们很有用。他们使用逻辑回归和线性回归。


3

除了更高级的方法,您还可以尝试贝叶斯公式

P(I | p1 ... pn)= P(p1 ... pn | I)P(I)/ sum_i(P(p1 ... pn | i)P(i))

P(I | p1 ... pn)是用户喜欢p1,..,pn的年龄段I的概率

P(i)是用户属于年龄段i的概率

P(p1 .. pn | i)是用户属于年龄段i时喜欢p1,..,pn的概率。

  • 您已经从数据中获得了P(i)的估算值:这只是年龄段I中用户的比例。
  • 为了估计P(p1 ... pn | i),对于每个年龄段,我估计概率(频率)p_ij就像页面j。要使所有j的p_ij不为零,可以以较小的权重混合整个总体的频率。

  • 然后log P(p1 ... pn | i)= sum(log p_ij,i = p1,..,pn),即新用户喜欢的所有页面的总和。假设用户独立喜欢其年龄组中的页面,则此公式将近似成立。

  • 从理论上讲,您还应该为他不喜欢的所有i添加对数(1-p_ij),但是在实践中,您应该发现对数(1-p_ij)的总和将很小,因此您也不需要很多内存。

如果您或其他人尝试过此操作,请对结果发表评论。


2

这是一个非常有趣的问题。

通过分析用户上传到社交网络的图片,我遇到了类似的问题。我做了以下方法:

  • 而不是将数据与年龄(15岁,27岁……)相关联,我要做的是建立不同的年龄组:小于18岁,从18岁到30岁,大于30岁(这是由于我们当时遇到的特定问题面对,但您可以选择所需的任何间隔)。该部门对解决问题有很大帮助。
  • 之后,我创建了一个层次聚类(划分性或聚合性)。然后,选择那些拥有已知年龄(或组年龄)用户的分支机构,然后为该分支机构将相同的年龄扩展到该组。

这种方法是半监督学习,如果您只标记了一些数据,我建议您使用。

请注意,在社交网络上,人们通常会撒谎年龄(只是为了娱乐,有时是因为他们想在社交网络上伪装自己)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.