在windows下运行Felzenszwalb的Deformable Part Model(DPM)源码voc-release3.1来训练自己的模型

来源:互联网 发布:cab格式软件 编辑:程序博客网 时间:2024/06/04 19:04

本文转自:http://blog.csdn.net/masibuaa/article/details/22855473

我的环境

DPM源码版本:voc-release3.1

VOC开发包版本:VOC2007_devkit_08-Jun

使用的训练数据集:VOC2007

                                 包括:训练验证集:VOC2007_trainval_06-Nov(438MB)

                                             测试集:VOC2007_test_06-Nov-2007(430MB)

Matlab版本:MatlabR2012b

c++编译器:VS2010

系统:Win7 32位

 

        为什么不使用voc-release4.01呢?因为第4版中加入了目标检测语法(Grammars),并且还使用了非对称部件分部等等,虽然准确度提高了,但源码变得更加复杂,不利于源码分析。而相对来说第3版精简了不少,更容易分析。

        首先需要下载voc-release3.1和VOCdevkit开发包:

        Deformable Part Model 第三版voc-release3.1下载:http://cs.brown.edu/~pff/latent-release3/

        PASCAL VOC 2007 数据集及开发包下载:http://pascallin.ecs.soton.ac.uk/challenges/VOC/voc2007/index.html

   注意不要只下载训练验证集VOC2007_trainval_06-Nov,还要下载测试集VOC2007_test_06-Nov-2007,然后把测试集中的xml标注文件拷贝到VOCdevkit\VOC2007\Annotations文件夹内,把测试集中的jpeg图片拷贝到VOCdevkit\VOC2007\JPEGImages文件夹内,这样整个数据集才完整,否则在训练或测试的时候可能出现找不到需要读取的标注文件或图片的错误。


       有关Deformable Part Model参见论文

       A Discriminatively Trained, Multiscale,Deformable Part Model[CVPR 2008]的中文翻译

       Object Detection with Discriminatively Trained Part Based Models[PAMI 2010]的中文翻译 

       及 有关可变形部件模型(Deformable Part Model)的一些说明

       Pedro Felzenszwalb的个人主页:http://cs.brown.edu/~pff/



1、修改globals.m中的一些全局变量(主要是目录设定)

cachedir= 'D:\DPMtrain\VOCCache\';

% 训练好的模型结果和中间数据的文件目录,此目录可以自己任意指定

 

tmpdir ='D:\DPMtrain\VOCtemp\';

% 训练中用到的临时文件的目录,临时文件可能会很大,此目录可以自己任意指定

 

VOCdevkit =['H:\文档文件\工作\█计算机视觉█\数据集\PascalVOC\VOC2007\VOCdevkit'];

% PASCAL VOC 开发包目录,定位到VOC开发包所在目录

 

2、修改VOCdevkit开发包中的VOCinit.m文件,设定数据集目录

我们使用VOC2007数据集,所以将VOC2006标识设为false(默认就是false)。

如果将解压出来的VOC2007数据集的文件夹放在VOCdevkit目录下的话,就不用再修改VOCinit.m中的目录设定了,因为代码中默认就是这样的目录安排。但如果想把数据集放到其他地方,可以修改VOCopts.datadir目录,指向数据集所在目录。

我是直接将VOC2007文件夹放在了VOCdevkit下,目录结构如下:

-VOCdevkit

   -local

      -VOC2006

      -VOC2007

   -results

      -VOC2006

      -VOC2007

   -VOC2007

      -Annotations

      -ImageSets

      -JPEGImages

      -SegmentationClass

      -SegmentationObject

   -VOCcode

 

 

3、pascal_data.m 从PASCAL数据集中获取指定类别目标的训练数据

分析代码时,为了避免加载整个数据集,所以我在VOCdevkit\VOC2007\ImageSets\Main中新建了两个图片文件列表:

trainval_smallset.txt和train_smallset.txt

每个里面只有一两百个文件名,分别拷贝自trainval.txt和train.txt。

对应的,在pascal_data.m中修改下代码,加载我新建的小文件集:

加载正样本列表改为:

ids= textread(sprintf(VOCopts.imgsetpath, 'trainval_smallset'), '%s');

负样本列表对应修改。

 

这里要注意下:VOCdevkit\VOC2007\ImageSets\Main中有几个列表文件容易混淆:

train.txt 是所有用来训练的图片文件的文件名列表

