对于卷积运算,假设输入维度为 i i i,卷积核的维度为 w w w,步长为 s s s,这里为了叙述方便仅描述一维且忽略pad(pad可以看做已经乘以2加到输入维度中去了)。在caffe框架下,按照平移的原则一步步算卷积,如果最后还剩下若干个不够卷积核大小的数,则直接被抛弃,因此卷积的输出维度为:
out = ⌊ i − w s ⌋ \lfloor\frac{i-w}{s}\rfloor ⌊si−w⌋+1
而在tensorflow中卷积的运算与padding的设置有关,这里顺便提一下tensorflow中padding=same和valid对应的计算方法。padding=valid时,其计算方法和caffe一样,也是从头开始卷积,卷到最右边或者最下边时有多余的不够一个卷积核大小的多余数据时直接扔掉。之前看一些博客中写到,此时输出维度的计算方法为:
out = ⌈ i − w + 1 s ⌉ \lceil{\frac{i-w+1}{s}\rceil} ⌈si−w+1⌉
上面两个式子是相等的,只是两种不同的写法而已,这里简单给个证明。
⌊ i − w s ⌋ \lfloor\frac{i-w}{s}\rfloor ⌊si−w⌋+1 = ⌈ i − w + 1 s ⌉ \lceil{\frac{i-w+1}{s}\rceil} ⌈si−w+1⌉
分以下几种情况:
- 当 s s s=1时,等式显然成立。
- 当
s
s
s!=1时,再分两种情况:
2.1:当 i − w s \frac{i-w}{s} si−w为整数时,即 i − w s \frac{i-w}{s} si−w= a a a。 i − w + 1 s {\frac{i-w+1}{s}} si−w+1= a + 1 s ∈ ( a , a + 1 ) ⇒ ⌈ i − w + 1 s ⌉ a+\frac{1}{s}\in(a,a+1)\Rightarrow\lceil{\frac{i-w+1}{s}\rceil} a+s1∈(a,a+1)⇒⌈si−w+1⌉= a + 1 a+1 a+1,等式两边均为 a + 1 a+1 a+1,等式成立。
2.2:当 i − w s \frac{i-w}{s} si−w不为整数时,即 i − w s \frac{i-w}{s} si−w= a + m n a+\frac{m}{n} a+nm,其中 m n \frac{m}{n} nm为不可约的真分数。
~对于等式左边,由于 m , n m,n m,n均为正整数,所以有 m + 1 ≤ n m+1\le{n} m+1≤n,则等式左边的值为 a + 1 a+1 a+1。
~对于等式右边,显然有 ⌈ i − w + 1 s ⌉ = ⌈ a + m n + 1 s ⌉ ≥ a + 1 \lceil{\frac{i-w+1}{s}\rceil}=\lceil{a+\frac{m}{n}+\frac{1}{s}\rceil}\ge{a+1} ⌈si−w+1⌉=⌈a+nm+s1⌉≥a+1。欲证等式成立,仅需证明
⌈ i − w + 1 s ⌉ = ⌈ a + m n + 1 s ⌉ ≤ a + 1 \lceil{\frac{i-w+1}{s}\rceil}=\lceil{a+\frac{m}{n}+\frac{1}{s}\rceil}\le{a+1} ⌈si−w+1⌉=⌈a+nm+s1⌉≤a+1。仅需证明 m n + 1 s ≤ 1 \frac{m}{n}+\frac{1}{s}\le{1} nm+s1≤1。
i − w s \frac{i-w}{s} si−w= a + m n = a s + s ′ s = a + s ′ s ⇒ m n = s ′ s a+\frac{m}{n}=\frac{as+s'}{s}=a+\frac{s'}{s}\Rightarrow\frac{m}{n}=\frac{s'}{s} a+nm=sas+s′=a+ss′⇒nm=ss′,由于 m n \frac{m}{n} nm为不可约分数,而 s ′ s \frac{s'}{s} ss′却不一定是不可约的,有 s ′ = k m , s = k n s'=km,s=kn s′=km,s=kn,其中 k k k为正整数,最小为1,即 s = k n ≥ n s=kn\ge{n} s=kn≥n。
则 m n + 1 s ≤ m n + 1 n = m + 1 n ≤ 1 ( m + 1 ≤ n ) \frac{m}{n}+\frac{1}{s}\le{\frac{m}{n}+\frac{1}{n}}=\frac{m+1}{n}\le{1}(m+1\le{n}) nm+s1≤nm+n1=nm+1≤1(m+1≤n),即证明了 ⌈ i − w + 1 s ⌉ ≥ a + 1 \lceil{\frac{i-w+1}{s}\rceil}\ge{a+1} ⌈si−w+1⌉≥a+1和 ⌈ i − w + 1 s ⌉ ≤ a + 1 \lceil{\frac{i-w+1}{s}\rceil}\le{a+1} ⌈si−w+1⌉≤a+1,则 ⌈ i − w + 1 s ⌉ = a + 1 \lceil{\frac{i-w+1}{s}\rceil}={a+1} ⌈si−w+1⌉=a+1,等式成立。
结论:caffe的卷积维度和tensorflow的padding=valid时的conv2d维度计算方法是一样的。而当padding=same时,输出的维度
out = ⌈ i s ⌉ \lceil{\frac{i}{s}}\rceil ⌈si⌉
当输入的维度不够凑足运算所需要的数值时,会自动做zero-padding,需要注意的是,zero-padding时是按照左右或上下对称的方式进行的,当出现奇数时,右边或者下边会多padding出一行或一列。另外,tensorflow也提供了padding的函数,用户可以显式的手动去选择在哪里做多少padding,然后再结合conv2d中的valid或same参数,就可以实现任意输出维度的卷积了。
caffe里面的pooling层维度计算和convolution不完全一样.pooling层输出的维度中,当最后还剩下几个数据不够一个kernel的大小时,convolution的做法是抛弃这些数据,相当于向下取整.而pooling层有一个round_mode可以设置是向上取整还是向下取整,默认是向上取整的.如果pooling中的round_mode设置为向下取整,那多余的那些数据依然被抛弃;如果设置为向上取整,在最后一次kernel对应的pooling运算中,还剩下几个数据,就从那几个数据中按照pooling的方式(max?average?min?)去算结果.比如max_pooling的kernel_size是3,可是最后只剩下2个数了且round_mode设置为CEIL,那就从剩下的两个数里选max作为pooling结果.emmmm,感觉caffe还是比较粗糙啊,难怪很多model从caffe转到tensorflow之后inference结果都有或多或少的差别…