在多核机器上的sklearn.naive_bayes.MultinomialNB上执行网格search不会使用所有可用的CPU资源

在多核机器上的sklearn.naive_bayes.MultinomialNB上执行网格search不会使用所有可用的CPU资源,第1张

概述在多核机器上的sklearn.naive_bayes.MultinomialNB上执行网格search不会使用所有可用的CPU资源

我目前正在尝试使用Python和Scikit-learn来构build一些文本分类工具。

我的文字不是英文的,因此,不会受到分解或其他基于英语的维度降低的惯常处理。

因此,TfIDfmatrix变得相当大(150,000×150,000)它可以使用普通的PC进行处理,但是对它们进行网格search会太多,所以我通过Amazon Web Service的帮助来运行网格search。 (我的参数设置也很大)

这是我的代码:

检查文件修改date和电子邮件,如果它已经改变

在主机上运行我的Intellij IDE,我需要ZeroMQ来与来宾的后端应用进行通信

linux ARM上的程序寄存器和堆栈的初始状态

什么是常用的库在linux上编写OpenGL 4.X应用程序?

上下文切换在linux中需要多长时间?

# Coding: utf-8 import os,Json,codecs,nltk import numpy as np from sklearn.feature_extraction.text import TfIDfVectorizer,CountVectorizer,TfIDftransformer from sklearn.grID_search import gridsearchcv from time import time from sklearn.pipeline import Pipeline from sklearn.naive_bayes import MultinomialNB print("importing dataset...") with open('y_data.Json','r') as fp: y = Json.load(fp) with open('dataset.Json','r') as fp: dataset = Json.load(fp) print("importing stop words...") with codecs.open('stopword.txt','r','utf-8') as fp: stopword = [] for w in fp: stopword.append(w.strip()) light_st = set(stopword) with codecs.open('st_data.txt','cp874') as fp: for w in fp: stopword.append(w.strip()) heavy_st = set(stopword) def pre_process_1(text): return text.replace("|"," ") def tokenize_1(text): return text.split() pipeline = Pipeline([('vec',CountVectorizer(enCoding='cp874',preprocessor=pre_process_1,tokenizer=tokenize_1,stop_words=heavy_st,token_pattern=None)),('tfIDf',TfIDftransformer()),('clf',MultinomialNB())]) parameters = { 'vec__max_df': (0.5,0.625,0.75,0.875,1.0),'vec__max_features': (None,5000,10000,20000),'vec__min_df': (1,5,10,20,50),'tfIDf__use_IDf': (True,False),'tfIDf__sublinear_tf': (True,'vec__binary': (True,'tfIDf__norm': ('l1','l2'),'clf__Alpha': (1,0.1,0.01,0.001,0.0001,0.00001) } if __name__ == "__main__": grID_search = gridsearchcv(pipeline,parameters,n_jobs=-1,verbose=2) t0 = time() grID_search.fit(dataset,y) print("done in {0}s".format(time() - t0)) print("Best score: {0}".format(grID_search.best_score_)) print("Best parameters set:") best_parameters = grID_search.best_estimator_.get_params() for param_name in sorted(List(parameters.keys())): print("t{0}: {1}".format(param_name,best_parameters[param_name]))

这里是我的软件环境的细节:

python3.4.2

scikit-learn 0.15.2(与Pip一起安装)

Ubuntu Server14.04 LTS,64位(使用HVM)

在ec2 r3.8xlarge实例上尝试

起初,我使用一个更小的实例(r3.2xlarge; 8个核心)来运行我的模型,但是从计算中发现需要相当长的时间(2天)。 所以,我决定放大我的机器并使用最大的实例(我使用r3,因为我的脚本内存密集)。 然而,这并没有像我所想的那么快。

当我试图监视cpu负载时(注意-n 5正常运行时间)…我发现,即使当我离开它运行一段时间时,平均cpu负载从不超过9。 (据我所知,一个三十二个核心机器,充分利用它的所有内核时,应该在32个左右)。

我试图改变

n_job

参数以不同的数字(8,32,128)与相同的结果。 (但是我认为这个脚本试图按照指示运行尽可能多的工作,因为当我终止这个过程时,我会看到类似于……“Process ForkPoolWorker-30:”和它们的回溯鞭打过屏幕)

使用ps x -C python3.4命令进行进一步检查可以得出只有8个python进程正在运行。 我推断这可能是从Python或 *** 作系统的某种限制(我使用t2.micro实例构build我的AMI,它没有太多的核心)所以,我决定重新从头开始重build我的环境,包括编译Python使用c3.4xlarge,并将 *** 作系统更改为Amazon linux(我认为Fedora的一个分支),以便与硬件更好地兼容。

