PCANet — 用于图像分类的深度学习基准
前言
论文网站:http://arxiv.org/abs/1404.3606
论文下载地址:PCANet: A Simple Deep Learning Baseline for Image Classification?
论文的matlab代码(第一个就是):Matlab Codes for Download
本文的C++ 和 Scala 代码:https://github.com/Ldpe2G/PCANet
该文提出了一个简单的深度学习网络,用于图像分类,用于训练的图像的特征的提取包含以下步骤:
1、cascaded principal component analusis 级联主成分分析;
2、binary hashing 二进制哈希;
3、block-wise histogram 分块直方图
PCA(主成分分析)被用于学习多级滤波器(multistage filter banks),然后用binary hashing 和 block histograms分别做索引和合并。 最后得出每一张训练图片的特征,每张图片的特征化为 1 × n 1 \times n 1×n 维向量,然后用这些特征向量来训练支持向量机,然后用于图像分类。
正文
训练过程
首先假设我们的训练图片的为N张, { I } i = 1 N \{{I \}}_{i=1}^N {I}i=1N,每张图片大小为 m × n m\times n m×n 。
第一阶段的主成分分析
1.对于每个像素,我们都在其周围进行一次 k 1 × k 2 k_1 \times k_2 k1×k2 的块采样(这里采样时逐个像素进行的,因此是完全的覆盖式采样)。
按像素来做一个分块的解释:假设分块大小为 k 1 × k 2 k_1 \times k_2 k1×k2 ,下图解释什么是按像素分块,假设图像是灰度图大小为 5 × 5 5 \times 5 5×5,分块大小为 2 × 2 2 \times 2 2×2。
按照上述计算公式可以得到的分块矩阵大小是 4 × 16 4 \times 16 4×16。
如果图像是RGB 图像,则首先将三个通道分开,每个通道都做上述的分块,得到的分块矩阵,做一个竖直方向上的合并得到RGB图像的分块矩阵,则如果RGB图像大小为 5 × 5 5 \times 5 5×5,分块大小 2 × 2 2 \times 2 2×2,则得到的分块矩阵大小为 12 × 16 12 \times 16 12×16。
2.收集所有的采样块进行级联,作为第
i
i
i 张图片的表示 ,即:
X
i
=
[
x
i
,
1
,
x
i
,
2
,
⋯
 
,
x
i
,
m
~
n
~
]
w
h
e
r
e
:
m
~
=
m
−
[
k
1
/
2
]
,
n
~
=
n
−
[
k
2
/
2
]
X_i = [x_{i,1},x_{i,2},\cdots,x_{i,\tilde m \tilde n}] \\ where:\tilde m = m - [k_1/2] , \quad \tilde n = n - [k_2/2]
Xi=[xi,1,xi,2,⋯,xi,m~n~]where:m~=m−[k1/2],n~=n−[k2/2]
3.接下来需要对采样得到的块进行零均值化:
X
ˉ
i
=
[
x
ˉ
i
,
1
,
x
ˉ
i
,
2
,
⋯
 
,
x
ˉ
i
,
m
~
n
~
]
\bar X_i = [\bar x_{i,1},\bar x_{i,2},\cdots,\bar x_{i,\tilde m \tilde n}]
Xˉi=[xˉi,1,xˉi,2,⋯,xˉi,m~n~]
4.对训练集中的其他图片也做相同处理,最终得到处理后的训练样本矩阵:
X
=
[
X
ˉ
1
,
X
ˉ
2
,
⋯
 
,
X
ˉ
N
]
∈
R
k
1
k
2
×
N
m
~
n
~
X = [\bar X_1,\bar X_2,\cdots,\bar X_N] \in \mathbb R^{k_1k_2 \times N \tilde m\tilde n}
X=[Xˉ1,Xˉ2,⋯,XˉN]∈Rk1k2×Nm~n~
5.假设在第
i
i
i 层的滤波器数量为
L
i
L_i
Li,PCA算法的目的就是通过寻找一系列的标准正交矩阵来最小化重构误差:
min
V
∈
R
k
1
k
2
×
L
1
∥
X
−
V
V
T
X
∥
F
2
,
s
.
t
.
V
V
T
=
I
L
1
\min\limits_{V \in \mathbb R^{k_1k_2 \times L_1}} \|X-VV^TX\|_F^2,\quad s.t. VV^T = I_{L_1}
V∈Rk1k2×L1min∥X−VVTX∥F2,s.t.VVT=IL1
这个问题的求解就是经典的主成分分析,即矩阵
X
X
X 的协方差矩阵的前
n
n
n 个特征向量,因此对应的PCA滤波器表示如下:
W
l
1
=
q
l
(
X
X
T
)
∈
R
k
1
×
k
2
,
l
=
1
,
2
,
⋯
 
