【caffe-Windows】以mnist为例的hdf5单标签处理——matlab实现

前言

主要是想尝试看一下多标签的caffe是如何进行输入输出的,但是目前还未找到基于原始caffe做多标签输入的代码,大部分都是基于源码做了一部分修改实现多标签分类,caffe官网倒是有一个多标签的Python程序,这个我慢慢研究研究,此篇博客先看看单标签的数据格式制作与训练,以hdf5和mnist数据集为例吧

【注】使用hdf5的好处有三个:①相对于前面制作的lmdb和leveldb数据集,用convert的那个代码转换前,一般都要求一张图片一个标签,也就是说猫图片的标签必须是“猫”,而不是”绿“、“猫”,而hdf5的数据格式就能支持后者,一张图片可有多个标签描述。②当我们的数据是非图片类型的,比如一维声音数据,也能用hdf5制作满足caffe输入的数据集。③当程序无法一次性读取太大的数据集,我们可以将数据集分别放到不同的hdf5文件

国际惯例,参考博客:

caffe HDF5Data 层使用及数据生成

解读创建hdf5的matlab程序

在caffe中自带了hdf5的处理程序,我们先来研究研究,然后再套入mnist数据集。

  • 前面说过一个数据集可以放入不同的hdf5文件中,那么我们肯定要现指定当前的数据存在哪个hdf5文件中
filename='trial.h5';
  • 由于自带的程序中没有调用指定数据集,所以事先随机生成了一系列样本
num_total_samples=10000;
% to simulate data being read from disk / generated etc.
data_disk=rand(5,5,1,num_total_samples); 
label_disk=rand(10,num_total_samples); 

​ 需要注意的是这个数据集的格式,data_disk的每个维度分别代表宽、高、通道数、样本数,刚好符合opencv的读取方式,而matlab读取图片的方式是高、宽,与这个刚好相反,所以用自己的数据集记得要翻转前两个维度,待会再说。此外label_disk的两个维度分别是标签的单热度编码、样本数,与我们的习惯也相反,我们习惯一行一个标签,而这里是一列是一个样本的标签。

然后我们看看到底是怎么写入文件的?

  1. 定义了三个变量,分别是每次读取的数据大小,是否覆盖写入原来的hdf5文件(1/0)

    chunksz=100;
    created_flag=false;
    totalct=0;

    看不懂没关系,接着往下读代码

    fprintf('batch no. %d\n', batchno);last_read=(batchno-1)*chunksz;% to simulate maximum data to be held in memory before dumping to hdf5 file batchdata=data_disk(:,:,1,last_read+1:last_read+chunksz); batchlabs=label_disk(:,last_read+1:last_read+chunksz);

    这里就是按照事先设置的chunksz分批读取数据。比如第一次读取第1-100个数据,第二次就是101-200,以此类推,当然读取数据的时候,虽然从每批的第一个数据(1/101/201…)开始读,但是有时候我们需要从这个数据的第m个样本的第n行第m列开始读,所以提供了这样一个结构体,用于指示读取数据的开始位置

    startloc=struct('dat',[1,1,1,totalct+1], 'lab', [1,totalct+1]);

    也就是从totalct+1个数据的第1行第1列第1个通道开始读取,标签同理

  2. 接下来就是存储每批数据到最开始指定的trial.h5文件中了

    curr_dat_sz=store2hdf5(filename, batchdata, batchlabs, ~created_flag, startloc, chunksz); 

    有兴趣可以看看store2hdf5的源码,这里分别介绍一下几个参数的含义:

    • filename:存储的hdf5文件名称
    • batchdata:读取的数据,一般是四个维度(宽、高、通道、批大小
    • batchlabs:读取的批数据对应的输出,可以是标签也可以是其它的东东,两维(类别、批大小)
    • created_flag:是否覆盖写入(0不覆盖,1覆盖),一般来说第一个批次肯定是覆盖写入(~false=1)
    • startloc:前面说的第一个数据开始位置
    • chunksz:批大小
    • curr_dat_sz:返回值,四维(宽、高、通道、已写入样本数)
  3. 接下来两个就是重置3中的下一个读取数据的位置totalct和4中的是否覆盖写入为否(0=~true)

     created_flag=true;% flag set so that file is created only oncetotalct=curr_dat_sz(end);% updated dataset size (#samples)

    【注】代码灵活多变,请不要循环类似于“为什么函数store2hdf5~created_flag而不把非号去掉?”诸如此类的问题。

  4. 后面有一行代码用于展示存储的hdf5数据情况

    h5disp(filename);

    自带的程序输出如下,一般我们核对核对大小和样本数就行咯:

    HDF5 trial.h5 
    Group '/' Dataset 'data' Size:  5x5x1x10000MaxSize:  5x5x1xInfDatatype:   H5T_IEEE_F32LE (single)ChunkSize:  5x5x1x100Filters:  noneFillValue:  0.000000Dataset 'label' Size:  10x10000MaxSize:  10xInfDatatype:   H5T_IEEE_F32LE (single)ChunkSize:  10x100Filters:  noneFillValue:  0.000000
  5. 这样还不够,我们还得检测一下数据是不是真的是我们输入的数据,也就是一致性

    data_rd=h5read(filename, '/data', [1 1 1 1000], [5, 5, 1, 1000]);
    label_rd=h5read(filename, '/label', [1 1000], [10, 1000]);
    fprintf('Testing ...\n');
    try assert(isequal(data_rd, single(data_disk(:,:,:,1000:1999))), 'Data do not match');assert(isequal(label_rd, single(label_disk(:,1000:1999))), 'Labels do not match');fprintf('Success!\n');
    catch errfprintf('Test failed ...\n');getReport(err)
    end

    ​ 可以发现读取了存储的trial.h5文件中从第[1 1 1 1000]个数据开始的随后1000个每个大小[5,5,1]的数据。其实也就是按照[5,5,1]从第1000个样本的第一个数值读,总共读1000个就行了,即完成了读取第1000-1999的样本数据和标签。随后在try catch语句中判断这读出来的和我们原始数据data_disklabel_disk是不是对应的,是就返回Success!,错误的话不仅返回Test failed ...而且还有错误原因,非常便于调试。

  6. 最后,当然就是指示一下我们的hdf5文件名字是什么,为什么用txt文档存?因为前面已经说了,一个大的数据集一般存在多个hdf5中,换行存储就行。自带源码只存储到了一个hdf5文件中,因而对应的list.txt存储只有一行,那就是:

    trial.h5
  7. 在prototxt中使用hdf5的方法,其实也就是换掉了type类型和指定hdf5存储的txt位置

    layer {name: "data"type: "HDF5Data"top: "data"top: "labelvec"hdf5_data_param {source: "/path/to/list.txt"batch_size: 64}
    }

以mnist为实例创建hdf5文件

制作训练集

去显示mnist手写数字这一博文中copy一下loadMNISTImagesloadMNISTLabels这两个文件,用于读取存储mnist的四个二进制文件,哪四个就不说了吧t10k-images-idx3-ubytet10k-labels-idx1-ubytetrain-images-idx3-ubytetrain-labels-idx1-ubyte

然后按照上面介绍的基本流程分别进行如下修改:

  • 数据集的读取

    data = loadMNISTImages('t10k-images-idx3-ubyte')';
    labels = loadMNISTLabels('t10k-labels-idx1-ubyte');
    num_total_samples=size(data,1);
    data_disk=reshape(data,[28,28,1,num_total_samples]);%将数据集读取出来(高*宽*通道*样本数)
  • 图片宽高翻转和标签的行列变换

    data_disk=permute(data_disk,[2 1 3 4]);%翻转matlab读取的高宽
    label_disk=permute(labels,[2 1]);%转换为caffe标签的输入格式(类别数*总样本数)
  • 验证一致性

    data_rd=h5read(filename, '/data', [1 1 1 1000], [28, 28, 1, 1000]);
    label_rd=h5read(filename, '/label', [1 1000], [1, 1000]);
  • 附上train.h5制作的完整代码,注意test.h5的制作相同,只需替换代码中的traintest以及测试数据对应的二进制文件即可。

    %% WRITING TO HDF5
    clear
    clc
    filename='train.h5';%可改test.h5% data = loadMNISTImages('train-images-idx3-ubyte')';%可改test的数据集
    % labels = loadMNISTLabels('train-labels-idx1-ubyte');%可改test的标签
    data = loadMNISTImages('train-images-idx3-ubyte')';
    labels = loadMNISTLabels('train-labels-idx1-ubyte');
    num_total_samples=size(data,1);
    data_disk=reshape(data,[28,28,1,num_total_samples]);%将数据集读取出来(高*宽*通道*样本数)
    %由于caffe正常的处理方法是opencv读取图片,与matlab的高宽相反
    data_disk=permute(data_disk,[2 1 3 4]);%翻转matlab读取的高宽
    label_disk=permute(labels,[2 1]);%转换为caffe标签的输入格式(类别数*总样本数)
    % num_total_samples=10000;
    % to simulate data being read from disk / generated etc.
    % data_disk=rand(5,5,1,num_total_samples); 
    % label_disk=rand(10,num_total_samples); chunksz=100;
    created_flag=false;
    totalct=0;
    for batchno=1:num_total_samples/chunksz
    fprintf('batch no. %d\n', batchno);
    last_read=(batchno-1)*chunksz;% to simulate maximum data to be held in memory before dumping to hdf5 file 
    batchdata=data_disk(:,:,1,last_read+1:last_read+chunksz); 
    batchlabs=label_disk(:,last_read+1:last_read+chunksz);% store to hdf5
    startloc=struct('dat',[1,1,1,totalct+1], 'lab', [1,totalct+1]);
    curr_dat_sz=store2hdf5(filename, batchdata, batchlabs, ~created_flag, startloc, chunksz); %1代表新建,0代表附加
    created_flag=true;% flag set so that file is created only once
    totalct=curr_dat_sz(end);% updated dataset size (#samples)
    end% display structure of the stored HDF5 file
    h5disp(filename);%% READING FROM HDF5% Read data and labels for samples #1000 to 1999
    data_rd=h5read(filename, '/data', [1 1 1 1000], [28, 28, 1, 1000]);
    label_rd=h5read(filename, '/label', [1 1000], [1, 1000]);
    fprintf('Testing ...\n');
    try 
    assert(isequal(data_rd, single(data_disk(:,:,:,1000:1999))), 'Data do not match');
    assert(isequal(label_rd, single(label_disk(:,1000:1999))), 'Labels do not match');fprintf('Success!\n');
    catch err
    fprintf('Test failed ...\n');
    getReport(err)
    end%delete(filename);% CREATE list.txt containing filename, to be used as source for HDF5_DATA_LAYER
    FILE=fopen('train.txt', 'w');%可改test.txt
    fprintf(FILE, '%s', filename);
    fclose(FILE);
    fprintf('HDF5 filename listed in %s \n', 'list.txt');% NOTE: In net definition prototxt, use list.txt as input to HDF5_DATA as: 
    % layer {
    %   name: "data"
    %   type: "HDF5Data"
    %   top: "data"
    %   top: "labelvec"
    %   hdf5_data_param {
    %     source: "/path/to/list.txt"
    %     batch_size: 64
    %   }
    % }

    运行结果,总共600个batch:

    HDF5 test.h5 
    Group '/' Dataset 'data' Size:  28x28x1x60000MaxSize:  28x28x1xInfDatatype:   H5T_IEEE_F32LE (single)ChunkSize:  28x28x1x100Filters:  noneFillValue:  0.000000Dataset 'label' Size:  1x60000MaxSize:  1xInfDatatype:   H5T_IEEE_F32LE (single)ChunkSize:  1x100Filters:  noneFillValue:  0.000000
    Testing ...
    Success!
    HDF5 filename listed in list.txt 

    同理制作test.h5文件。

    以hdf5为输入进行训练

    把原始的lenet_train_test.prototxt的前两个’layer’改一下:

    name: "LeNet"
    layer {
    name: "mnist"
    type: "HDF5Data"
    top: "data"
    top: "label"
    include {phase: TRAIN
    }
    hdf5_data_param {source: "train.txt"batch_size: 64
    }
    }
    layer {
    name: "mnist"
    type: "HDF5Data"
    top: "data"
    top: "label"
    include {phase: TEST
    }
    hdf5_data_param {source: "test.txt"batch_size: 100
    }
    }

    写个bat文件训练试试

    E:\caffeDEV1\caffe-master\Build\x64\Release\caffe.exe  train --solver=lenet_solver.prototxt
    pause

    截取了部分运行过程

    I0621 11:01:55.571880 10520 solver.cpp:244]     Train net output #0: loss = 2.29
    63 (* 1 = 2.2963 loss)
    I0621 11:01:55.571880 10520 sgd_solver.cpp:106] Iteration 6600, lr = 0.00683784
    I0621 11:01:56.463932 10520 solver.cpp:228] Iteration 6700, loss = 2.29493
    I0621 11:01:56.464931 10520 solver.cpp:244]     Train net output #0: loss = 2.29
    493 (* 1 = 2.29493 loss)
    I0621 11:01:56.464931 10520 sgd_solver.cpp:106] Iteration 6700, lr = 0.00680711
    I0621 11:01:57.424986 10520 solver.cpp:228] Iteration 6800, loss = 2.28502
    I0621 11:01:57.425987 10520 solver.cpp:244]     Train net output #0: loss = 2.28
    502 (* 1 = 2.28502 loss)
    I0621 11:01:57.425987 10520 sgd_solver.cpp:106] Iteration 6800, lr = 0.0067767
    I0621 11:01:58.465046 10520 solver.cpp:228] Iteration 6900, loss = 2.29951
    I0621 11:01:58.466047 10520 solver.cpp:244]     Train net output #0: loss = 2.29
    951 (* 1 = 2.29951 loss)
    I0621 11:01:58.466047 10520 sgd_solver.cpp:106] Iteration 6900, lr = 0.0067466
    I0621 11:01:59.259091 10520 solver.cpp:337] Iteration 7000, Testing net (#0)
    I0621 11:01:59.883127 10520 solver.cpp:404]     Test net output #0: accuracy = 0
    .1049
    I0621 11:01:59.884127 10520 solver.cpp:404]     Test net output #1: loss = 2.385
    52 (* 1 = 2.38552 loss)
    I0621 11:01:59.889127 10520 solver.cpp:228] Iteration 7000, loss = 2.29426
    I0621 11:01:59.889127 10520 solver.cpp:244]     Train net output #0: loss = 2.29
    426 (* 1 = 2.29426 loss)
    I0621 11:01:59.889127 10520 sgd_solver.cpp:106] Iteration 7000, lr = 0.00671681

    好了,附件打包:

    程序和prototxt以及bat下载地址: 链接:http://pan.baidu.com/s/1hr4UM2o 密码:bqiy

    mnist手写数字:链接:http://pan.baidu.com/s/1jHYCQJ8 密码:vaeo
    后续研究将扩展到多标签中,预先参考文献戳这里

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246647.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【caffe-Windows】基于Python多标签方法——VOC2012数据集

前言 按照上一篇博客所遗留的话题:多标签分类,进行初步探索,此篇博客针对caffe官网的多分类进行配置,只不过是Python接口的,不过官网在开头说明可以使用HDF5或者LMDB进行操作,只不过Python更加方便罢了 国…

【theano-windows】学习笔记一——theano中的变量

前言 因为目前需要搭建一些关于RBM或者其他之类的模型,感觉不太会折腾caffe,然而我发现了几个有趣网址,使用theano实现了各种各样的模型,所以,尝试学一下theano。主要以官方教程为主,所以博客会以译文的方…

【theano-windows】学习笔记二——theano中的函数和共享参数

前言 上一篇博客中学到了theano中的变量类型,也就是dscalar、dvector之类的, 然后还有一个theano.function和eval函数, 将我们所定义的操作转换成theano可执行的函数,类似于def, 还有就是简单的线性代数运算操作。 在神经网络(NN)中, 我们声明了权重、…

【theano-windows】学习笔记三——theano中的导数

前言 就一个NN而言,包含梯度、偏置、参数更新,而前面第一篇博客学习了theano中符号变量的定义, 第二篇博客学习了变量的随机初始化, 变量之间的互相操作(类似于sigmoid(w∗xb)), 但是参数更新还应涉及到损失函数的偏导计算,这一章节就是看看…

