本文主要译自 MCMC: The Metropolis Sampler

正如之前的文章讨论的,我们可以用一个马尔可夫链来对目标分布 \(p(x)\) 进行采样,通常情况下对于很多分布 \(p(x)\),我们无法直接进行采样。为了实现这样的目的,我们需要为马尔可夫链设计一个状态转移算子(transition operator),是的这个马尔可夫链的稳态分布与目标分布吻合。Metropolis 采样算法(更通常的是 Metropolis-Hastings 采样算法)采用简单的启发式方法实现了这样的状态转移算子。

Metropolis 采样

从一个随机的初始状态\(x^{(0)}\thicksim \pi^{(0)}\)开始,算法首先从建议分布(proposal distribution)\(q(x|x^{(t-1)})\)生成一个可能的抽样\(x^*\)。(译者按:这里的建议分布(proposal distribution)区别于目标分布(target distribution),通常比目标分布要简单,可以通过计算机直接生成按建议分布的随机变量)和普通的马尔可夫链转移算子相同,建议分布仅仅取决于马尔可夫链当前的状态。然而,Metropolis 算法的状态转移算子有一个附加步骤,那就是评估目标分布在建议状态(proposed state 译者按:通过建议分布采样得到的状态)下是否有足够大的密度函数来支持这个建议状态是合理的,从而将其设置为马尔可夫链的下一个状态。如果密度函数\(p(x)\) 在建议状态下很小,那么,它就很有可能(但不一定)被拒绝。接受或者拒绝建议状态的评判标准由下面的启发式算法定义:

1. 如果\(p(x^*)\geq p(x^{(t-1)})\),那么建议状态 \(x^*\) 将被保留为一个采样点,从而设置为马尔可夫链上的下一个状态(i.e. 始终向 \(p(x)\) 不变或者变大的方向移动马尔可夫链的状态)。

2. 如果\(p(x^*)<p(x^{(t-1)})\),表示 \(p(x)\) 在 \(x^*\) 附近的密度值小于前一个状态,但是这个建议的状态 \(x^*\) 仍然有可能被接受,但是是随机的,接受的概率是\(\frac{p(x^*)}{p(x^{(t-1)})}\)

这些启发步骤可以被整合到一起,为建议状态计算接受概率(acceptance probability),

\(\alpha = \mathrm{min}\left(1, \frac{p(x^*)}{p(x^{(t-1)})}\right)\)

掌握了接受概率,metropolis 算法的转移算子是这样工作的:如果一个随机均与分布 \(u\) 小于等于 \(\alpha\),那么我们就接受 \(x^*\) 作为下一个状态,反之,这个建议状态被拒绝, 我们将继续生成下一个建议状态。为了用 metropolis 算法得到 \(M\) 个抽样,我们运行下面的算法:

1. set t = 0 设置 t = 0,表示初始时刻一次迭代都没发生

2. generate an initial state \(x^{(0)}\) from a prior distribution \(\pi^{(0)}\) over initial states

3. repeat until \(t = M\)

  set t=t+1

  generate a proposal state \(x^*\) from \(q(x|x^{(t-1)})\)

  calculate the acceptance probability \(\alpha = \mathrm{min}\left(1,\frac{p(x^*)}{p(x^{(t-1)})}\right)\)

  draw a random number \(u\) from Unif(0,1)

    if \(u\leq\alpha\), accept the proposal and set \(x^{(t)} = x^*\)

    else set \(x^{(t)}=x^{(t-1)}\)

Example: Using the Metropolis algorithm to sample from an unknown distribution

假如我们有这样一个神秘的概率分布函数:

\(p(x) = (1+x^2)^{-1}\)

我们想生成符合这个密度函数的随机采样。为了使用 Metropolis 采样算法,我们需要定义两件事:(1)马尔可夫链初始状态的先验分布\(\pi^{(0)}\),以及(2)建议分布函数 \(q(x|x^{(t-1)})\)(译者按:这里再强调一下,我们的建议分布函数为 proposal distribution,是比较好采样的,目标函数 target distribution 是不好采样的,我们通过好采样的函数采样,然后判断采到的样本是否被接受)。对于这个例子,我们定义:

\(\pi^{(0)}\thicksim \mathcal{N}(0, 1)\)

\(q(x^{(t)}|x^{(t-1)})\thicksim \mathcal{N}(x^{(t-1)}, 1)\),

这两者都是简单的正态分布,一个以0为中心,另一个以上一个状态的取值为中心。下面的一块 MATLAB 代码采用了上面的推荐分布和先验分布,运行了 Metropolis 采样。

% METROPOLIS SAMPLING EXAMPLE
randn('seed',12345); % DEFINE THE TARGET DISTRIBUTION
p = inline('(1 + x.^2).^-1','x'); % 定义目标分布 % SOME CONSTANTS
nSamples = 5000; % 抽取5000个样本
burnIn = 500;
nDisplay = 30; % 将展示前30个抽样过程
sigma = 1; % 建议分布的标准差定义为1
minn = -20; maxx = 20;
xx = 3*minn:.1:3*maxx; % 抽样的区间
target = p(xx); % 目标函数在区间上的取值,用于下面画函数图
pauseDur = .8; % 动态展示过程中每个抽样需要暂停0.8秒 % INITIALZE SAMPLER
x = zeros(1 ,nSamples); % 初始化抽样序列
x(1) = randn; % 初始化第一个抽样
t = 1; % 抽样编号 % RUN SAMPLER
while t < nSamples % 当没有抽满指定数目的样本时
t = t+1; % SAMPLE FROM PROPOSAL
xStar = normrnd(x(t-1) ,sigma); % 按照建议抽样函数进行采样
proposal = normpdf(xx,x(t-1),sigma); % 建议抽样函数在整个区间上的取值 % CALCULATE THE ACCEPTANCE PROBABILITY
alpha = min([1, p(xStar)/p(x(t-1))]); % 接受概率 % ACCEPT OR REJECT?
u = rand; % Metropolis 采样的核心部分,按照接受概率决定是否接受当前采样
if u < alpha
x(t) = xStar;
str = 'Accepted';
else
x(t) = x(t-1);
str = 'Rejected';
end % DISPLAY SAMPLING DYNAMICS
if t < nDisplay + 1 % 动态展示前 nDisplay 个采样过程
figure(1);
subplot(211);
cla
plot(xx,target,'k'); % 目标函数图像
hold on;
plot(xx,proposal,'r'); % 建议函数图像
line([x(t-1),x(t-1)],[0 p(x(t-1))],'color','b','linewidth',2) % 目标函数在上一个采样点的函数值
scatter(xStar,0,'ro','Linewidth',2) % 将当前采样点表示在x轴上
line([xStar,xStar],[0 p(xStar)],'color','r','Linewidth',2) % 目标分布函数在当前采样点的函数值
plot(x(1:t),zeros(1,t),'ko') % 将已经采样过的点表示在x轴上
legend({'Target','Proposal','p(x^{(t-1)})','x^*','p(x^*)','Kept Samples'}) switch str
case 'Rejected'
scatter(xStar,p(xStar),'rx','Linewidth',3) %如果拒绝,就用x表示这个点
case 'Accepted'
scatter(xStar,p(xStar),'rs','Linewidth',3) %如果接受,用方块表示这个点
end
scatter(x(t-1),p(x(t-1)),'bo','Linewidth',3) % 目标函数在上一个采样点的函数值
title(sprintf('Sample % d %s',t,str))
xlim([minn,maxx])
subplot(212);
hist(x(1:t),50); colormap hot;
xlim([minn,maxx])
title(['Sample ',str]);
drawnow
pause(pauseDur);
end
end % DISPLAY MARKOV CHAIN
figure(1); clf
subplot(211);
stairs(x(1:t),1:t, 'k');
hold on;
hb = plot([-10 10],[burnIn burnIn],'b--');
ylabel('t'); xlabel('samples, x');
set(gca , 'YDir', 'reverse');
ylim([0 t]);
axis tight;
xlim([-10 10]);
title('Markov Chain Path');
legend(hb,'Burnin'); % DISPLAY SAMPLES
subplot(212);
nBins = 200;
sampleBins = linspace(minn,maxx,nBins);
counts = hist(x(burnIn:end), sampleBins);
bar(sampleBins, counts/sum(counts), 'k');
xlabel('samples, x' ); ylabel( 'p(x)' );
title('Samples'); % OVERLAY ANALYTIC DENSITY OF STUDENT T
nu = 1;
y = tpdf(sampleBins,nu);
%y = p(sampleBins);
hold on;
plot(sampleBins, y/sum(y) , 'r-', 'LineWidth', 2);
legend('Samples',sprintf('Theoretic\nStudent''s t'))
axis tight
xlim([-10 10]);

采样过程如下面的GIF图所示,图片来自原文

  

图中展示了前30次抽样过程,黑线表示目标分布函数 \(p(x)\),在 x 轴上移动的红线表示建议分布函数 \(q(x|x^{(t-1)})\) 。蓝色竖线(它在红色分布函数的轴线上)表示 \(p(x^{(t-1)})\) 的值,红色竖线表示 \(p(x^*)\),\(x^*\) 是根据红色建议分布函数生成的建议采样。每一次迭代,如果红色竖线比蓝色竖线长,那么采样 \(x^*\) 将会被接受,建议分布函数(红色曲线)的中心将会移动到新的采样点的位置。如果蓝色的竖线更长,那么建议采样将会随机地被接受或拒绝。

但是为什么要随机地接受“坏的”(\(p(x^*)<p(x^{(t-1)})\) 的点 \(x^*\))采样呢? 因为这样做可以使得马尔可夫链时不时地访问目标分布中概率小的状态点。这是一个合理的性质,如果我们想要对目标分布的整体(包括尾巴的部分)进行随机采样。

Metropolis 算法一个很有吸引力的地方是,它不需要目标分布 \(p(x)\) 归一化为概率分布。这是因为,接受概率是基于两个目标分布函数值的比值的,分子分母的归一化因子 \(Z=\int p(x)\mathrm{dx}\)  可以消掉:

如果 \(p(x)\) 是一个未归一化的分布函数,那么:

\(p^*(x) = \frac{p(x)}{Z}\)

是其归一化的分布函数,归一化常数为 Z,于是:

\(p(x) = Zp^*(x)\)

然后,当我们计算接受概率 \(\alpha\) 时,我们需要计算:

\(\frac{p(a)}{p(b)} = \frac{Zp^*(a)}{Zp^*(b)} = \frac{p^*(a)}{p^*(b)}\)

归一化常数 Z 被消掉了!这个好性质在贝叶斯方法中十分有用,因为一个分布的归一化常数不容易直接计算。事实上,我们上面例子中采样的“神秘”分布是一个没有归一化的 1 自由度 Student's-t 分布。我们比较 \(p(x)\) 和 Student's-t 分布的定义:

\(Student(x,\nu) = \frac{\Gamma(\frac{\nu+1}{2})}{\sqrt{\nu\pi}\Gamma(\frac{\nu}{2})}\left(1+\frac{x^2}{\nu}\right)^{-\frac{\nu+1}{2}}\)

自由度为1时,\(\nu=1\),带入上式,令常数项为 \(\frac{1}{Z}\),有:

\(Student(x,\nu) = \frac{(1+x^2)^{-1}}{Z} = \frac{p(x)}{Z}\)

我们看到 \(p(x)\) 是一个自由度为1的 Student's-t 分布,但是少了归一化常数:

\(Z = \left(\frac{\Gamma(\frac{\nu +1}{2})}{\sqrt{\nu\pi}\Gamma(\frac{\nu}{2})}\right)^{-1}\)

下面是上方代码的另一个输出,展示了 Metropolis 采样得到了符合归一化了的 Student's-t 分布的随机数,尽管 \(p(x)\) 没有归一化。

上面的输出展示了马尔可夫链从 \(x^{(0)}\) (上方)到 \(x^{(5000)}\) (下方)更新的过程。这个链的 burn in 区间定为500次迭代,它被蓝色的虚线表示出来了。

下面的图像用黑色表示了马尔可夫链采集到的样例。红色曲线表示 1 自由度 Student's-t 分布的理论值。我们看到 Metropolis 采样得到的的样例符合 Student's-t 分布,尽管转移算子中用到的函数 \(p(x)\) 并没有被归一化成概率分布函数。

转移算子的可逆性(Reversibility of the transition operator)

事实证明为了使马尔可夫链稳定在一个固定分布(也就是我们所关心的目标分布),状态转移算子有一个理论上的约束条件。这个约束条件说的是:\(x^{(t)}\rightarrow x^{(t+1)}\) 的转移概率与反向 \(x^{(t+1)}\rightarrow x^{(t)}\) 转移概率相等。这个可逆性通常被称为细致平衡(detailed balance)。对于 Metropolis 算法的转移算子,如果推荐概率分布 \(q(x|x^{(t-1)})\) 是对称的,那么其可逆性将被得到保证。也就是说:\(q(x^{(t+1)}|x^{(t)}) = q(x^{(t)}|x^{(t+1)})\),对于离散的情况,这个条件的意思是:推荐转移矩阵是对称的。连续的情况,有很多概率分布函数也是对称的,例如正态分布,柯西分布,Student's-t 分布,均匀分布。

上面的例子中,我们的推荐分布函数为方差为1的正态分布,正态分布的均值为上一个函数取值,也就是:

\(q(x^{(t)}|x^{(t-1)})\thicksim\mathcal{N}(x^{(t-1)},1) = \frac{1}{\sqrt{2\pi}}\mathrm{exp}\left(\frac{(x^t-x^{(t-1)})^2}{2}\right)\)

显然,

\(q(x^{(t)}|x^{(t-1)}) = q(x^{(t-1)}|x^{(t)}) \)

满足了上面提到的约束条件,也就是:推荐函数是对称的。

然而,使用对称的推荐函数或许不能够准确、高效地对所有目标分布函数取样。例如,如果一个目标分布定义在 x 轴正半轴,我们希望推荐分布也定义在同样的区间,这就导致了不对称性的出现。这就是为什么我们接下来会引入 Metropolis-Hastings 采样算法。我们接下来的文章将会介绍 Metropolis-Hastings 算法是如何通过简单地改变接受概率的计算方式,来允许我们使用非对称的推荐分布的。

译者按:

这篇文章介绍了 Metropolis 算法,并给出了限制条件。算法可以总结为:

1. 选一个推荐分布(离散有限维空间下为一个转移矩阵,连续空间下为一系列函数,例如上例中方差为1,均值为当前采样点的正态分布函数)

2. 根据推荐分布生成采样 \(x^*\)

3. 计算 \(\alpha = \mathrm{min}(\frac{p(x^*)}{p(x^{(t)})},1)\)

4. 生成0到1之间的均匀分布随机数\(u\),如果\(u<\alpha\) 那么就接受 \(x^*\) 作为第 t+1 个采样,否则拒绝 \(x^*\),第 t+1 个采样仍然与 \(x^{(t)}\) 相同

重复上面到足够多的次数,然后扔掉 burn in 的部分,剩下的就是符合目标分布的随机采样点。

使用这个算法,需要注意的一个重要条件是:推荐分布(状态转移函数)必须是对称的,我们的例子中的正态分布正是对称的。

