一、山东省第三届数据应用创新创业大赛【烟火云雾识别】

山东省第三届数据应用创新创业大赛主赛场以“协同创新 强省惠民”为主题,加快推动公共数据资源开发利用,充分释放公共数据资源的经济价值和社会价值,集聚数据应用相关企业、团队、爱好者,打造一批具有创新性的数据产品、数据服务,促进发挥数据“优政、惠民、兴业”作用。本赛题是其中 生态环境部分中的一项。

随着公共安全需求的发展,在森林防火和城市消防需求下。对于火灾的防范以和及时发现的需求越来越强烈。现有的烟火识别算法在实际应用中效果较差,主要原因在于需要在复杂场景下准确分辨出烟雾与云雾的区别,火焰与城市霓虹灯等干扰的区别。

烟火云雾识别竞赛地址: http://data.sd.gov.cn/cmpt/cmptDetail.html?id=61

1.任务

本次比赛将提供烟火云雾以及城市霓虹灯的标注数据,需要选手在各种复杂干扰项下准确定位出烟火云雾的位置,并降低误报率和漏报率。比赛分为初赛和复赛,初赛和复赛分别为不同的任务。

初赛任务:初赛将提供城市霓虹灯、火焰、烟雾、云四个类别的图片数据集,每张图片只会出现一个类别目标,需要选手建立分类识别模型,检测出每张图片的类别。

2.数据集

训练集为774张图片,A榜测试集为200张图片。训练集包含images文件夹和train.csv文件。其中train.csv具体字段含义如下:

3.评分指标

初赛: Precision=图片label预测正确的数量 / 所有图片的数量

二、环境准备

主要分为以下几步:

  • 一是安装PaddlePaddle-GPU(AI Studio平台已自带)
  • 二是下载并安装PaddleClas图像分类套件

具体操作如下:

# git下载PaddleClas源码
!git clone https://gitee.com/paddlepaddle/PaddleClas.git --depth=1
Cloning into 'PaddleClas'...
remote: Enumerating objects: 1037, done.[K
remote: Counting objects: 100% (1037/1037), done.[K
remote: Compressing objects: 100% (918/918), done.[K
remote: Total 1037 (delta 331), reused 478 (delta 95), pack-reused 0[K
Receiving objects: 100% (1037/1037), 59.94 MiB | 3.57 MiB/s, done.
Resolving deltas: 100% (331/331), done.
Checking connectivity... done.
%cd ~/PaddleClas
# 更新pip
!pip install -U pip
# 安装依赖
!pip install -r requirements.txt
# 本地安装paddleclas
!pip install -e ./

三、数据准备

主要有以下几步

  • 一是解压缩数据
  • 二是查看数据分布情况
  • 三是划分train、eval数据集
  • 四是制作数据标签待用

1.解压缩数据

# 解压缩数据集
!unzip -qoa data/data124756/省厅-视频赛场-烟火云霓虹灯识别-算法赛-初赛A榜.zip
# 重命名目录
!mv '省厅-视频赛场-烟火云霓虹灯识别-算法赛-初赛A榜' mydata
# 查看数据
%cd ~
!head -n5 mydata/train/train.csv
/home/aistudio
# 查看图片
from PIL import Image
img=Image.open('mydata/train/images/tr-768.jpg')
# 查看尺寸
print(img.size)
img
(440, 587)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hOF3KVTO-1642081207124)(output_8_1.png)]

2.查看数据分布情况

通过分析可见,烟最少,云最多,大致均衡,

  • 2 223
  • 1 200
  • 3 194
  • 0 157
%cd ~
from matplotlib import pyplot as plt
import  pandas as pd
from sklearn.utils import shuffle

# 读取数据
data=pd.read_csv('mydata/train/train.csv')
# 统计数据分布
print(data['label'].value_counts())
# 打乱数据集
data=shuffle(data)
print(len(data))
data.head()
/home/aistudio
2    223
1    200
3    194
0    157
Name: label, dtype: int64
774
image_namelabel
474tr-204.jpg2
562tr-83.jpg2
678tr-622.jpg3
590tr-534.jpg3
426tr-161.jpg2
data['label'].value_counts().plot(kind="bar")
<matplotlib.axes._subplots.AxesSubplot at 0x7fc620bee910>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UJ9tX888-1642081207125)(output_11_1.png)]