【theano-windows】学习笔记四——theano中的条件语句

前言 按照官网教程,学习条件语句Switch和ifelse的使用 参考地址: conditions 性能对比 ifElse是将布尔变量和两个变量当做输入 Switch是将张量和两个变量当做输入. 因为Switch是元素级操作,所以比ifElse更具一般性 Switch需要对所有输出变量进行评…

【theano-windows】学习笔记五——theano中张量部分函数

前言 至此感觉应该可以写出一个logistic回归程序了,但是为了达到对theano中张量的更灵活的使用, 还是先看一下thenao.tensor对变量都提供了哪些操作,最全的文档戳这里或者这里, 这里就稍微摘取一点自我感觉以后可能用得多的函数 基本张量函数 创建张量…

【theano-windows】学习笔记六——theano中的循环函数scan

前言 Scan是Theano中最基础的循环函数, 官方教程主要是通过大量的例子来说明用法. 不过在学习的时候我比较习惯先看看用途, 然后是参数说明, 最后再是研究实例. 国际惯例, 参考网址 官网关于Scan的11个例子 官网更全面的介绍 简介 用途 递归的一般形式, 可以被用于循环s…

多标签分类、多任务分类、多输出回归概念

前言 虽然不是搞分类的,但是还是看看多标签和多分类的区别。为了避免自己的错误理解, 当然是选择原谅他啊…….找正规文档看哇. 以下翻译分别来自scikit-learn.org和 维基 喂鸡百科 国际惯例,贴上来源: Multiclass and multilabel algorithms Multi-…

【theano-windows】学习笔记七——logistic回归

