『阿里云云栖号』阿里云云效团队在家高效开发实录,战“疫”期

背景在数据科学世界 , Python是一个不可忽视的存在 , 且有愈演愈烈之势 。 而其中主要的使用工具 , 包括Numpy、Pandas和Scikit-learn等 。
NumpyNumpy是数值计算的基础包 , 内部提供了多维数组(ndarray)这样一个数据结构 , 用户可以很方便地在任意维度上进行数值计算 。
『阿里云云栖号』阿里云云效团队在家高效开发实录,战“疫”期
文章图片
我们举一个蒙特卡洛方法求解Pi的例子 。 这背后的原理非常简单 , 现在我们有个半径为1的圆和边长为2的正方形 , 他们的中心都在原点 。 现在我们生成大量的均匀分布的点 , 让这些点落在正方形内 , 通过简单的推导 , 我们就可以知道 , Pi的值=落在圆内的点的个数/点的总数*4 。
这里要注意 , 就是随机生成的点的个数越多 , 结果越精确 。
用Numpy实现如下:
importnumpyasnpN=10**7#1千万个点data=https://pcff.toutiao.jxnews.com.cn/p/20200416/np.random.uniform(-1,1,size=(N,2))#生成1千万个x轴和y轴都介于-1和1间的点inside=(np.sqrt((data**2).sum(axis=1))<1).sum()#计算到原点的距离小于1的点的个数pi=4*inside/Nprint('pi:%.5f'%pi)可以看到 , 用Numpy来进行数值计算非常简单 , 只要寥寥数行代码 , 而如果读者习惯了Numpy这种面相数组的思维方式之后 , 无论是代码的可读性还是执行效率都会有巨大提升 。
pandaspandas是一个强大的数据分析和处理的工具 , 它其中包含了海量的API来帮助用户在二维数据(DataFrame)上进行分析和处理 。
pandas中的一个核心数据结构就是DataFrame , 它可以简单理解成表数据 , 但不同的是 , 它在行和列上都包含索引(Index) , 要注意这里不同于数据库的索引的概念 , 它的索引可以这么理解:当从行看DataFrame时 , 我们可以把DataFrame看成行索引到行数据的这么一个字典 , 通过行索引 , 可以很方便地选中一行数据;列也同理 。
我们拿movielens的数据集作为简单的例子 , 来看pandas是如何使用的 。 这里我们用的是Movielens20MDataset.
importpandasaspdratings=pd.read_csv('ml-20m/ratings.csv')ratings.groupby('userId').agg({'rating':['sum','mean','max','min']})通过一行简单的pandas.read_csv就可以读取CSV数据 , 接着按userId做分组聚合 , 求rating这列在每组的总和、平均、最大、最小值 。
“食用“pandas的最佳方式 , 还是在Jupyternotebook里 , 以交互式的方式来分析数据 , 这种体验会让你不由感叹:人生苦短 , 我用xx()
scikit-learnscikit-learn是一个Python机器学习包 , 提供了大量机器学习算法 , 用户不需要知道算法的细节 , 只要通过几个简单的high-level接口就可以完成机器学习任务 。 当然现在很多算法都使用深度学习 , 但scikit-learn依然能作为基础机器学习库来串联整个流程 。
我们以K-最邻近算法为例 , 来看看用scikit-learn如何完成这个任务 。
importpandasaspdfromsklearn.neighborsimportNearestNeighborsdf=pd.read_csv('data.csv')#输入是CSV文件 , 包含20万个向量 , 每个向量10个元素nn=NearestNeighbors(n_neighbors=10)nn.fit(df)neighbors=nn.kneighbors(df)fit接口就是scikit-learn里最常用的用来学习的接口 。 可以看到整个过程非常简单易懂 。
Mars——Numpy、pandas和scikit-learn的并行和分布式加速器Python数据科学栈非常强大 , 但它们有如下几个问题:
现在是多核时代 , 这几个库里鲜有操作能利用得上多核的能力 。 随着深度学习的流行 , 用来加速数据科学的新的硬件层出不穷 , 这其中最常见的就是GPU , 在深度学习前序流程中进行数据处理 , 我们是不是也能用上GPU来加速呢?这几个库的操作都是命令式的(imperative) , 和命令式相对应的就是声明式(declarative) 。 命令式的更关心howtodo , 每一个操作都会立即得到结果 , 方便对结果进行探索 , 优点是很灵活;缺点则是中间过程可能占用大量内存 , 不能及时释放 , 而且每个操作之间就被割裂了 , 没有办法做算子融合来提升性能;那相对应的声明式就刚好相反 , 它更关心whattodo , 它只关心结果是什么 , 中间怎么做并没有这么关心 , 典型的声明式像SQL、TensorFlow1.x , 声明式可以等用户真正需要结果的时候才去执行 , 也就是lazyevaluation , 这中间过程就可以做大量的优化 , 因此性能上也会有更好的表现 , 缺点自然也就是命令式的优点 , 它不够灵活 , 调试起来比较困难 。为了解决这几个问题 , Mars被我们开发出来 , Mars在MaxCompute团队内部诞生 , 它的主要目标就是让Numpy、pandas和scikit-learn等数据科学的库能够并行和分布式执行 , 充分利用多核和新的硬件 。