海量数据的二度人脉挖掘算法(Hadoop 实现)

2019-03-28 13:28|来源: 网络

最近做了一个项目,要求找出二度人脉的一些关系,就好似新浪微博的“你可能感兴趣的人” 中,间接关注推荐;简单描述:即你关注的人中有N个人同时都关注了 XXX 。

在程序的实现上,其实我们要找的是:若 User1 follow了10个人 {User3,User4,User5,... ,User12}记为集合UF1,那么 UF1中的这些人,他们也有follow的集合,分别是记为: UF3(User3 follow的人),UF4,UF5,...,UF12;而在这些集合肯定会有交集,而由最多集合求交产生的交集,就是我们要找的:感兴趣的人。

我在网上找了些,关于二度人脉算法的实现,大部分无非是通过广度搜索算法来查找,由于深度已经明确了2以内;这个算法其实很简单,第一步找到你关注的人;第二步找到这些人关注的人,最后找出第二步结果中出现频率最高的一个或多个人,即完成。

但如果有千万级别的用户,那在运算时,就肯定会把这些用户的follow 关系放到内存中,计算的时候依次查找;先说明下我没有明确的诊断对比,这样做的效果一定没 基于Hadoop实现的好;只是自己,想用hadoop实现下,最近也在学;若有不足的地方还请指点。

首先,我的初始数据是文件,每一行为一个follow 关系 ida+‘\t’+idb;表示 ida follow idb。其次,用了2个Map/Reduce任务。

Map/Reduce 1:找出 任意一个用户 的 follow 集合与 被 follow 的集合。如图所示:

代码如下:

Map任务: 输出时 key :间接者 A 的ID ,value:follow 的人的ID 或 被follow的人的ID

    public void map(Text key, IntWritable values, Context context) throws IOException,InterruptedException{
  int value = values.get();
  //切分出两个用户id
  String[] _key = Separator.CONNECTORS_Pattern.split(key.toString());
  if(_key.length ==2){
   //"f"前缀表示 follow;"b" 前缀表示 被follow
   context.write(new Text(_key[0]), new Text("f"+_key[1]));
   context.write(new Text(_key[1]), new Text("b"+_key[0]));
   
   
  }
 }

Reduce任务: 输出时    key :间接者 A 的ID , value为 两个String,第一个而follow的所有人(用分割符分割),第二个为 被follow的人(同样分割)

    protected void reduce(Text key, Iterable<TextPair> pairs, Context context)
  throws IOException,InterruptedException{
  StringBuilder first_follow = new StringBuilder();
  StringBuilder second_befollow = new StringBuilder();
  
  for(TextPair pair: pairs){
      String id = pair.getFirst().toString();
      String value = pair.getSecond().toString();
   if(id.startsWith("f")){
    first_follow.append(id.substring(1)).append(Separator.TABLE_String);
   } else if(id.startsWith("b")){
    second_befollow.append(id.substring(1)).append(Separator.TABLE_String);
   }
  }
  
  context.write(key, new TextPair(first_follow.toString(),second_befollow.toString()));
    }

其中Separator.TABLE_String为自定义的分隔符;TextPair为自定义的 Writable 类,让一个key可以对应两个value,且这两个value可区分。

Map/Reduce 2:在上一步关系中,若B follow A,而 A follow T ,则可以得出 T 为 B 的二度人脉,且 间接者为A ,于是找出 相同二度人脉的不同间接人。如图所示:

代码如下:

Map 任务:输出时 key 为 由两个String 记录的ID表示的 二度人脉关系,value 为 这个二度关系产生的间接人的ID

public void map(Text key, TextPair values, Context context) throws IOException,InterruptedException{
       //Map<String, String> first_follow = new HashMap<String, String>();
       //Map<String, String> second_befollow = new HashMap<String, String>();
       //String _key = key.toString();
       String[] follow = values.getFirst().toString().split(Separator.TABLE_String);
      
       String[] befollow = values.getSecond().toString().split(Separator.TABLE_String);
      
       for(String f : follow){
        for(String b : befollow){
             //避免自己关注自己
            if(!f.equals(b)){
             context.write(new TextPair(f.getKey() ,b.getKey()), new Text(key));
         }
        }
       }
 }

