过去一段时间在对python版本的评分卡模型做效率优化。之前的版本已经实现了所有功能但是速度实在太慢。13W的数据量包含130个特征(其中30个连续值)使用原来的版本需要花费将近两小时的时间才能够计算出所有特征值的IV。这个效率实在是。。。。
经过优化,现在可以将时间控制在5s左右。可以说是相当不错了。
接下来小结一下关于python代码方面优化的方法。(算法方面没啥可改的就是简单的统计数)
环境
python版本:python 2.7
包:numpy和pandas
效率优化方法
pandas一些优化的细节
使用DataFrame.concat()代替DataFrame.append()
将数据处理好存储为list,再将list用concat连接。
这种方法的效率比直接在DataFrame后面使用append。效率要高出30%~50%- Dataframe的append效能很低,如果我们知道未来表的条目,预先分配好空间,将来直接向里面填入内容会快不少
# 例子 # 预先分配好内存空间 outdf = pd.DataFrame(pd.np.empty((output_index_num, len(indf.columns))) * pd.np.nan, columns = indf.columns) # 用for循环来补充数据 for outindex in range(0, output_index_num): # have some fun here outdf.loc[outindex] = indf.loc[int(len(indf) * outindex / output_index_num)]
- pandas中loc,iloc,ix,at这几种方法的选择
%timeit outdf.loc[0] = indf.loc[0] 100 loops, best of 3: 11.7 ms per loop %timeit outdf.iloc[0] = indf.iloc[0] 100 loops, best of 3: 11.4 ms per loop %timeit outdf.ix[0] = indf.ix[0] 100 loops, best of 3: 11.6 ms per loop %timeit outdf.at[0,'time'] = indf.at[0,'time'] 10000 loops, best of 3: 25.3 µs per loop
loc,iloc,ix速度相似,可是at却快了将近1000倍。
可惜的是at只能选择某个单元而不是整行。- 并行计算
这个所有加速效率中最简单效果也是最稳定的方法了。
python中有几种多进程的方法。
1.multiprocessing
2.joblib中的Parallel,delayed
# joblib例子
from joblib import delayed, Parallel
def square(x): return x*x
values = Parallel(n_jobs=NUM_CPUS)(delayed(square)(x) for x in range(1000))
# Parallel(n_jobs=cpu核心数)
#(delayed(函数名)(函数参数列表) for x ...)
2. python垃圾自动回收机制
Python常用的垃圾回收(GC)算法有这几种引用计数(Reference Count)、Mark-Sweep、Copying、分代收集。在Python中使用的是引用计数。
工作原理:为每个内存对象维护一个引用计数。
因 此得知每次内存对象的创建与销毁都必须修改引用计数,从而在大量的对象创建时,需要大量的执行修改引用计数操作(footprint),对于程序执行过程 中。
这个方法大概能够提高10%左右的效率。
- 使用pypy编译器
PyPy是用RPython(CPython的子集)实现的Python,根据官网的基准测试数据,它比CPython实现的Python要快6倍以上。快的原因是使用了Just-in-Time(JIT)编译器,即动态编译器,与静态编译器(如gcc,javac等)不同,它是利用程序运行的过程的数据进行优化。由于历史原因,目前pypy中还保留着GIL,不过正在进行的STM项目试图将PyPy变成没有GIL的Python。
如果python程序中含有C扩展(非cffi的方式),JIT的优化效果会大打折扣,甚至比CPython慢(比Numpy)。所以在PyPy中最好用纯Python或使用cffi扩展。
由于numpy和pandas底层许多方法由C语言实现,所以在实际使用过程中,pypy编译的效率反而变得更加慢。可以看出如果对于pure python代码,使用pypy编译可以得到效率极大的提高。
使用numba加速
numba中加速的方法和pypy加速的方法是相同的。就是使用JIT来提高python脚本语言的执行速度。缺点也相同,对于python程序中含有C扩展(非cffi的方式)效果反而不够好。
使用Cython来进行加速
这个就需要有C语言开发的基础了。可以很方便的将一些函数使用C语言的方法进行重写,从而加快代码的执行效率。
使用向量化来操作pandas
这个效率提高特别高。在我的代码中使用这个方法将效率提高了700+倍。相同的数据量下时间花费也从原来的接近两小时降低到只要10s左右。可见这个效率提升之恐怖。
具体操作请查看参考”优化Pandas代码执行速度入门指南”
存储优化方法
第一种方法是对pandas中数值型数据的降级。比如将int32转为int16.float64转为float32.
第二种方法是将objcet类型转换为category类型。这个是最节约空间的方法。具体优化方法请见参考 “用pandas处理大数据———减少90%内存消耗的小贴士”
如何提高pandas读取速度
可以查看参考 ” 使用Python Pandas处理亿级数据”
这里小结一下这段时间尝试的方法,同时也对python的优化有了一些认识。希望对大家有一点借鉴作用。
参考:
- 简单两步,大幅提高python数据处理速度
- Python多进程并发(multiprocessing)
- python平行(3):【parallel python】与【sklearn joblib的parallel和delayed】性能对比
-Python 代码性能优化技巧-ibm
-Python内存管理机制及优化简析
-如何让 Python 像 Julia 一样快地运行-ibm
-优化Pandas代码执行速度入门指南
-用pandas处理大数据———减少90%内存消耗的小贴士
-使用Python Pandas处理亿级数据