但是,这篇文章也有不足的地方,那就是没有告诉我们,为什么采用这种算法就可以得到我们的目标分布,而推荐分布(转移算子)又为什么必须是对称的。下面本人将尝试给出一种不严格的证明,或者是解释,来说明这个算法的确可以得到我们想要的分布。

假如我们希望马尔可夫链可以收敛到目标分布函数 \(\pi(x)\),转移算子为 \(T\),\(T(a,b)\) 表示从状态 a 转移到状态 b 的概率。推荐转移算子为\(Q\),\(Q(a,b)\) 表示按照推荐分布从状态 a 转移到状态 b 的概率,根据前面的要求,Q 必须是对称的:\(Q(a,b)=Q(b,a)\)。那么根据我们的算法,从状态 a 转移到状态 b 的概率等于推荐函数的转移概率乘以接受率,即:

\(T(a,b) = Q(a,b)*\mathrm{min}\left(1,\frac{\pi(b)}{\pi(a)}\right)\)

那么,如果马尔可夫链达到稳态分布 \(\pi(x)\)(也就是细致平稳条件):

\(\pi(a)\cdot T(a,b) = \pi(a)\cdot Q(a,b)\mathrm{min}\left(1,\frac{\pi(b)}{\pi(a)}\right)\)

\(= Q(a,b)\mathrm{min}(\pi(a), \pi(b))\)

\(= \pi(b)\cdot Q(a,b)\mathrm{min}\left(\frac{\pi(a)}{\pi(b)}, 1\right)\)

\(= \pi(b)\cdot Q(b,a)\mathrm{min}\left(\frac{\pi(a)}{\pi(b)}, 1\right)\)

\(= \pi(b)\cdot T(b,a)\)

果然,在稳态分布时各个状态之间的转移达到平衡。我们同时也知道了,为什么一定要求推荐分布是对称的。

Metropolis 算法给出了一个可以对任意已知分布进行采样的方法,这里我们再回顾一下为什么我们要对已知分布进行采样:

我们要计算:

\(E(x) = \int f(x)p(x)\mathrm{dx}\)

只要产生了足够多的按照 \(p(x)\) 分布的点:\(x_1,x_2,...x_N\),就可以将上面的积分近似为:

\(E(x)=\frac{1}{N}\sum\limits_{n=1}^Nf(x_n)\)

应用实例

写到这里,再举一个经典的应用 Matropolis 算法的例子:"Hard disk in a box model"。

统计物理学家想研究盒子中的气体的一些物理性质,这些性质是所有气体分子的位置的函数,我们假设二维的边长为1的盒子中有 N 个气体分子,它们的位置由各自的横、纵坐标唯一确定。那么,每一个位置分布都代表了盒内气体的一种状态,状态空间为:

\(X=(x_1,y_1,x_2,y_2,...,x_N,y_N)\)

玻尔兹曼方程可以计算任何一种分布的概率:

对于任何一个状态 \(x\in X\),其概率为:

\(\pi(x) = \frac{1}{Z}\mathrm{exp}(-\frac{\mathcal{E}(x)}{kT})\)

其中 Z 为归一化常数,k 是玻尔兹曼常数,T 是温度。\(\mathcal{E}(x)\) 是气体的能量,将每个气体分子的位置带入公式可以算出来。归一化常数 Z 是所有可能的位置带入到 \(\pi(x)\) 的分子中,算出来的数再累加的结果,显然 Z 是不可解的,因为我们无法穷尽气体分子分布的所有可能情况。

我们如果想计算该系统的某个宏观参数,事实上,气体系统的一切宏观参数都是某种函数的“均值”(或者说期望)。例如压强 p,可以把它看成某个关于气体分布状态 \(x\) 的函数 \(f(x)\) 的期望:

\(p = E(f(x)) = \int f(x)\pi(x)\mathrm{dx}\)

该如何计算呢?显然根据上面的讨论 \(\pi(x)\) 因为归一化常数 Z 太复杂,无法直接算出来,更别提对它进行积分了。但是我们可以采用蒙特卡洛方法计算这个 \(f(x)\) 的期望:

首先生成符合 \(\pi(x)\) 分布的一系列采样,\(x_1,x_2,x_3,...x_N\)

然后带入用公式:

\(E(f(x))\approx\frac{1}{N}\sum_{n=1}^Nf(x_n)\)

求出 \(f(x)\) 的期望。

但是,如何生成关于 \(\pi(x)\) 的采样呢?我们就要用到本文前面介绍的 Metropolis 算法了:

虽然我们不知道 \(pi(x)\) 的归一化常数 Z,但是因为它是常数,我们可以在 Metropolis 算法中计算接受概率时把它扔掉,只考虑分子部分。

也就是说,在算法中,我们使用 \(\tilde{\pi}=\mathrm{exp}(-\frac{\mathcal{E}(x)}{kT})\)

下面我们需要确定的是,推荐转移概率分布(proposal transition distribution),这里我们做如下分析:

1. 只要有一个分子的位置发生改变,那么这个气体系统的状态就发生了改变,因此,每次我们从 N 个分子中挑出一个分子,改变它的位置,从而获得一个新的状态。

2. 一个气体分子虽然可以随机移动,但是基本上只会在周围一定的空间内随机移动,而不会发生从盒子左上角一下子移动到右下角的情况,因此,我们认为每次单个分子的移动范围在以它为中心,\(2\alpha\) 为边长的正方形盒子里。

3. 单个分子在以它为中心 \(2\alpha\) 为半径的盒子内是均匀随机移动的。

由于每次随机选取的点是均匀分布的,因此这里的推荐转移分布是对称的,那么,我们可以按这样的步骤采样:

1. 随机从 N 个分子中抽取一个分子

2. 将这个分子按均匀分布随机移动到以它为中心,\(2\alpha\) 为边长的盒子中的某个点,得到新的状态 \(x^*\)

3. 计算接受概率\(p(accept) = \mathrm{min}(1,\frac{\tilde{\pi}(x^*)}{\tilde{\pi}(x^{(t)})})\)

4. 随机接受或者拒绝这个取样

5. 重复上面1至4步,得到足够多的取样

通过上面的步骤,我们就可以采集到符合 \(\pi(x)\) 分布的样本了,接下来将它们代入蒙特卡洛方法的公式中,计算出系统的压强 p 。当然,这里的压强也可以换成别的什么宏观参数。

MCMC: The Metropolis Sampler的更多相关文章

  1. MCMC: The Metropolis-Hastings Sampler

    本文主要译自:MCMC:The Metropolis-Hastings Sampler 上一篇文章中,我们讨论了Metropolis 采样算法是如何利用马尔可夫链从一个复杂的,或未归一化的目标概率分布 ...

  2. MCMC:Gibbs 采样(matlab 实现)

    MCMC: The Gibbs Sampler 多元高斯分布的边缘概率和条件概率 Marginal and conditional distributions of multivariate norm ...

  3. A Brief Introduction to Markovs Chains

    本文译自A Brief Introduction to Markovs Chains 译者按: 前面一篇文章讲的是蒙特卡洛积分,也就是通过生成符合特定分布的随机变量来近似计算积分值,例如: \(E = ...

  4. 从随机过程到马尔科夫链蒙特卡洛方法(MCMC)

    从随机过程到马尔科夫链蒙特卡洛方法 1. Introduction 第一次接触到 Markov Chain Monte Carlo (MCMC) 是在 theano 的 deep learning t ...

  5. [转] - MC、MC、MCMC简述

    贝叶斯集锦(3):从MC.MC到MCMC 2013-07-31 23:03:39 #####一份草稿 贝叶斯计算基础 一.从MC.MC到MCMC 斯坦福统计学教授Persi Diaconis是一位传奇 ...

  6. Metropolis Hasting算法

    Metropolis Hasting Algorithm: MH算法也是一种基于模拟的MCMC技术,一个非常重要的应用是从给定的概率分布中抽样.主要原理是构造了一个精妙的Markov链,使得该链的稳态 ...

  7. [Bayes] prod: M-H: Independence Sampler for Posterior Sampling

    M-H是Metropolis抽样方法的扩展,扩展后可以支持不对称的提议分布. 对于M-H而言,根据候选分布g的不同选择,衍生出了集中不同的变种: (1)Metropolis抽样方法 (2)随机游动Me ...

  8. MCMC&Gibbs sampling

    Note of Markov Chain Monte Carlo and Gibbs Sampling :  http://pan.baidu.com/s/1jHpWY1o 序:A major lim ...

  9. 蒙特卡洛马尔科夫链(MCMC)

    蒙特卡洛马尔科夫链(MCMC) 标签: 机器学习重要性采样MCMC蒙特卡洛 2016-12-30 20:34 3299人阅读 评论(0) 收藏 举报  分类: 数据挖掘与机器学习(41)  版权声明: ...

随机推荐

  1. Linux 动态链接库

    如何使用动态链接库 Linux下打开使用动态链接库需要三步(实际上和windows下基本一样):1.加载动态链接库,通过调用库函数dlopen()获得链接库的句柄,对应于windows下的 AfxLo ...

  2. Visor 应用之一 通过ER 设计生成数据库脚本和实体对象

    前言 Visor(http://www.visor.com.cn)   是一个基于HTML5 Canvas 开发的IDE 框架和设计开发平台,有关Visor的设计架构和技术应用,在以后的文章里会逐渐跟 ...

  3. cheap gucci bags for women finish fashion jewellery has to move

    Is certainly his dresser seem or dress creation process into video clip. Bus dropped???? Especially ...

  4. Linux 命令 find

    find命令的基本格式是:find [路径] [选项] [操作]路径是find命令所查找的范围,如用.来表示当前目录,用/来表示根目录,选项用于指定查找条件,如:可以指定按照文件的属主,更改时间文件类 ...

  5. http://tool.oschina.net 在线API文档库java jquery ,php,很全的文档库

    http://tool.oschina.net  1.6API文档(中文)的下载地址: ZIP格式:http://download.java.net/jdk/jdk-api-localizations ...

  6. DataList无数据如何显示

    <FooterTemplate> <asp:Label runat="server" ID="emptyLb" Text="No D ...

  7. pushlet

    自己准备做一个小游戏,租个云服务,然后挂在网上,可以跟同学一起玩,不过首先布置的是,这个游戏是否能实现,多人在线网页游戏,考虑到是否能够实时查询,在网上借鉴了下聊天原理,http长连接,搜索到push ...

  8. Scala编程--基本类型和操作

    如果你熟悉Java,你会很开心地发现Java基本类型和操作符在Scala里有同样的意思.然而即使你是一位资深Java开发者,这里也仍然有一些有趣的差别使得本章值得一读.因为本章提到的一些Scala的方 ...

  9. Ubuntu下freeradius的EAP-MD5,PEAPv0/EAP-MSCHAPv2,EAP-TTLS/MD5,EAP-TTLS/MSCHAPv2方式认证(基于mysql)

    基于freeradius+mysql,今天验证下freeradius的EAP认证:1.EAP-MD5:2.EAP-PEAP 一.EAP-MD5方式认证 1.修改配置文件 (1)/usr/local/e ...

  10. 使用CSS3各个属性实现小人的动画

    使用CSS3各个属性实现带有音乐小人的动画,完全不使用JS代码: 注:chrome浏览器效果最佳,最终效果静态图: HTML代码如下: <!DOCTYPE html> <html&g ...