3.数据集划分

# 划分train、eval数据集并保存
test=data.iloc[0:int(0.2*len(data))]
train=data.iloc[int(0.2*len(data))-1:-1]

print(train.shape)
print(test.shape)

test.to_csv('mydata/train/test.txt', index=None, header=None, sep=' ')
train.to_csv('mydata/train/train.txt', index=None, header=None, sep=' ')
(620, 2)
(154, 2)

4.生成label列表

手动生成label_list.txt,需要注意的是,使用writefile魔法时,第一行必须是 %%writefile ,否则会报错。

%%writefile mydata/train/label_list.txt
0123 霓虹灯
Writing mydata/train/label_list.txt

四、模型训练

网络选择轻量级 MobileNetV3 ,可快速进行验证。

PaddleClas/ppcls/configs/ImageNet/MobileNetV3/MobileNetV3_large_x1_25.yaml 为基础进行修改配置

1.全局参数

# global configs
Global:
  # 恢复训练点
  checkpoints: null
  # 预训练模型地址
  pretrained_model: null
  # 输出地址
  output_dir: ./output/
  # gpu等选择
  device: gpu
  # 模型保存间隔
  save_interval: 1
  # 是否再训练时进行eval
  eval_during_train: True
  # 评估间隔
  eval_interval: 10
  # 训练轮数设置
  epochs: 360
  print_batch_step: 10
  # 是否启用visualdl可视化训练
  use_visualdl: False
  # used for static mode and model export
  image_shape: [3, 224, 224]
  save_inference_dir: ./inference

2.网络配置

# model architecture
Arch:
  #网络配置
  name: MobileNetV3_large_x1_25
  # 分类数量
  class_num: 4
 
# loss function config for traing/eval process
Loss:
  Train:
    - CELoss:
        weight: 1.0
        epsilon: 0.1
  Eval:
    - CELoss:
        weight: 1.0


Optimizer:
  name: Momentum
  momentum: 0.9
  lr:
    name: Cosine
    #学习率,可适当更爱
    learning_rate: 0.01
    warmup_epoch: 50
  regularizer:
    name: 'L2'
    coeff: 0.00004

3.数据集配置

# data loader for train and eval
DataLoader:
  Train:
    # 训练数据集配置
    dataset:
      name: ImageNetDataset
      image_root: /home/aistudio/mydata/train/images
      cls_label_path: /home/aistudio/mydata/train/train.txt
      # 数据增强配置
      transform_ops:
        - DecodeImage:
            to_rgb: True
            channel_first: False
        - RandCropImage:
            size: 224
        - RandFlipImage:
            flip_code: 1
        - RandAugment:
            num_layers: 2 
            magnitude: 5                   
        - NormalizeImage:
            scale: 1.0/255.0
            mean: [0.485, 0.456, 0.406]
            std: [0.229, 0.224, 0.225]
            order: ''
        - RandomErasing:
            EPSILON: 0.5
            sl: 0.02
            sh: 0.4
            r1: 0.3
            mean: [0., 0., 0.]   
        - Cutout:
            n_holes: 1
            length: 112


    sampler:
      name: DistributedBatchSampler
      # 训练 单次 数量 配置
      batch_size: 512
      drop_last: False
      shuffle: True
    loader:
      num_workers: 4
      use_shared_memory: True

  Eval:
    dataset: 
      name: ImageNetDataset
      image_root: /home/aistudio/mydata/train/images
      cls_label_path: /home/aistudio/mydata/train/test.txt
      transform_ops:
        - DecodeImage:
            to_rgb: True
            channel_first: False
        - RandCropImage:
            size: 224
        - RandFlipImage:
            flip_code: 1
        - NormalizeImage:
            scale: 1.0/255.0
            mean: [0.485, 0.456, 0.406]
            std: [0.229, 0.224, 0.225]
            order: ''

    sampler:
      name: DistributedBatchSampler
      batch_size: 512
      drop_last: False
      shuffle: True
    loader:
      num_workers: 4
      use_shared_memory: True