trianval.txt是所有用来训练和验证的图片文件的文件名列表

val.txt是所有用来验证的图片文件的文件名列表

上面三个集合对应所有目标类别的训练和验证。

还有几个train_train.txt,train_trainval.txt,train.val.txt

这三个是“火车”类别的训练、训练+验证、验证图片集,

所以要分清楚。

 

4、修改rewritedat.m文件中的两个系统调用命令

在matlab命令行中运行pascal(‘person’,1),即训练含一个组件(component)模型的人体类别DPM模型,看看出什么错误,一点一点来修改。

错误如下:

'mv' 不是内部或外部命令,也不是可运行的程序 

Error in rewritedat (line 38)

所以来修改下rewritedat.m文件

将第13行的 unix(['mv ' datfile ' ' oldfile]);

替换为:system(['move ' datfile ' ' oldfile]);

第44行的 unix(['cp ' inffile ' ' oldfile]);

替换为:system(['copy ' inffile ' ' oldfile]);

 

5、修改train.m文件

修改完rewritedat.m文件后,再次调用pascal(‘person’,1),这次的问题是:

executing: ./learn 0.0020 1.0000 D:\DPMtrain\VOCtemp\person.hdr D:\DPMtrain\VOCtemp\person.dat D:\DPMtrain\VOCtemp\person.mod D:\DPMtrain\VOCtemp\person.inf D:\DPMtrain\VOCtemp\person.lob
'.' 不是内部或外部命令,也不是可运行的程序或批处理文件。 

这又是一个linux下的系统调用,所以需要修改train.m,

将第123行的    cmd = sprintf('./learn %.4f %.4f %s %s %s %s %s', ...
                                                   C, J, hdrfile, datfile, modfile, inffile, lobfile);

命令字符串中的./去掉,变成:

cmd = sprintf('learn %.4f %.4f %s %s %s %s %s', ...
                           C, J, hdrfile, datfile, modfile, inffile, lobfile);

将第128行的    status = unix(cmd);

替换为: status = system(cmd);

修改完这部分后,还是会提示'learn' 不是内部或外部命令,也不是可运行的程序 ,因为我们还没有编译learn.cc呢。


6、编译learn.cc

首先将learn.cc改名为learn.cpp,在VS2010中新建一个空的控制台工程,添加原文件learn.cpp

尝试编译,错误提示为:Cannot open include file: 'sys/time.h': No such file or directoryc:\test\dpm_learn\dpm_learn\learn.cpp5

这是linux中的目录格式,直接将第5行的#include <sys/time.h> 改为 #include <time.h>,再次编译,然后就出现了一大堆错误,有以下几点:

(1) windows中的time.h文件中没有结构体timeval的定义,也没有gettimeofday函数,从网上找了一段代码添加到learn.cpp中。

(2) 上一步加入的代码需要添加头文件windows.h,而包含进这个头文件后,就包含了系统中定义的min和max函数,所以需要注释掉learn.cpp中定义的min和max函数,否则出错。

(3) windows中没有drand48和srand48的定义,把网友博客中自己写的这两个函数添加进去。

(4) windows中没有INFINITY的定义,自己定义一个。

(5) main函数中的int buf[labelsize+2];出错,原因是VS中的c++编译器不允许用变量指定数组长度,改为使用new动态分配:

int *buf = new int[labelsize+2]; ,同时,在同一作用域最后delete [] buf;

以上5点修改完后,就没有错误了,当然还有些警告,不过不用管,编译运行,生成learn.exe可执行文件,拷贝到voc-release3.1目录下,等待训练时被matlab代码通过系统调用来执行。

