Caffe(二)-Python-自定义网络层

原创
2018/12/16 22:17
阅读数 1.2K

这里我们用一个例子先来体验一下

  • 首先定义一下我们的环境变量 $PYTHONPATH,我这儿是Windows开发环境,至于Windows Caffe怎么编译由读者自己下去搞定

我使用的控制台是 Windows PowerShell

添加环境变量

$env:PATHPATH="F:\caffe-python\python\;F:\caffe-windows\windows\install\python"

这里F:\caffe-python\python 是我的新Layer的路径F:\caffe-windows\windows\install\python 是我的Caffe编译以后install的路径

编写自己的TestLayer

import caffe
import numpy as np
class TestLayer(caffe.Layer):
    def setup(self, bottom, top):
        if len(bottom) != 1:
            raise Exception("Need two inputs to compute distance.")

    def reshape(self, bottom, top):
        print("-----------------1---------------------")
        top[0].reshape(1)

    def forward(self, bottom, top):
        top[0].data[...] = bottom[0].data
        print("-----------------2---------------------")
    def backward(self, top, propagate_down, bottom):
        bottom[...].data=top[0].data
        pass
  • 官方给出的一个例子

import caffe
import numpy as np

class EuclideanLossLayer(caffe.Layer):

    def setup(self, bottom, top):
        # 输入检查
        if len(bottom) != 2:
            raise Exception("Need two inputs to compute distance.")

    def reshape(self, bottom, top):
        # 输入检查
        if bottom[0].count != bottom[1].count:
            raise Exception("Inputs must have the same dimension.")
        # 初始化梯度差分zeros_like函数的意义是创建一个与参数等大小的全0矩阵
        self.diff = np.zeros_like(bottom[0].data, dtype=np.float32)
        # loss 输出(loss是一个标量)
        top[0].reshape(1)
		
	#前向传播(计算loss bottom[0].data是第一个输入 bottom[1].data是第二个输入)
	#注意:前向传播是输出top
    def forward(self, bottom, top):
        self.diff[...] = bottom[0].data - bottom[1].data
        top[0].data[...] = np.sum(self.diff**2) / bottom[0].num / 2.
	#后向传播
	#注意:前向传播是输出到bottom
    def backward(self, top, propagate_down, bottom):
        for i in range(2):
            if not propagate_down[i]:
                continue
            if i == 0:
                sign = 1
            else:
                sign = -1
			#误差向后扩散
            bottom[i].diff[...] = sign * self.diff / bottom[i].num

编写完我们的ayers以后写出网络结构

name: "TEST"
layer {
  name: "cifar"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mean_file: "examples/cifar10/Release/cifar10/mean.binaryproto"
  }
  data_param {
    source: "examples/cifar10/Release/cifar10/cifar10_train_lmdb"
    batch_size: 100
    backend: LMDB
  }
}
layer {
  name: "cifar"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    mean_file: "examples/cifar10/Release/cifar10/mean.binaryproto"
  }
  data_param {
    source: "examples/cifar10/Release/cifar10/cifar10_test_lmdb"
    batch_size: 100
    backend: LMDB
  }
}
layer {
  name: "test1"
  type: "Python"
  bottom: "data"
  top: "test1"
  python_param {
    module: "test_layer"
    layer: "Test_Layer"
  }
}

可视化我们的网络结构以后如图

编写solver

net: "F:/caffe-python/python/test_layer.prototxt"
base_lr: 0.001
lr_policy: "fixed"
max_iter: 10
solver_mode: CPU

接下来在powershell里面去启动caffe
先cd到caffe所在的目录
我的目录是这样的

cd F:\Smart_Classroom\3rdparty\ALLPLATHFORM\caffe-windows\windows\examples\cifar10\Release

然后执行caffe

./caffe.exe train --solver=F:/caffe-python/python/test_python_layer_solver.prototxt

如下图:

在后向和前向传播的过程中我们成功的调用了两个print
至此,编写自己的Caffe层就成功了

PS: 编写的时候严格注意路径否则会出现以下报错

展开阅读全文
打赏
0
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部