More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  笑对人生,傲立寰宇PhotosProfileFriendsMore Tools Explore the Spaces community

笑对人生,傲立寰宇

无边的大海上,一只白帆,勇敢地航行着,就为了前面的点点星光
Updated 10/7/2007
Updated 11/8/2007
Updated 8/23/2007
Updated 4/2/2007
Updated 11/8/2007
Updated 1/29/2007
Updated 1/31/2007
Updated 10/4/2006
Updated 9/25/2006
Updated 8/5/2006
Updated 6/21/2006
May 07

让MATLAB更快

MATLAB是一门在数值运算方面非常高效的语言,对于提高MATLAB的效率,有一些大家熟知的方法,比如避免使用for循环,向量化,使用C-mex写核心,等等。这些原则大体是没错的,但是教条地运用有时反而会降低效率。

根据问题的规模,适当选择向量化的策略

向量化的基本思想是以空间换时间,通过把要处理的对象转化成一个矩阵,集中处理。这比起非向量化的处理方式往往需要消耗更多的内存。在内存紧张的时候,内存分配的开销可能是很大的。

比如,给定一个列向量v1,和一个行向量v2, 计算矩阵M,使得M(i, j) = v1(i) + v2(j)。一种常用的向量化实现:

m = length(v1); 
n = length(v2);
M = repmat(v1, [1, n]) + repmat(v2, [m, 1]);

这个过程中,除了M以外,还要创建两个大小为m x n的临时矩阵。repmat创建临时矩阵有一定的overhead,主要花费在元素索引上。由于元素加法的向量化收益本身并不显著,扣除repmat的额外开销后,得益就更小了。另外,当这些矩阵很大,接近物理内存容纳能力的时候,必然导致和虚拟内存进行频繁的交换,耗费大量的IO时间,向量化可能得不偿失。这种情况下,下面这种向量化程度略低的方式可能是更好的选择:

M = zeros(m, n);
if m < n
    for i = 1 : m
        M(i, :) = v1(i) + v2;
    end
else
    for i = 1 : n
        M(:, i) = v1 + v2(i);
    end
end

这个例子是要说明在设计向量化的时候,要对其它潜在的影响因素也进行考虑,权衡得失。对于这个例子本身,在2007版以后的matlab,有一个通用的简洁的写法。

M = bsxfun(@plus, v1, v2);

MATLAB内部对于bsxfun有很专业的优化,这个写法在时间和空间上都比较节省。

对一组d x d矩阵求逆,假设这些矩阵放在大小为d x d x n的数组里。在一般条件下,多个矩阵求逆没有特别的向量化方法,通常就是逐个求

n = size(A, 3);
B = zeros(size(A));
for i = 1 : n
    B(:, :, i) = inv(A(:, :, i));
end

不过,当d很小而n很大的时候,比如对大量2x2矩阵求逆(这在设计几何的问题中很常见),那么直接利用2x2矩阵的求逆共识,进行向量化了:

a = reshape(A(1, 1, :), [1, n]);
b = reshape(A(1, 2, :), [1, n]);
c = reshape(A(2, 1, :), [1, n]);
d = reshape(A(2, 2, :), [1, n]);

g = 1 ./ (a .* d - b .* c);
r11 = d .* g;
r12 = -b .* g;
r21 = -c .* g;
r22 = a .* g;

B = reshape([r11; r21; r12; r22], [2, 2, n]); 

在正式的代码中,还需要处理可能为奇异(a*d-b*c=0)的情况。

某些非数值计算问题的向量化

有些问题,表面上不像是数值计算,但是通过适当的转化,也可以通过向量化解决。

非等量复制: 比如有一组数[10, 20, 30], 各自要复制成[3, 2, 5]份,最终产生出 [10 10 10 20 20 30 30 30 30 30]。这个问题,虽然简单,但是因为不是那么“整齐”,因此向量化不是特别直接。下面给出一种思路:

首先产生出起始位置标志向量[1 0 0 1 0 1 0 0 0 0],然后通过cumsum,产生出[1 1 1 2 2 3 3 3 3 3],最后以此为索引,可以得到结果。

% vs: the values to be copied
% ns: the numbers of copies 

vs = vs(ns > 0);
ns = ns(ns > 0);

sp = [1, cumsum(ns(1:end-1)) + 1];
result = vs(cumsum(sp));

对于图像处理或者二维信号问题,善用filter。

比如,要对每个像素,基于其局部邻域进行一些计算。即使整个计算本身不是线性的,但是只要能分解成线性局部运算的组合,就可以利用filter。

比如,对于图像I, 产生V,使得V(i, j)是像素I(i, j)周围w x w邻域的像素的方差。

I = im2double(I);
h = ones(w, w) / (w * w);
M = imfilter(I, h, 'symmetric');
M2 = imfilter(I.^2, h, 'symmetric');
V = M2 - M.^2;
April 19

图˙谱˙马尔可夫过程˙聚类结构


题目中所说到的四个词语,都是Machine Learning以及相关领域中热门的研究课题。表面看属于不同的topic,实际上则是看待同一个问题的不同角度。不少文章论述了它们之间的一些联系,让大家看到了这个世界的奇妙。

从图说起

这里面,最简单的一个概念就是“图”(Graph),它用于表示事物之间的相互联系。每个图有一批节点(Node),每个节点表示一个对象,通过一些边(Edge)把这些点连在一起,表示它们之间的关系。就这么一个简单的概念,它对学术发展的意义可以说是无可估量的。几乎所有领域研究的东西,都是存在相互联系的,通过图,这些联系都具有了一个统一,灵活,而又强大的数学抽象。因此,很多领域的学者都对图有着深入探讨,而且某个领域关于图的研究成果,可以被其它领域借鉴。

矩阵表示:让代数进入图的世界

在数学上,一种被普遍使用的表达就是邻接矩阵(Adjacency Matrix)。一个有N个节点的图,可以用一个N x N的矩阵G表示,G(i, j)用一个值表示第i个节点和第j个节点的联系,通常来说这个值越大它们关系越密切,这个值为0表示它们不存在直接联系。这个表达,很直接,但是非常重要,因为它把数学上两个非常根本的概念联系在一起:“图”(Graph)和“矩阵”(Matrix)。矩阵是代数学中最重要的概念,给了图一个矩阵表达,就建立了用代数方法研究图的途径。数学家们几十年前开始就看到了这一点,并且开创了数学上一个重要的分支——代数图论(Algebraic Graph Theory)。

代数图论通过图的矩阵表达来研究图。熟悉线性代数的朋友知道,代数中一个很重要的概念叫做“谱”(Spectrum)。一个矩阵的很多特性和它的谱结构——就是它的特征值和特征向量是密切相关的。因此,当我们获得一个图的矩阵表达之后,就可以通过研究这个矩阵的谱结构来研究图的特性。通常,我们会分析一个图的邻接矩阵(Adjacency Matrix)或者拉普拉斯矩阵(Laplace Matrix)的谱——这里多说一句,这两种矩阵的谱结构刚好是对称的。

谱:“分而治之”的代数

谱,这个词汇似乎在不少地方出现过,比如我们可能更多听说的频谱,光谱,等等。究竟什么叫“谱”呢?它的概念其实并不神秘,简单地说,谱这个概念来自“分而治之”的策略。一个复杂的东西不好直接研究,就把它分解成简单的分量。如果我们把一个东西看成是一些分量叠加而成,那么这些分量以及它们各自所占的比例,就叫这个东西的谱。所谓频谱,就是把一个信号分解成多个频率单一的分量。

矩阵的谱,就是它的特征值和特征向量,普通的线性代数课本会告诉你定义:如果A v = c v,那么c 就是A的特征值,v就叫特征向量。这仅仅是数学家发明的一种数学游戏么?——也许有些人刚学这个的时候,并一定能深入理解这么个公式代表什么。其实,这里的谱,还是代表了一种分量结构,它为使用“分而治之”策略来研究矩阵的作用打开了一个重要途径。这里我们可以把矩阵理解为一个操作(operator),它的作用就是把一个向量变成另外一个向量:y = A x。对于某些向量,矩阵对它的作用很简单,A v = cv,相当于就把这个向量v 拉长了c倍。我们把这种和矩阵A能如此密切配合的向量v1, v2, ... 叫做特征向量,这个倍数c1, c2, ...叫特征值。那么来了一个新的向量x 的时候,我们就可以把x 分解为这些向量的组合,x = a1 v1 + a2 v2 + ...,那么A对x的作用就可以分解了:A x = A (a1 v1 + a2 v2 + ...) = a1 c1 v1 + a2 c2 v2 ... 所以,矩阵的谱就是用于分解一个矩阵的作用的。

这里再稍微延伸一点。一个向量可以看成一个关于整数的函数,就是输入i,它返回v( i )。它可以延伸为一个连续函数(一个长度无限不可数的向量,呵呵),相应的矩阵 A 变成一个二元连续函数(面积无限大的矩阵)。这时候矩阵乘法中的求和变成了积分。同样的,A的作用可以理解为把一个连续函数映射为另外一个连续函数,这时候A不叫矩阵,通常被称为算子。对于算子,上面的谱分析方法同样适用(从有限到无限,在数学上还需要处理一下,不多说了)——这个就是泛函分析中的一个重要部分——谱论(Spectral Theory)。

马尔可夫过程——从时间的角度理解图

回到“图”这个题目,那么图的谱是干什么的呢?按照上面的理解,似乎是拿来分解一个图的。这里谱的作用还是分治,但是,不是直观的理解为把图的大卸八块,而是把要把在图上运行的过程分解成简单的过程的叠加。如果一个图上每个节点都有一个值,那么在图上运行的过程就是对这些值进行更新的过程。一个简单,大家经常使用的过程,就是马尔可夫过程(Markov Process)。

学过随机过程的朋友都了解马尔可夫过程。概念很简单——“将来只由现在决定,和过去无关”。考虑一个图,图上每个点有一个值,会被不断更新。每个点通过一些边连接到其它一些点上,对于每个点,这些边的值都是正的,和为1。在图上每次更新一个点的值,就是对和它相连接的点的值加权平均。如果图是联通并且非周期(数学上叫各态历经性, ergodicity),那么这个过程最后会收敛到一个唯一稳定的状态(平衡状态)。

图上的马尔可夫更新过程,对于很多学科有着非常重要的意义。这种数学抽象,可以用在什么地方呢?(1) Google对搜索结果的评估(PageRank)原理上依赖于这个核心过程,(2) 统计中一种广泛运用的采样过程MCMC,其核心就是上述的转移过程,(3) 物理上广泛存在的扩散过程(比如热扩散,流体扩散)和上面的过程有很重要的类比,(4) 网络中的信息的某些归纳与交换过程和上述过程相同 (比如Random Gossiping),还有很多。非常多的实际过程通过某种程度的简化和近似,都可以归结为上述过程。因此,对上面这个核心过程的研究,对于很多现象的理解有重要的意义。各个领域的科学家从本领域的角度出发研究这个过程,得出了很多实质上一致的结论,并且很多都落在了图的谱结构的这个关键点上。

图和谱在此联姻

根据上面的定义,我们看到邻接矩阵A其实就是这个马尔可夫过程的转移概率矩阵。我们把各个节点的值放在一起可以得到一个向量v,那么我们就可以获得对这个过程的代数表示, v(t+1) = A v(t)。稳定的时候,v = A v。我们可以看到稳定状态就是A的一个特征向量,特征值就是1。这里谱的概念进来了。我们把A的特征向量都列出来v1, v2, ...,它们有 A vi = ci vi。vi其实就是一种很特殊,但是很简单的状态,对它每进行一轮更新,所有节点的值就变成原来的ci倍。如果0 < ci < 1,那么,相当于所有节点的值呈现指数衰减,直到大家都趋近于0。

一般情况下,我们开始于一个任意一个状态u,它的更新过程就没那么简单了。我们用谱的方法来分析,把u分解成 u = v1 + c2 v2 + c3 v3 + ... (在数学上可以严格证明,对于上述的转移概率矩阵,最大的特征值就是1,这里对应于平衡状态v1,其它的特征状态v2, v3, ..., 对应于特征值1 > c2 > c3 > ... > -1)。那么,我们可以看到,当更新进行了t 步之后,状态变成 u(t) = v1 + c2^t v2 + c3^t v3 + ...,我们看到,除了代表平衡状态的分量保持不变外,其它分量随着t 增长而指数衰减,最后,其它整个趋近于平衡状态。

从上面的分析看到,这个过程的收敛速度,其实是和衰减得最慢的那个非平衡分量是密切相关的,它的衰减速度取决于第二大特征值c2,c2的大小越接近于1,收敛越慢,越接近于0,收敛越快。这里,我们看到了谱的意义。第一,它帮助把一个图上运行的马尔可夫过程分解为多个简单的字过程的叠加,这里面包含一个平衡过程和多个指数衰减的非平衡过程。第二,它指出平衡状态是对应于最大特征值1的分量,而收敛速度主要取决于第二大特征值。

我们这里知道了第二大特征值c2对于描述这个过程是个至关重要的量,究竟是越大越好,还是越小越好呢?这要看具体解决的问题。如果你要设计一个采样过程或者更新过程,那么就要追求一个小的c2,它一方面提高过程的效率,另外一方面,使得图的结构改变的时候,能及时收敛,从而保证过程的稳定。而对于网络而言,小的c2有利于信息的迅速扩散和传播。

聚类结构——从空间的角度理解图

c2的大小往往取决于图上的聚类结构。如果图上的点分成几组,各自聚成一团,缺乏组与组之间的联系,那么这种结构是很不利于扩散的。在某些情况下,甚至需要O(exp(N))的时间才能收敛。这也符合我们的直观想象,好比两个大水缸,它们中间的只有一根很细的水管相连,那么就需要好长时间才能达到平衡。有兴趣的朋友可以就这个水缸问题推导一下,这个水缸系统的第二大特征值和水管流量与水缸的容积的比例直接相关,随比例增大而下降。

对于这个现象进行推广,数学上有一个重要的模型叫导率模型(Conductance)。具体的公式不说了,大体思想是,节点集之间的导通量和节点集大小的平均比例和第二大特征值之间存在一个单调的上下界关系。导率描述的是图上的节点连接的空间结合,这个模型把第二特征值c2和图的空间聚集结构联系在一起了。

图上的聚类结构越明显, c2越大;反过来说,c2越大,聚类的结构越明显,(c2 = 1)时,整个图就断裂成非连通的两块或者多块了。从这个意义上说,c2越大,越容易对这个图上的点进行聚类。机器学习中一个重要课题叫做聚类,近十年来,基于代数图论发展出来的一种新的聚类方法,就是利用了第二大特征值对应的谱结构,这种聚类方法叫做谱聚类(Spectral Clustering)。它在Computer Vision里面对应于一种著名的图像分割方法,叫做Normalized Cut。很多工作在使用这种方法。其实这种方法的成功,取决于c2的大小,也就是说取决于我们如何构造出一个利于聚类的图,另外c2的值本身也可以作为衡量聚类质量,或者可聚类性的标志。遗憾的是,在paper里面,使用此方法者众,深入探讨此方法的内在特点者少。

归纳起来

  • 图是表达事物关系和传递扩散过程的重要数学抽象
  • 图的矩阵表达提供了使用代数方法研究图的途径
  • 谱,作为一种重要的代数方法,其意义在于对复杂对象和过程进行分解
  • 图上的马尔可夫更新过程是很多实际过程的一个重要抽象
  • 图的谱结构的重要意义在于通过它对马尔可夫更新过程进行分解分析
  • 图的第一特征值对应于马尔可夫过程的平衡状态,第二特征值刻画了这个过程的收敛速度(采样的效率,扩散和传播速度,网络的稳定程度)。
  • 图的第二特征分量与节点的聚类结构密切相关。可以通过谱结构来分析图的聚类结构。

马尔可夫过程代表了一种时间结构,聚类结构代表了一种空间结构,“谱”把它们联系在一起了,在数学刻画了这种时与空的深刻关系。

 

April 14

策己

留学大半年,经历着不一样的生活,品尝着不一样的滋味,发现自己还有太多的东西需要学习。

对自己,要学会省思;

对朋友,要学会尊重;

对生活,要学会坚强;

对学问,要学会谦恭。

April 10

How to get a solution?

我们所做的topic,一般有几个阶段:

  • Analysis: 分析问题,找到问题的关键
  • Modeling / Formulation:  对问题进行数学抽象,建立模型,或者formulate目标函数
  • Solving: 设计出求解的算法
  • Experiments: 实验

最近的工作都集中在Solving这部分,就说说这个吧。

求解的方法

求解问题有很多不同的方法,就我知道的来说,大概有这么几个大家族。

  1. Heuristics。就是根据对问题的观察而设计的一些简单的方法,不一定遵循什么规范,或者有什么深刻的数学根据。这类方法往往比较简单易懂,intuition比较明显,很多时候performance也挺不错的,不见得比高深的方法差,因而在实际工程中很受欢迎,几乎应用在全部的学科。不过,好像很多朋友对这类方法颇为不屑,认为“没有技术含量”,或者叫做“没有理论深度”。

    确实,有相当部分的Heuristics纯粹粗制滥造,投机取巧。不过,还有很多Heuristics虽然简单,但是切中问题要害,在长期的复杂的实际应用中经受住了考验。这些方法,表面看来可能只是再简单不过的几条四则运算公式,说不上多少理论,但是并不代表它没有深刻的理论基础。一个典型的例子是Google PageRank中使用的传导公式(简单版本),道理和公式都很简单,可是,做过类似工作的朋友可能都知道,它和代数图论以及马尔可夫随机过程有着很深的联系。 又比如,Fourier Transform在刚出来的时候,仅仅是工程师的一些heuristics,后来关于它的理论已经成为了泛函分析的一个核心组成部分,也是信号处理的理论基础之一。

    真正好的heuristics,它的好处肯定不是瞎懵出来,而是有内在原因的。对它们的原理的探索,不断带动理论方面的发展,甚至创造了新的理论方向。说到这里,有人可能会argue,这是“理论家们在故弄玄虚混饭吃”。Hmm,这种说法我不能认同,但是,确实存在“把工程方法胡乱进行理论化”的事实。什么才叫有价值的理论化,而不是故弄玄虚,确实值得思考,这里先不展开了。

  2. Analytical Solution。当你把问题formulate出来后,有些情况是直接可以从问题推导出解析解的。这种情况通常存在于objective function是Linear或者Quadratic的情况。大家都很喜欢这种情况的出现,理论漂亮,实现简洁。但是,据我的观察,很多情况下,这种elegance是通过减化模型换取的。把cost写成quadratic term,把distribution假设为Gauss,很多时候都能得到这样的结果。

    我不反对进行简化,也欣赏漂亮的analytical solution,如果它把问题解决得很好。但是,这里面有个问题,很多能获得简单解析解的问题已经被做过了,剩下的很多难点,未必是一个简化模型能有效解决的。简化是一种很好的方法,但是,使用起来,尤其是在实际中的应用必须慎重,要清楚了解它们可能带来的问题。

    比如说,很多模型喜欢使用差的平方来衡量误差大小。但是,这很早就被指出是unrobust的,一个很大的deviation会dominate整个optimization,使得solution严重偏离方向。如果这种robustness在带解决的问题中是一个必须考虑的要素,那么用平方误差就要仔细考虑了。

  3. Numerical Optimization。如果formulation没有解析解,那么自然的想法就是使用数值方法求解。目前大家常用的是基于Gradient/Hessian之类的local optimization的方法,有时会加上random initialization。如果objective function是convex的,那么这种方法保证收敛到global optimal,这是大家很希望的。convex problem无论在formulation还是在solution的阶段,都是很有学问的。很多问题可以formulate成convex的,但是未必都那么直接,这需要有这方面的基础。Solving一个convex problem有现成的方法,但是,如果能对问题的结构有insightful的观察,可能能利用问题本身的特点大幅度降低求解的复杂度——这往往比直接把问题扔进solver里面等答案更有意义。

    除了convex optimization,还有一种数值方法应用非常广泛,叫做coordinate ascend或者alternate optimization。大概的思路是,几个有关的变量,轮流选择某个去优化,暂时固定其它的。在Machine Learning里面非常重要的Expectation-Maximization (EM算法)就属于这个大家族。另外,很多复杂的graphical model采用的variational inference也是属于此类。使用这类方法,有两个问题:一个是如果几个variable之间相互影响,变一个,其他跟着变的话,那么直接使用这种方法可能是错误的,并不能保证收敛。另外一个问题是,如果problem不是convex的话,可能没有任何保证你得到的solution和global solution有联系。很可能,你得到的解和真正的全局最优解相差十万八千里。这个没有什么通用有效的途径来解决。不过,针对具体问题的结构特点,在求解过程中施加一定的引导是有可能的。

  4. Dynamic Programming。这个方法更多见于经典计算机算法中,不过现在越来越多在Vision和Learning见到它的影子。主要思路是把大问题分解为小问题,总结小问题的solution为大问题的solution。至于如何设计分解和综合的过程,依赖于对问题的观察和分析,并无通用的法则可循。用DP解决问题的洞察力需要逐步的积累。不少经典算法就源自于DP,比如shotest path。一个可能有用的观察是,如果问题或者模型呈现链状,树状,或者有向无环图结构的,可能很有希望能通过DP高效解决。

  5. Local Exchange。很多建立在图上的问题,都可以通过某种局部交换来达到全局的平衡。像Belief propagation, Junction tree等等在graphical model的重要inference方法,还有tranduction model,都用到了类似的策略。这在实践中被证明为非常有效。但是,并不是随便设计的局部交换过程都是收敛的。这里面需要关注两个问题:(1)交换过程是不是能保证某些重要的invariance不被破坏;(2)交换过程中,是不是有一个objective,比如距离全局平衡的deviation,它在每一步都保持单调。有很多交换过程,在有向无环图中保证收敛,但是,在带环图中由于信息的重复传递可能引起不稳定,或者不能收敛到正确的解。

  6. Monte Carlo Sampling。蒙特卡罗采样的原理非常简单,就是用样本平均,来逼近期望(这个可能需要用intractable的积分完成,没法直接算)。求平均很简单,关键在于采样过程。我们求解问题,通常是在后验分布中采样,这种分布在大部分问题中,不要说直接采样了,可能连解析形式都没法给出。如果采样问题有效解决了,基本上我们研究的大部分问题其实都可以通过采样完成。

    由于直接采样往往非常困难,于是就产生了其它的方法,间接做这个事情。一种想法就是,既然p(x)不好直接采,我找一个比较容易采样的q(x)来逼近p(x),然后给从q(x)采出的每个样本加一个weight,p(x) / q(x)。这在理论上被严格证明是对的——这种方法叫做Importance Sampling。这里的问题在于,如果q(x)和p(x)不太接近,那么采样效率非常低下,如果在一个高维空间,可能采1000年都达不到要求。可是,要得到一个approximate很好的q(x)本身不比直接从p(x)采样来得容易。

    还有一种聪明一点的方法,叫sequential importance sampling。在这里面q(x),不是一蹴而就建立起来的,而是每个样本先采一部分,然后根据那部分,确定下一部分的proposal distribution,继续采,也就是说q(x)和样本都是dynamically built up。这个方法在vision里面一个非常著名的应用是用于tracking,相应发展出来的方法论叫做particle filtering。

    另外一大类重要的采样方法,叫Markov Chain Monte Carlo(MCMC)。这个的想法是,设计一个马尔科夫链,让它的平衡分布恰好是p(x),那么等它平衡时开始采。以前我们做随机过程作业是已知一个markov chain,求equilibrium distribution,设计MCMC就是反过来了。最重要的MCMC方法莫过于Metropolis-Hastings Algorithm和Gibbs Sampling,前者常被用于设计在solution space的随机游走(Random walk),后者则是conditional sampling的基础方法。

    可是Markov过程怎么转移呢。最简单的Random Walk结合acceptance rate之后理论上是对的。可是,让sampler随便乱走,猴年马月才能把solution space走一遍阿。于是,有人提出结合一个solution space的局部信息来引导它往有用的方向走。一个重要的方法叫做Hybric Monte Carlo(HMC),想法就是把它模拟成一个物理场,把要sample的分布视为波尔兹曼分布后获得物理场的势能,通过哈密顿动力学模型(其实就是牛顿力学的推广)来驱动sampler。可是,如果问题更为复杂呢,比如整个solution space有几个井,sample掉到某一个井可能出不来了。为了解决这个问题,一种重要的方法叫Tempering,就是开始给分子充分加热,让它获得足够的动能能在各个井之间来回跳,然后逐步冷却,从而能捕捉到多个势井。

    Monte Carlo方法较早的时候主要用于统计物理,目前已经广泛应用于计算机,生物,化学,地质学,经济学,社会学等等的研究。这是目前所知道的用于求解复杂的真实模型的最有效的方法。它的核心,就是猜——你直接解不出来,只好猜了,呵呵。但是,怎样才能猜得准,则是大有学问——几十年来各个领域关于Monte Carlo研究的工作汗牛充栋,有很多进展,但是还有很长的路要走。

和这里很多留学生一样,我一向潜心于自己的学习和研究。可是最近,我们的世界并不宁静,我认识的不只一个在美国的朋友受到了不太友好的挑衅——在不知不觉中,我们可能已经身处反分裂和支持奥运的前线。我看到包括MIT CSSA在内的很多学生团体开始组织起来支持自己的祖国。我没有具体帮上什么,但是,我对所有在用自己的行动捍卫国家荣誉的同胞怀有最深的敬意。我也希望,我的努力,能让外国的朋友明白中国人是值得尊敬的。

April 02

深入问题本身

很多做research的朋友喜欢top-down approach,包括我自己。就是说,在开始一个topic的时候,在第一时间就设定了大体的formulation,model又或者methodology。至于选择哪种设定,往往取决于研究者本身的偏好,知识背景,或者对问题的第一反应。

接下来的事情就顺理成章了,推导数学模型和相关公式以及算法步骤,然后设计程序进行实验。当然少不了再拉上几个相关工作,比较一番。如果自己的设计很幸运地有明显的improvement,于是非常满意,开始写paper(在不少情况下,paper的理论部分甚至提前写好了)。可是,如果不work呢? 通常大家会采取下面一些方法中的一种或者几种:

  • 观察实验结果,猜想几个不work的原因,然后回头局部调整模型和算法;
  • 换一下数据集,看看能不能work
  • 祭起“终极法宝”——调参数,人工修改或者写脚本遍历,直到找到一组work的参数为止。不过,那些作为“绿叶”用的参照算法,通常是没有这种待遇了。

无论如何,你总算把实验搞定了。但是,为什么work呢?除了几条曲线,你总得找一些“让人信服”的理由。在我所在的领域,有一些理由几乎是万能的,因而普遍出现在paper里面:

  • 以前的算法,不考虑某某因素,而这个因素是很重要的,我的算法考虑了,所以效果更好
  • 以前的算法,把某些因素分开考虑,但是它们实际上是相关联了,我的算法把它们结合在一起,体现了这种关联关系,所以更好
  • 以前的算法是线性的,但是这个问题本身明显是非线性的,我这里用了非线性的方法,所以更符合实际。为了进一步解释清楚,还画出一些二维或者三维的toy samples,显示出线性和非线性有“多么巨大的差别”
  • 以前的方法用的是参数化模型(比如高斯分布),而现实世界明显不是这样子,我这里采用非参数化模型,能更准确地逼近实际分布
  • 主流方法大都采用某某算法完成某个步骤,或者某某特征来描述某个方面,其实这个算法或者特征在这里不太适合,我换了一个更适合的或者更“先进”的。

还有很多,不一而足。总体来说,就是增加了某方面的复杂性,推广了模型,或者把某些部分变得更加时髦,数学更深。正因为多了东西可以调节,只要花上足够时间去设定参数,还是有很大机会能找到一组能得到improvement的参数的。可是,这种improvement是不是真正有意义呢?是不是足够significant,以至于所增加的复杂性是值得的呢?

我们的世界总是无限复杂的,和无数的因素相关,这些因素又总是有某种联系。我们的前辈们留给我们的最好的方法,就是从问题中分离出最关键的要素,和最重要的关系,而非不断地增加价值不大的因素,建立意义不大的联系。

我并不是一个完全拒绝复杂,但是我个人觉得对复杂性的增长应该慎重。每增加一个要素,都应该是基于对问题的深入分析,而不是先入为主的设想和冠冕堂皇的理由。这不完全是知识能力的问题,更多的是一种治学态度——是不是愿意安心下来对问题本身进行深入细致的解剖,找出问题本身的关键所在,而不是脱离问题预先构想某种“漂亮”模型或者“巧妙”方法,并且通过上面所述的种种方法推销出去。

研究是一种创新的过程,广拓思路是必须的。但是真正有价值的novelty应该是建立在对问题本身的深入理解,确实发现了别人忽略的关键因素,或者主流算法的真正不足,并且创造性地提出解决方法。这需要持之以恒的努力。真正经得起考验的学术价值,源于解决还没有被解决的问题,而不是使用了某种所谓别人没用过的“新颖”方法来解决本来已经解决的问题,又或者给模型加入某个要素来取得非实质性的性能改进。

上面所说的这些问题,几乎都发生在我的身上。而汤老师的很多建议,其实正是指出了这些问题,却没有被我认真思考,反而总是以为只要理论做得高深,模型设计得精巧,就是好的工作。来了MIT之后,更多地阅读一些有历史价值的文章(现在看CVPR反而比较少了),接触一些更加solid的工作。许多有重要贡献的工作,往往未必有很炫的方法和模型,但是,其对于问题本身的深入发掘和洞察却令我惭愧。

要做真正的学问,首先要戒除浮躁。

March 30

MATLAB的思维风格

最近做course project的时候,我发现所写的程序中有几个地方特别能反映MATLAB与别的高级语言很不一样的风格。

例1:一批user去访问文件,比如u1访问了f11, f12, ..., u2访问了f21, f22, ...,每个用户访问的文件数目可能不等,要求输出一个表M, M(i, j)是用户 i 和 j 都访问过的文件的个数。

先用高级语言给出一个比较直接的解决吧,下面是python的代码。(其实C++/C#/Java的也类似,不过python的代码比较简洁)

首先,建立一个访问字典(或者叫map),记录每个文件都被哪些人访问过。

# input is a map named ufiles, 
# ufiles[u] is a set of files accessed by u

acc_dict = {}
for u in users:
    for f in ufiles[u]:
        if f in acc_dict:
            acc_dict[f].add(u)  # add u to an existing set
        else:
            acc_dict[f] = set([u])  # initialize the set

然后,基于这个字典进行计数。对每一个文件,给每一对访问过它的用户的相应计数加1

# initialize the table
M = {}
for u1 in users:
    for u2 in users:
        M[(u1, u2)] = 0

# do counting
for f in acc_dict:
    uset = acc_dict[f]
    for u1 in uset:
        for u2 in uset:
            M[(u1, u2)] += 1

这样就基本完成计数了。

MATLAB没有像python那样丰富的数据结构,比如set(集合)和dict(映射表,字典)。但是,在这个表面上需要依靠经典数据结构完成的问题,我们可以用MATLAB给出一个更加高效简洁的解决方法

给出代码之前,先做点数学分析。令F是一个矩阵,F(u, f) = 1代表u访问过这个文件,否则F(u, f) = 0。那么M其实就可以写成:

M(u1, u2) = sum_f F(u1, f) F(u2, f) --- 很容易看出,这就是u1, u2都访问过的文件的数目。
写成矩阵形式:
M = F * F'

下面的代码就很顺理成章了

% Input: ufiles is a cell array of indices of files accessed by each user
% ufiles(i) is a row vector of the indices accessed by user i

% construct F 
n = length(ufiles)
% to produce usrs like {[1 1 1 1 ...], [2 2 2 ...], ...}
usrs = arrayfun(@(i) i * ones(1, length(ufiles{i})), 1:n, ...
                'UniformOutput', false)

I = [usrs{:}]  % concatenate the indices into one long vector
J = [ufiles{:}]
F = sparse(I, J, 1);

% compute M 
M = F * F'

注意这里用sparse matrix, 那么运算复杂度会显著降低,并且只依赖于实际访问的数量。实际性能上,通过MATLAB的稀疏矩阵乘法比自己用高级语言实现更快。

熟悉kernel的朋友可能已经看出来,MATLAB的做法其实是用file access indicator vector作为每个user的feature,构造出来的M则是相应的Gram matrix。不过,如果没有这方面的思维习惯的话,未必能很快就把一个统计文件访问量的问题联想到矩阵乘法或者内积计算。

例2:给出一组数字,算出每个不同数字出现的次数。

python的实现

counts = {}
for v in values:
    if v in counts:
        counts[v] += 1
    else:
        counts[v] = 1
用高级语言实现,一般需要一个映射表来快速定位某个数字的计数器。

Matlab的实现

svalues = sort(values);
dp = find(diff(svalues));
sp = [1, dp+1];
ep = [dp, length(svalues)];
U = svalues(sp);   % U is the set of distinct values
C = ep - sp + 1;   % C is the corresponding counts of these values

一般情况下,两种实现的时间复杂度都是O(n log(n))。不过,它们体现了不太一样的思维方式。高级语言倾向于通过数据结构加速每个元素的处理,而MATLAB没有复杂的数据结构,它注重于以整体方式进行操作。

March 19

MATLAB 2008

这几个星期一直忙着作业和考试,这里有些天没有更新了。刚过了mid-term,回到这里和朋友们说说话。

今年3月,Mathworks推出了MATLAB一个重要的新版本,MATLAB 2008a,也叫做MATLAB 7.6。在这个版本里,MATLAB解决了几个长期以来固有的弊端,而且加入了一些重要的能力。这次的更新是非常aggressive的,可能代表了MATLAB的一种历史性的转型。

  1. 完全实现面向对象编程。其实,在MATLAB的早期版本里面,也有class的概念,不过大家如果使用过的话,可能知道那是一种不太好的设计。功能不强,过程繁琐,而且,很多很tricky的地方,尤其是重载numel, subsref这类函数的时候。而新的设计抛开了历史包袱,现在写出来的类和在python里面写的长得差不多,舒服多了。这套设计,吸取(或者“抄袭”)了Python和C#的优点,除了支持封装(encapsulation),继承(inheritance),和多态(polymorphism)这些基本特性以外,还支持了一些新兴的特性,包括属性(property),事件(event),和静态方法(static method)。
  2. 支持Handle类型——用另外一种说法,就是支持函数调用传引用。以前matlab传递参数只有一种方法,copy on write。就是说,当你传一个东西进去,如果它要发生改变,那么,这个东西会整个copy一份,然后修改会在副本上生效。这使得实现动态数据结构变得非常困难。比如一个列表,如果每添加一个元素,都要拷贝整个列表一次,将是什么效果呢?因此,传统上matlab擅长于以矩阵为基础的算法,但是对于以经典动态数据结构为基础的算法,比如动态列表,哈希表,搜索树,图等,就力不从心了。这个新版本终于引入了对引用的支持,这将使MATLAB实现经典数据结构和算法变得前所未有的轻松。现在,数值和统计算法与经典算法越来越多地合流,很多应用都需要同时使用两方面的算法,MATLAB的这个变化正好适应了这种需求。
  3. 引入了名空间的管理。以前,MATLAB所有的函数都在同一个global的名空间下面。比如两个工具包里面出现了同名函数,解决起来很麻烦。比如现在有两个算法叫LDA,一个是Latent Dirichlet Allocation,一个是Linear Discriminant Analysis,在一个应用中需要同时用到两个算法,而写这两个算法的人各自把它们命名为lda.m,那么问题就出来了。一种naive的方法是改名字,不过会直接破坏掉那些toolbox里面对那个函数的依赖。而这个版本,它借鉴其它高级语言的经验,终于引入了namespace,给这个问题一个很好的解决。

从这些特点看来,MATLAB这个版本的重要改变,就是全面吸收其它高级语言的特性,从一个数值运算语言开始迈向一个以数值计算为强项的通用语言,以应对复杂或者更大规模应用的需要。

一直以来,由于matlab缺乏处理高级数据结构和建立复杂应用的能力,它有一个有力的竞争者numpy,这是python里面进行矩阵和数值运算的包,它建基于python这种著名的通用语言,并且提供matlab矩阵的部分能力。这次MATLAB的全面升级,对于numpy无疑提出了严峻的挑战。

除了程序设计结构方面的变化,MATLAB 2008在多个方面也有重要进步。

  1. 它的优化工具箱(optimization toolbox)首次引进了interior point algorithm。interior point algorithm在convex optimization中占有重要地位,并且性能优越。MATLAB optimization toolbox一直以为因为使用老式算法,性能太差,而饱受诟病。这次终于引入interior point,希望它的优化性能能得到显著改善。
  2. 重写核心JIT引擎(运行时编译,可以显著提高运行效率),并且采用了最新的BLAS/Lapack核心,运算速度会有相当程度的提高。另外,还大幅度提高了对sparse matrix的计算速度。
  3. 它的统计工具箱增强了对很多著名的统计算法的有力支持,比如HMM, GMM,还有NMF(Nonnegative Matrix Factorization),并且开始引入对蒙特卡罗采样的支持。

MATLAB 2008刚刚发行,现在学校内部还没开始支持。不过,这个版本确实非常值得期待。

March 07

课业

这两周经历了这个学期第一个忙碌的高峰。

这里的课业本来就很繁重,而且,很多时候并不均衡。最近,两门课程“不约而同”地把整个学期30%以上的作业量集中到了两个星期——我不记得这两周除了完成各种接续不断的assignment,还做过什么。

学计算机的人都知道循环语句,可是,如果这些人做TA,并且在布置作业的时候使用for循环,那是什么一种情况呢?最近一次作业的一道大题,竟然使用三重循环来布置,实在令人佩服。题目大概是长成这个样子:

1. (a).  (a.1) xxxx, (a.2), xxxx, .... (a.n) xxxx, (a.(n+1)) change some condition, please repeat from (a.1) to (a.n) ...... (b) ..... (c) ..... (d) ........ (e) with a new setting, please repeat (a) to (d) ..... 2 ..... 3 ..... 4 ...... 5 in a new method, please repeat 1 to 4.

除了两门课的作业和实验,还需要完成Network的research proposal。这里的课程project都有一个特点,全部都是不命题的。学生需要自己完成,从survey, proposal, formulation, experiment, 到最后的report的全过程。Network这门课的老师特别强调,project必须探索这个领域的研究前沿,最后的report必须写成可以发表的paper的形式,中间有一次中期检查,最后还有一次答辩。他不只一次的告诉我们,每年都有相当数量的project paper成功发表到top conference上——这应该是他对我们的一种期待——这对于这门课的学生,尤其是不在这个领域的,确实是极具挑战性的。

CS的决策人确实是用心良苦——要求每个学生修的课必须覆盖3大领域(system, theory, AI),而在大部分的课程中,教授都要求学生完成一个从选题到最后报告的完整的课题研究过程。虽然非常辛苦,但是,学生确实可以获得在计算机科学的各大领域开展研究的经验。另外一方面,几年前CS把所属的全部实验室合并成CSAIL——常年有800人工作的超大型实验室,鼓励各个研究小组相互交流。强制性的跨领域修课政策加上大实验室制,使得CSAIL内部的交叉研究特别活跃。很多研究课题都是“杂交”的。每个老师管着不同领域的课题,每个学生参与不同小组的meeting,已经司空见惯。在某些具体的领域,CSAIL的研究未必是最好的,但是,这里确实是世界上交叉学科发展最为蓬勃的地方。

February 21

Homework? Review paper for Science

今天作业的一部分,是以Science的reviewer的身份去review一篇文章,并攥写review报告。

这篇文章是已经在1996年发表于Science上,标题非常有趣:

Statistical Learning by 8-Month-Old Infants

大家可以非常容易在google上找到这篇文章的全文。

文章指出一个一个很值得思考的心理学实验结果:一个很小的婴儿,只需要听上两分钟的连续语音,就能形成对以后听到的连续语音进行有效分词的能力。

这篇文章阐述的是在语言学习方面的结果,而事实上,在所有智能领域,我们都可以看到类似的观察。比如在Vision,人们都没有经过系统的可控的物体识别训练,但是却非常容易获得在复杂的世界上对对象进行迅速的分割,识别,以及获取其它方面信息的能力,而目前computer vision的能力在最简单的可控实验中依旧举步维艰。

人类只需要很少的训练的情况下能够迅速获得非常灵活有效的“模型”去应对充满变化和干扰的实际输入,而计算机学习算法通过在大量样本训练,也很难接近哪怕是婴儿的水平呢? 人类的学习机制和目前人工智能研究所采用的方式究竟有什么不同?

现在统计学习领域百花齐放,但是,大部分的方法,无论formulation有多大的数学上的差别,基本上都是让一个具有某种结构的model按照某种准则去"fit"训练数据,通常还加上某种复杂性的约束。不过,很难想像人类是使用类似的方法从现实中学习的。我们每天感受到的是一个不断变化,各种要素充分融合的世界,没有分离的“训练数据”去学。我们的大脑能够理解非常复杂的东西,但是我们所接触的“训练集”按照经典统计学系理论的观点是无法支持这种复杂性的。虽然,我们经常会犯被观察所误导的错误,但是,相比于机器学习算法,我们overfitting的机会和程度远小得多。

我相信,我们的学习过程远比目前所有的机器学习算法聪明得多,绝不仅仅是observed->fitting这样的统计形式。AI的主要领域的研究现在过分依赖于统计建模,可是统计有它固有的瓶颈。早在Vapnik他们建立统计学习基础的时代,已经明确告诉了大家,统计学习受到复杂性的根本制约。因此,统计学习本身并没有足够能力到达人工智能的目标。相对于人类真正的智能来说,统计所能产生的智能只能认为是一种非常初级的形式。

从rule-based的专家系统到神经网络,再到统计学习,AI几十年内经历了几次大规模方法论更新的浪潮,但是是不是离真正的智能越来越近了呢?我们究竟是不是走在一个正确的方向上?

February 18

有价值的paper

CVPR 2008的审稿期刚刚结束了。今年,我对于所审的paper,采取了更加宽容的态度。

Vision依旧很热闹,但是,我感觉这个领域在喧嚣的背后似乎有点疲态了。年复一年,每年成百上千的paper仍旧是在那几个旧的舞台上唱着老调子。比如object recognition,无数打着"novel framework"旗号的车子,仍旧挤在local feature extractor + classifier (SVM/AdaBoost ...)的独木桥上,难道,这是唯一的方法么?

在没有看到有人开辟新的道路的时候,我更欣赏那些专注解决于一个具体的小问题,并且提出了有见地的方法的文章。对于那种表面华美的,而内里却仅仅是把A feature换成B feature,C model换成D model的,我一般评价很低。

这里的一位教授在谈到写paper的时候,提到了一种很多人都会犯的毛病。还是用object recognition的工作为例子,为了完成实验,你必须做大量的工作,把整个framework搭建起来,从data到feature到classifier,要写很多很多的code,花很多很多的时间去debug。为了对得起这些付出,很多人想把这些努力都写到paper上去,因此形成了很多并不新颖的工作每年都在投。而事实上,这些工作并不完全是没有新的东西,但是,那一点新的东西,在整个framework式的表述中被喧宾夺主了。

要写一篇有吸引力的文章,必须有取舍的决断。有些为了完成实验必须做的工作,你即使在上面付出了半年时间,但是如果缺乏真正的学术价值,在paper中应该尽量简省,把大部分的篇幅着力于那些真正的有意义的地方(哪怕那个地方其实你只花了3个小时想出来)。评paper不是评劳模(当然有些reviewer可能有这种倾向),不能把工作量的因素拿来布局paper的篇幅,不能把对某些工作“舍不得”的情绪带到paper的presentation当中。

CVPR审稿落幕了,我们的reading group又开始了。这个学期,John决定让大家自己轮流选paper,lead每个星期的reading。他说,除非有充分的理由,不要选近五年的文章。他上学期其实就是这样的风格,选的很多都是五六十年代的文章——信息论和统计学习的奠基者们那种seminal的经典著述。这些paper让我感慨前辈们的工作是多么有生命力,今天无数的主流算法仍旧发源于40年前的某篇文章,而且事实上没有走远多少。科技日新月异,其核心学理的进化则缓慢得多,艰难得多。

在paper里面通过比较几个近期工作来claim自己的东西是新的很容易,但是,要让一个工作放在这个学科的整个发展历史中去考量却依然有价值,则是非常艰难。这个学期,我开始要参加Alan的meeting, 他是MIT另外一个大实验室LIDS的director。有一次和Alan meeting的时候,大家提到一些最新发表的算法,他说,这些东西has been done 40 years ago。他人很nice,但是一项工作要得到他的认同很难。那次,我在他面前present了40分钟我的新工作,很多的东西都被他认为是在数学领域已经解决的(虽然vision里面没有出现这样的publication),不过庆幸的是,还是有一个point,被他指出I have never seen people working on this。后来两个星期,我在这个point上投入了很多时间去思考,发现这确实是一个很有价值的问题。

我在这里所接触的教授都很nice,平常对学生的工作也不干涉太多,但是对于一项工作的评价非常挑剔。John告诉我,要解决最困难的问题,容易解决的问题让别人做去。这半年来,脱离了CVPR的指挥棒,在沿着自己的道路一点一点的缓慢前进着,但是走的很踏实。刚来的时候,对MIT的氛围有点不太习惯,好像CVPR也好,NIPS也好,都没什么要紧的。现在才慢慢觉得,只有从conference的指挥棒中走出来,才能脱离浮躁,实实在在的进行有意义的探索。

两个星期后,将轮到我挑选reading group上讨论的paper。这么长时间大家都讨论的是信息论和统计方面的文章,我说,我要变一下,找vision的paper,John答应了,不过条件是paper必须是经得住考验的真正的好paper。我现在不知道哪篇能达到这个要求。

February 12

统计模型 or not

开学第一周,下岗了很长时间的闹钟又开始工作了。在上课和作业中,生活又恢复了忙碌。

这个学期选的一门Natural Language Processing,上课的风格还是让我觉得颇有创意。这门课每隔两周都要学生完成一篇类似GRE Issue这样的作文,就某个看上去有点深度的问题进行辩论。

在第一堂课,就布置了这样的讨论题:

比较统计模型和语法模型在自然语言建模中的优劣。

其实原题给出的是两个虚拟的Google员工的辩论,要求对其发表评论,上面这句话只是一个简要的归纳。题目中有一个很有意思的类比:

牛顿基于开普勒的天文观测数据归纳出万有引力定律。假设我们有充分多的天文数据,是不是可以直接Learn出一个统计模型,并且用它来predict行星在任何时间的运行位置和速度呢。

事实上,离开自然语言这样一个context,更广义上说,这里做的是让经验模型PK核心定律。

这里继续引申,可以到达一个听起来有点离经叛道的思考,前辈们在过去几百年间通过艰辛的努力和积累,建立起了以物理定律为基础的科学,

那么物理定律,能不能通过统计方法学出来呢?或者说,牛顿能不能被统计算法所取代呢。

我不是“统计万能”的支持者,但是,我相信,对这些问题的思考,有助于于理解统计方法的本质能力——它究竟能做什么,不能做什么。在过去的十几年里,统计学习在AI的众多领域里占据了主导地位。AI在继专家系统和神经网络之后,迎来了“统计时代”。但是,统计是不是就是建立真正意义的人工智能的钥匙呢?在享受统计方法给我们带来的一切好处的同时,也许,我们也许还需要一种批判的眼光去审视当今科学研究中的统计潮流。

February 10

再访纽约

上一次去纽约,已经是一年半前的事情了——参加2006年的CVPR。

昨天,我再次来到了纽约——因为要给Dylan当搬运工,同时也看看远道而来的小呆了,呵呵。

纽约是在很多人心中国际大都会的象征。但是,无论从哪个角度说,它都不属于那种人见人爱的城市。不同于东方的几个明星城市像香港和新加坡,纽约给我的第一印象就是既破又脏。

作为游客,我在纽约的主要交通工具是地铁——这里的地铁是世界上最古老的地铁之一,不过,也是我见过的最破烂的地铁。黑森森的地铁站里面站着,目无表情的人,从楼梯,站台,乃至铁轨上面到处都是垃圾和烟头——散发着令人不太愉悦的味道。很多地铁站内没有线路牌,地铁里面很多时候也是不报站的。不过,只要留心观察,要是有足够的素材让你判断火车到了哪个站了——虽然不是特别清晰显眼。

曼哈顿的主要区域都可以用“坐标”定位,主要的街和大道排成规则的纵横网格,都是用数字编号,使得在这个大城市里面找地方变得非常方便。曼哈顿岛上有大片的鳞次栉比的高楼群(从总数上超过香港的中环很多)。在美国的很多城市(包括Boston, San Diego乃至Houston)晚上都是颇为安静的,街上的商店很早就关门了。而纽约和这个国家的其它城市不同,到了晚上12点,主要的街道上依旧车水马龙,热闹非凡——就像香港的弥敦道。

三教九流的人共融在这个城市里。在这里,你经常可以看到豪华的加长林肯招摇过市,也可以看到在街边的衣衫褴褛的乞丐。在高耸入云的摩天大厦的下面就是遍地烟头的街道和破败不堪的地铁站。

纽约,不是一个花园城市,但却是一个充满魅力的城市——它的魅力源于它海纳百川的胸襟——藏龙卧虎和又藏污纳垢——鲜明的反差渗透在这个城市的每一个角落,构成了纽约最独特的性格。

February 06

开学了

新学期开始啦——寒假后,又要开始面对繁忙的课程了。

开学第一天,就和mentor meeting了——他非常满意,算是给这个学期开了个好头。这个学期的任务还是很重的,选了两门课

Computer Networks:选这门课,是因为系里要求学生在qualify前选择的课程必须横跨三个领域,在System领域,我们大家合计选这门了——因为考试的比重比较少。不过,这门课是research-oriented的,课程project要求很高。

The best projects are sure to be publishable (as they have in past years) in top ACM or IEEE conferences in the area, such as SIGCOMM, INFOCOM, or MOBICOM, or appear as articles in journals like SIGCOMM's Computer Communications Review (CCR). I have a strong feeling that you will far surpass my already high expectations with wonderful work that will further the state-of-the-art in network research.

看来有得忙活了。如果上三个月课作出来的project就能发到mobicom/sigcomm,我估计得考虑转行做网络了,哈哈。历史上是有这号牛人的,敬仰一把。

还有一门Natural Language and Computer Representation of Knowledges。这门本不是我要选的,只因为Computer Vision课被Freeman取消了,起码今年没有。不得不在AI领域另选一门。不过看了一些syllabus,内容还是很interesting的。

开拓视野,博纳众长,说不定对自己的research还有所启发。

最后,祝愿大家新春快乐!

February 03

Is computer vision as good as thought?

随手翻开这期TechTalk, 在头版的大标题computer vision的字样赫然入目。第一次在TechTalk看到自己领域的文章,自然很感兴趣。

先介绍一下,TechTalk是MIT内部一份免费派发的报纸,每周一期,主要报道学校的各种科学研究的进展。一直以来,占据这份报纸头版的主要是生命科学,能源科学,或者新材料。

这篇文章的标题是 Computer vision may not be as good as thought

文章的作者来自 McGovern Institute of Brain Research @ MIT。

文章主要是针对近期在Object recognition所取得的“进展”而发的。它开篇就旗帜鲜明地提出:

The apparent success of object recognition may be misleading because the tests being used are inadvertently stacked in favor of computers.

在MIT McGovern Institute和Harvard Rowland Institute的一项联合研究中,他们认为,被广泛用于评价object recognition性能的Caltech 101 database并不能有效反映出算法在真实条件下的能力。文章指出,object recognition的核心困难源于一个物体在形成图像过程中,由于方向,位置,光照,外界环境等等的要素影响而发生的各种变化。而以Caltech 101为代表的主流测试库,在获取过程中实际上是隐含了有利于计算机辨别的因素,而不能真实反映客观世界的复杂变化,并且掩盖了实际问题的复杂性。

The ease with which we recognize visual objects belies the computational difficulty of this feat.

在他们的实验中,他们做了一个非常naive的算法作为baseline,该算法仅仅用到了一些非常初级的信息,而且没有进行特别处理和分析。他们原以为这个算法会fail,但是他们惊奇地发现,这个naive算法在Caltech 101上表现出色(surprisingly well),其性能甚至超过了5个最新提出的state-of-the-art的算法。

从这样的实验结果中,他们对主流的算法评价体系提出了质疑

We suspected that the supposedly natural images in current computer vision tests do not really engage the central problem of variability.

为了验证他们的想法,他们设计了这样的实验,只使用飞机和车两类物体,但是,尽可能引入各种真实变化的条件。他们发现,那些在Caltech 101上面分多类分得很好的算法,在这里分两类都分得一蹋糊涂。这个团对得到这样的结论:

The model did well on the Caltech101 image set not because it is a good model but because the so-called 'natural' images in the test set fail to adequately capture real world variability.

他们提出,computer vision的研究人员应该抛弃现有的不科学的评价体系。

作为脑科学系的研究人员,他们研究object recognition的方法,主要是探索our brain's own solution,并且尽可能地去模仿它。他们认为,这是一个正确的方向。

January 27

关于平均值

小时候,老师就告诉我们,读书讲究先由薄而厚,再由厚而薄。前者是吸收和积累,后者是融会和消化。

这些年,读了不少关于统计学习的东西,很多东西都记不清楚了。从我自己的角度看来(可能是很肤浅的),学概率和统计,关键是记住三个概念:测度(measure),期望(expectation),和独立性(independence)。

测度是现代概率理论的基石。在经典的概率论里面——比如我们在本科学的那些——大多是通过举例子和文字说明的方式告诉你概率是什么,这容易明白,不过缺乏严密的公理化根基。现代概率论整个建立在测度理论的基础上,概率的定义非常简单,不过也很抽象——所谓“概率”,就是归一化的测度。没有测度,就没有整个概率论的大厦,所以它很重要——不过,它在实用中直接用上的机会不大,所以不是这篇文章的主体。关于独立性,以及它的一个孪生的名词:Markov,也扮演着非常重要的角色,它是Graphical models的基础。有兴趣的可以去读M. I. Jordan的书。

而在统计学习的实际应用中,就是你平时写code,用得最多的就是期望,或者一个通俗点的版本——平均值。其实这两者不太一样,期望是从model出发演绎的,平均值通常是指从data出发归纳的。不过它们的关系确实非常密切。

统计学习在很多情况下,就是求平均值

我们平常说去Learn一个model——其实,在很多情况下,这就是干一件听上去很简单的事情,求平均值。我们知道,我们所接触的大部分重要的概率分布,都属于exponential family,比如Gauss, Binomial, Multinomial, Dirichlet, Poisson, Exponential, Gamma等等分布都属于这个家族。它的一个重要特点就是——得期望者得天下。就是说,知道了某些统计量的期望,就知道了整个model,至于model的参数,或者就是期望本身(比如Gauss),或者不难从期望中得到。可以证明,对于这些model,对它们的最大似然估计(Maximum Likelihood estimation),就是从data中算出某些统计量的平均值作为model的期望。

在Bayes学习中,我们还考虑先验分布(prior)。在这里,model的估计还是求平均值。所谓prior是怎么来的?就是以前曾经观察过的data那里总结得到的,然后以prior的形式影响当前的model估计。一般而言,使用exponential family,我们通常会使用conjugate prior,这种prior,基本就是沿着刚才说的,假想我们已经看过一些data的思路得到的,它的形式和data mean几乎如出一辙。而带了prior的估计,还是在求平均值,不过这里的平均值就是(假想)以前观察过的数据和当前的数据合在一起求平均。

对于更加复杂的Graphical model,每个节点的estimate和update,很多时候,其实是做了这样的事情——把其它节点传来的平均值和这个节点接触的数据的平均值混合进行新的平均。从最简单的Gauss, 到更加复杂的Gaussian Mixture Model, Latent Dirichlet Allocation, Markov Random Field, Generalized Kalman Filtering概莫能外——大家可以仔细看看它们的每一个update公式,看看哪个不是在求平均值。

怎样求平均值

平均值是很重要的。不过怎么求呢?这似乎是小学初中就解决了的问题。不过,求平均值的世界其实是如此博大精深。如果说它是少林武学,我现在这点水平,也就够在嵩山下扫扫地罢了。很多在世界上赫赫有名的数学家,穷毕生心血,方能一窥堂奥。

虽然,只有扫地的水平,不过起码也看过大师们练武。这门学问主要有两个方面:得到data求平均值,得到model求期望。

先说说求data的平均值。这太简单了,有什么好说的。不就是加法和乘法么,小学学过算术的人都会算,即使没学过,拿个计算器也照样算。在通常的实数空间内,确实很简单;不过对于一般的求平均值的情况,就非常非常困难了。一般来说,求平均值有两个流派,一种是基于线性代数(linear algebra),另外一种是基于度量空间(metric space)。前面一种大家很熟悉:

m = (x1 + x2 + ... + xn) * (1/n)。

这是我们读了这么多年书最常见的平均值。不过,这样定义太局限了,它要求这些东西能做加法和数乘——我不得不说,这个要求实在太高,只有线性空间(这种空间是数学里面的贵族,它们什么好处都全了)能够满足——对于数学领域更广大的人民群众(各种更一般的数学结构,比如群,拓扑流形),加法和数乘简直是一种奢侈得不切实际的活动。

其实平均值是一个非常广泛的概念,不仅仅存在于线性空间中,还为广大人民群众服务。对于某个度量空间,它的一般性定义是这么给出的

使得 d(m, x1) + d(m, x2) + ... + d(m, xn) 最小的那个m

也就是说,求平均值是一个优化问题。关于这个问题,在不同的空间中有不同的答案:在最高级的希尔伯特空间中(定义了内积的完备线性空间),m就是上面给出的基于线性代数的形式。所以说,基于线性代数的定义仅仅是基于度量空间的定义的一个特例。不过由于这个特例被广泛使用,所以大家一说平均值就想起它,而不是一般形式。在推广一些的巴拿赫空间中(定义了范数的完备线性空间),上述的问题是一个凸优化问题,因为范数必然是凸函数。它具有唯一的最优解。

最困难的是在非线性空间中。一个典型的例子是黎曼流形(注意,这里我们只讨论黎曼流形,对于更为一般的拓扑流形或者微分流形,因为不具有度量结构,所以不能定义均值。)在黎曼流形上,两点间的距离是通过测地距离给出的。在黎曼流形上,通过测地距离定义的平均值,叫做黎曼中心。一部分朋友对于这几个术语可能不太熟悉,还是举个形象点的例子。比如,在地球上给出几个地点,你要在地面上找一个“平均地点”,使得它到那几个地点的“地面距离”的平方和最小。如果,用传统的算术方法拿这些地点的三维坐标来算,你估计得在那钻个油井了。对于“球面平均”问题(专门一点的说法叫做特殊正交群SO(3)的黎曼中心,恩,这个名词我也有点晕),到了在本世纪,在数学里依旧可以发paper,目前还没有一般情况下的解析解。

别的领域我不懂,不过“球面平均”在vision里面价值是很大的,它是对三维旋转变换建立统计模型的基础——我们再一次看到了求平均值对于统计的重要意义。球面平均求的是“平均”的旋转,如果对于一般的仿射变换(Affiine transform),“平均”的变换又怎么求呢?这是个open problem,留待大家思考。

怎样求期望

说完从data求平均值,再说说从model得到期望(expectation)——这们学问就更博大了。虽然,期望的定义很简单——求和或者积分就行了。不过,它的实际计算,对于很多实际模型是intractable的。

概率论最早源于掷色子,我们的前辈数学家们为了破解求复杂模型求期望的问题,提出的方法就是掷色子。在学术上,美其名曰“蒙特卡罗方法”(Monte Carlo)。原理很简单,不断地掷色子来大量采样,然后从采来的样本求平均值来逼近模型的期望。

掷色子是世界上最有学问的之一,正因为如此,我们对于“赌神”,“赌王”之类的人物崇拜犹如滔滔江水,因为它们掷色子掷得好。无数的统计学家把毕生经历奉献给掷色子(采样)事业,并且做出伟大成就。关于采样的专著和文献,汗牛充栋。

掷色子就这么难么?是的。据估算,即使对于一个复杂度不高的model,要得到一个可以接受的估计,所需的样本量往往大得惊人,而且指数增长。如果不掌握要领,你即使掷到宇宙末日,估计离一个靠谱的估计还远着呢。采样技术名目繁多,最流行的莫过于重要性采样(importance sampling)和马尔科夫链蒙特卡罗过程(MCMC)。具体就不多说了。

January 23

漫话距离

我们的生活从来不缺乏距离的概念,无论是时间的还是空间的,可以测量的还是不可以测量的。自我们