Layer實際上定義了Layer的基本操做,即初始化層、前向傳播和反向傳播。在前向傳播中根據bottom blob獲得top blob,反向傳播則根據top反傳到bottom。並且在前傳的時候還能夠計算loss,通常來講只有最後一層纔會計算loss,雖然每一個層都有計算loss的功能。Layer類在沒有實現GPU前傳和反傳的時候會自動使用CPU的實現。下面給出Layer類的具體介紹。html
layer {
name: "data"
type: "Python"
top: "data"
top: "label"
python_param {
module: "voc_layers" #模塊名,必須在PYTHONPATH中
layer: "SBDDSegDataLayer" #模塊中的類名
param_str: "{\'sbdd_dir\': \'../data/sbdd/dataset\', \'seed\': 1337, \'split\': \'train\', \'mean\': (104.00699, 116.66877, 122.67892)}" #這裏面的東西都會在setup以前被放在PythonLayer對象的屬性中,在setup中解析這些參數,在forward和backward等中使用。
}
}python
class
VOCSegDataLayer(caffe.Layer):
git
def
setup(
self
, bottom, top):
# config
params
=
eval
(
self
.param_str)
self
.voc_dir
=
params[
'voc_dir'
] #是否是以爲挺突兀的?爲何在include裏的PythonLayer類中沒有定義voc_dir這些屬性,VOCSegDataLayer類中也沒有定義這些屬性,此處卻表示VOCSegDataLayer有這些屬性呢?由於是自動放進去的,在python_layer.hpp中有相關代碼
self
.split
=
params[
'split'
]
self
.mean
=
np.array(params[
'mean'
])
self
.random
=
params.get(
'randomize'
,
True
)
self
.seed
=
params.get(
'seed'
,
None
)
# two tops: data and label
if
len
(top) !
=
2
:
raise
Exception(
"Need to define two tops: data and label."
)
# data layers have no bottoms
if
len
(bottom) !
=
0
:
raise
Exception(
"Do not define a bottom."
)
# load indices for images and labels
split_f
=
'{}/ImageSets/Segmentation/{}.txt'
.
format
(
self
.voc_dir,
self
.split)
self
.indices
=
open
(split_f,
'r'
).read().splitlines()
self
.idx
=
0
# make eval deterministic
if
'train'
not
in
self
.split:
self
.random
=
False
# randomization: seed and pick
if
self
.random:
random.seed(
self
.seed)
self
.idx
=
random.randint(
0
,
len
(
self
.indices)
-
1
)
def
reshape(
self
, bottom, top):
# load image + label image pair
self
.data
=
self
.load_image(
self
.indices[
self
.idx])
self
.label
=
self
.load_label(
self
.indices[
self
.idx])
# reshape tops to fit (leading 1 is for batch dimension)
top[
0
].reshape(
1
,
*
self
.data.shape)
top[
1
].reshape(
1
,
*
self
.label.shape)
def
forward(
self
, bottom, top):
# assign output
top[
0
].data[...]
=
self
.data
top[
1
].data[...]
=
self
.label
# pick next input
if
self
.random:
self
.idx
=
random.randint(
0
,
len
(
self
.indices)
-
1
)
else
:
self
.idx
+
=
1
if
self
.idx
=
=
len
(
self
.indices):
self
.idx
=
0
def
backward(
self
, top, propagate_down, bottom):
pass
def
load_image(
self
, idx):
"""
Load input image and preprocess for Caffe:
- cast to float
- switch channels RGB -> BGR
- subtract mean
- transpose to channel x height x width order
"""
im
=
Image.
open
(
'{}/JPEGImages/{}.jpg'
.
format
(
self
.voc_dir, idx))
in_
=
np.array(im, dtype
=
np.float32)
in_
=
in_[:,:,::
-
1
]
in_
-
=
self
.mean
in_
=
in_.transpose((
2
,
0
,
1
))
return
in_
https://chrischoy.github.io/research/caffe-python-layer/github
http://blog.csdn.net/thesby/article/details/51264439dom
https://www.cnblogs.com/fanhaha/p/7247839.htmlspa
這兩個博客講的好.net