Matlab vs. scipy & numpy

Matlab vs. scipy & numpy « Free Mind

Matlab vs. scipy & numpy

实际上关于 Matlab 和 Python 的争论和比较已经非常非常多了。Matlab 本来是在相关领域可以算作“标准”的平台和工具了,然而 Python 有了 numpy ,又有了 scipy ,似乎相当有潜力和 Matlab 一较高下。在 scipy 的网站上有一个页面专门讲 Matlab 中常见的功能和函数在 numpy 中如何实现:NumPy for Matlab Users。看起来似乎还挺不错的。所以我之前都有想在 scipy/numpy 的基础上搭建相关的平台的想法,并且我在“漫谈 Clustering 系列”的前面几篇文章中也使用了 Python 代码作为示例。但是在我写系列中的第 4 篇(关于 Gaussian Mixture Model )的时候,还是直接用了 Matlab 代码。因为在那个时候我已经暂时放弃了工作在 scipy/numpy 里的想法。下面我还是从我自己的角度来谈一谈我对两者比较吧。

要比较 Matlab 和 Python ,不得不说的就是 license 了,前者是非常典型的昂贵的商业软件,而后者是开源软件的典范。如果说其他方面差不多的话,对于个人、科研或者教育方面使用来说,应当更优先选择 Python 了。但是情况显然不是这么简单,而且若仅仅是考虑 Matlab 的那些特性的话,也有一个开源的 clone Octave 可供选择。而 Python 的魅力似乎更多地在于 Matlab 所不具有的那些特性上。

Matlab 的脚本语言是专门针对科学计算而设计的,有丰富的运算符支持(例如矩阵转置 ' 、乘法 * 和点乘 .* 以及丰富的取 sub-matrix 的运算符支持等),还有一些特性(比如数据的 Copy on Write 等)让计算变得很方便,然而它却并不适合于 general purpose programming (当然不适合并不等于不能),而这却是 Python 的强项。这取决于你要做的事情,如果你需要的仅仅是一段 20 行的 Matlab 代码做一些运算的话,完全可以无视 general purpose programming 的能力,然而我自己有时候确实会碰到一些比较麻烦的情况,例如我想用一个 Hash 表来管理一大堆的数据,再例如有一次我想用一下 Priority Queue 。还有其他一些影响代码美观或者冗余性的地方,比如函数的 default parameter 等。

另外,其实我觉得 numpy 里面的那个 ndarray 的接口挺不错的,用起来也很舒服。但是和 Matlab 正好相反,由于 Python 本身是设计做通用编程的,科学计算只是后来作为库加入进去的,因此也会带来许多不便:

  • 一个最典型的情况是运算符的支持,虽然 Python 支持运算符“重载”,但是对于语言里本身没有的运算符就没法重载了,所以不能有 '.* 这样的运算符,而计算两个矩阵的乘法还得调用 dot 函数,实在是显得非常不自然。
  • 另外,虽然我觉得 Python 本身的库函数已经非常混乱了,在加入了 numpy/scipy 之后,情况就更加糟糕了。简单的例子是全局函数 sum 和 numpy 中可以对 ndarray 进行操作的对应的函数;还有 math 模块中的函数似乎也并不能直接应用到 ndarray 上。而 numpy 本身也有两套基本数据结构的接口:ndarray 和 matrix ,对于表达式 A*B ,如果其中有一个是 matrix 的话,这表示矩阵乘法,否则则是按元素的“点乘”;A[0] 对于一个 2 维的 ndarray 来说会得到一个向量,而对于一个 matrix 来说会得到一个单行的 matrix (注意还是一个 matrix ,而不是一个向量,前者的 shape 属性是一个 2-tuple ,而后者是 1-tuple )。

    似乎 numpy 内部的大部分函数都是处理 ndarray 接口的,那么好吧,直接乎略 matrix 接口好了。可是当我准备用一个文本数据集来跑一下 K-means 的时候,发现 scipy 提供的稀疏矩阵库用的是 matrix 接口,一个办法就是把稀疏矩阵转化为正常的矩阵,最终变成一个 ndarray 来处理,但是这对于文本数据集来说是不可忍受的。因为文本数据通常都是维度非常高并且非常稀疏的向量,转化为普通矩阵之后占用的空间和计算所消耗的时间都会大幅增加甚至到不能承受的地步。那么让 k-means 能同时处理 matrix 和 ndarray ?在发现连乘法这个基本操作都有不同的语意之后,我决定放弃了,犯不着这么折腾,直接用 Matlab 好了。这个(加上后面要提到的 eigs )大概算是我目前完全放弃 numpy 的直接原因吧。

  • 基本运算的支持。其实我在 NumPy for Matlab Users 中也只看到 eigs 这个函数 numpy 中并没有提供。这个函数在 Matlab 中用来求前 k 个最大(或者最小)的特征值。当然,可以用 eig 求出所有的特征值然后排序再取前 k 个,但是这对于比较巨大的矩阵来说是不能忍受的。

    不过既然是开源的,为何不自己贡献一个 eigs 的实现呢?确实,《数值分析》这门课上确实有讲计算前 k 个特征值的迭代算法,要找应该也可以找到标准算法,不过这并不是我目前特别感兴趣和在行的地方(让我感到非常幸运的是我现在还可以选择只做自己感兴趣的事情),而且现在我对跨平台的代码极其有好感,但是 Windows 平台下繁琐的编译方法让我对写 Python/Ruby 的 Native Extension 也产生了一点厌恶,除非有足够强的 Motivation ,我想我大概暂时也不会去考虑这个事情了。

  • 其他的库支持。Python 的库可以算是非常全的了,就我平时要用到的来说的话,比如对应 Matlab 的 2D 绘图功能有 matplotlib 可以用,虽然没有 3D 绘图功能,但是那个平时几乎也不常用到。对于基本的图像读取和处理,也有 Python Image Library 可以用。不过用这些东西多少有些堆砌起来的感觉,例如要用 PIL 读取一个图片,用 numpy 来处理然后再保存到文件中的话,就得在 PIL 和 numpy 的数据结构之间转换来转换去。PIL 提供的转换函数在处理有透明通道的 PNG 文件的时候有 bug ,我发现他代码里面对于 ndarray 的维度处理不对,把建议贴到 PIL 的邮件列表之后他说那段代码是 numpy guy 写的,让我去 numpy 的邮件列表问。之后我在 numpy 的邮件列表里找到了一个比较老的帖子讨论这个问题,再回头问 PIL 是否在最新版本已经 fix 了这个问题的时候,就再也没有消息了。不得不承认,开源社区虽然理论上来讲是完全开放的,但是也确实会不时地碰到这样的问题。 :-/

除此之外,就是开发工具了。Matlab 虽然类似于一个 IDE 的环境,但是并不是很好用,那个编辑器亦是如此,不过我用 Emacs 编辑 .m 文件的时候遇到过突然卡死的情况,似乎 Emacs 提供的那个 matlab-mode 不是很好用,所以我平时也用 Vim 来编辑 Matlab 代码。不过至少 Matlab 提供了调试功能,虽然不是特别强大,但是足够用了,而且似乎开启调试功能之后运行速度并没有感觉到下降呢,这对于那些可能要跑很长一段时间才能重现出来的 bug 尤其有用啊。而 Python 的话,我至今还没有用过它的 debugger 呢,所以也没法评价。

总而言之,现在我在要做计算时的选择是:如果有 Matlab 可以用的话,就用 Matlab 好了。

你可能感兴趣的:(matlab)