找回密码
 立即注册
搜索

干货!机器学习中,如何优化数据功能

本文次要经过优化数据结构以及一些运用中的留意点来提高在大数据量下数据的处理速度。


作者 | 中国农业银行研发中心 张梓聪

出品 | AI 科技大本营(ID:rgznai100)

头图 | 下载于视觉中国

得益于覆盖各种需求的第三方库,Python在明天曾经成为了研讨机器学习的主流工具。不过由于其解释型言语的特性,在运转速度上往往和传统编译型言语有较大差距。特别是当训练数据集非常庞大时,很多时分处理数据本身就会占用大量的工夫。

Python中本身提供了非常弱小的数据存储结构:numpy库下的ndarry和pandas库下的DataFrame。前者提供了很多list没有完成的便利功能,而后者是最方便的column-row型数据的存储方式,异样提供了大量方便的随机访问函数。

但是不正确的运用很多时分反而会适得其反,给人一种如此高级的三方库功能还不如list手动造轮子的错觉。

本文次要经过优化数据结构以及一些运用中的留意点来提高在大数据量下数据的处理速度。
避免运用append来逐行添加结果


很多人在逐行处理数据的时分,喜欢运用append来逐即将结果写入DataFrame或ndarry。相似下面的写法:



这是非常不好的习气,numpy或pandas在完成append的时分,实践上对内存块停止了拷贝——当数据块逐渐变大的时分,这一操作的开支会非常大。

下面是官方文档对此的描画:

Numpy:



Pandas.DataFrame:



实践上,受list的append操作的影响,开发者会不假思索的以为numpy和pandas中的append也是简单的数组尾部拼接。这实践上是一个很严重的曲解,会产生很多不必要的拷贝开支。笔者没有深化研讨它们这么设计缘由,猜测能够是为了保证拼接后的数组在内存中依然是延续区块——这对于高功能的随机查找和随机访问是很有必要的。

处理办法:除非必须,在运用DataFrame的部分函数时,思索将inplace=True。出于保证原始数据的分歧性,DataFrame的大部分方法都会前往一个原始数据的拷贝,假如要将前往结果写回,用这种方式效率更高。

除非必须,避免运用逐行处理。Numpy和pandas都提供了很多非常方便的区块选取及区块处理的办法。这些功能非常弱小,支持按条件的选取,能满足大部分的需求。同时由于ndarry和DataFrame都具有良好的随机访问的功能,运用条件选取执行的效率往往是高于条件判别再执行的。



特殊状况下,运用预先声明的数据块而避免append。假如在某些特殊需求下(例如当前行的处理逻辑依赖于上一行的处理结果)并且需求构造新的数组,不能直接写入源数据时。这种状况下,建议提早声明一个足够大的数据块,将自增的逐行添加改为逐行赋值。



这种写法本质上是经过空间换取工夫,即便数据量非常宏大,无法一次性写入内存,也可以经过数据块的方式,减少不必要的拼接操作。需求留意的是,数据块的边界处理条件,以避免漏行。

避免链式赋值


链式赋值是几乎一切pandas的新人都会在不知不觉中犯的错误,并且产生恼人而又意义不明的SettingWithCopyWarning正告。实践上这个正告是在提示开发者,你的代码能够没按你的预期运转,需求检查——很多时分能够产生难以调试发现的错误。当运用DataFrame作为输入的第三方库时,非常容易产生这类错误,且难以判别成绩到底出如今哪儿。

在继续讲解链式复制前,需求先了解pandas的方法有一部分是前往的是输入数据的视图(view)一部分前往的是输入数据的拷贝(copy),还有少部分是直接修正源数据。



上图很好的解释了视图与拷贝的关系。当需求对df2停止修正时,有时分我们希望df1也能被修正,有时分则不希望。而当运用链式赋值时,则有能够产生歧义。这里的歧义指的是面向开发人员的,代码执行是不会有歧义的。

链式索引,就是对同一个数据延续的运用索引,形如data[1:5][2:3]这样。而链式赋值,就是运用链式索引停止赋值操作。下图是一个链式赋值的例子,解释器给出了SettingWithCopyWarning正告,同时对data的赋值操作也没有成功。



处理办法:上图中的正告建议,当你想修正原始数据时,运用loc来确保赋值操作被在原始数据上执行,这种写法对开发人员是无歧义的(开发人员往往会误以为链式赋值修正的依然是源数据)。

反过来的状况并不会发生这种歧义。假如开发人员想选取源数据的一部分,修正其中某列的值并赋给新的变量而不修正源数据,那么正常的写法就是无歧义的。



但是有些隐蔽的链式索引往往并不是简单的像上述状况那样,有能够跨越多行代码,甚至函数。下图的例子中,data_part是对data的选取,而赋值操作又对data_part停止了选取,此时构成了链式索引。



处理办法:当你确定是要构造拷贝时,明白指明构造拷贝。避免对有能够是视图的中间变量停止修正。



需求留意的是:DataFrame的索引操作到底是前往视图还是前往拷贝,取决于数据本身。对于单类型数据(全是某一类型的DataFrame)出于效率的思索,索引操作总是前往视图,而对于多类型数据(列与列的数据类型不一样)则总是前往拷贝。但也请不要依赖这一特性,由于根据内存规划,其行为未必总是分歧。最好的方法还是明白指定——假如想要写入副本数据,就在索引时明白拷贝;假如想要修正源数据,就运用loc严厉赋值。
总结


1.可以直接修正源数据就修正源数据,避免不必要的拷贝;

2.运用条件索引替代逐行遍历;

3.构造数据块替代逐行添加;

4.想修正源数据时运用data.loc[row_index, col_index]替代链式赋值;

5.想构造副本时严厉运用copy消弭隐形链式赋值。

参考材料:

https://numpy.org/doc/stable/reference/generated/numpy.append.html

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.append.html

https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#indexing-label

https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#indexing-view-versus-copy

https://zhuanlan.zhihu.com/p/41202576
编辑:王菁

校正:林亦霖

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

大神点评5

moxiuluolun 2021-6-23 13:05:23 显示全部楼层
分享了
回复

使用道具 举报

分享了
回复

使用道具 举报

看起来不错
回复

使用道具 举报

看不到角 2021-6-25 13:31:46 显示全部楼层
无论是不是沙发都得回复下
回复

使用道具 举报

邦枝5葵 2021-6-26 12:06:58 显示全部楼层
元芳你怎么看?
回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies