神经网络对数据到底进行了一个什么操作呢?我们以一维的输入为例,做一个简单的实验。
取 A=[−13,13] , B=[−1,−23]∪[23,1] , C=(−∞,−1)∪(−13,−23)∪(13,23)∪(1,∞) ,输入数据 x∈A∪B .由于输入是一维的,且在一维空间中线性不可分,因此,我们在隐藏节点中至少需要2个节点,将数据映射到二维。最后输出为一个节点,当输入x∈A时,目标输出为1,当输入x∈B时目标输出为0,整个过程其实就是一个二分类问题.
上图中蓝色部分为集合B,红色为A,黑色为C。
%上图对应的代码
A=(-1.0/3.0)+rand(1,10000)*(2.0/3.0);
B=[(1.0/3.0)*rand(1,5000)-1 (1.0/3.0)*rand(1,5000)+(2.0/3.0)];
%这里(-∞,-1)和(1,∞)两个区间只取了部分数据
C=[-11+rand(1,2500)*10 (-2/3)+rand(1,2500)*(1.0/3.0) (1/3)+rand(1,2500)*(1.0/3.0) plot(A,zeros(1,10000),'.r'); hold on; plot(B,zeros(1,10000),'.b'); plot(C,zeros(1,10000),'.k');
显然在这个一维的输入空间中并不存在一个分割超平面(即横轴上的一个点)完全分离A和B。
现在,我们在A、B、C三个集合中随机各抽样10000个点,
利用matlab的nntool工具建立一个三层NN(1个输入节点、2个隐层节点、1个输出节点,其中隐层和输出层节点的激活函数都是sigmoid函数)如下所示:
当训练时使用 x∈A∪B 共20000个点作为训练集,训练出的模型参数如下(由于训练数据是随机的,每次运行的产生的模型参数都可能不同),而使用模型参数进行模拟时使用 x∈A∪B∪C 以便于比较:
W1=[-17.8767;-28.1038];
b1=[8.8756;-14.1648];
W2=[31.3236 -35.2991];
b2=[-22.6651];
输入层(第一层)输出为:
a(1)=x
隐藏层(第二层)的输入为:
z(2)=W(1)a(1)+b(1)
隐藏层输出为:
a(2)=σ(z(2))=11+e−z(2)
第三层的输入为:
z(3)=W(2)a(2)+b(2)
现在,我们来看看数据都发生了什么样的变化:
下图是对右下角进行了放大:
再次放大:
以下是上图对应的代码
a1=[A B C];
z2=bsxfun(@plus, W1*a1, b1);
a2=1./(1+exp(-z2));
plot(a2(1,1:10000),a2(2,1:10000),'.r');
hold on;
plot(a2(1,10001:20000),a2(2,10001:20000),'.b');
plot(a2(1,20001:30000),a2(2,20001:30000),'.k');
可以看到,经过隐层的变换后,一维的点被映射到了二维(一维流形),但是它们之间的拓扑关系并没有发生变化,即ABC中各个点之间的相邻关系并没有变化。从输入数据到隐层的输出相当于进行了一个同胚映射。此时的点分布已经变成线性可分了,这个分割超平面对应第二层的参数:
W(2)a(2)+b(2)=0
将 a(2) 改写为变量得:
W(2)[x,y]T+b(2)=[W(2)1,W(2)2]⋅[x,y]T+b(2)=0
变形得:
y=−W(2)1W(2)2x−b(2)W(2)2
代入训练好的模型参数:
y=−31.3236−35.2991x−−22.6651−35.2991
上式即为分离超平面的方程。
利用上式,我们很容易在matlab中绘制出它的图像(图中黄线):
这部分的代码如下:
x=[-11:0.0001:11];
y=(31.3236/35.2991)*x-(22.6651/35.2991);
plot(x,y,'y');
在黄线之上的数据,通过最后一层的sigmoid函数后将被输出为0,之下的数据将被输出为1.
参考文章:
http://colah.github.io/posts/2014-03-NN-Manifolds-Topology/
http://ufldl.stanford.edu/wiki/index.php/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C