Neural network caffe:模型定义:使用caffe.NetSpec()编写具有不同阶段的同一层

Neural network caffe:模型定义:使用caffe.NetSpec()编写具有不同阶段的同一层,neural-network,deep-learning,caffe,Neural Network,Deep Learning,Caffe,我想用python设置一个caffe CNN,使用caffe.NetSpec()接口。虽然我看到我们可以将测试网放在solver.prototxt中,但我想用不同的阶段在model.prototxt中编写它。例如,实现两个具有不同阶段的数据层: layer { name: "data" type: "Data" top: "data" top: "label" include { phase: TRAIN } .... } layer { name: "dat

我想用python设置一个caffe CNN,使用
caffe.NetSpec()
接口。虽然我看到我们可以将测试网放在
solver.prototxt
中,但我想用不同的阶段在
model.prototxt
中编写它。例如,实现两个具有不同阶段的数据层:

layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
....
}
layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
....
}

我应该如何在python中实现这样的实现呢?

我假设您指的是在使用
caffe.NetSpec
编写prototxt时如何定义阶段

from caffe import layers as L, params as P, to_proto
import caffe

ns = caffe.NetSpec()
ns.data = L.Data(name="data", 
                 data_param={'source':'/path/to/lmdb','batch_size':32},
                 include={'phase':caffe.TEST})
如果你想让train和test两个层都在同一个prototxt中,我通常做的是为train和所有层制作一个
ns
,另一个
ns\u test
,只制作重复层的测试版本。然后,在写入实际prototxt文件时:

with open('model.prototxt', 'w') as W:
  W.write('%s\n' % ns_test.to_proto())
  W.write('%s\n' % ns.to_proto())

这样,您将在同一个prototxt中拥有两个阶段。我知道这有点不太对劲。

我想你的意思是在使用
caffe.NetSpec
编写prototxt时如何定义阶段

from caffe import layers as L, params as P, to_proto
import caffe

ns = caffe.NetSpec()
ns.data = L.Data(name="data", 
                 data_param={'source':'/path/to/lmdb','batch_size':32},
                 include={'phase':caffe.TEST})
如果你想让train和test两个层都在同一个prototxt中,我通常做的是为train和所有层制作一个
ns
,另一个
ns\u test
,只制作重复层的测试版本。然后,在写入实际prototxt文件时:

with open('model.prototxt', 'w') as W:
  W.write('%s\n' % ns_test.to_proto())
  W.write('%s\n' % ns.to_proto())

这样,您将在同一个prototxt中拥有两个阶段。我知道有点不正常。

如果你的网络像:

layer {phase: TRAIN}
layer {phase: TEST}
layer {}
layer {phase: TRAIN}
layer {}
layer {phase: TEST}
layer {}
layer {}
layer {phase: TEST}
创建列车网络
ns
, 创建一个测试网络
ns\u测试

现在您基本上有两个字符串
str(ns.to_proto())
str(ns_test.to_proto())


考虑到所需的层顺序,使用python正则表达式合并这两个元素。

如果您的网络类似:

layer {phase: TRAIN}
layer {phase: TEST}
layer {}
layer {phase: TRAIN}
layer {}
layer {phase: TEST}
layer {}
layer {}
layer {phase: TEST}
创建列车网络
ns
, 创建一个测试网络
ns\u测试

现在您基本上有两个字符串
str(ns.to_proto())
str(ns_test.to_proto())

考虑到所需的层顺序,使用python正则表达式合并这两个元素。

我找到了另一种方法。
我可以解决返回原始字符串的问题。
基本上,您可以添加带有要替换的层的字符串(在我的示例中,是第一层)

我找到了另一种方法。
我可以解决返回原始字符串的问题。
基本上,您可以添加带有要替换的层的字符串(在我的示例中,是第一层)


我找到了一个有用的方法

您可以为测试阶段层添加名为
name
的键,并修改键
ntop
top
就这样,

net.data = L.Data(name='data', 
                include=dict(phase=caffe_pb2.Phase.Value('TRAIN')),
                ntop=1)
net.test_data = L.Data(name='data', 
                    include=dict(phase=caffe_pb2.Phase.Value('TEST')),
                    top='data',
                    ntop=0)

我找到了一个有用的方法

您可以为测试阶段层添加名为
name
的键,并修改键
ntop
top
就这样,

net.data = L.Data(name='data', 
                include=dict(phase=caffe_pb2.Phase.Value('TRAIN')),
                ntop=1)
net.test_data = L.Data(name='data', 
                    include=dict(phase=caffe_pb2.Phase.Value('TEST')),
                    top='data',
                    ntop=0)

虽然已经给出了几个答案,但没有一个答案涵盖了更真实的场景,即您甚至不知道(在编写代码时)层的名称。例如,当您从较小的块组装网络时,您不能写入:

n.data = L.Data(#...
n.test_data = L.Data(#...
因为块的每一次实例化都将覆盖
数据
测试数据
(或
批处理规范
,更可能被放入块中)

幸运的是,您可以通过
\uuu getitem\uuu
分配给NetSpec对象,如下所示:

layer_name = 'norm{}'.format(i) #for example
n[layer_name + '_train'] = L.Data(#...
n[layer_name + '_test']  = L.Data(#...

虽然已经给出了几个答案,但没有一个答案涵盖了更真实的场景,即您甚至不知道(在编写代码时)层的名称。例如,当您从较小的块组装网络时,您不能写入:

n.data = L.Data(#...
n.test_data = L.Data(#...
因为块的每一次实例化都将覆盖
数据
测试数据
(或
批处理规范
,更可能被放入块中)

幸运的是,您可以通过
\uuu getitem\uuu
分配给NetSpec对象,如下所示:

layer_name = 'norm{}'.format(i) #for example
n[layer_name + '_train'] = L.Data(#...
n[layer_name + '_test']  = L.Data(#...

是的,我使用caffe.NetSpec(),但问题是我想定义两个名称相同但阶段不同的层,比如ns.data=L.data(name=“data”,data_param={'source':'/path/to/lmdb','batch_size':32},include={'phase':caffe.TEST})ns.data=L.data(name=“data”,data_param={'source':'/path/to/lmdb','batch_size':32},include={'phase':caffe.TRAIN}),但这只会使测试阶段的ns.data发生变化,它解决了我的问题。但是,这样做,solver.test_net中没有数据。这是否意味着如果我想在特定的训练过程之后测试预测,我必须手动将阶段设置为测试?我想做的是使用solver.solve()并让解算器自动训练和测试网络。@user3162707我没有完全理解你的评论。如果相应地设置测试数据源,并在解算器prototxt中设置测试间隔,则解算器应自动使用测试数据以指定间隔测试网络。在任何情况下,如果这解决了您的问题(就像我的问题一样,尽管有点不对劲),应该将其标记为正确答案。是的,我使用caffe.NetSpec(),但问题是我想定义两个名称相同但阶段不同的层,比如ns.data=L.data(name=“data”,data\u param={'source':'/path/to/lmdb','batch_size':32},include={'phase':caffe.TEST})ns.data=L.data(name=“data”,data_param={'source':'/path/to/lmdb','batch_size':32},include={'phase':caffe.TRAIN})但是这样做只会使测试阶段的ns.data变为ks,这就解决了我的问题。但是,这样做,solver.TEST_net中没有数据。这是否意味着如果我想在某个训练过程后测试预测,我必须手动将阶段设置为TEST?我想做的是使用solver.solve()并让解算器自动训练和测试网络。@user3162707我没有完全理解你的评论。如果是