C++实现Vgg19分类器(二)数据池

本文详细介绍了VGG19模型的构建过程,包括各层参数的初始化及权重偏移的读取。对比了不同文件读取方式对加载速度的影响,并探讨了二进制读取的潜在优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现在正式开始,准备数据存放池,先看图:

按该图定义:

struct Vgg19模型
{
    //组
	层数据 * Conv1;//2
	层数据 * Conv2;//2
	层数据 * Conv3;//4
	层数据 * Conv4;//4
	层数据 * Conv5;//4
	层数据 * fc6;//1
	层数据 * fc7;//1
	层数据 * fc8;//1 (共19层)

	
	//构造函数
	Vgg19模型();

};

建立:

Vgg19模型::Vgg19模型()
{

	int size;
	层数据 * 层;

	//用于一层(宏)
	/*输入维度,输出维度,核宽*/
	#define 初始化ONE层(IN,OUT,KW) \
	\
	层->输入维度=IN;\
	层->输出维度=OUT;\
	层->核宽=KW;\
	层->权重长度=层->输出维度*层->输入维度*层->核宽*层->核宽;\
	层->权重_数据=(float*)malloc(sizeof(float) * 层->权重长度);\
	层->偏移长度=层->输出维度;\
	层->偏移_数据=(float*)malloc(sizeof(float) * 层->偏移长度);\
\
	层++;\

	//用于一组(宏)
	/*组名称,输入维度,输出维度,核宽,组中层数*/
	#define 初始化层(ConvX,IN,OUT,KW,Num) \
	size = sizeof(层数据)*Num;\
\
	层=ConvX =(层数据 *)malloc(size);\
	初始化ONE层(IN,OUT,KW)\
	for (int i=0;i<Num-1 ;i++ )\
	{\
		初始化ONE层(OUT,OUT,KW)\
	}\

	//Conv1: 2层
	/*名称,输入维度,输出维度,核宽,组中层数*/
	初始化层(Conv1,3,64,3,2) 

	//Conv2: 2层
	初始化层(Conv2,64,128,3,2)

	//Conv3: 4层
	初始化层(Conv3,128,256,3,4)

	//Conv4: 4层
	初始化层(Conv4,256,512,3,4)

	//Conv5: 4层
	初始化层(Conv5,512,512,3,4)


	//fc6: 1层
	初始化层(fc6,512,4096,7,1)

	//fc7: 1层
	初始化层(fc7,4096,4096,1,1)

	//fc8: 1层
	初始化层(fc8,4096,1000,1,1)

}

现在可以载入数据了,把caffe的模型转换成文本方式(方法见之前的文章),500M的文件已经变成了3.4G了

下面载入:

bool loadModel(Vgg19模型 *sr)
{

	char name[]= "VGG_ILSVRC_19_layers.caffemodel.txt";
	std::ifstream fin(name);

	//检查文件是否存在
	if (!fin)
	{
		return false;
	}

		cout<<"正在载入‘Vgg19模型’的数据"<<endl;

	//从档案载入
	int len;
	float *	data;
		



	层数据 * 层;

		//读入卷积
		//定义一个宏
		#define 读入卷积(ConvX,Num) \
		层=sr->ConvX;\
		for (int i=0;i<Num ;i++ )\
		{\
			/*1。读入权重*/\
			len=层->权重长度;/*需要载入的个数*/ \
			data=层->权重_数据;\
							   \
			in2(fin,len,data);\
							   \
			/*2。读入偏移*/\
			len=层->偏移长度;\
			data=层->偏移_数据;\
							   \
			in2(fin,len,data);\
			层++;\
		}\

		cout<<"Conv1..."<<endl;
	读入卷积(Conv1,2)
		cout<<"Conv2..."<<endl;
	读入卷积(Conv2,2)
		cout<<"Conv3..."<<endl;
	读入卷积(Conv3,4)
		cout<<"Conv4..."<<endl;
	读入卷积(Conv4,4)
		cout<<"Conv5..."<<endl;
	读入卷积(Conv5,4)
		cout<<"fc6..."<<endl;
	读入卷积(fc6,1)
		cout<<"fc7..."<<endl;
	读入卷积(fc7,1)
		cout<<"fc8..."<<endl;
	读入卷积(fc8,1)


	cout<<"加载完成"<<endl;
	fin.close ();  
	return true;
}

这个真的太慢了,应该是文件太大了,换一个c方式试试:

void in_c(FILE *fp,int &len,	float *	data);

bool loadModel2(Vgg19模型 *sr)
{
	char name[]= "VGG_ILSVRC_19_layers.caffemodel.txt";//

		cout<<"正在载入‘Vgg19模型’的数据"<<endl;

	FILE *fp;
	//if((fp=fopen(name,"r"))==NULL) 
	//if(fopen_s(&fp,name,"r")!=0) 
	if((fp=openfile(name,"r"))==NULL) 
		cout<<"打开文件出错了:"<<name<<endl;
	//从档案载入
	int len;
	float *	data;


	层数据 * 层;

		//读入卷积
		//定义一个宏
		#define 读入卷积2(ConvX,Num) \
		层=sr->ConvX;\
		for (int i=0;i<Num ;i++ )\
		{\
			/*1。读入权重*/\
			len=层->权重长度;/*需要载入的个数*/ \
			data=层->权重_数据;\
							   \
			in_c(fp,len,data);\
							   \
			/*2。读入偏移*/\
			len=层->偏移长度;\
			data=层->偏移_数据;\
							   \
			in_c(fp,len,data);\
			层++;\
		}\

		cout<<"Conv1..."<<endl;
	读入卷积2(Conv1,2)
		cout<<"Conv2..."<<endl;
	读入卷积2(Conv2,2)
		cout<<"Conv3..."<<endl;
	读入卷积2(Conv3,4)
		cout<<"Conv4..."<<endl;
	读入卷积2(Conv4,4)
		cout<<"Conv5..."<<endl;
	读入卷积2(Conv5,4)
		cout<<"fc6..."<<endl;
	读入卷积2(fc6,1)
		cout<<"fc7..."<<endl;
	读入卷积2(fc7,1)
		cout<<"fc8..."<<endl;
	读入卷积2(fc8,1)


	cout<<"加载完成"<<endl;
	fclose(fp);
	return true;
}

这个快一点了,但还是太慢,

如果把这个文件以二进制方式保存,再来读取是不是可以呢?

先这样吧

 

### VGG19 分类器 VGG19 是一种基于卷积神经网络 (CNN) 的深度学习模型,最初由牛津大学视觉几何组 (Visual Geometry Group, VGG) 提出并发表在论文《Very Deep Convolutional Networks for Large-Scale Visual Recognition》中[^1]。该模型以其简单而有效的架构设计著称,在多个计算机视觉任务中表现出优异性能。 VGG19 特别适合用于图像分类任务,其核心特点在于通过堆叠多层小型卷积核(通常为 \(3 \times 3\)),逐步提取输入图像的空间特征和语义信息。相比其他复杂结构的模型VGG19 更易于理解和实现。 --- ### PyTorch 中 VGG19 模型的使用方法 以下是利用 PyTorch 实现 VGG19 并将其作为分类器的具体参数配置与代码示例: #### 安装依赖库 确保已安装 `torch` 和 `torchvision` 库: ```bash pip install torch torchvision ``` #### 构建 VGG19 模型实例 可以通过调用 `torchvision.models.vgg19(pretrained=True)` 来快速获取预训练好的 VGG19 模型。如果需要自定义修改,则可以继承 `nn.Module` 类来自定义模型结构。 ```python import torch from torchvision import models # 初始化预训练的 VGG19 模型 model = models.vgg19(pretrained=True) # 如果不希望微调整个网络,冻结所有参数 for param in model.parameters(): param.requires_grad = False # 修改最后一层全连接层以适配新的分类任务 num_features = model.classifier[-1].in_features output_classes = 10 # 假设目标数据集有 10 类 model.classifier[-1] = torch.nn.Linear(num_features, output_classes) ``` 上述代码片段展示了如何加载预训练模型,并调整最后的全连接层以适应特定的任务需求[^2]。 #### 数据预处理 为了使输入数据能够被 VGG19 正确接收,需对其进行标准化处理。以下是一个典型的图像预处理管道: ```python from torchvision import transforms transform = transforms.Compose([ transforms.Resize((224, 224)), # 调整图片大小至 224x224 transforms.ToTensor(), # 将 PIL 图像转换成张量 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 归一化 ]) ``` 这些均值 (`mean`) 和标准差 (`std`) 参数来源于 ImageNet 数据集统计结果,适用于大多数迁移学习场景。 #### 预测函数定义 完成模型初始化后,可编写如下预测逻辑: ```python def predict(image_path, model, transform, device): image = Image.open(image_path).convert('RGB') input_tensor = transform(image).unsqueeze(0).to(device) # 添加批次维度并将数据移至 GPU/CPU with torch.no_grad(): # 关闭梯度计算以节省内存 outputs = model(input_tensor) probabilities = torch.softmax(outputs, dim=1)[0] topk_probabilities, indices = torch.topk(probabilities, k=5) # 获取前五高概率类别及其索引 return [(i.item(), p.item()) for i, p in zip(indices, topk_probabilities)] # 设置运行环境 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model.to(device) model.eval() # 测试单张图片 result = predict("test_image.jpg", model, transform, device) print(result) ``` 此部分实现了从读取测试图片到返回预测结果的整体流程。 --- ### 注意事项 - **硬件资源**:由于 VGG19 层次较深且参数较多,建议在具备 CUDA 支持的 GPU 上执行推理操作。 - **超参数调节**:实际应用过程中可能还需要进一步优化批量大小、学习率等超参数设置。 - **数据增强**:对于小规模数据集而言,适当引入随机裁剪、翻转等方式有助于提升泛化能力。 ---
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值