前言 前面只是学了最基本的theano操作,但是theano中还有很多其他的东西,比如图结构,自定义函数等,这些暂时没有用到就先不看了,后续学啥用啥,没必要一口气吃个胖子,免得消化不良还把前面吃的东…

【theano-windows】学习笔记八——预备知识

前言 按照上一个博客所说的,直接按照深度学习0.1文档进行学习,当然在此之前我们需要了解这一系列教程所需要的数据集,以及一些概念性的东西 国际惯例,参考博客网址: 深度学习0.1文档 深度学习0.1文档-中文翻译 基…

【theano-windows】学习笔记九——softmax手写数字分类

前言 上一篇博客折腾了数据集的预备知识, 接下来按照官方的Deep learning 0.1 documentation一步步走, 先折腾softmax, 关于softmax和logistic回归分类的联系, 我在之前写过一个小博客 国际惯例, 参考博客走一波: Classifying MNIST digits using Logistic Regression soft…

【theano-windows】学习笔记十——多层感知机手写数字分类

前言 上一篇学习了softmax, 然后更进一步就是学习一下基本的多层感知机(MLP)了. 其实多层感知机同时就是w*xb用某个激活函数激活一下, 得到的结果作为下一层神经元的输入x, 类似于 output⋯f3(f2(f1(x∗w1b2)∗w2b2)∗w3b3)⋯output=\cdots f^3(f^2(f^1(x*w^1+b^2)*w^2+b^2)*…

【theano-windows】学习笔记十一——theano中与神经网络相关函数

前言 经过softmax和MLP的学习, 我们发现thenao.tensor中除了之前的博客【theano-windows】学习笔记五——theano中张量部分函数提到的张量的定义和基本运算外, 还有一个方法称为nnet, 如果自己实现过前面两篇博客中的代码就会发现用到了theano.tensor.nnet.sigmoid和thenao.te…

【caffe-windows】全卷积网络特征图分析

前言 突然就想分析一下全卷积网络的转置卷积部分了, 就是这么猝不及防的想法, 而且这个网络对图片的输入大小无要求,这么神奇的网络是时候分析一波了,我个人的学习方法调试代码,然后对照论文看理论 本次分析主要针对每层的权重大小和特征图…

【theano-windows】学习笔记十二——卷积神经网络

前言 按照进度, 学习theano中的卷积操作 国际惯例, 来一波参考网址 Convolutional Neural Networks (LeNet) 卷积神经网络如何应用在彩色图像上? 卷积小知识 三大特性:局部感知(稀疏连接), 权值共享, 池化 上图很重要, 描述的是前一个隐层m-1具有四…

【theano-windows】学习笔记十三——去噪自编码器

前言 上一章节学习了卷积的写法,主要注意的是其实现在theano.tensor.nnet和theano.sandbox.cuda.dnn中都有对应函数实现, 这一节就进入到无监督或者称为半监督的网络构建中. 首先是自编码器(Autoencoders)和降噪自编码器(denoising Autoencoders) 国际惯例, 参考网址: Denoi…

梯度优化算法Adam

前言 最近读一个代码发现用了一个梯度更新方法, 刚开始还以为是什么奇奇怪怪的梯度下降法, 最后分析一下是用一阶梯度及其二次幂做的梯度更新。网上搜了一下, 果然就是称为Adam的梯度更新算法, 全称是:自适应矩估计(adaptive moment estimation) 国际惯例, 参考博文: 一文看…

读写bin

前言 工程中经常将参数文件存储为bin格式, 但是实际中为了分析其参数, 也不好用C去读取调试它, 所以可以用matlab或者python去读取它, 但是还是蛮坑的 Matlab中的读取和写入 写入文件 比较坑的是, 一定要注意自己的文件存储的类型, 比如数值是float还是double之类的, 不然很…

【theano-windows】学习笔记十四——堆叠去噪自编码器

前言 前面已经学习了softmax,多层感知器,CNN,AE,dAE,接下来可以仿照多层感知器的方法去堆叠自编码器 国际惯例,参考文献: Stacked Denoising Autoencoders (SdA) Greedy Layer-Wise Training of Deep Networks 理…

【theano-windows】学习笔记十五——受限玻尔兹曼机

前言 终于到了最喜欢的模型: 受限玻尔兹曼机(RBM)了, 发现关于RBM是如何从能量模型发展过来的介绍非常不错, 而关于详细理论证明, 可以去看我前面的受限玻尔兹曼机的一系列博客. 国际惯例, 参考博客,超级强推第二个博客, 证明过程很给力: Restricted Boltzmann Machines (R…