Caffe 之 使用非图片的鸢尾花(IRIS)数据集(hdf5格式) 训练网络模型

1. 鸢尾花卉数据集


鸢尾花卉数据集包含150个样本,4个特征(花萼长度,花萼宽度,花瓣长度和花瓣宽度),3个类别(山鸢尾,变色鸢尾和维吉尼亚鸢尾)[1]。

2. 所需的准备文件说明


(1)prototxt文件

xx_ deploy.prototxt:设置网络 中间层的结构。data层仅定义4D的 input_dim(分别表示batch大小,通道数,滤波器高度,滤波器宽度),最后一层没有loss层。提取特征或预测输出时使用[2];
xx_ solver.prototxt:设置训练网络所需的 网络结构文件(xx_train_test.prototxt)和 超参数,训练网络时使用;
xx_ train_test.prototxt:设置网络 每层的结构。data层中include的phase为TRAIN或TEST区分是输入数据是训练数据还是测试数据。data层有完整的定义,最后一层为loss层,训练和测试网络时都用。



(2)txt文件

xx_train_data.txt:设置xx_train_data.hdf5文件名[4];
xx_test_data.txt:设置xx_test_data.hdf5文件名。

(3)hdf5文件

xx_train_data.hdf5:存放训练数据的data和label;
xx_test_data.hdf5:存放测试数据的data和label。

3. 代码各部分说明[3]


设置Python编译环境,导入需要的库。
加载iris数据。targets的列数为3(标签或类的个数),把整数变成one-hot格式,比如2->[0 0 1]。new_data是字典:input,output分别为输入数据和输出标签的索引,输入数据为4D张量,如data层的input_dim定义。输出标签为2D矩阵(列为样本数,行为标签one-hot格式)。
[python]  view plain  copy
  1. def load_data():  
  2.     ''''' 
  3.     Load Iris Data set 
  4.     '''  
  5.     data = load_iris()  
  6.     print(data.data)  
  7.     print(data.target)  
  8.     targets = np.zeros((len(data.target), 3))  
  9.     for count, target in enumerate(data.target):  
  10.         targets[count][target]= 1      
  11.     print(targets)  
  12.       
  13.     new_data = {}  
  14.     #new_data['input'] = data.data  
  15.     new_data['input'] = np.reshape(data.data, (150,1,1,4))  
  16.     new_data['output'] = targets  
  17.     #print(new_data['input'].shape)  
  18.     #new_data['input'] = np.random.random((150, 1, 1, 4))  
  19.     #print(new_data['input'].shape)     
  20.     #new_data['output'] = np.random.random_integers(0, 1, size=(150,3))      
  21.     #print(new_data['input'])  
  22.       
  23.     return new_data  

保存hdf5文件:将data这个块(blob)写入磁盘。这里写入的是train_data和test_data(都是new_data),分别得到xx_train_data.hdf5文件和xx_test_data.hdf5文件。
[python]  view plain  copy
  1. def save_data_as_hdf5(hdf5_data_filename, data):  
  2.     ''''' 
  3.     HDF5 is one of the data formats Caffe accepts 
  4.     '''  
  5.     with h5py.File(hdf5_data_filename, 'w') as f:  
  6.         f['data'] = data['input'].astype(np.float32)  
  7.         f['label'] = data['output'].astype(np.float32)  

设置训练网络的模式(CPU还是GPU),get_solver从xx_solver.prototxt文件获得训练网络的超参数给solver,xx_solver.prototxt文件中的net参数定义为xx_train_test.prototxt,所以 xx_solver.prototxt不仅包含了训练用到的超参数,还把训练和测试的网络结构链接进来了。solver获得网络结构和训练用到的超参数后,solve开始训练。
[python]  view plain  copy
  1. def train(solver_prototxt_filename):  
  2.     ''''' 
  3.     Train the ANN 
  4.     '''  
  5.     caffe.set_mode_cpu()  
  6.     solver = caffe.get_solver(solver_prototxt_filename)  
  7.     solver.solve()  

打印网络参数:打印了输入,输出,块和参数的网络结构。
[python]  view plain  copy
  1. def print_network_parameters(net):  
  2.     ''''' 
  3.     Print the parameters of the network 
  4.     '''  
  5.     print(net)  
  6.     print('net.inputs: {0}'.format(net.inputs))  
  7.     print('net.outputs: {0}'.format(net.outputs))  
  8.     print('net.blobs: {0}'.format(net.blobs))  
  9.     print('net.params: {0}'.format(net.params))    