Reduce任务:输出时 key 仍然为二度人脉关系, value 为所有间接人 的ID以逗号分割。

protected void reduce(TextPair key, Iterable<Text> values, Context context)
 throws IOException, InterruptedException {
 
 StringBuilder resutl = new StringBuilder();
 for (Text text : values){
  resutl.append(text.toString()).append(",");
 }
 
 context.write(key, new Text(resutl.toString()));
}

到这步,二度人脉关系基本已经挖掘出来,后续的处理就很简单了,当然也可以基于二度人脉挖掘三度,四度:)

相关问答

更多
  • Mahout也是使用的MapReduce,只是Mahout将算法自行封装了而已
  • 数据挖掘需要人工智能、数据库、机器语言和统计分析知识等很多跨学科的知识。再者,数据挖掘的出现需要条件,第一个条件:海量的数据;第二个条件:计算机技术大数据量的处理能力;第三个条件:计算机的存储与运算能力;第四个条件:交叉学科的发展。 大数据只是数据挖掘的出现的一个条件。
  • 按我的理解,数据挖掘是一种处理数据,提取数据之间关系的技术。做数据挖掘可分为两种,一种基于算法的研究和程序实现,一种基于数据挖掘软件,例如:SAS、SPSS Clementine。数据挖掘包含的那些算法其实是对数据做处理的一种方式,比如聚类算法,就是将一堆数据聚为几类,而如何完成聚类就要靠算法的应用程序来实现。 你理解的应用程序里面提取数据的方式是按照算法来的,是对的,但是得对应相应的算法。
  • 尝试删除路径中的MovieCollection。 Image Source =“{Binding Path = Rating.UserRatingURL}” Try to remove MovieCollection in your path. Image Source ="{Binding Path=Rating.UserRatingURL}"
  • 您可以使用“self in”和“Subquery”请求进行尝试。 没有测试过这种特殊情况,但这应该是你必须要去的方式 NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setEntity:[NSEntityDescription entityForName:@"B" inManagedObjectContext:context]]; NSPredicate* predicate = [NSPred ...
  • 对于大数据集上的这种连接,现代RDBMS通常会使用称为列表合并的算法。 使用你的例子: 准备一份住在芝加哥的所有作者的名单A,并按O(Nlog(N))时间作者对他们进行排序。* 准备一份所有(作者,书名)对的列表B,并按O(Mlog(M))时间中的作者对它们进行排序。* 将这两个列表“并排”放在一起,然后比较每堆中“顶部”(词典上最小)元素的作者。 他们是一样的吗? 如果是这样: 从top(B)输出(作者,书名top(B) 移除B桩的顶部元素 转到3。 否则,是top(A).author < top(B). ...
  • 是的你可以。 在scikit学习SGD partial fit ; 与你的块一起使用它 http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html#sklearn.linear_model.SGDClassifier partial_fit(X, y[, classes, sample_weight]) Fit linear model with Stochastic Gradient De ...
  • 变 neighbor=nb$name, # h/t @MrFlick for this shortcut 至 neighbor=names(unlist(nb)), # h/t @MrFlick for this shortcut 它现在正在为我工作。 > A lookupnode neighbor 1 A A 2 A B 3 A C 4 H 5 ...
  • DataServiceContextFactory是你自己的类,对吗? (因为那不是你通常实例化DataServiceContext的方式)。 假设它最终创建了一个普通的DataServiceContext实例,那么急切加载多个级别的方法就是在你的Expand扩展调用中指定多个级别。 例如:context.Customers.Expand(“订单/产品”)将返回所有客户,他们的订单以及这些订单的所有产品。 要使LoadProperty正常工作,请确保在DataServiceContext上将属性MergeO ...
  • 如果你不需要使用原始最小二乘公式计算拟合误差(即最小化Σ| y i - (ax i 2 + bx i )| 2 ),你可以尝试执行y/x的线性拟合,因为(ax 2 + bx)/ x = ax + b。 如果必须使用相同的误差度量,请直接构造系数矩阵并使用numpy.linalg.lstsq : coeff = numpy.transpose([x*x, x]) ((a, b), _, _, _) = numpy.linalg.lstsq(coeff, y) polynomial = numpy.poly1d ...