当前位置: 首页 > news >正文

基于PaddleClas的人物年龄分类项目

目录

一、任务概述

二、算法研发

2.1 下载数据集

2.2 数据集预处理

2.3 安装PaddleClas套件

2.4 算法训练

2.5 静态图导出

2.6 静态图推理

三、小结


一、任务概述

    最近遇到个需求,需要将图像中的人物区分为成人和小孩,这是一个典型的二分类问题,打算采用飞桨的图像分类套件PaddleClas来完成算法研发。本文记录相关流程。

二、算法研发

2.1 下载数据集

    本文采用MaGaAge_Asian数据集,该数据集主要由亚洲人图片组成,训练集包含40000张图像,验证集包含3495张图像,每张图像都有对应的年龄真值,所有图像均处理成了统一的大小,宽178像素,高218像素。

数据集地址下载链接。数据集部分示例如下图所示:

    该数据集本意是用来做年龄预测的,属于一个数值回归任务,本文将其变成二分类任务,以13岁年龄为界限,小于该年龄的属于小孩,大于该年龄的属于成人。这里之所以选择13岁,因为这个任务是需要筛选出长得很“像”小孩的小孩,13岁以上的青少年很多本身已经长的像成人了,因此,选择13岁作为分界线。

    下面首先对该数据集进行处理。

