当前位置: 首页 > 科技观察

三行Python代码,让数据预处理速度提升2到6倍

时间:2023-03-12 02:51:40 科技观察

Python是机器学习领域最好的编程语言。但是当我们面对大量数据时,就会出现一些问题……目前,大数据一词通常用来指代包含数十万个数据点的数据集。在这种规模下,添加到工作进程的任何额外计算都需要持续关注以保持效率。在设计机器学习系统时,数据预处理非常重要——在这里我们必须对所有数据点应用某种操作。默认情况下,Python程序是单个进程,使用单个CPU内核执行。大多数现代机器学习硬件至少有一个双核处理器。这意味着如果不进行优化,在数据预处理时会出现“一核难,九核在看”的情况——超过50%的算力会被浪费掉。对于当前的四核处理器(英特尔酷睿i5)和六核处理器(英特尔酷睿i7),这将变得更加明显。幸运的是,Python库中内置了一些隐藏功能,可以让我们充分利用所有CPU内核的强大功能。通过使用Python的concurrent.futures模块,我们只需要3行代码就可以将一个普通的程序转换成适合在多核处理器上并行处理的程序。标准方法让我们举一个简单的图像数据集示例,该数据集在一个文件夹中包含数万张图像。这里我们决定使用1000张。在将所有图像传递给深度神经网络之前,我们希望将所有图像的大小调整为600×600像素分辨率。这是您经常在GitHub上看到的标准Python代码:resize(img,(600,600))上面的程序遵循处理数据脚本时经常看到的简单模式:从需要处理的文件(或其他数据)列表开始。使用for循环逐条处理每条数据,然后在每次循环迭代时运行预处理。让我们在包含1000个jpeg文件的文件夹上测试这个程序,看看运行需要多长时间:timepythonstandard_res_conversion.py在我的Corei7-8700k6核CPU上运行了7.9864秒!在如此高端的CPU上看着这个速度似乎无法接受,让我们看看我们能做些什么。更快的方法要理解并行化的改进,假设我们需要执行相同的任务,例如将1000颗钉子钉入木头,如果需要一秒钟才能钉一颗,那么一个人将需要1000秒才能完成任务。四人一组只需250秒。在我们有1000张图像的示例中,可以让Python执行类似的工作:将jpeg文件列表分成4组;在Python解释器中运行4个独立的实例;让每个Python实例处理4个数据组中的一个;将四个过程得到的结果结合起来,得到最终的结果列表。这种方法的要点是Python为我们处理所有艰苦的工作。我们只需告诉它我们要运行哪个函数,要使用多少个Python实例,剩下的就由它来完成!只需更改三行代码。实例:importglobimportosimportcv2importconcurrent.futuresdefload_and_resize(image_filename):###Readintheimagedataimg=cv2.imread(image_filename)###Resizetheimageimg=cv2.resize(img,(600,600))###Createapoolofprocesses.Bydefault,oneiscreatedforeachCPUinyourmachine.withconcurrent.futures.Process.)asexecutor:###Getalistofffilestoprocessimage_files=glob.glob("*.jpg")###Processthelistofffiles,但将工作拆分到进程池中以使用所有CPU###循环遍历当前文件夹中的所有jpg文件###Resizeeachonetosize600x600executor.map(load_and_resize,image_filesfromtheabovecodeextractline)ProcessPoolExecutor()asexecutor:你拥有的内核越多,你启动的Python进程就越多。我的CPU有6个内核。实际处理代码如下:executor.map(load_and_resize,image_files)"executor.map()"将你要运行的函数和一个列表作为输入,其中列表中的每个元素都是我们函数的单个输入。由于我们有6个核心,我们将同时处理此列表中的6个项目!如果我们再次运行我们的程序:timepythonfast_res_conversion.py,我们可以将运行时间降低到1.14265秒,几乎是6倍的加速!注意:生成更多Python进程并在它们之间编组数据会产生一些开销,因此加速并不总是那么明显。但总的来说,速度提升还是很可观的。总是那么快吗?如果你有一个数据列表要处理并在每个数据点上执行类似的操作,那么使用Python并行池是一个不错的选择。但有时这不是最好的解决方案。并行池处理的数据不会以任何可预测的顺序处理。如果您对处理后的结果有特殊的排序要求,那么这种方式可能不适合您。您处理的数据也必须是Python可以“烹饪”的类型。幸运的是,这些指定类别非常普遍。以下内容来自Python官方文档:None、True和False整数、浮点数、复杂字符串、字节、字节数组仅包含可选对象的元组、列表、集合和字典在模块顶层定义的函数(使用def,而不是lambda)定义在模块顶层的内置函数类定义在此类类的模块实例的顶层,其__dict__或调用__getstate__()的结果是可选择的(参见名为“PicklingClassInstances”的部分”)。原文链接:https://towardsdatascience.com/heres-how-you-can-get-a-2-6x-speed-up-on-your-data-pre-processing-with-python-847887e63be5【本文为专栏《机器之心》组织原译,微信公众号《机器之心(id:almosthuman2014)》】点此查看作者更多好文

猜你喜欢