但是,我的脚本仍然没有超过8个核心。 最后,使用Scikit-learn网站的演示文本分类代码: http ://scikit-learn.org/stable/auto_examples/grID_search_text_feature_extraction.HTML(使用SGDClassifIEr代替MultinomialNB)它可以与所有32个核心完美的运行!

所以…也许,与网格searchalgorithm和朴素贝叶斯分类器有关?

我正在考虑提交一个BUG,但是想知道这是否是Naive Bayes的预期行为,或者如果我的代码出错了?

更新

我无法find一种方法来testing内存带宽是否是直接的罪魁祸首。 但是我尝试用各种方式来计算我的并行代码和cpu使用情况,以确定瓶颈的确切位置。

实验1:只进行vector化和转换。

使用我的真实数据作为input(150,000文本文档;每个包含大约130个字)


参数空间大约是400。


multithreading是由Joblib完成的(与Scikit-learn使用的模块相同)。 我有:


使用8个线程:在841.017783164978 s完成,使用24.636999999999993%的cpu。


使用16个线程:在842.9525656700134中完成,使用24.700749999999985%的cpu。


使用全部32个线程:在857.024197101593中完成,使用24.242250000000013%的cpu。

结果清楚地表明,随着处理能力的增加,vector化过程不能成比例。

实验2:这次我只对预vector化数据执行MultinomialNB。

使用约400的参数空间,我得到了:


使用8个线程:完成2102.0565922260284秒,使用25.486000000000054%的cpu。


使用16个线程:在1385.6887295246124s完成,使用49.83674999999993%的cpu。


使用全部32个线程:在1319.416403055191s完成,使用89.90074999999997%的cpu。

从8个线程到16个线程的转换显示了巨大的改进。 但是,随着线程数量增加到32个,总体完成时间只会略微缩短,而cpu使用率则会大幅增加。 这一点我不太明白。

实验3:我将这两个过程结合在一起。

使用8个线程:完成3385.3253166675568秒,使用25.68999999999995%的cpu。


使用16个线程:在2066.499200105667s完成,使用49.359249999999996%的cpu。


使用全部32个线程:在2018.8800330162048 s完成,使用54.55375000000004%的cpu。

从我自己的并行代码和gridsearchcv获得的时间之间有一些差异,但这可能是因为我在代码中完成的简化(我没有进行交叉valIDation或全参数迭代GrIDsearch)

结论

从我的testing中,我得出这样的结论。 (如果我错了,请纠正我)

vector化阶段使用内存更encryption集; 因此最有可能使带宽饱和。 这可以从完成时间和cpu利用率观察到,它遇到了某种瓶颈,并没有规模。 但是,这是一个相对较快的过程。 (因为所有数据都存储在RAM上,所以消除了IO限制,在这段时间内存使用量约为30%)

MultinomialNB使用比vector化器更less的内存; 大部分的计算似乎是在核心处理。 因此,它可以比vector化器(8> 16)更好地缩放,但是之后它也会碰到某种瓶颈,MultinomialNB比vector化器需要更多的时间。

在将两个进程结合在一起时,完成时间performance出与MultinomialNB相同的趋势,因为在我看来,内存带宽可能是向量化阶段的瓶颈,但与MultinomialNB相比这个阶段相对较短。 因此,如果并发任务数量less,则可以同时进行这两个阶段,而不会使带宽饱和,但是当进程数量足够多时,会有足够数量的并发进程执行vector化来饱和带宽; 从而迫使 *** 作系统减less运行过程。 (解释一下我之前发现的运行python的进程只有8-9)

我不是很确定,但我认为SGDClassifIEr可以使用100%cpu的原因是SGDClassifIEr比MultinomialNB有更长的核心处理时间。 因此,在每次迭代中,大部分时间都用于内核计算SGDClassifIEr,而不是进行vector化,并且SGDClassifIEr需要很长时间来计算的事实减less了许多工人同时进入vector化阶段的机会(如每个vector化任务相对较短但内存密集)

我想现在我最好的select是去集群计算。 总结

以上是内存溢出为你收集整理的在多核机器上的sklearn.naive_bayes.MultinomialNB上执行网格search不会使用所有可用的CPU资源全部内容,希望文章能够帮你解决在多核机器上的sklearn.naive_bayes.MultinomialNB上执行网格search不会使用所有可用的CPU资源所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1269087.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存