,
L
1
W_l^1 = q_l (XX^T) \in \mathbb R^{k_1 \times k_2} , \quad l = 1,2,\cdots,L_1
Wl1=ql(XXT)∈Rk1×k2,l=1,2,⋯,L1
这个方程的含义就是提取
X
X
X 的协方差矩阵的前
L
1
L_1
L1 个最大特征值对应的特征向量来组成特征映射矩阵。这些主成分中保留了这些零均值的训练样本的主要信息。当然,与DNN和ScatNet相似,我们同样可以通过提高网络层数来提取更为抽象的特征。 然后第一阶段的主成分分析就完成了。
第二阶段的主成分分析
过程基本上和第一阶段一样。不同的是第一阶段输入的
N
N
N 幅图像
I
i
I_i
Ii 要和第一阶段得到的滤波器
W
l
1
,
l
=
1
,
2
,
⋯
 
,
L
1
W_l^1,l = 1,2,\cdots,L_1
Wl1,l=1,2,⋯,L1 分别做卷积,得到
L
1
×
N
L_1 \times N
L1×N 张第二阶段的训练图片。
I
i
l
=
I
i
∗
W
l
1
,
i
=
1
,
2
,
⋯
 
,
N
{{I_i^l}} = {{I_i}} * W_l^1 , \qquad i=1,2,\cdots,N
Iil=Ii∗Wl1,i=1,2,⋯,N
$ I_i$ 在卷积之前首先做一个0边界填充,使得卷积之后的图片和
I
i
I_i
Ii 大小相同。
第二层同样对输入矩阵(第一层的映射输出)进行块采样、级联、零均值化:
Y
i
l
=
[
y
i
,
l
,
1
,
y
i
,
l
,
2
,
⋯
 
,
y
i
,
l
,
m
~
n
~
,
]
Y
ˉ
i
l
=
[
y
ˉ
i
,
l
,
1
,
y
ˉ
i
,
l
,
2
,
⋯
 
,
y
ˉ
i
,
l
,
m
~
n
~
,
]
Y_i^l = [y_{i,l,1},y_{i,l,2},\cdots, y_{i,l,\tilde m \tilde n},]\\ \bar Y_i^l = [\bar y_{i,l,1},\bar y_{i,l,2},\cdots,\bar y_{i,l,\tilde m \tilde n},]\\
Yil=[yi,l,1,yi,l,2,⋯,yi,l,m~n~,]Yˉil=[yˉi,l,1,yˉi,l,2,⋯,yˉi,l,m~n~,]
Y
l
=
[
Y
ˉ
1
l
,
Y
ˉ
2
l
,
⋯
 
,
Y
ˉ
N
l
,
]
∈
R
k
1
k
2
×
N
m
~
n
~
Y
=
[
Y
1
,
Y
2
,
⋯
 
,
Y
L
1
]
∈
R
k
1
k
2
×
L
1
N
m
~
n
~
Y^l = [\bar Y_1^l,\bar Y_2^l,\cdots,\bar Y_N^l,] \in \mathbb R^{k_1k_2 \times N\tilde m \tilde n}\\ Y = [Y^1,Y^2,\cdots,Y^{L_1}] \in \mathbb R^{k_1k_2 \times L_1N\tilde m \tilde n}
Yl=[Yˉ1l,Yˉ2l,⋯,YˉNl,]∈Rk1k2×Nm~n~Y=[Y1,Y2,⋯,YL1]∈Rk1k2×L1Nm~n~
但实际上在代码的实现上,同一张图片对应的所有滤波器的卷积是放在一起的,其实就是顺序的不同,对结果的计算没有影响。
同理,第二层的PCA滤波器同样通过选取协方差矩阵对应的特征向量来组成:
W
ℓ
2
=
m
a
t
k
1
,
k
2
(
q
ℓ
(
Y
Y
T
)
)
∈
R
k
1
×
k
2
,
ℓ
=
1
,
2
,
⋯
 
,
L
2
W_{\ell}^2 = mat_{k_1,k_2}(q_{\ell}(YY^T)) \in \mathbb R^{k_1\times k_2}, \qquad \ell = 1,2,\cdots,L_2
Wℓ2=matk1,k2(qℓ(YYT))∈Rk1×k2,ℓ=1,2,⋯,L2
由于第一层具有
L
1
L_1
L1 个滤波器核,第一层一次会产生
L
1
L_1
L1 个输出矩阵,在第二层中针对第一层输出的每一个特征矩阵,对应都产生
L
2
L_2
L2 个特征输出。最终对于每一张样本,二阶PCANet都会产生
L
1
×
L
2
L_1 \times L_2
L1×L2 个输出的特征矩阵:
O
i
l
=
{
I
i
l
∗
W
ℓ
2
}
ℓ
=
1
L
2
{ O}_i^l = \{{I}_i^l * W_{\ell}^2\}_{\ell=1}^{L_2}
Oil={Iil∗Wℓ2}ℓ=1L2
第一层和第二层在结构上是十分相似的,因此很容易将PCANet扩展成包含更多层的深度网络结构。
输出层:哈希和直方图
我们对第二层的每个输出矩阵都进行二值处理,得到的结果中只包含整数和零,然后再对其进行二值化哈希编码,编码位数与第二层的滤波器个数相同:
T
i
l
=
∑
ℓ
=
1
L
2
2
ℓ
−
1
H
(
I
i
l
∗
W
ℓ
2
)
{T}_i^l = \sum\limits_{\ell = 1}^{L_2} 2^{\ell-1}H({I}_i^l*W_{\ell}^2)
Til=ℓ=1∑L22ℓ−1H(Iil∗Wℓ2)
这里的函数
H
(
.
)
H(.)
H(.) 类似于一个单位阶跃函数。经过上述处理,每个像素值都被编码成为
(
0
,
255
)
(0,255)
(0,255) 之间的整数(在
L
2
=
8
L_2=8
L2=8 的情况下)。当然这里的编码值与权重并没联系,因为我们将每个编码值都视为一个独立的关键字。
对于第一层的每个输出矩阵
T
i
l
,
l
=
1
,
2
,
⋯
 
,
L
1
{T}_i^l,l=1,2,\cdots,L_1
Til,l=1,2,⋯,L1 ,将其分成
B
B
B 块,得到的分块矩阵大小为
k
1
k
2
×
B
k_1k_2 \times B
k1k2×B,然后统计分块矩阵的直方图矩阵,直方图的范围是
[
0
,
2
L
2
−
1
]
[0,2^{L_2} -1]
[0,2L2−1],直方图矩阵大小为
2
L
2
×
B
2^{L_2} \times B
2L2×B 。然后将直方图矩阵行向量化得到
B
h
i
s
t
(
T
i
l
)
Bhist({T}_i^l)
Bhist(Til) ,最后将所有的
T
i
l
,
l
=
1
,
2
,
⋯
 
,
L
1
{T}_i^l,l =1,2,\cdots,L_1
Til,l=1,2,⋯,L1 的
B
h
i
s
t
(
T
i
l
)
Bhist(T_i^l)
Bhist(Til) 连接起来得到代表每张训练图的特征向量。
f
i
=
[
B
h
i
s
t
(
T
i
1
)
,
⋯
 
,
B
h
i
s
t
(
T
i
L
1
)
]
T
∈
R
(
2
L
2
)
L
1
B
f_i = [Bhist({ T}_i^1),\cdots,Bhist({T}_i^{L_1})]^T \in \mathbb R^{(2^{L_2})L_1B}
fi=[Bhist(Ti1),⋯,Bhist(TiL1)]T∈R(2L2)L1B
直方图统计简单解释:
在进行直方图分块时同样可以采用重叠分块和非重叠分块模式,需要视情况而定。实验表明非重叠分块适用于人脸识别,重叠分块模式使用于手写数字识别、文本识别、目标识别等等。此外直方图特征还为PCANet提取到的特征添加了一些变换上的稳定性(例如尺度不变形)。
测试&结果
svm的核函数用的是线性核函数,论文的matlab用的是Liblinear,由国立台湾大学Chih-Jen Lin博士开发的,主要是应对large-scale的data classification。
然后opencv的svm的类型我选择了CvSVM::C_SVC,参数C设为1。
这是我将论文的matlab代码移植到opencv的测试结果,
用了120张图片作测试,精确度为65.5%,比论文中用同样的数据集caltech101,
得到的精度68%要差一点。
参考:
《PCANet: A Simple Deep Learning Baseline for Image Classification》中文翻译总结