2.2 数据集预处理

    MaGaAge_Asian数据集每张图片对应的人物年龄存放在list文件夹的两个文件中,其中train_age.txt存放训练集对应的年龄真值,test_age.txt存放验证集对应的年龄真值。下面要写一个脚本,将所有小于13岁的图片移动到一个文件夹内,所有大于等于13岁的图片移动到另一个文件夹内。

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@文件        :split_asian.py
@说明        :拆分megaage_asian数据集,将小于13岁的移动到一个文件夹,大于等于13岁的移动到另一个文件夹
@时间        :2024/07/16 09:11:16
@作者        :Bin Qian
@版本        :1.0
'''import os
import cv2thr = 13 # 年龄阈值# 读取年龄列表
agefile = 'megaage_asian/list/test_age.txt'
f=open(agefile) 
ageLst = f.read().splitlines()
f.close() # 读取图像
imgFolder = 'megaage_asian/val'
imgnames = os.listdir(imgFolder)
index = 50000
for imgname in imgnames:imgPath = os.path.join(imgFolder,imgname)img = cv2.imread(imgPath)if img is None:continueprint(imgPath)imgindex = int(imgname.split('.')[0])age = int(ageLst[imgindex-1])if age < thr:dstFolder = 'ageclas/child'else:dstFolder = 'ageclas/adult'savePath = os.path.join(dstFolder,str(index)+'_asian.jpg')cv2.imwrite(savePath,img)index += 1
print('完成')

值得注意的是MaGaAge_Asian数据集中有很多质量较差的图像,这些“脏”图像会影响学习效果,最好手工检查这些数据并将其剔除。

另外,为了能够取得更好的效果,本文从互联网和FFHQ数据集里面再挑选出一些小孩和成人的照片进行补充。部分代码如下:

import os
import cv2# 读取图像
imgFolder = 'adult'
imgnames = os.listdir(imgFolder)
index = 1
for imgname in imgnames:imgPath = os.path.join(imgFolder,imgname)img = cv2.imread(imgPath)if img is None:continueprint(imgPath)dstFolder = 'ageclas/adult'savePath = os.path.join(dstFolder,str(index)+'_data.jpg')cv2.imwrite(savePath,img)index += 1
print('完成')

补充完整后,最后对整理好的数据集进行拆分,并且获得对应的文件列表:

# 导入系统库
import os
import random
import cv2# 定义参数
img_folder = 'ageclas'
trainlst = 'train_list.txt'
vallst = 'val_list.txt'
ratio = 0.95 # 训练集占比
labellst='label.txt'def writeLst(lstpath,namelst):'''保存文件列表'''print('正在写入 '+lstpath)random.shuffle (namelst)# 写入训练样本文件f=open(lstpath, 'a', encoding='utf-8')for i in range(len(namelst)):text = namelst[i]+'\n'f.write(text)f.close()print(lstpath+ '已完成写入')def main():'''主函数'''# 查找文件夹folderlst = os.listdir(img_folder)print('共找到 %d 个文件夹' % len(folderlst))# 循环处理trainnamelst = list()valnamelst = list()labelnamelst = list()for i in range(len(folderlst)):class_name = folderlst[i]class_label = iprint('开始处理 '+class_name+' 文件夹')# 获取子文件夹文件列表filenamelst = os.listdir(os.path.join(img_folder,class_name))totalNum = len(filenamelst)print('当前文件夹图片数量为: ' + str(totalNum)) trainNum = int(ratio*totalNum)text =  str(class_label)+ ' ' + class_namelabelnamelst.append(text)# 检查并校验图像for j in range(totalNum):imgpath = os.path.join(img_folder,class_name,filenamelst[j])img = cv2.imread(imgpath, cv2.IMREAD_COLOR)if img is None:continuetext = imgpath + ' ' + str(class_label)if j <= trainNum: trainnamelst.append(text)else:valnamelst.append(text)writeLst(trainlst,trainnamelst)writeLst(vallst,valnamelst)   writeLst(labellst,labelnamelst)     print('全部完成')if __name__ == '__main__':'''程序入口'''main()

运行后会生成train_lst.txt、val_lst.txt以及label.txt三个文件,有了这三个文件就可以使用PaddleClas套件进行算法研发了。

2.3 安装PaddleClas套件

git clone https://gitee.com/paddlepaddle/PaddleClas.git
cd PaddleClas
sudo python setup.py install

2.4 算法训练

在PaddleClas目录下新建一个配置文件config_lcnet.yaml,采用PPLCNet_x0_5模型来训练,配置文件代码如下:

# global configs
Global:checkpoints: nullpretrained_model: nulloutput_dir: ./output/device: gpusave_interval: 5eval_during_train: Trueeval_interval: 5epochs: 200print_batch_step: 10use_visualdl: True# used for static mode and model exportimage_shape: [3, 224, 224]save_inference_dir: ./output/inference
# model architecture
Arch:name: PPLCNet_x0_5class_num: 2# loss function config for traing/eval process
Loss:Train:- CELoss:weight: 1.0epsilon: 0.1Eval:- CELoss:weight: 1.0Optimizer:name: Momentummomentum: 0.9lr:name: Cosinelearning_rate: 0.8warmup_epoch: 5regularizer:name: 'L2'coeff: 0.00003# data loader for train and eval
DataLoader:Train:dataset:name: ImageNetDatasetimage_root: ../process_data/cls_label_path: ../process_data/train_list.txttransform_ops:- DecodeImage:to_rgb: Truechannel_first: False- ResizeImage:size: [224,224]- RandFlipImage:flip_code: 1- NormalizeImage:scale: 1.0/255.0mean: [0.485, 0.456, 0.406]std: [0.229, 0.224, 0.225]order: ''sampler:name: DistributedBatchSamplerbatch_size: 64drop_last: Falseshuffle: Trueloader:num_workers: 4use_shared_memory: TrueEval:dataset: name: ImageNetDatasetimage_root: ../process_data/cls_label_path: ../process_data/val_list.txttransform_ops:- DecodeImage:to_rgb: Truechannel_first: False- ResizeImage:size: [224,224]- NormalizeImage:scale: 1.0/255.0mean: [0.485, 0.456, 0.406]std: [0.229, 0.224, 0.225]order: ''sampler:name: DistributedBatchSamplerbatch_size: 64drop_last: Falseshuffle: Falseloader:num_workers: 4use_shared_memory: TrueInfer:infer_imgs: "../testimgs/10.jpg"batch_size: 1transforms:- DecodeImage:to_rgb: Truechannel_first: False- ResizeImage:size: [224,224]- NormalizeImage:scale: 1.0/255.0mean: [0.485, 0.456, 0.406]std: [0.229, 0.224, 0.225]order: ''- ToCHWImage:PostProcess:name: Topktopk: 1class_id_map_file: "../process_data/label.txt"Metric:Train:- TopkAcc:topk: [1]Eval:- TopkAcc:topk: [1]

然后使用下面的命令进行训练:

export CUDA_VISIBLE_DEVICES=0,1
python3 -m paddle.distributed.launch \--gpus="0,1" \tools/train.py \-c config_lcnet.yaml 

训练完成后可以使用下面的命令可视化查看训练结果:

visualdl --logdir results/vdl

运行效果如下:

可以看到,基本在epoch=100以后就收敛了,最高top1准确率达到97.5%,准确率还是比较高的。

下面可以使用动态图对单张图像进行测试,命令如下:

python3 tools/infer.py -c config_lcnet.yaml -o Global.pretrained_model=output/PPLCNet_x0_5/best_model

输出如下:

[{'class_ids': [1], 'scores': [0.93522], 'file_name': '../testimgs/10.jpg', 'label_names': ['adult']}]

2.5 静态图导出

为了方便后面进行模型部署,将训练好的最佳模型进行静态图导出。具体命令如下:

python3 tools/export_model.py \-c config_lcnet.yaml \-o Global.pretrained_model=output/PPLCNet_x0_5/best_model \-o Global.save_inference_dir=output/inference

导出的静态图模型存放在output/inference文件夹下面,整个模型参数加起来不超过3M,因此可以看出这个训练好的PPLCNet_x0_5模型是一个非常轻量级的模型。

2.6 静态图推理

下面使用静态图来进行推理。在推理前先使用visualdl工具查看下静态图模型的输入和输出,这将为编写推理脚本奠定基础。

可以看到,输入是[batch,3,224,224]的float型图像数据,输出是[batch,2]的float型数据。尤其是输出的两个值,代表的是两个类别的概率。

有了上面的分析,下面可以用PaddleInference写一个推理脚本infer.py:

import cv2
import numpy as np
from paddle.inference import create_predictor
from paddle.inference import Config as PredictConfig# 加载静态图模型
model_path = "./output/inference/inference.pdmodel"
params_path = "./output/inference/inference.pdiparams"
pred_cfg = PredictConfig(model_path, params_path)
pred_cfg.enable_memory_optim()  # 启用内存优化
pred_cfg.switch_ir_optim(True)
pred_cfg.enable_use_gpu(500, 0)  # 启用GPU推理
predictor = create_predictor(pred_cfg)  # 创建PaddleInference推理器# 解析模型输入输出
input_names = predictor.get_input_names()
input_handle = {}
for i in range(len(input_names)):input_handle[input_names[i]] = predictor.get_input_handle(input_names[i])
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])# 图像预处理
img = cv2.imread("../testimgs/10.jpg", flags=cv2.IMREAD_COLOR)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (224, 224), interpolation=cv2.INTER_AREA)
img = img.astype(np.float32)
PIXEL_MEANS =(0.485, 0.456, 0.406)    # RGB格式的均值和方差
PIXEL_STDS = (0.229, 0.224, 0.225)
img/=255.0
img-=np.array(PIXEL_MEANS)
img/=np.array(PIXEL_STDS)
img = np.transpose(img[np.newaxis, :, :, :], (0, 3, 1, 2))# 预测
input_handle["x"].copy_from_cpu(img)
predictor.run()
results = output_handle.copy_to_cpu()# 后处理
results = results.squeeze(0)
if results[0]>results[1]:print('小孩'+"  "+str(results[0]))
else:print('大人'+"  "+str(results[1]))

从网上随便找两张照片,运行效果如下:

输出结果:

小孩  0.7256172

输出结果:

大人  0.9533998

可以看到,推理效果还是比较满意的。

三、小结

本文以项目为主线,使用了PaddleClas算法套件解决了年龄分类问题。后续读者如果想要深入学习PaddlePaddle(飞桨)及相关算法套件,可以关注我的书籍(链接)。

相关文章:

基于PaddleClas的人物年龄分类项目

目录 一、任务概述 二、算法研发 2.1 下载数据集 2.2 数据集预处理 2.3 安装PaddleClas套件 2.4 算法训练 2.5 静态图导出 2.6 静态图推理 三、小结 一、任务概述 最近遇到个需求&#xff0c;需要将图像中的人物区分为成人和小孩&#xff0c;这是一个典型的二分类问题…...

20240725java的Controller、DAO、DO、Mapper、Service层、反射、AOP注解等内容的学习

在Java开发中&#xff0c;‌controller、‌dao、‌do、‌mapper等概念通常与MVC&#xff08;‌Model-View-Controller&#xff09;‌架构和分层设计相关。‌这些概念各自承担着不同的职责&#xff0c;‌共同协作以构建和运行一个应用程序。‌以下是这些概念的解释&#xff1a;‌…...

dynslam的安装

1. 安装opencv 2.4.9 下载opencv2.4.9 apt-get install build-essential apt-get install libgtk2.0-dev libavcodec-dev libavformat-dev libtiff4-dev libswscale-dev libjasper-dev apt-get install cmake apt-get install pkg-config 进入安装包文件&#xff1a; m…...

stats 监控 macOS 系统

Stats 监控 macOS 系统 CPU 利用率GPU 利用率内存使用情况磁盘利用率网络使用情况电池电量 brew install stats参考 stats github...

后端面试题日常练-day05 【Java基础】

题目 希望这些选择题能够帮助您进行后端面试的准备&#xff0c;答案在文末 在Java中&#xff0c;以下哪个关键字用于表示方法重写&#xff08;Override&#xff09;&#xff1f; a) override b) overrule c) overwrite d) supercede Java中的HashMap和Hashtable有什么区别&am…...

mac|安装PostgreSQL

1、官网下载&#xff1a;EDB: Open-Source, Enterprise Postgres Database Management 选择需要的版本&#xff1a; 双击得到的.dmg文件 双击&#xff0c;弹窗选择打开&#xff0c;一路next&#xff0c;然后输入你要设置的密码&#xff0c;默认账号名字为&#xff1a;postgres…...

内网对抗-隧道技术篇防火墙组策略FRPNPSChiselSocks代理端口映射C2上线

知识点&#xff1a; 1、隧道技术篇-传输层-工具项目-Frp&Nps&Chisel 2、隧道技术篇-传输层-端口转发&Socks建立&C2上线Frp Frp是专注于内网穿透的高性能的反向代理应用&#xff0c;支持TCP、UDP、HTTP、HTTPS等多种协议。可以将内网服务以安全、便捷的方式通过…...

arinc664总线协议

AFDX总线协议简介 &#xff08;1&#xff09;AFDX的传输速率高&#xff1a;带宽100MHZ&#xff0c;远远高于其他的类型的航空总线。&#xff08;2&#xff09;AFDX网络的鲁棒性高&#xff1a;AFDX的双冗余备份网络可以在某一个网络出现故障时&#xff0c;仍能正常通讯。 其中…...

UNIX 域协议

1. UNIX域协议 利用socket编程接口实现本地进程间通信 UNIX域协议套接字&#xff1a;可以使用TCP&#xff0c;也可以使用UDP SOCK_STREAM -----> TCP 面向字节流 SOCK_DGRAM -----> UDP 面向数据报 UNIX域协议并不是一个实际的协议族&#xff0c;而是在单个主机上执…...

昇思25天学习打卡营第17天|LLM-基于MindSpore的GPT2文本摘要

打卡 目录 打卡 环境准备 准备阶段 数据加载与预处理 BertTokenizer 部分输出 模型构建 gpt2模型结构输出 训练流程 部分输出 部分输出2&#xff08;减少训练数据&#xff09; 推理流程 环境准备 pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspo…...

Clion开发STM32——移植FreeModbus

STM32型号 &#xff1a;STM32H743VIT6 FreeModbus版本 &#xff1a;1.6 使用工具&#xff1a;stm32cubeMX&#xff0c;Clion 使用STM32作从机&#xff0c;模式&#xff1a;RTU 网上用keil的比较多&#xff0c;用Clion的比较少&#xff0c;如果你也用Clion&#xff0c;那么希望…...

c++栈笔记

一种常见的数据结构&#xff0c;遵循后进先出&#xff0c;先进后出的原则。地址不连续&#xff0c;栈顶&#xff08;top&#xff09; 1.常见函数 stack<int> s;定义一个参数类型为int 的栈 名为ss.push()向栈中插入元素s.emplace()压栈&#xff0c;无返回值s.pop()删除…...

Oracle配置TCPS加密协议测试

文章目录 一、环境信息二、配置过程1.创建证书2.监听配置2.1.配置sqlnet.ora2.2.配置listener.ora文件2.3.配置tnsnames.ora文件2.4.重载监听 3.数据库本地测试3.1. tcps登录测试3.2.日志监控 一、环境信息 操作系统&#xff1a;Linux 版本信息&#xff1a;Oracle 19c 参考文档…...

Jetpack Compose 通过 OkHttp 发送 HTTP 请求的示例

下面是一个使用 Kotlin 和 Jetpack Compose 来演示通过 OkHttp 发送 HTTP 请求的示例。这个示例包括在 Jetpack Compose 中发送一个 GET 请求和一个 POST 请求&#xff0c;并显示结果。 添加okhttp依赖 首先&#xff0c;在你的 build.gradle.kts 文件中添加必要的依赖&#xf…...

Pytorch使用教学3-特殊张量的创建与类型转化

1 特殊张量的创建 与numpy类似&#xff0c;PyTorch中的张量也有很多特殊创建的形式。 zeros:全0张量 # 形状为2行3列 torch.zeros([2, 3]) # tensor([[0., 0., 0.], # [0., 0., 0.]])ones:全1张量 # 形状为2行3列 torch.ones([2, 3]) # tensor([[1., 1., 1.], # …...

【日记】办个护照不至于有这种刑事罪犯一样的待遇吧……(737 字)

正文 暴晒&#xff0c;中午出去骑共享单车&#xff0c;座垫都不敢坐。 至于为什么&#xff0c;中午觉都不睡跑出去&#xff0c;是因为今天他们办承兑汇票的业务&#xff0c;搞了一天&#xff0c;中午不休息&#xff0c;说可能还会用到我的指纹&#xff0c;让我 on call。我心想…...

【矩阵微分】在不涉及张量的前提下计算矩阵对向量的导数并写出二阶泰勒展开

本篇内容摘自CMU 16-745最优控制的第10讲 “Nonlinear Trajectory Optimization”。 如何在不涉及张量运算的前提下&#xff0c;计算矩阵对向量的导数并写出二阶泰勒展开 在多维微积分中&#xff0c;计算矩阵对向量的导数和二阶泰勒展开是一项重要的任务。本文将介绍如何在不涉…...

数据结构之判断平衡二叉树详解与示例(C,C++)

文章目录 AVL树定义节点定义计算高度获取平衡因子判断是否为平衡二叉树完整示例代码结论 在计算机科学中&#xff0c;二叉树是一种非常重要的数据结构。它们被广泛用于多种算法中&#xff0c;如排序、查找等。然而&#xff0c;普通的二叉树在极端情况下可能退化成链表&#xff…...

深入解析仓颉编程语言:函数式编程的核心特性

摘要 仓颉编程语言以其独特的语法和功能&#xff0c;为开发者提供了强大的编程工具。本文将深入探讨仓颉语言中的嵌套函数、Lambda 表达式和闭包等函数式编程的核心特性&#xff0c;帮助开发者更好地理解和利用这些工具。 引言 在现代编程语言中&#xff0c;函数式编程范式越…...

springboot惠农服务平台-计算机毕业设计源码50601

目录 1 绪论 1.1 研究背景 1.2研究意义 1.3论文结构与章节安排 2 惠农服务平台app 系统分析 2.1 可行性分析 2.2 系统功能分析 2.3 系统用例分析 2.4 系统流程分析 2.5本章小结 3 惠农服务平台app 总体设计 3.1 系统功能模块设计 3.2 数据库设计 表access_token (…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter

java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用&#xff08;Math::max&#xff09; 2 函数接口…...