Net搭网络:根据网络参数(NetParameter)将网络的每层连接成有向循环图(DAG)[5],这里需要的文件是xxx_deploy.prototxt,同时网络类型为TEST,所以生成的网络不包含损失层,同时生成后缀为caffemodel的文件。forward得到前向输出的结果给out,out.outputs[0]返回的是块中第1个样本的结果。
[python]  view plain  copy
  1. def get_predicted_output(deploy_prototxt_filename, caffemodel_filename, input, net = None):  
  2.     ''''' 
  3.     Get the predicted output, i.e. perform a forward pass 
  4.     '''  
  5.     if net is None:  
  6.         net = caffe.Net(deploy_prototxt_filename,caffemodel_filename, caffe.TEST)  
  7.      
  8.     out = net.forward(data=input)  
  9.     return out[net.outputs[0]]  

根据NetParameter打印网络结构,用于保存deploy和train_test的网络结构。
[python]  view plain  copy
  1. import google.protobuf  
  2. def print_network(prototxt_filename, caffemodel_filename):  
  3.     ''''' 
  4.     Draw the ANN architecture 
  5.     '''  
  6.     _net = caffe.proto.caffe_pb2.NetParameter()  
  7.     f = open(prototxt_filename)  
  8.     google.protobuf.text_format.Merge(f.read(), _net)  
  9.     caffe.draw.draw_net_to_file(_net, prototxt_filename + '.png' )  
  10.     print('Draw ANN done!')  