Infer:
  infer_imgs: docs/images/whl/demo.jpg
  batch_size: 10
  transforms:
    - DecodeImage:
        to_rgb: True
        channel_first: False
    - ResizeImage:
        resize_short: 256
    - CropImage:
        size: 224
    - NormalizeImage:
        scale: 1.0/255.0
        mean: [0.485, 0.456, 0.406]
        std: [0.229, 0.224, 0.225]
        order: ''
    - ToCHWImage:
  PostProcess:
    name: Topk
    topk: 3
    # 标签配置
    class_id_map_file: /home/aistudio/mydata/train/label_list.txt

Metric:
  Train:
    - TopkAcc:
        topk: [1, 3]
  Eval:
    - TopkAcc:
        topk: [1, 3]

4.注意事项

  • 一是开始学习率不要太大,不然loss会NaN
  • 二是Topk根据情况设置,例如分类为4,用Topk5就不合适了
  • 三是数据增强需要注意顺序及参数
# 覆盖配置
!cp -r ~//MobileNetV3_large_x1_25.yaml PaddleClas/ppcls/configs/ImageNet/MobileNetV3/MobileNetV3_large_x1_25.yaml

5.开始训练

%cd ~/PaddleClas/
!python3 tools/train.py \
        # 训练配置文件设置
        -c ./ppcls/configs/ImageNet/MobileNetV3/MobileNetV3_large_x1_25.yaml \
        # 训练输出目录配置
        -o Global.output_dir="output_Fireworks_cloud_neon_lamp" \
        -o Arch.pretrained=True

日志输出:

[2022/01/07 22:13:48] root INFO: Already save model in output_Fireworks_cloud_neon_lamp/MobileNetV3_large_x1_25/epoch_1
[2022/01/07 22:13:48] root INFO: Already save model in output_Fireworks_cloud_neon_lamp/MobileNetV3_large_x1_25/latest
[2022/01/07 22:13:54] root INFO: [Train][Epoch 2/360][Iter: 0/2]lr: 0.00030, top1: 0.16406, top3: 0.68945, CELoss: 1.62538, loss: 1.62538, batch_cost: 4.31696s, reader_cost: 3.72142, ips: 118.60189 images/sec, eta: 0:51:39
[2022/01/07 22:13:55] root INFO: [Train][Epoch 2/360][Avg]top1: 0.17903, top3: 0.70484, CELoss: 1.61036, loss: 1.61036
[2022/01/07 22:13:55] root INFO: Already save model in output_Fireworks_cloud_neon_lamp/MobileNetV3_large_x1_25/epoch_2
[2022/01/07 22:13:55] root INFO: Already save model in output_Fireworks_cloud_neon_lamp/MobileNetV3_large_x1_25/latest
[2022/01/07 22:14:02] root INFO: [Train][Epoch 3/360][Iter: 0/2]lr: 0.00050, top1: 0.20508, top3: 0.71875, CELoss: 1.59324, loss: 1.59324, batch_cost: 3.94291s, reader_cost: 3.36189, ips: 129.85339 images/sec, eta: 0:47:03

五、评估训练模型

%cd ~/PaddleClas/
!python  tools/eval.py \
        -c ./ppcls/configs/ImageNet/MobileNetV3/MobileNetV3_large_x1_25.yaml \
        -o Global.pretrained_model=./output_Fireworks_cloud_neon_lamp/MobileNetV3_large_x1_25/best_model

六、预测

1.导处静态模型

根据配置save_inference_dir: ./inference 导出到 inference 目录

!python3 tools/export_model.py \
    -c  ./ppcls/configs/ImageNet/MobileNetV3/MobileNetV3_large_x1_25.yaml  \
    -o Global.pretrained_model=./output_Fireworks_cloud_neon_lamp/MobileNetV3_large_x1_25/best_model     

2.修改预测脚本

修改 PaddleClas/deploy\python/predict_cls.py,添加输出到文件代码

# 拷贝已经修改好的脚本, 覆盖git下的默认脚本
!cp -r ~/predict_cls.py  ~/PaddleClas/deploy/python/predict_cls.py 

