我有一个十多万条的数据集,里面有一些类别型变量和数值型变量,现在需要找出其中最相似的部分,于是我打算计算整个数据集的距离。
我做了以下尝试,都报错说内存不够(我电脑才16G内存):
1.用cluster包的daisy(data, metric = "gower")直接算。只算一万条的时候电脑还能活蹦乱跳的,十万条的时候就直接歇菜了。
2.有个K-prototpe的聚类方法是专门针对混合型数据的,其中算距离那一步针对类别型变量用得是“汉明距离”,于是我用e1071包中的hamming.distance函数来只对类别型变量算,但还是报错内存不够。

此处吐个槽,由于我R和Python都得用用且跑数的时候会看任务管理器,就发现R跑起来是内存涨得多,而Python跑起来CPU涨得多。

    解决这个问题没什么技巧,先生成下标对,按下标对并行就是了
    https://github.com/nanxstats/protr/blob/master/R/par-01-parSeqSim.R#L60

    如果数据太大,想更有效利用内存,可以实现一个缓存机制分批并行
    https://github.com/nanxstats/protr/blob/master/R/par-01-parSeqSim.R#L169

    整体来说 16G 内存的机器会大大限制你的并行规模和速度,所以有必要增加核数和内存

      yuanfan

      这是古典场景,深度学习训练时经常会用的解决办法,就是不要一股脑地把数据都载入嘛,先随机抽一批计算,然后留下核心点和参数,把旧数据丢掉载入新数据,重复以上直到核心点和参数的变动小于某个阈值。

      2 年 后

      nan.xiao
      我有一个疑问。做聚类时,从初始聚类中心到最终聚类中心的过程是不断迭代的,是像上一楼所说那样,下一次迭代是在上一次基础上比较出来的。迭代从本质上来讲应该属于串行,我一时想不明白应该怎么并行呢?把数据随机分割,强行并行么?

        yuanfan

        你想找数据中最相似的部分,如果是n条记录,那么两两配对计算距离就是n(n - 1)/2个记录对需要计算。这些配对之间的计算是独立的,可以并行。这就是 nan.xiao 提到的按下标对并行。当然你如果直接在R/python中这么并行的话,很有可能还是内存先爆,所以需要一些并行的实现上的优化。

        迭代的时候这一步依赖上一步,那不好并行。但是现在讨论的相当于是数据集已经大到这“一步”内的计算量都需要并行了。

        楼上正解。计算距离/相似度矩阵和做聚类是可以分开看的两件事情。如果有内存高效的聚类实现那当然好,如果没有那就得加内存或者手工做某些计算来限制空间占用。我在 2 楼提到的思路就是解决计算这个占用内存的距离矩阵的问题:先能在不爆内存的情况下更快计算出这个矩阵,再考虑能直接接受距离/相似度矩阵作为输入的聚类方法,或者自己实现。

        对于这种内存过小已经成为瓶颈的情况,我个人倾向于先加内存到 64G 到 128G,如果还是爆内存或单线程太慢,再去考虑代码层面优化的问题(假设已有的聚类方法的实现已经比较高效)。

        这个问题时隔两年,本 R 新手也稍微进步了一小丢丢。暂且撇开一楼原来的问题先不说,我现在遇到的问题也还是不知道怎么并行。实际上,“不知道怎么并行”分为两个问题。

        问题一

        背景是这样的,集群上面有7个节点可以给我用,由于平时负载不高,所以如果我会用的话,每个节点可以用50%的资源。但我不会……我现在在其中2个上面分别安装了 R 和 Rstudio Server,倒是可以手动并行,就是分别把数据导过去,然后分别手动执行代码。但我不知道应该怎么让2个或者说7个节点的资源同时为我所用。这一部分,俺一片混沌。

        问题二

        本来串行的算法应该怎么并行?比如逐步回归,比如 XGBoost 等。话说关于 XGBoost 如何并行这个问题,我拿去问了下新必应,它的答案是这样的:

        正在搜索: R xgboost parallel computing example code
        正在为你生成答案...

        好的,我找到了一些网上的示例代码,你可以参考一下:

        • 如果你想用XGBoost的nthread参数来实现隐式并行计算,你可以参考这个网站1上的代码,它展示了
          如何用xqboost函数来训练一个二分类模型,并设置nthread为4。

        • 如果你想用tune包和future包来实现显式并行计算,你可以参考这个网站2上的代码,它展示了如何用tune_grid函数来调整一个多分类模型的超参数,并设置control参数为control_grid(verbose=FALSE parallel_over = "everything”)。

        • 如果你想用caret包和doParallel包来实现显式并行计算,你可以参考这个网站了上的代码,它展示了如何用train函数来训练一个回归模型,并设置method为"xgbTree",以及使用registerDoParallel函数来注册一个并行后端。希望这些代码对你有帮助。
          了解详细信息: :1.r-bloggers.com 2. statology.org 3. xgboost.readthedocs.io

        如果说我想要在7个节点上都能执行 R 代码,前提是不是也得先给它们都装上 R 和 R 包?如果是的话,那我好像应该先照着湘云写的 Docker 入门先弄一个完整的镜像出来,然后挨个复制到其他节点上面去……

        我在上次的中国R语言会议上稍微介绍了点并行计算,也许能帮到你一点。

        简而言之确实需要各节点上都能有R运行起来才能并行。配置方面如果用docker的话可能在配置的时候需要做好端口转发,这样当你主节点上的R要分配任务是才能连接到从节点机器docker内的R中。

        我个人推荐可以从future和同系列的future.apply,furrr等入门。你在futureplan函数里配置好并行的基础设置(有多少节点,如何链接等),接下来支持future后端的函数就会自动进行并行计算。

        关于问题2就只能case by case了,一些算法的实现本身就没有考虑并行,那么你可能需要自己手写甚至是从头进行支持并行的设计。一些算法的软件包实现中考虑了并行,但是采用的到底是如何的并行实现也只有具体看了才知道:比方说有的只支持本机并行,有的则可以跨机器分布式计算。

          fenguoerbian
          你去年在会上讲的内容我听了的,哈哈,对于你举的那个小孩算数的例子印象贼深刻。不过我记得你原本是说要讲自动化特征工程的,我对这个也很期待,希望以后有机会能听你讲这个。

          你的答案我看明白了,对我这样的 R 新手来说真的是,道阻且长。不过我最近把这个帖子捞上来的具体原因是,我用xgboost 寻参的方法是网格寻参,很慢,所以想着是不是可以用并行计算加快速度。但是没想到要学会用那些资源还得瞎折腾一波。又但是,我翻出来一个寻参很快的 R 包 ParBayesianOptimization。感觉学个新的 R 包,能比折腾 Docker 镜像上手更快,还不用担心后续维护管理问题。

          也许下半年我会考虑折腾学习一下你推荐的future,要是那时没被劝退的话,再来向你请教。