回答这个问题的标题:
HDF5 文件的根目录应该有两个数据集,分别命名为“data”和“label”。形状是 (data amount, dimension)。我只使用一维数据,所以我不确定channel、width 和height 的顺序是什么。也许没关系。 dtype 应该是浮点数或双精度数。
使用h5py 创建训练集的示例代码是:
导入 h5py,操作系统
将 numpy 导入为 np
f = h5py.File('train.h5', 'w')
# 1200个数据,每个都是一个128维向量
f.create_dataset('data', (1200, 128), dtype='f8')
# 数据的标签,每个都是一个 4-dim 向量
f.create_dataset('label', (1200, 4), dtype='f4')
# 用固定模式填充一些东西
# 将值正则化到 0 到 1 之间,否则 SigmoidCrossEntropyLoss 将不起作用
对于我在范围内(1200):
a = np.empty(128)
如果我 % 4 == 0:
对于范围内的 j (128):
a[j] = j / 128.0;
l = [1,0,0,0]
elif 我 % 4 == 1:
对于范围内的 j (128):
a[j] = (128 - j) / 128.0;
l = [1,0,1,0]
elif 我 % 4 == 2:
对于范围内的 j (128):
a[j] = (j % 6) / 128.0;
l = [0,1,1,0]
elif 我 % 4 == 3:
对于范围内的 j (128):
a[j] = (j % 4) * 4 / 128.0;
l = [1,0,1,1]
f['数据'][i] = a
f['标签'][i] = l
f.close()
另外,精度层不是必需的,只需将其删除即可。下一个问题是损失层。由于SoftmaxWithLoss只有一个输出(最大值维度的索引),它不能用于多标签问题。感谢 Adian 和 Shai,我发现 SigmoidCrossEntropyLoss 在这种情况下很好。
以下是完整的代码,从数据创建、训练网络到获取测试结果:
main.py(根据 caffe lanet 示例修改)
导入操作系统、系统
PROJECT_HOME = '.../项目/'
CAFFE_HOME = '.../caffe/'
os.chdir(PROJECT_HOME)
sys.path.insert(0, CAFFE_HOME + 'caffe/python')
导入咖啡,h5py
从 pylab 导入 *
从 caffe 导入图层为 L
定义网(hdf5,batch_size):
n = caffe.NetSpec()
n.data, n.label = L.HDF5Data(batch_size=batch_size, source=hdf5, ntop=2)
n.ip1 = L.InnerProduct(n.data, num_output=50, weight_filler=dict(type='xavier'))
n.relu1 = L.ReLU(n.ip1, in_place=True)
n.ip2 = L.InnerProduct(n.relu1, num_output=50, weight_filler=dict(type='xavier'))
n.relu2 = L.ReLU(n.ip2, in_place=True)
n.ip3 = L.InnerProduct(n.relu2, num_output=4, weight_filler=dict(type='xavier'))
n.loss = L.SigmoidCrossEntropyLoss(n.ip3, n.label)
返回 n.to_proto()
使用 open(PROJECT_HOME + 'auto_train.prototxt', 'w') 作为 f:
f.write(str(net(PROJECT_HOME + 'train.h5list', 50)))
使用 open(PROJECT_HOME + 'auto_test.prototxt', 'w') 作为 f:
f.write(str(net(PROJECT_HOME + 'test.h5list', 20)))
caffe.set_device(0)
caffe.set_mode_gpu()
求解器 = caffe.SGDSolver(PROJECT_HOME + 'auto_solver.prototxt')
求解器.net.forward()
求解器.test_nets[0].forward()
求解器.step(1)
尼特 = 200
测试间隔 = 10
train_loss = zeros(niter)
test_acc = zeros(int(np.ceil(niter * 1.0 / test_interval)))
打印长度(test_acc)
输出 = zeros((niter, 8, 4))
# 主求解器循环
在范围内(niter):
solver.step(1) # Caffe 的 SGD
train_loss[it] = solver.net.blobs['loss'].data
solver.test_nets[0].forward(start='data')
output[it] = solver.test_nets[0].blobs['ip3'].data[:8]
如果它 % test_interval == 0:
打印'迭代',它,'测试......'
正确 = 0
数据 = solver.test_nets[0].blobs['ip3'].data
标签 = solver.test_nets[0].blobs['label'].data
对于范围内的 test_it(100):
求解器.test_nets[0].forward()
# 正值映射到标签1,负值映射到标签0
对于我在范围内(len(数据)):
对于范围内的 j (len(data[i])):
如果数据[i][j] > 0 并且标签[i][j] == 1:
正确 += 1
elif 数据[i][j] %lt;= 0 和标签[i][j] == 0:
正确 += 1
test_acc[int(it/test_interval)] = 正确 * 1.0 / (len(data) * len(data[0]) * 100)
# 训练和测试完成,输出收敛图
_, ax1 = subplots()
ax2 = ax1.twinx()
ax1.plot(arange(niter), train_loss)
ax2.plot(test_interval * arange(len(test_acc)), test_acc, 'r')
ax1.set_xlabel('迭代')
ax1.set_ylabel('训练损失')
ax2.set_ylabel('测试精度')
_.savefig('converge.png')
# 查看最后一批的结果
打印solver.test_nets[0].blobs['ip3'].data
打印solver.test_nets[0].blobs['label'].data
h5list 文件每行只包含 h5 文件的路径:
train.h5list
/home/foo/bar/project/train.h5
test.h5list
/home/foo/bar/project/test.h5
和求解器:
auto_solver.prototxt
train_net: "auto_train.prototxt"
test_net:“auto_test.prototxt”
测试者:10
测试间隔:20
base_lr:0.01
动量:0.9
重量衰减:0.0005
lr_policy:“inv”
伽玛:0.0001
功率:0.75
显示:100
最大迭代器:10000
快照:5000
快照前缀:“sed”
求解器模式:GPU
收敛图:
最后一批结果:
[[ 35.91593933 -37.46276474 -6.2579031 -6.30313492]
[ 42.69248581 -43.00864792 13.19664764 -3.35134125]
[ -1.36403108 1.38531208 2.77786589 -0.34310576]
[2.91686511 -2.88944006 4.34043217 0.32656598]
...
[35.91593933 -37.46276474 -6.2579031 -6.30313492]
[ 42.69248581 -43.00864792 13.19664764 -3.35134125]
[ -1.36403108 1.38531208 2.77786589 -0.34310576]
[2.91686511 -2.88944006 4.34043217 0.32656598]]
[[ 1. 0. 0. 0.]
[ 1. 0. 1. 0.]
[ 0. 1. 1. 0.]
[ 1. 0. 1. 1.]
...
[ 1. 0. 0. 0.]
[ 1. 0. 1. 0.]
[ 0. 1. 1. 0.]
[1. 0. 1. 1.]]
我认为这段代码还有很多需要改进的地方。任何建议表示赞赏。