您的位置:首页 > 编程语言 > Python开发

Python layer

2016-07-20 11:04 239 查看
Fully Convolutional Networks for Semantic Segmentation 论文中公布的代码作为示例,解释python层该怎么写。

https://github.com/shelhamer/fcn.berkeleyvision.org

First

you have to build Caffe with WITH_PYTHON_LAYER option 1. Run make clean to delete all the compiled binaries. Then

> WITH_PYTHON_LAYER=1 make && make pycaffe

caffe的大多数层是由c++写成的,借助于c++的高效性,网络可以快速训练。
但是我们有时候需要自己写点输入层以应对各种不同的数据输入,比如你因为是需要在图像中取块而不想写成LMDB,这时候可以考虑使用python直接写一个层。而且输入层不需要GPU加速,所需写起来也比较容易。

每个类都是层,类的名字就是layer参数的名字。这两个都是数据输入层,由于需要一个data,一个label,所以有两个top,没有bottom。

类直接继承的是caffe.Layer,然后必须重写setup(),reshape(),forward(),backward()函数,其他的函数可以自己定义,没有限制。

setup()是类启动时该做的事情,比如层所需数据的初始化。

reshape()就是取数据然后把它规范化为四维的矩阵。每次取数据都会调用此函数。

forward()就是网络的前向运行,这里就是把取到的数据往前传递,因为没有其他运算。

backward()就是网络的反馈,data层是没有反馈的,所以这里就直接pass。

python_param中的这三个参数需要注意:

module:模块名,我们先前编写的data层,本身就是一个文件,也就是一个模块,因此模块名就是文件名。

layer:层的名字,我们在文件中定义的类的名字。这里比较巧合,module和layer的名字相同。

param_str:所有的需要传给data层的参数都通过这个参数来传递。这里简单的使用了Python字典的格式的字符串,在data层中使用eval来执行(o(╯□╰)o 这其实并不是一个好习惯),从而获取参数,当然也可以使用别的方式来传递,比如json或者xml等。

最后,你在训练的时候可能会报错,说找不到你刚刚的层,或者找不到caffe,只需要把这个层的代码所在的文件夹的路径加入到PYTHONPATH中即可。

export PYTHONPATH=PYTHONPATH:/path/to/your/layer/:/path/to/caffe/python

这样就完成了我们的Data层的编写,是不是非常简单?

Python in Solving

Python in data_layer

# helper function for common structures
def conv_relu(bottom, ks, nout, stride=1, pad=0, group=1):
conv = L.Convolution(bottom, kernel_size=ks, stride=stride, num_output=nout, pad=pad, group=group)
return conv, L.ReLU(conv, in_place=True)

# another helper function
def fc_relu(bottom, nout):
fc = L.InnerProduct(bottom, num_output=nout)
return fc, L.ReLU(fc, in_place=True)

# yet another helper function
def max_pool(bottom, ks, stride=1):
return L.Pooling(bottom, pool=P.Pooling.MAX, kernel_size=ks, stride=stride)

# main netspec wrapper
def caffenet_multilabel(data_layer_params, datalayer):
# setup the python data layer
n = caffe.NetSpec()
n.data, n.label = L.Python(module = 'pascal_multilabel_datalayers', layer = datalayer, ntop = 2, param_str=str(data_layer_params))
print n.data

# the net itself
n.conv1, n.relu1 = conv_relu(n.data, 11, 96, stride=4)
n.pool1 = max_pool(n.relu1, 3, stride=2)
n.norm1 = L.LRN(n.pool1, local_size=5, alpha=1e-4, beta=0.75)
n.conv2, n.relu2 = conv_relu(n.norm1, 5, 256, pad=2, group=2)
n.pool2 = max_pool(n.relu2, 3, stride=2)
n.norm2 = L.LRN(n.pool2, local_size=5, alpha=1e-4, beta=0.75)
n.conv3, n.relu3 = conv_relu(n.norm2, 3, 384, pad=1)
n.conv4, n.relu4 = conv_relu(n.relu3, 3, 384, pad=1, group=2)
n.conv5, n.relu5 = conv_relu(n.relu4, 3, 256, pad=1, group=2)
n.pool5 = max_pool(n.relu5, 3, stride=2)
n.fc6, n.relu6 = fc_relu(n.pool5, 4096)
n.drop6 = L.Dropout(n.relu6, in_place=True)
n.fc7, n.relu7 = fc_relu(n.drop6, 4096)
n.drop7 = L.Dropout(n.relu7, in_place=True)
n.score = L.InnerProduct(n.drop7, num_output=20)
n.loss = L.SigmoidCrossEntropyLoss(n.score, n.label)

return str(n.to_proto())


在这里自定义conv_relufc_relu的原因是convolution和fc layer需要使用activity function,通过自定义函数的方法直接将激活函数加入到卷积层中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: