caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结

caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用),附:问题总结

前言

论文名称:Densely Connected Convolutional Networks(CVPR 2017, Best Paper Award)
论文链接:https://arxiv.org/pdf/1608.06993.pdf
源码链接:https://github.com/liuzhuang13/DenseNet
caffe版源码: https://github.com/liuzhuang13/DenseNetCaffe
cifar10链接 : http://www.cs.toronto.edu/~kriz/cifar.html

准备阶段

操作系统:windows 10

环境:caffe

一、下载DenseNetCaffe文件

到GitHub下载Densenet网络文件

caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第1张图片
make_densenet.py:python文件用于生产train_densenet.prototxt文件、test_densenet.prototxt文件、solver.prototxt文件。
solver.prototxt: caffe: 超参数文件
train_densenet.prototxt:训练用到的网络文件
test_densenet.prototxt:验证用到的网络文件
train.sh: Linux下运行文件(windows下用不到)

二、下载cifar文件

在这里插入图片描述
一共有三个版本,其他版本网络上介绍都有很多,这里主要是举例用bin版本,也就是提供给c语言使用的版本。

解压bin版本

caffe有带有对cifar数据处理的程序,这里介绍的用OpenCV+vs2013保存图片。

#include 
#include 
#include "opencv2/highgui/highgui.hpp"
#include "opencv/cv.h"
using namespace std;
int main()
{
 	unsigned char FileData[3073];
	FILE* fp;
 	unsigned char* p;
 	unsigned char* p2;
 	int i;
 	int j;

 	fopen_s(&fp, "../cifar-10-batches-bin/data_batch_1.bin", "rb");
 	if (NULL == fp){
		printf("Read File Err!");}
 	for (int k = 0; k < 10000;k++){
 	 	cv::Mat img(32, 32, CV_8UC3, cv::Scalar(0, 255, 255));
 	 	fread(&FileData, 1, 3073, fp);
  		p = img.ptr<uchar>(0);
  		p2 = &FileData[1 + 0 * 3073];
  		for (i = 0; i < 32; i++)
  		{
   			for (j = 0; j < 32; j++)
   			{
	    			*p++ = p2[i * 32 + j + 2 * 32 * 32];
	    			*p++ = p2[i * 32 + j + 1 * 32 * 32];
	    			*p++ = p2[i * 32 + j + 0 * 32 * 32];
	   		}
	 	 }
	  	//printf(" %d ", FileData[0 * 3073]);
	  	char buff[256];
	 	 sprintf_s(buff, "../ciffarimg/%d/%d.jpg", FileData[0], k);
	  	cv::imwrite(buff, img);
	  	img.release();
	}
	fclose(fp);
	fopen_s(&fp, "../cifar-10-batches-bin/data_batch_2.bin", "rb");
	if (NULL == fp)
	{
		  printf("Read File Err!");
 	}
	for (int k = 0; k < 10000; k++)
	{
		  cv::Mat img(32, 32, CV_8UC3, cv::Scalar(0, 255, 255));
		  fread(&FileData, 1, 3073, fp);
		  p = img.ptr<uchar>(0);
		  p2 = &FileData[1 + 0 * 3073];
		  for (i = 0; i < 32; i++)
		  {
		   	for (j = 0; j < 32; j++)
		  	 {
				    *p++ = p2[i * 32 + j + 2 * 32 * 32];
				    *p++ = p2[i * 32 + j + 1 * 32 * 32];
				    *p++ = p2[i * 32 + j + 0 * 32 * 32];
			}
		  }
		  //printf(" %d ", FileData[0 * 3073]);
	
		  sprintf_s(buff, "../ciffarimg/%d/%d.jpg", FileData[0], 10000 + k);
		  cv::imwrite(buff, img);
		  img.release();
	}
	 fclose(fp);
	 
	 fopen_s(&fp, "../cifar-10-batches-bin/data_batch_3.bin", "rb");
	 if (NULL == fp){printf("Read File Err!");}
	 for (int k = 0; k < 10000; k++){
		  cv::Mat img(32, 32, CV_8UC3, cv::Scalar(0, 255, 255));
		  fread(&FileData, 1, 3073, fp);
		  p = img.ptr<uchar>(0);
		  p2 = &FileData[1 + 0 * 3073];
		  for (i = 0; i < 32; i++){
		   	for (j = 0; j < 32; j++){
			    *p++ = p2[i * 32 + j + 2 * 32 * 32];
			    *p++ = p2[i * 32 + j + 1 * 32 * 32];
			    *p++ = p2[i * 32 + j + 0 * 32 * 32];
		    	}
	 	  }
		  char buff[256];
		  sprintf_s(buff, "../ciffarimg/%d/%d.jpg", FileData[0], 20000 + k);
		  cv::imwrite(buff, img);
		  img.release();
	}
	 fclose(fp);
	 
	 fopen_s(&fp, "../cifar-10-batches-bin/data_batch_4.bin", "rb");
	 if (NULL == fp){printf("Read File Err!");}
	 for (int k = 0; k < 10000; k++){
		  cv::Mat img(32, 32, CV_8UC3, cv::Scalar(0, 255, 255));
		  fread(&FileData, 1, 3073, fp);
		  p = img.ptr<uchar>(0);
		  p2 = &FileData[1 + 0 * 3073];
		  for (i = 0; i < 32; i++){
			   for (j = 0; j < 32; j++){
				    *p++ = p2[i * 32 + j + 2 * 32 * 32];
				    *p++ = p2[i * 32 + j + 1 * 32 * 32];
				    *p++ = p2[i * 32 + j + 0 * 32 * 32];
		  	 }
		  }
		  char buff[256];
		  sprintf_s(buff, "../ciffarimg/%d/%d.jpg", FileData[0], 30000 + k);
		  cv::imwrite(buff, img);
		  img.release();
	}
	fclose(fp);
		
	 fopen_s(&fp, "../cifar-10-batches-bin/data_batch_5.bin", "rb");
	 if (NULL == fp){printf("Read File Err!");}
	 for (int k = 0; k < 10000; k++){
		  cv::Mat img(32, 32, CV_8UC3, cv::Scalar(0, 255, 255));
		  fread(&FileData, 1, 3073, fp);
		  p = img.ptr<uchar>(0);
		  p2 = &FileData[1 + 0 * 3073];
		  for (i = 0; i < 32; i++){
			   for (j = 0; j < 32; j++){
				    *p++ = p2[i * 32 + j + 2 * 32 * 32];
				    *p++ = p2[i * 32 + j + 1 * 32 * 32];
				    *p++ = p2[i * 32 + j + 0 * 32 * 32];
			   }
		  }
		  char buff[256];
		  sprintf_s(buff, "../ciffarimg/%d/%d.jpg", FileData[0], 40000 + k);
		  cv::imwrite(buff, img);
		  img.release();
	 }
	 fclose(fp);
	
	 fopen_s(&fp, "../cifar-10-batches-bin/test_batch.bin", "rb");
	 if (NULL == fp){printf("Read File Err!");}
	 for (int k = 0; k < 10000; k++){
		  cv::Mat img(32, 32, CV_8UC3, cv::Scalar(0, 255, 255));
		  fread(&FileData, 1, 3073, fp);
		  p = img.ptr<uchar>(0);
		  p2 = &FileData[1 + 0 * 3073];
		  for (i = 0; i < 32; i++){
			   for (j = 0; j < 32; j++){
				    *p++ = p2[i * 32 + j + 2 * 32 * 32];
				    *p++ = p2[i * 32 + j + 1 * 32 * 32];
				    *p++ = p2[i * 32 + j + 0 * 32 * 32];
			   }
		  }
		  char buff[256];
		  sprintf_s(buff, "../test/%d/%d.jpg", FileData[0], 20000 + k);
		  cv::imwrite(buff, img);
		  img.release();
	 }
	 fclose(fp);	
	 return 0;
}	

需要注意的是文件的位置和保存的文件夹是写死的,可以自己修改地址,如果用源码的话要在相应位置创建文档

解压完了之后会有两个文件夹
在这里插入图片描述
在这里插入图片描述
对应有10个文件夹(对应官网上的10个类)

caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第2张图片
每个文件夹包含对于的图片

caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第3张图片

lmdb的制作

首先是制作对应的train.txt文件、val.txt文件,这里可以写一个c语言程序自动读取。
在这里插入图片描述

caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第4张图片
这里需要注意后面会进行打乱操作

然后新建一个txt文件把txt文件改为create_lmdb.bat并添加以下代码

G:\Project\caffe-master\Build\x64\Release\convert_imageset.exe --shuffle --resize_width=32 --resize_height=32   G:/Project/xxx/xxx/caffar-10-atches/train/ train.txt  train_lmdb -backend=lmdb
G:\Project\caffe-master\Build\x64\Release\convert_imageset.exe --shuffle --resize_width=32 --resize_height=32   G:/Project/xxx/xxx/caffar-10-atches/val/ val.txt  val_lmdb -backend=lmdb
pause

双机运行即可
这里需要注意shuffle是打乱的操作,如果图片是灰度图的话要加上–gray,在运行bat是就能看见是否添加。如果存在lmdb文件夹需要删除,在运行程序。resize_width = 32 resize_height = 32: 是图片缩放到32*32
运行成功后,对应的文件夹里会生成data和lock两个文件,注意如果大小是1024kb的话,就说明生成失败

caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第5张图片

然后就是制作mean文件,同样在当前文件下创建一个bat文件,加入以下代码。

G:\Project\caffe-master\Build\x64\Release\compute_image_mean.exe G:\Project\xxx\xxx\caffar-10-atches\train_lmdb G:\Project\xxx\xxx\caffar-10-atches\mean.binaryproto
pause

生成mean文件后可以将两个lmdb文件夹和均值文件夹复制到DenseNet文件所在文件夹下,笔者是放在G:\Project\caffe-master\examples\DenseNetCaffe-master下
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第6张图片

三、修改DenseNet进行训练

修改test_densenet.prototxt文件

caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第7张图片这里需要注意的是有需要修改的是mean文件地址,
source也就是lmdb地址,
batch_size:这个要根据你GPU的显存修改,最佳是50。

修改train_densenet.prototxt文件

caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第8张图片
同上述一样处理,这里需要注意的是,batch可以不一致。

修改solver.prototxt

这里需要修改主要是应为,上述修改了验证的batch_size
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第9张图片
需要保证test_iter*batch_size = 验证图片张数,这里的batch是指test里的batch

制作train,bat文件

跟上述流程一样生成bat文件并加入代码

SET GLOG_logtostderr=1
G:\Project\caffe-master\Build\x64\Release\caffe.exe train --solver G:\Project\caffe-master\examples\DenseNetCaffe-master\solver.prototxt 
pause

然后双机运行就开始漫长的训练时间了。

四、效果测试(VS2013)

首先可以使用caffe.exe test 测试100个批次的测试集情况,用bat文件测试

SET GLOG_logtostderr=1
G:\Project\caffe-master\Build\x64\Release\caffe.exe test -model=G:\Project\caffe-master\examples\DenseNetCaffe-master\test_densenet.prototxt -weights=G:\Project\caffe-master\examples\DenseNetCaffe-master\_iter_230000.caffemodel -iterations=100
pause

测试完了就可以开始VS2013工程测试了,首先要做的就是制作Deploy.prototxt文件,简单说来就是把test_densenet.prototxt文件来做修改。
1、复制test_densenet.prototxt文件,并改名为densenet.prototxt
2、删除头和尾,即data层和accuracy层

caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第10张图片
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第11张图片
3、在文件最开始增加Input层、这里注意
第一个dim:对待识别样本进行数据增广的数量,这里设置为1是不进行数据增广的数量。
第二个dim:图片通道数
第三、四个dim:图片的长和宽和训练时一致
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第12张图片
4、修改Input层后面接着的Convolution层(上到下第二个层)。
这里由于Input层name为data所以需要改名为data。
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第13张图片
5、修改SoftmaxWithLoss层(文件最后一个layer)
由于最后不是计算SoftmaxWithLoss所以需要改为SoftMax,同时要除去
bottom:”data2“
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第14张图片
到这里就制作完成了densenet.prototxt文件了就可以开始C++测试程序制作了。
1、建立程序,由于前面有文章介绍过lenet测试程序的制作,这里不再介绍(这里是直接复制lenet测试程序来修改的)
2、将mean.binaryproto、_iter_230000.caffemodel、_iter_230000.solverstate、densenet.prototxt 四个文件复制到程序bin目录下,并修改mian函数里面导入的数据

在这里插入图片描述
然后根据官网提供的cifar数据排列修改lable_fikle.txt
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第15张图片
即可开始测试效果。
这里需要注意的是由于是复制lenet程序的网络所以在头文件了没有加相应的layer如果没有添加运行会报错误
在这里插入图片描述
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第16张图片
然后就能得到预期的测试效果

caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第17张图片
至此完成了densenet的训练和预测了!

五、训练时出现的问题

1、训练的num_output和验证的num_output不一致导致的
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第18张图片

2、显存不足,这个需要减小batch_size来解决,最低可以验证和训练都设置为1
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第19张图片
3、训练样本lmdb文件未正确生成导致的问题,重新生成lmdb文件
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第20张图片
4、acc一直为1 ,loss 会持续降低,原因是由于 lmdb顺序未打散,生成时加入shuffle就可以,或者是学习率base_lr太高问题,降低即可
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第21张图片

正常情况下程序运行结果
caffe学习(二)Windows10+Cifar10+DenseNet 训练和预测(C++)详细过程(训练自己的图片也试用)附:问题总结_第22张图片
最后等待生成模型文件即可。

你可能感兴趣的:(windows)