打印网络权重时用的是train_test.prototxt,用deploy.prototxt也行。绘制的网络结构图中的data和loss层为蓝色矩形块,而ip1~ip3为灰色八边形块。因为 data层的输出和loss层的输出为不带权重的真实值,所以它俩在即使在net.params中,各自的所有权重也是相同的。实验保存的图片中没有xxx_weights_xx_data/loss.png也验证了这一点。heatmap反映了 某网络中间层的输入节点和输出节点之间的权重,而histogram反映同一层网络中间层的 权重值的分布
[python]  view plain  copy
  1. def print_network_weights(prototxt_filename, caffemodel_filename):  
  2.     ''''' 
  3.     For each ANN layer, print weight heatmap and weight histogram 
  4.     '''  
  5.     net = caffe.Net(prototxt_filename,caffemodel_filename, caffe.TEST)  
  6.     for layer_name in net.params:  
  7.         # weights heatmap  
  8.         arr = net.params[layer_name][0].data  
  9.         plt.clf()  
  10.         fig = plt.figure(figsize=(10,10))  
  11.         ax = fig.add_subplot(111)  
  12.         cax = ax.matshow(arr, interpolation='none')  
  13.         fig.colorbar(cax, orientation="horizontal")  
  14.         plt.savefig('{0}_weights_{1}.png'.format(caffemodel_filename, layer_name), dpi=100, format='png', bbox_inches='tight'# use format='svg' or 'pdf' for vectorial pictures  
  15.         plt.close()  
  16.           
  17.         # weights histogram    
  18.         plt.clf()  
  19.         plt.hist(arr.tolist(), bins=20)  
  20.         plt.savefig('{0}_weights_hist_{1}.png'.format(caffemodel_filename, layer_name), dpi=100, format='png', bbox_inches='tight'# use format='svg' or 'pdf' for vectorial pictures  
  21.         plt.close()  
  22.       
  23. def get_predicted_outputs(deploy_prototxt_filename, caffemodel_filename, inputs):  
  24.     ''''' 
  25.     Get several predicted outputs 
  26.     '''  
  27.     outputs = []  
  28.     net = caffe.Net(deploy_prototxt_filename,caffemodel_filename, caffe.TEST)  
  29.     for input in inputs:  
  30.         outputs.append(copy.deepcopy(get_predicted_output(deploy_prototxt_filename, caffemodel_filename, input, net)))  
  31.     return outputs      



get_predicted_output深拷贝后的predicted_outputs的每个位阈值化为0或1,这样好和one-hot格式的true_outputs比较。output_number为标签类数(这里为3)。predicted_outputs由很多深拷贝的output数组组成,每个数组都是1个维数为(1*3)的数据类型为float32的矩阵。所以predicted_outputs[i][0][j]表示第i个样本的第j个标签位的概率。
[python]  view plain  copy
  1. def get_accuracy(true_outputs, predicted_outputs):  
  2.   
  3.     number_of_samples = true_outputs.shape[0]  
  4.     number_of_outputs = true_outputs.shape[1]  
  5.     threshold = 0.0 # 0 if SigmoidCrossEntropyLoss ; 0.5 if EuclideanLoss  
  6.     for output_number in range(number_of_outputs):  
  7.         predicted_output_binary = []  
  8.         for sample_number in range(number_of_samples):  
  9.             #print(predicted_outputs)  
  10.             #print(predicted_outputs[sample_number][output_number])              
  11.             if predicted_outputs[sample_number][0][output_number] < threshold:  
  12.                 predicted_output = 0  
  13.             else:  
  14.                 predicted_output = 1  
  15.             predicted_output_binary.append(predicted_output)  
  16.               
  17.         print('accuracy: {0}'.format(sklearn.metrics.accuracy_score(true_outputs[:, output_number], predicted_output_binary)))  
  18.         print(sklearn.metrics.confusion_matrix(true_outputs[:, output_number], predicted_output_binary))  

主函数中:
(1)定义需要用到的prototxt文件名称;
(2)加载训练和测试数据;
(3)保存数据为hdf5文件格式;
(4)训练网络;
(5)预测输出;
(6)打印网络结构和权重;
(7)根据预测输出计算准确度。
[python]  view plain  copy
  1. def main():  
  2.     ''''' 
  3.     This is the main function 
  4.     '''  
  5.       
  6.     # Set parameters  
  7.     solver_prototxt_filename = 'iris_solver.prototxt'  
  8.     train_test_prototxt_filename = 'iris_train_test.prototxt'  
  9.     deploy_prototxt_filename  = 'iris_deploy.prototxt'  
  10.     deploy_prototxt_filename  = 'iris_deploy.prototxt'  
  11.     deploy_prototxt_batch2_filename  = 'iris_deploy_batchsize2.prototxt'  
  12.     hdf5_train_data_filename = 'iris_train_data.hdf5'  
  13.     hdf5_test_data_filename = 'iris_test_data.hdf5'  
  14.     caffemodel_filename = 'iris_iter_5000.caffemodel' # generated by train()  
  15.       
  16.     # Prepare data  
  17.     data = load_data()  
  18.     print(data)  
  19.     train_data = data  
  20.     test_data = data  
  21.     save_data_as_hdf5(hdf5_train_data_filename, data)  
  22.     save_data_as_hdf5(hdf5_test_data_filename, data)  
  23.       
  24.     # Train network  
  25.     train(solver_prototxt_filename)  
  26.          
  27.     # Get predicted outputs  
  28.     input = np.array([[ 5.1,  3.5,  1.4,  0.2]])  
  29.     print(get_predicted_output(deploy_prototxt_filename, caffemodel_filename, input))  
  30.     input = np.array([[[[ 5.1,  3.5,  1.4,  0.2]]],[[[ 5.9,  3. ,  5.1,  1.8]]]])  
  31.     #print(get_predicted_output(deploy_prototxt_batch2_filename, caffemodel_filename, input))  
  32.       
  33.     # Print network  
  34.     print_network(deploy_prototxt_filename, caffemodel_filename)  
  35.     print_network(train_test_prototxt_filename, caffemodel_filename)  
  36.     print_network_weights(train_test_prototxt_filename, caffemodel_filename)  
  37.       
  38.     # Compute performance metrics  
  39.     #inputs = input = np.array([[[[ 5.1,  3.5,  1.4,  0.2]]],[[[ 5.9,  3. ,  5.1,  1.8]]]])  
  40.     inputs = data['input']  
  41.     outputs = get_predicted_outputs(deploy_prototxt_filename, caffemodel_filename, inputs)  
  42.     get_accuracy(data['output'], outputs)  

4. 参考链接

[2] dirlt.com/caffe.html
[5] caffe.berkeleyvision.org/doxygen/classcaffe_1_1Net.html#details
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值