修改完后的完整learn.cpp文件为:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <math.h>  
  5. //#include <sys/time.h>  
  6. #include <errno.h>  
  7.   
  8. #include <time.h> //windows中用以替代sys/time.h  
  9. #include <windows.h>//windows中用以替代sys/time.h  
  10.   
  11. /* 
  12.  * Optimize LSVM objective function via gradient descent. 
  13.  * 
  14.  * We use an adaptive cache mechanism.  After a negative example 
  15.  * scores beyond the margin multiple times it is removed from the 
  16.  * training set for a fixed number of iterations. 
  17.  */  
  18.   
  19. // Data File Format  
  20. // EXAMPLE*  
  21. //   
  22. // EXAMPLE:  
  23. //  long label          ints  
  24. //  blocks              int  
  25. //  dim                 int  
  26. //  DATA{blocks}  
  27. //  
  28. // DATA:  
  29. //  block label         float  
  30. //  block data          floats  
  31. //  
  32. // Internal Binary Format  
  33. //  len           int (byte length of EXAMPLE)  
  34. //  EXAMPLE       <see above>  
  35. //  unique flag   byte  
  36.   
  37. // number of iterations  
  38. #define ITER 5000000  
  39.   
  40. // small cache parameters  
  41. #define INCACHE 3  
  42. #define WAIT 10  
  43.   
  44. // error checking  
  45. #define check(e) \  
  46. (e ? (void)0 : (printf("%s:%u error: %s\n%s\n", __FILE__, __LINE__, #e, strerror(errno)), exit(1)))  
  47.   
  48. // number of non-zero blocks in example ex  
  49. #define NUM_NONZERO(ex) (((int *)ex)[labelsize+1])  
  50.   
  51. // float pointer to data segment of example ex  
  52. #define EX_DATA(ex) ((float *)(ex + sizeof(int)*(labelsize+3)))  
  53.   
  54. // class label (+1 or -1) for the example  
  55. #define LABEL(ex) (((int *)ex)[1])  
  56.   
  57. // block label (converted to 0-based index)  
  58. #define BLOCK_IDX(data) (((int)data[0])-1)  
  59.   
  60. //windows中没有INFINITY的定义,自己定义一个  
  61. #define INFINITY 0xFFFFFFFFF    
  62.   
  63.   
  64. int labelsize;  
  65. int dim;  
  66.   
  67. //windows下没有gettimeofday函数,从网上找的一个替代函数    
  68. int gettimeofday(struct timeval *tp, void *tzp)    
  69. {    
  70.     time_t clock;    
  71.     struct tm tm;    
  72.     SYSTEMTIME wtm;    
  73.     GetLocalTime(&wtm);    
  74.     tm.tm_year     = wtm.wYear - 1900;    
  75.     tm.tm_mon     = wtm.wMonth - 1;    
  76.     tm.tm_mday     = wtm.wDay;    
  77.     tm.tm_hour     = wtm.wHour;    
  78.     tm.tm_min     = wtm.wMinute;    
  79.     tm.tm_sec     = wtm.wSecond;    
  80.     tm. tm_isdst    = -1;    
  81.     clock = mktime(&tm);    
  82.     tp->tv_sec = clock;    
  83.     tp->tv_usec = wtm.wMilliseconds * 1000;    
  84.     return (0);    
  85. }    
  86.   
  87. //参照网上自己写的drand48和srand48函数  
  88.   
  89. #define MNWZ 0x100000000      
  90. #define ANWZ 0x5DEECE66D      
  91. #define CNWZ 0xB16     
  92.   
  93. static unsigned long long seed = 1;    
  94.   
  95. double drand48(void)      
  96. {      
  97.     seed = (ANWZ * seed + CNWZ) & 0xFFFFFFFFFFFFLL;      
  98.     unsigned int x = seed >> 16;      
  99.     return  ((double)x / (double)MNWZ);         
  100. }    
  101.   
  102. //static unsigned long long seed = 1;    
  103.   
  104. void srand48(unsigned int i)      
  105. {      
  106.     seed  = (((long long int)i) << 16) | rand();      
  107. }    
  108.   
  109. // comparison function for sorting examples   
  110. int comp(const void *a, const void *b) {  
  111.   // sort by extended label first, and whole example second...  
  112.   int c = memcmp(*((char **)a) + sizeof(int),   
  113.          *((char **)b) + sizeof(int),   
  114.          labelsize*sizeof(int));  
  115.   if (c)  
  116.     return c;  
  117.     
  118.   // labels are the same    
  119.   int alen = **((int **)a);  
  120.   int blen = **((int **)b);  
  121.   if (alen == blen)  
  122.     return memcmp(*((char **)a) + sizeof(int),   
  123.           *((char **)b) + sizeof(int),   
  124.           alen);  
  125.   return ((alen < blen) ? -1 : 1);  
  126. }  
  127.   
  128. // a collapsed example is a sequence of examples  
  129. struct collapsed {  
  130.   char **seq;  
  131.   int num;  
  132. };  
  133.   
  134. // set of collapsed examples  
  135. struct data {  
  136.   collapsed *x;  
  137.   int num;  
  138.   int numblocks;  
  139.   int *blocksizes;  
  140.   float *regmult;  
  141.   float *learnmult;  
  142. };  
  143.   
  144. // seed the random number generator with the current time  
  145. void seed_time() {  
  146.  struct timeval tp;  
  147.  check(gettimeofday(&tp, NULL) == 0);  
  148.  srand48((long)tp.tv_usec);  
  149. }  
  150.   
  151. //包含include.h后,系统中有min和max函数的定义,所以注释掉下面的定义,否则出错  
  152. //static inline double min(double x, double y) { return (x <= y ? x : y); }  
  153. //static inline double max(double x, double y) { return (x <= y ? y : x); }  
  154.   
  155. // gradient descent  
  156. void gd(double C, double J, data X, double **w, double **lb) {  
  157.   int num = X.num;  
  158.     
  159.   // state for random permutations  
  160.   int *perm = (int *)malloc(sizeof(int)*X.num);  
  161.   check(perm != NULL);  
  162.   
  163.   // state for small cache  
  164.   int *W = (int *)malloc(sizeof(int)*num);  
  165.   check(W != NULL);  
  166.   for (int j = 0; j < num; j++)  
  167.     W[j] = 0;  
  168.   
  169.   int t = 0;  
  170.   while (t < ITER) {  
  171.     // pick random permutation  
  172.     for (int i = 0; i < num; i++)  
  173.       perm[i] = i;  
  174.     for (int swapi = 0; swapi < num; swapi++) {  
  175.       int swapj = (int)(drand48()*(num-swapi)) + swapi;  
  176.       int tmp = perm[swapi];  
  177.       perm[swapi] = perm[swapj];  
  178.       perm[swapj] = tmp;  
  179.     }  
  180.   
  181.     // count number of examples in the small cache  
  182.     int cnum = 0;  
  183.     for (int i = 0; i < num; i++) {  
  184.       if (W[i] <= INCACHE)  
  185.     cnum++;  
  186.     }  
  187.   
  188.     for (int swapi = 0; swapi < num; swapi++) {  
  189.       // select example  
  190.       int i = perm[swapi];  
  191.       collapsed x = X.x[i];  
  192.   
  193.       // skip if example is not in small cache  
  194.       if (W[i] > INCACHE) {  
  195.     W[i]--;  
  196.     continue;  
  197.       }  
  198.   
  199.       // learning rate  
  200.       double T = t + 1000.0;  
  201.       double rateX = cnum * C / T;  
  202.       double rateR = 1.0 / T;  
  203.   
  204.       if (t % 10000 == 0) {  
  205.     printf(".");  
  206.     fflush(stdout);  
  207.       }  
  208.       t++;  
  209.         
  210.       // compute max over latent placements  
  211.       int M = -1;  
  212.       double V = 0;  
  213.       for (int m = 0; m < x.num; m++) {  
  214.     double val = 0;  
  215.     char *ptr = x.seq[m];  
  216.     float *data = EX_DATA(ptr);  
  217.     int blocks = NUM_NONZERO(ptr);  
  218.     for (int j = 0; j < blocks; j++) {  
  219.       int b = BLOCK_IDX(data);  
  220.       data++;  
  221.       for (int k = 0; k < X.blocksizes[b]; k++)  
  222.         val += w[b][k] * data[k];  
  223.       data += X.blocksizes[b];  
  224.     }  
  225.     if (M < 0 || val > V) {  
  226.       M = m;  
  227.       V = val;  
  228.     }  
  229.       }  
  230.         
  231.       // update model  
  232.       for (int j = 0; j < X.numblocks; j++) {  
  233.     double mult = rateR * X.regmult[j] * X.learnmult[j];  
  234.     for (int k = 0; k < X.blocksizes[j]; k++) {  
  235.       w[j][k] -= mult * w[j][k];  
  236.     }  
  237.       }  
  238.       char *ptr = x.seq[M];  
  239.       int label = LABEL(ptr);  
  240.       if (label * V < 1.0) {  
  241.     W[i] = 0;  
  242.     float *data = EX_DATA(ptr);  
  243.     int blocks = NUM_NONZERO(ptr);  
  244.     for (int j = 0; j < blocks; j++) {  
  245.       int b = BLOCK_IDX(data);  
  246.       double mult = (label > 0 ? J : -1) * rateX * X.learnmult[b];        
  247.       data++;  
  248.       for (int k = 0; k < X.blocksizes[b]; k++)  
  249.         w[b][k] += mult * data[k];  
  250.       data += X.blocksizes[b];  
  251.     }  
  252.       } else if (label == -1) {  
  253.     if (W[i] == INCACHE)  
  254.       W[i] = WAIT;  
  255.     else  
  256.       W[i]++;  
  257.       }  
  258.     }  
  259.   
  260.     // apply lowerbounds  
  261.     for (int j = 0; j < X.numblocks; j++) {  
  262.       for (int k = 0; k < X.blocksizes[j]; k++) {  
  263.     w[j][k] = max(w[j][k], lb[j][k]);  
  264.       }  
  265.     }  
  266.   
  267.   }  
  268.   
  269.   free(perm);  
  270.   free(W);  
  271. }  
  272.   
  273. // score examples  
  274. double *score(data X, char **examples, int num, double **w) {  
  275.   double *s = (double *)malloc(sizeof(double)*num);  
  276.   check(s != NULL);  
  277.   for (int i = 0; i < num; i++) {  
  278.     s[i] = 0.0;  
  279.     float *data = EX_DATA(examples[i]);  
  280.     int blocks = NUM_NONZERO(examples[i]);  
  281.     for (int j = 0; j < blocks; j++) {  
  282.       int b = BLOCK_IDX(data);  
  283.       data++;  
  284.       for (int k = 0; k < X.blocksizes[b]; k++)  
  285.         s[i] += w[b][k] * data[k];  
  286.       data += X.blocksizes[b];  
  287.     }  
  288.   }  
  289.   return s;    
  290. }  
  291.   
  292. // merge examples with identical labels  
  293. void collapse(data *X, char **examples, int num) {  
  294.   collapsed *x = (collapsed *)malloc(sizeof(collapsed)*num);  
  295.   check(x != NULL);  
  296.   int i = 0;  
  297.   x[0].seq = examples;  
  298.   x[0].num = 1;  
  299.   for (int j = 1; j < num; j++) {  
  300.     if (!memcmp(x[i].seq[0]+sizeof(int), examples[j]+sizeof(int),   
  301.         labelsize*sizeof(int))) {  
  302.       x[i].num++;  
  303.     } else {  
  304.       i++;  
  305.       x[i].seq = &(examples[j]);  
  306.       x[i].num = 1;  
  307.     }  
  308.   }  
  309.   X->x = x;  
  310.   X->num = i+1;    
  311. }  
  312.   
  313. int main(int argc, char **argv) {    
  314.   seed_time();  
  315.   int count;  
  316.   data X;  
  317.   
  318.   // command line arguments  
  319.   check(argc == 8);  
  320.   double C = atof(argv[1]);  
  321.   double J = atof(argv[2]);  
  322.   char *hdrfile = argv[3];  
  323.   char *datfile = argv[4];  
  324.   char *modfile = argv[5];  
  325.   char *inffile = argv[6];  
  326.   char *lobfile = argv[7];  
  327.   
  328.   // read header file  
  329.   FILE *f = fopen(hdrfile, "rb");  
  330.   check(f != NULL);  
  331.   int header[3];  
  332.   count = fread(header, sizeof(int), 3, f);  
  333.   check(count == 3);  
  334.   int num = header[0];  
  335.   labelsize = header[1];  
  336.   X.numblocks = header[2];  
  337.   X.blocksizes = (int *)malloc(X.numblocks*sizeof(int));  
  338.   count = fread(X.blocksizes, sizeof(int), X.numblocks, f);  
  339.   check(count == X.numblocks);  
  340.   X.regmult = (float *)malloc(sizeof(float)*X.numblocks);  
  341.   check(X.regmult != NULL);  
  342.   count = fread(X.regmult, sizeof(float), X.numblocks, f);  
  343.   check(count == X.numblocks);  
  344.   X.learnmult = (float *)malloc(sizeof(float)*X.numblocks);  
  345.   check(X.learnmult != NULL);  
  346.   count = fread(X.learnmult, sizeof(float), X.numblocks, f);  
  347.   check(count == X.numblocks);  
  348.   check(num != 0);  
  349.   fclose(f);  
  350.   printf("%d examples with label size %d and %d blocks\n",  
  351.      num, labelsize, X.numblocks);  
  352.   printf("block size, regularization multiplier, learning rate multiplier\n");  
  353.   dim = 0;  
  354.   for (int i = 0; i < X.numblocks; i++) {  
  355.     dim += X.blocksizes[i];  
  356.     printf("%d, %.2f, %.2f\n", X.blocksizes[i], X.regmult[i], X.learnmult[i]);  
  357.   }  
  358.   
  359.   // read examples  
  360.   f = fopen(datfile, "rb");  
  361.   check(f != NULL);  
  362.   printf("Reading examples\n");  
  363.   char **examples = (char **)malloc(num*sizeof(char *));  
  364.   check(examples != NULL);  
  365.   for (int i = 0; i < num; i++) {  
  366.     // we use an extra byte in the end of each example to mark unique  
  367.     // we use an extra int at the start of each example to store the   
  368.     // example's byte length (excluding unique flag and this int)  
  369.   
  370.     //int buf[labelsize+2]; //windows下不支持这样分配,换成new动态分配  
  371.       int *buf = new int[labelsize+2]; //动态分配  
  372.   
  373.     count = fread(buf, sizeof(int), labelsize+2, f);  
  374.     check(count == labelsize+2);  
  375.     // byte length of an example's data segment  
  376.     int len = sizeof(int)*(labelsize+2) + sizeof(float)*buf[labelsize+1];  
  377.     // memory for data, an initial integer, and a final byte  
  378.     examples[i] = (char *)malloc(sizeof(int)+len+1);  
  379.     check(examples[i] != NULL);  
  380.     // set data segment's byte length  
  381.     ((int *)examples[i])[0] = len;  
  382.     // set the unique flag to zero  
  383.     examples[i][sizeof(int)+len] = 0;  
  384.     // copy label data into example  
  385.     for (int j = 0; j < labelsize+2; j++)  
  386.       ((int *)examples[i])[j+1] = buf[j];  
  387.     // read the rest of the data segment into the example  
  388.     count = fread(examples[i]+sizeof(int)*(labelsize+3), 1,   
  389.           len-sizeof(int)*(labelsize+2), f);  
  390.     check(count == len-sizeof(int)*(labelsize+2));  
  391.   
  392.     delete [] buf;  //删除buf  
  393.   }  
  394.   fclose(f);  
  395.   printf("done\n");  
  396.   
  397.   // sort  
  398.   printf("Sorting examples\n");  
  399.   char **sorted = (char **)malloc(num*sizeof(char *));  
  400.   check(sorted != NULL);  
  401.   memcpy(sorted, examples, num*sizeof(char *));  
  402.   qsort(sorted, num, sizeof(char *), comp);  
  403.   printf("done\n");  
  404.   
  405.   // find unique examples  
  406.   int i = 0;  
  407.   int len = *((int *)sorted[0]);  
  408.   sorted[0][sizeof(int)+len] = 1;  
  409.   for (int j = 1; j < num; j++) {  
  410.     int alen = *((int *)sorted[i]);  
  411.     int blen = *((int *)sorted[j]);  
  412.     if (alen != blen ||   
  413.     memcmp(sorted[i] + sizeof(int), sorted[j] + sizeof(int), alen)) {  
  414.       i++;  
  415.       sorted[i] = sorted[j];  
  416.       sorted[i][sizeof(int)+blen] = 1;  
  417.     }  
  418.   }  
  419.   int num_unique = i+1;  
  420.   printf("%d unique examples\n", num_unique);  
  421.   
  422.   // collapse examples  
  423.   collapse(&X, sorted, num_unique);  
  424.   printf("%d collapsed examples\n", X.num);  
  425.   
  426.   // initial model  
  427.   double **w = (double **)malloc(sizeof(double *)*X.numblocks);  
  428.   check(w != NULL);  
  429.   f = fopen(modfile, "rb");  
  430.   for (int i = 0; i < X.numblocks; i++) {  
  431.     w[i] = (double *)malloc(sizeof(double)*X.blocksizes[i]);  
  432.     check(w[i] != NULL);  
  433.     count = fread(w[i], sizeof(double), X.blocksizes[i], f);  
  434.     check(count == X.blocksizes[i]);  
  435.   }  
  436.   fclose(f);  
  437.   
  438.   // lower bounds  
  439.   double **lb = (double **)malloc(sizeof(double *)*X.numblocks);  
  440.   check(lb != NULL);  
  441.   f = fopen(lobfile, "rb");  
  442.   for (int i = 0; i < X.numblocks; i++) {  
  443.     lb[i] = (double *)malloc(sizeof(double)*X.blocksizes[i]);  
  444.     check(lb[i] != NULL);  
  445.     count = fread(lb[i], sizeof(double), X.blocksizes[i], f);  
  446.     check(count == X.blocksizes[i]);  
  447.   }  
  448.   fclose(f);  
  449.     
  450.   // train  
  451.   printf("Training");  
  452.   gd(C, J, X, w, lb);  
  453.   printf("done\n");  
  454.   
  455.   // save model  
  456.   printf("Saving model\n");  
  457.   f = fopen(modfile, "wb");  
  458.   check(f != NULL);  
  459.   for (int i = 0; i < X.numblocks; i++) {  
  460.     count = fwrite(w[i], sizeof(double), X.blocksizes[i], f);  
  461.     check(count == X.blocksizes[i]);  
  462.   }  
  463.   fclose(f);  
  464.   
  465.   // score examples  
  466.   printf("Scoring\n");  
  467.   double *s = score(X, examples, num, w);  
  468.   
  469.   // Write info file  
  470.   printf("Writing info file\n");  
  471.   f = fopen(inffile, "w");  
  472.   check(f != NULL);  
  473.   for (int i = 0; i < num; i++) {  
  474.     int len = ((int *)examples[i])[0];  
  475.     // label, score, unique flag  
  476.     count = fprintf(f, "%d\t%f\t%d\n", ((int *)examples[i])[1], s[i],   
  477.                     (int)examples[i][sizeof(int)+len]);  
  478.     check(count > 0);  
  479.   }  
  480.   fclose(f);  
  481.     
  482.   printf("Freeing memory\n");  
  483.   for (int i = 0; i < X.numblocks; i++) {  
  484.     free(w[i]);  
  485.     free(lb[i]);  
  486.   }  
  487.   free(w);  
  488.   free(lb);  
  489.   free(s);  
  490.   for (int i = 0; i < num; i++)  
  491.     free(examples[i]);  
  492.   free(examples);  
  493.   free(sorted);  
  494.   free(X.x);  
  495.   free(X.blocksizes);  
  496.   free(X.regmult);  
  497.   free(X.learnmult);  
  498.   
  499.   return 0;  
  500. }  


7 数组下标越界错误

数组越界错误有好几处,我注意到的有:

(1)pascal_train.m中

合并模型并进行LSVM训练部分

即注释 %merge models and train using latent detections & hard negatives下的

model = train(cls, model, pos, neg(1:200), 0, 0, 2, 2, 2^28, true, 0.7);

原因是这里我的负样本集neg中的负样本数目没有达到200个,所以这里改为:

model = train(cls, model, pos, neg(1:min(length(neg),200)), 0, 0, 2, 2, 2^28, true, 0.7);


还有添加部件更新模型部分

即注释% add parts and update models using latent detections & hard negatives.下的两处调用train函数的地方,

都将neg(1:200)改为neg(1:min(length(neg),200))


(2)网友pozen提出的rewritedat.m中可能出现的下标越界情况,

将28行左右的dim = info(end);改为:

    if length(info) == 0
        dim = 0;
    else
        dim = info(end);
    end

将38行左右的dim = y(end);改为:

    if length(y) == 0
        dim = 0;
    else
        dim = y(end);
    end


参考:

http://blog.csdn.net/pozen/article/details/7103412

http://blog.csdn.net/dreamd1987/article/details/7399151


自己用少量数据训练了一个单组件人体模型,截取trainval.txt中的前50个图片文件名做正样本,train.txt中的前300个做负样本,经过pascal.data函数处理后,获得了含176个负样本的neg数组,含45个正样本的pos数组。learn.cc中的迭代次数我没改,还是每次train迭代500万次(感觉时间都花在这里了,如果只是做测试的话,可以修改learn.cc中的迭代次数ITER值),训练过程用了大概1小时左右吧,训练完后用PASCAL开发包中的评价函数做了评价,正确率和召回率都是0,平均精度AP也是0,在预料之中。

训练完后,最终结果在cachedir目录中,很多中间数据也在这个目录中,如下:

其中person_final.mat就是训练好的最终模型。源码中训练的每个阶段都会将中间数据保存下来,所以即使某一阶段出现了错误,下次重新运行时自动加载上次保存的数据,而不用再次计算,非常方便。


训练出来的模型的可视化如下:


0 0