跳转至

2023全球智能汽车挑战赛日志

Day0 23/11/10

事项

  1. 赛事报名
  2. 数据资源下载
  3. 提交baseline

收获

  1. 明确赛题任务:生成视频对应的内容分析

  2. 环境配置:由于paddle结构较为混乱,按照如下方式安装

pip install common, dual, tight, data, prox
pip install paddlepaddle==2.5.2
pip install paddleclip
  1. 了解飞桨平台使用方法

Day1 23/11/17

事项

  1. 学习CLIP论文论文解读

  2. 学习baseline解读

收获

  1. CLIP模型:
  • 动机:

    • 使用自然语言中的监督信号
    • 迁移性强的模型
  • 原理:

    image-20231119215211903

    架构:图像编码器,文本编码器

    训练:

    • 数据类型:(Image, text),即图像与其对应的描述文本
    • 对于大小为\(N\)的batch,对应的图像文本对为正样本,共\(N\)个;非对应的为负样本,共\(N^2-N\)
    • 采用对比学习手段进行训练

    模型参数量大,使用对比学习手段降低计算量

    预测:

    • 利用提示词模板,将类别嵌入形成描述性语句

    训练数据采取描述性文本,此处应根据类别构造提示文本形成语句

    • 利用图像编码器与文本编码器提取特征
    • 分别计算图像特征与各文本特征的余弦相似性,取相似性最高的作为预测结果
  • 结论:

    • 图像、文本模型的复杂程度与模型性能呈正相关
    • 使用大数据集(4亿图像文本对)训练模型得到较好效果
    • 使用描述性文本而非标签可减小标签收集难度
    • 模型具有较强zero-shot推理能力,通过固定模型本体训练分类头的方式微调,few-shot效果甚至不如zero-shot
  • 局限性:

    • 迁移性强,而非针对每个具体领域性能都强
    • 存在分布偏移问题,在MNIST上的效果奇差
  1. baseline解读:

baseline使用百度飞桨提供的clip模型,从视频中抽帧进行识别

clip_id = video_path.split('/')[-1]
cap = cv2.VideoCapture(video_path)
img = cap.read()[1]
image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
image = Image.fromarray(image)
image = transforms(image).unsqueeze(0)

由于clip模型并非能胜任所有检测任务,故仅利用clip做天气与道路结构识别的任务

for keyword in en_match_words.keys():
    if keyword not in ["weather", "road_structure"]:
        continue

Day2 23/11/19

事项

  1. 第一次提交
  2. 更换CLIP模型
  3. 尝试提示词工程

收获

  1. 将CLIP模型更换至openai-clip使用最大图像Transformer训练的模型,使用pytorch库进行推理,baseline修改如下
import torch
import clip
from PIL import Image
import cv2
import glob

device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load("ViT-L/14@336px", device=device)
paths = glob.glob('../../Dataset/Tianchi2023/初赛测试视频/*')
paths.sort()
video_path = paths[0]
clip_id = video_path.split('\\')[-1]
cap = cv2.VideoCapture(video_path)
img = cap.read()[1]
image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
image = Image.fromarray(image)
image = preprocess(image).unsqueeze(0).to(device)
text = clip.tokenize(["clear","cloudy","raining","foggy","snowy"]).to(device)
with torch.no_grad():
    image_features = model.encode_image(image)
    text_features = model.encode_text(text)
    logits_per_image, logits_per_text = model(image, text)
    probs = logits_per_image.softmax(dim=-1).cpu().numpy()

注:

  1. cap.read()[0]会引发报错,故取cap.read()[1]作为第一帧
  2. 使用最大的模型ViT-L/14@336px
  3. 使用GPU加速
  1. 由于需要将类别嵌入句子,构造如下提示词模板:
en_prompt = {
        "scerario": [f"It's a photo of {_}" for _ in en_match_words["scerario"]],
        "weather": [f"It's a {_} day" for _ in en_match_words["weather"]],
        "period": [f"It's {_} now" for _ in en_match_words["period"]],
        "road_structure": [f"The road structure is {_}" for _ in en_match_words["road_structure"]],
        "general_obstacle": [f"{_} is in the road" for _ in en_match_words["general_obstacle"]],
        "abnormal_condition": [f"{_} is happening" for _ in en_match_words["abnormal_condition"]],
        "ego_car_behavior": [f"The car in the  photo is {_}" for _ in en_match_words["ego_car_behavior"]],
        "closest_participants_type": [f"The participant is {_}" for _ in en_match_words["closest_participants_type"]],
        "closest_participants_behavior": [f"The participant is {_}" for _ in en_match_words["closest_participants_behavior"]]
    }
  1. 对于模型返回Unknow的处理:设定阈值,当模型预测最大概率与最小概率差小于阈值时,认为结果未知
threshold = 0.1

if np.max(probs[0]) - np.min(probs[0]) > threshold:
 single_video_result[keyword] = texts[probs[0].argsort()[::-1][0]]
else:
 single_video_result[keyword] = "unknown"
  1. 改进方向:由于预测手段为抽帧静态分析,故无法完成动态特征检测,需利用不同模型完成不同任务

第一次提交

image-20231119220742196

注:由于主办方提供的检测程序中场景一词错误的拼写为scerario,私自更正将会导致提交时报错

注意到利用阈值判断unknown导致大量特征变为unknown,利用先验为预测结果赋初值:

single_video_result = {
    "clip_id": clip_id,
    "scerario": "city street",
    "weather": "clear",
    "period": "daytime",
    "road_structure": "normal",
    "general_obstacle": "nothing",
    "abnormal_condition": "nothing",
    "ego_car_behavior": "go straight",
    "closest_participants_type": "passenger car",
    "closest_participants_behavior": "braking"
}

同时,由于部分路况仅在视频的某些部分出现,其出现概率中间帧大于起始帧,故取中间帧进行分析

img = imgs[len(imgs) // 2]

将分数提升至134分

image-20231119222131479