修改 PaddleClas/deploy\python/predict_cls.py

def main(config):
    cls_predictor = ClsPredictor(config)
    image_list = get_image_list(config["Global"]["infer_imgs"])

    batch_imgs = []
    batch_names = []
    cnt = 0
    # 新建保存文件
    f=open('/home/aistudio/result.txt', 'w')
    # 写入表头
    f.write('image_name' +','+ 'label'+'\n') 
    for idx, img_path in enumerate(image_list):
        img = cv2.imread(img_path)
        if img is None:
            logger.warning(
                "Image file failed to read and has been skipped. The path: {}".
                format(img_path))
        else:
            img = img[:, :, ::-1]
            batch_imgs.append(img)
            img_name = os.path.basename(img_path)
            batch_names.append(img_name)
            cnt += 1

        if cnt % config["Global"]["batch_size"] == 0 or (idx + 1
                                                         ) == len(image_list):
            if len(batch_imgs) == 0:
                continue
            batch_results = cls_predictor.predict(batch_imgs)
            
            for number, result_dict in enumerate(batch_results):
                filename = batch_names[number]
                clas_ids = result_dict["class_ids"]
                scores_str = "[{}]".format(", ".join("{:.2f}".format(
                    r) for r in result_dict["scores"]))
                label_names = result_dict["label_names"]
                print("{}:\tclass id(s): {}, score(s): {}, label_name(s): {}".
                      format(filename, clas_ids, scores_str, label_names))
                # 写入预测数据
                f.write(filename +','+ str(clas_ids[0])+'\n')
            
            batch_imgs = []
            batch_names = []
    f.close()
    if cls_predictor.benchmark:
        cls_predictor.auto_logger.report()
    return

3.开始预测

%cd /home/aistudio/PaddleClas/deploy
!python3 python/predict_cls.py \
    # 使用生成的配置
    -c configs/inference_cls.yaml \
    # 设置要预测的图片目录
    -o Global.infer_imgs=/home/aistudio/mydata/test-A榜/images \
    # 设置静态模型
    -o Global.inference_model_dir=../inference/ \
    # 取消标签(比赛用数字标签,而不是真实数值)
    -o PostProcess.Topk.class_id_map_file=None

日志输出

e-A1194.jpg:	class id(s): [3, 2, 0, 1], score(s): [0.94, 0.03, 0.02, 0.01], label_name(s): []
te-A2804.jpg:	class id(s): [1, 3, 0, 2], score(s): [0.87, 0.08, 0.03, 0.02], label_name(s): []
te-A4245.jpg:	class id(s): [2, 3, 1, 0], score(s): [0.88, 0.06, 0.04, 0.01], label_name(s): []
te-A4660.jpg:	class id(s): [2, 3, 0, 1], score(s): [0.59, 0.28, 0.07, 0.06], label_name(s): []
te-A4742.jpg:	class id(s): [0, 3, 2, 1], score(s): [0.77, 0.12, 0.06, 0.05], label_name(s): []
te-B1132.jpg:	class id(s): [3, 2, 0, 1], score(s): [0.93, 0.04, 0.02, 0.01], label_name(s): []
te-B1517.jpg:	class id(s): [2, 1, 0, 3], score(s): [0.58, 0.18, 0.12, 0.11], label_name(s): []
te-B1575.jpg:	class id(s): [0, 1, 3, 2], score(s): [0.86, 0.08, 0.04, 0.02], label_name(s): []
# 查看预测结果
! head -n10 ~/result.txt
image_name,label
te-A1194.jpg,3
te-A2804.jpg,1
te-A4245.jpg,2
te-A4660.jpg,2
te-A4742.jpg,0
te-B1132.jpg,3
te-B1517.jpg,2
te-B1575.jpg,0
te-B1587.jpg,1

pg,3
te-B1517.jpg,2
te-B1575.jpg,0
te-B1587.jpg,1

七、提交结果

提交生成的result.txt文件,即可得到分数。

这样就完成比赛啦,大家可以选择精度更高的更先进的模型配置、使用数据增强手段来提分了。

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