Mapreduce实现机器学习(自己动手实现)

6 篇文章 0 订阅
5 篇文章 6 订阅

        因为涉及到机器学习,首先一点需要说明的就是为什么使用Mapreduce而不是Spark,其实Mapreduce之所以一直被人诟病就是因为Mapreduce是基于磁盘交互的迭代计算框架,在迭代过程中(不是中间shuffle结果)都是基于磁盘交互,也就是写入磁盘再从磁盘中读出。这里需要说明的是很多文章对于Spark和Mapreduce的定义就是一个是基于内存交互,一个是基于磁盘交互,当然这样说更省力更好理解,但是往往都是对此的误解,因为不管是哪一个框架,中间shuffle结果都是基于磁盘的,也是一个小坑。

        最终影响速度的就是迭代结果的io消耗。

当然,就算如此我们也可以用Spark,不错当然可以,前提你是有一台性能较好的服务器或者自用电脑,本人在用16GB内存的电脑,搭建分布式集群在执行复杂度较高的算法,并且有一定量的数据时,报错这是最难解决的,当然排查日志当然是第一首选手段,你要知道几十MB的log日志打开电脑基本上是卡死状态,你也可以用某些比较好的中间软件notepad++,不过一样使用手感极差。所以我觉得在某种程度上MR框架是优于Spark的。

        回归整题

那么Mapreduce如何可以实现机器学习算法呢?我相信不少人使用过Mahout框架,上面确实集成了不少的经典算法,但是在排查源码时,和我们自己手动写的Map和Reduce框架还是有所不同,当然你可以深追源码。

首先实现机器学习,比如聚类算法的Kmeans首先需要解决的不是参数问题,而是变量问题,在分块之后如何可以将簇质心位置同步给每一个节点。

tips:我发现大家对分布式有一个误解,那就是分布式是分布式进行计算结果,而不是分布式聚类,得到若干个聚类结果,然后进行聚类集成。首先聚类集成是一个非常难的问题,尤其是在标签问题上,很多文章提出用投票法来解决标签问题来合并簇,我觉得并非是一个好的选择。

因为要分发,所以引入一个概念:全局变量

查阅比较多的资料并且在实际中我主要是用到了两种全局变量。

  1. 在driver类中的conf设置参数
  2. 使用distributioncache来分发文件

首先来说明第一种,我觉得完全没用,首先如果你在编码阶段知道的实际参数值,你完全可以在map和reduce阶段进行赋值,如果是需要在外部接收参数,在使用hadoop jar方式进行运行时是完全接收不到,当然这里使用的是将参数分解提取,无效

第二种就是机器学习实现的关键,可以将参数存入文件中,在读取,尤其是在机器学习中这种全局变量的方式是最好的。

  job.addCacheFile(new Path("1.txt").toUri());

在driver中添加如下代码,便可对所有节点进行分发文件。

另外需要补充的就是,在Reduce中使用全局变量(类全局变量)无效,具体是什么原因还需要排查源码才可知道,但是在Map(类全局变量)有效。

在Reduce中定义集合,添加对象会使得集合中重复最后一条元素。

好了至此,Mapreduce实现机器学习的步骤已经讲完,Kmeans并不是多么难的算法可以自己动手来写一写,下面贴一部分代码。

 public static Path buildClusters(Configuration conf, Path input, Path clustersIn, Path output,
    int maxIterations, String delta, boolean runSequential) throws IOException,
    InterruptedException, ClassNotFoundException {
    
    double convergenceDelta = Double.parseDouble(delta);
    List<Cluster> clusters = new ArrayList<>();
    KMeansUtil.configureWithClusterInfo(conf, clustersIn, clusters);
    
    if (clusters.isEmpty()) {
      throw new IllegalStateException("No input clusters found in " + clustersIn + ". Check your -c argument.");
    }
    
    Path priorClustersPath = new Path(output, Cluster.INITIAL_CLUSTERS_DIR);
    ClusteringPolicy policy = new KMeansClusteringPolicy(convergenceDelta);
    ClusterClassifier prior = new ClusterClassifier(clusters, policy);
    prior.writeToSeqFiles(priorClustersPath);
    
    if (runSequential) {
      ClusterIterator.iterateSeq(conf, input, priorClustersPath, output, maxIterations);
    } else {
      ClusterIterator.iterateMR(conf, input, priorClustersPath, output, maxIterations);
    }
    return output;
  }

特地说明一下,对于Mapreduce来实现Kmeans,串行job,然后根据簇质心或者其他收敛条件皆可。

最后祝大家五一快乐!!

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值