YAOTU INSIGHTS

coco-cn中文多模态数据集实战:跨语言图像描述与检索指南

coco-cn中文多模态数据集实战:跨语言图像描述与检索指南
简介COCO-CN 是一个在 MS-COCO 基础上通过人工书写中文句子与标签扩充而成的双语图像描述数据集面向从事图像字幕、图像标注及跨语言多媒体检索的研究者与开发者用于解决中文场景下跨语言图像理解任务缺乏高质量标注数据的问题。资源包共 519 个文件以 Python 脚本、JavaScript 前端代码、文本与 Shell 脚本为主另含少量模型权重、网页模板与字体资源压缩包约 133.53MB涵盖数据处理、评测工具与演示界面等模块。201805 版包含 20,341 张图像划分为训练、验证与测试集并关联 22,218 条人工书写中文句子及 5,000 条人工翻译句子同时提供基于 ResNext-101 的评测工具便于在 COCO-CN 测试集上对比不同字幕系统效果。目前已有 820 人学习下载适合需要开展跨语言图像标注、字幕生成与检索实验的读者参考使用。1. 中文多模态数据集的稀缺到底卡在哪一步做跨语言图像描述和检索的同行大概都有体会MS-COCO 的英文标注质量极高每张图 5 条 caption 加 80 类标签但一旦任务切到中文能直接拿来训练的数据集屈指可数。很多团队的做法是拿翻译 API 把英文 caption 批量转成中文结果训练出来的模型在中文表达上总有一股翻译腔标签体系也对不上中文语义习惯。coco-cn 这个资源就是冲着这个缺口来的——它在 MS-COCO 原有结构上为图像补充了中文句子描述和中文标签让 image-captioning、image-tagging、cross-lingual-image-retrieval 这几类任务有了原生的中文监督信号。它适合正在做中文多模态预训练、跨语言检索对齐、或者需要中文 caption 评测基准的从业者。下面我按实际拆包和跑通的顺序把这份资源的结构、用法和坑讲清楚。2. 拆开 coco-cn文件结构、标注格式与跨语言对齐逻辑2.1 数据集目录与核心文件说明拿到 coco-cn 之后第一件事是确认目录结构。它沿用了 MS-COCO 的经典布局但增加了中文标注文件。常见做法是保持 images 目录不变在 annotations 下新增中文 JSON。我一般会先跑一遍文件清点确认图片数量和标注条目能对上。# 清点图片与标注文件确认数据完整性 find ./coco-cn/images -type f -name *.jpg | wc -l ls -lh ./coco-cn/annotations/ # 典型输出会包含 # captions_train_zh.json # captions_val_zh.json # image_tags_zh.json # instances_train.json沿用原始结构逻辑说明图片目录沿用 COCO 的 train2017/val2017 命名中文标注单独成文件避免污染原始英文标注。参数上要注意如果你的下游任务同时需要中英文建议把两个 JSON 都加载后按 image_id 做 merge而不是覆盖。2.2 中文标注 JSON 的字段结构中文 caption 文件的结构和 COCO 官方 captions 文件一致只是把caption字段换成了中文句子。标签文件则更接近多标签分类的格式。下面这段代码是我常用的加载与校验方式。import json # 加载中文 caption 标注 with open(./coco-cn/annotations/captions_train_zh.json, r, encodingutf-8) as f: zh_captions json.load(f) # 检查字段完整性 sample zh_captions[annotations][0] print(sample.keys()) # dict_keys([image_id, id, caption]) # 统计每张图的中文句子数量确认是否与英文一致 from collections import Counter cnt Counter([a[image_id] for a in zh_captions[annotations]]) print(每图句子数分布:, Counter(cnt.values())) # 正常应集中在 5 条左右逻辑说明image_id是与原始 COCO 对齐的关键外键id是标注条目唯一编号。参数上如果你的训练框架要求 caption 长度统一建议在这里就统计一下中文句子的 token 长度分布中文按字切分和按词切分差异很大后面会细说。2.3 跨语言对齐为什么不能只靠翻译coco-cn 的价值不在于“把英文翻成中文”而在于中文句子和标签是独立标注或经过母语者校验的。跨语言检索任务里模型需要把中文文本和图像映射到同一语义空间。如果中文 caption 是机翻的会出现“一只猫坐在沙发上”被翻成“一只猫是坐着的在沙发上”这类语序问题对比学习时正样本对的质量会下降。我一般会检查中文标注里是否保留了原始 COCO 的 80 类物体标签体系如果标签也是中文独立映射的那 cross-lingual-image-retrieval 的评测才站得住。提示如果你的任务只做中文 caption可以只用 captions_zh但做跨语言对齐时务必保留英文标注做平行语料否则无法构造正负样本对。3. 把 coco-cn 接进训练流程加载、分词与跨语言检索实战3.1 用 PyTorch Dataset 封装中文 caption 数据直接读 JSON 训练效率低我一般会写一个轻量 Dataset。这里以 image-captioning 为例展示如何把中文句子和图像配对加载。import os import json from PIL import Image from torch.utils.data import Dataset from torchvision import transforms class CocoCNCaptionDataset(Dataset): def __init__(self, img_root, ann_file, transformNone): with open(ann_file, r, encodingutf-8) as f: data json.load(f) self.img_root img_root self.annotations data[annotations] # 建立 image_id 到文件名的映射 self.img_name {img[id]: img[file_name] for img in data[images]} self.transform transform or transforms.ToTensor() def __len__(self): return len(self.annotations) def __getitem__(self, idx): ann self.annotations[idx] img_path os.path.join(self.img_root, self.img_name[ann[image_id]]) image Image.open(img_path).convert(RGB) if self.transform: image self.transform(image) caption ann[caption] # 中文句子 return image, caption逻辑说明img_name映射避免每次拼路径时重复查找。参数上transform建议训练时用 RandomResizedCrop 加 ColorJitter验证时只做 Resize 和 CenterCrop。注意中文 caption 不要在这里做 tokenize留给后面的 tokenizer 统一处理否则多进程加载时容易出编码问题。3.2 中文分词与 tokenizer 选择中文 caption 和英文最大的区别在于分词。英文按空格切中文得选字级别还是词级别。我试过几种方案字级别对未登录词更稳词级别语义更紧凑。常见做法是用 jieba 先切词再喂给 BERT 的中文 tokenizer如果追求端到端直接用 BERT 自带的字级别 tokenizer 也行。from transformers import BertTokenizer tokenizer BertTokenizer.from_pretrained(bert-base-chinese) captions [一只猫坐在沙发上, 桌子上有一杯咖啡] encoded tokenizer(captions, paddingTrue, truncationTrue, max_length32, return_tensorspt) print(encoded[input_ids].shape) # torch.Size([2, 32])逻辑说明max_length32对中文 caption 通常够用因为中文句子平均 10 到 20 字。参数上truncationTrue防止个别长句撑爆显存。如果你的任务对长描述敏感可以调到 64但要注意 batch 内 padding 带来的显存开销。3.3 跨语言检索的对比学习构造cross-lingual-image-retrieval 的核心是让中文文本和图像在共享空间里对齐。我一般用双塔结构图像走 CNN 或 ViT中文走 BERT然后用 InfoNCE 损失拉近正样本对。coco-cn 的好处是同一张图既有中文 caption 又有英文 caption可以构造中英平行对做额外约束。import torch import torch.nn.functional as F def contrastive_loss(img_emb, txt_emb, temperature0.07): # 归一化 img_emb F.normalize(img_emb, dim-1) txt_emb F.normalize(txt_emb, dim-1) # 计算相似度矩阵 logits img_emb txt_emb.t() / temperature labels torch.arange(logits.size(0), devicelogits.device) loss_i F.cross_entropy(logits, labels) loss_t F.cross_entropy(logits.t(), labels) return (loss_i loss_t) / 2逻辑说明temperature控制 softmax 的锐度太小容易过拟合太大区分度不够0.07 是常见起点。参数上batch size 尽量大对比学习对负样本数量敏感单卡不够可以用梯度累积。注意中文和英文文本如果混在一个 batch 里要确保 image_id 对齐否则正样本对就错了。3.4 标签任务的接入方式image-tagging 任务里coco-cn 的中文标签可以直接做多标签分类。我一般把标签转成 one-hot 或 multi-hot 向量用 BCEWithLogitsLoss 训练。中文标签的类别数和英文一致但语义映射要检查比如“沙发”和“长椅”在中文里区分度比英文更细。import numpy as np # 假设标签文件里 tags 是中文列表 tag_list [猫, 沙发, 桌子, 咖啡] tag2idx {t: i for i, t in enumerate(tag_list)} def encode_tags(tags): vec np.zeros(len(tag_list), dtypenp.float32) for t in tags: if t in tag2idx: vec[tag2idx[t]] 1.0 return vec逻辑说明tag2idx要固定训练和推理必须用同一套映射。参数上如果标签有层级关系可以考虑用 sigmoid 而不是 softmax因为一张图可能同时有多个标签。4. 避坑与排查中文多模态训练里最容易翻车的五件事4.1 中文编码不一致导致乱码现象加载 JSON 时报 UnicodeDecodeError或者读出来的 caption 是问号。原因文件保存时用了 GBK 而读取时用 UTF-8或者反过来。解决统一用encodingutf-8并在保存标注时显式指定ensure_asciiFalse。# 保存时避免中文被转义 with open(captions_zh.json, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2)4.2 image_id 对不上导致图文错配现象训练 loss 不降检索时图文完全不匹配。原因中文标注的 image_id 和图像文件名映射错位常见于自己合并中英文标注时。解决加载后先做一次断言检查确认每个 image_id 都能在 images 列表里找到。img_ids {img[id] for img in data[images]} ann_ids {a[image_id] for a in data[annotations]} assert ann_ids.issubset(img_ids), 存在无法映射的 image_id4.3 中文分词粒度与预训练模型不匹配现象用英文 BERT 的 tokenizer 处理中文token 全变成 [UNK]。原因英文 BERT 词表里没有中文字符。解决换bert-base-chinese或chinese-roberta-wwm-ext这些模型词表覆盖常用汉字和词。4.4 对比学习 batch 内负样本泄露现象检索指标虚高但实际推理效果差。原因同一张图的多个中文 caption 被分到同一 batch互相成为负样本模型学到了“同图不同句”的虚假差异。解决构造 batch 时确保每个 image_id 只出现一次或者用去重采样。4.5 标签体系与英文不一致导致跨语言评测失真现象中文标签分类准确率很高但跨语言检索时标签对齐很差。原因中文标签做了合并或拆分和英文 80 类不是一一对应。解决保留一份中英标签映射表评测时按映射表对齐后再算指标。注意如果你打算用 coco-cn 做 zero-shot 跨语言迁移务必在划分 train/val 时按 image_id 切分而不是按 caption 条目切分否则同一张图的句子会同时出现在训练和验证集里。5. 进阶技巧用 coco-cn 做中英双向检索的验证与调参5.1 构造中英平行验证集coco-cn 的一个隐藏用法是拿同一张图的中英 caption 做双向检索验证。我一般会从 val 集里抽 1000 张图每张图取一条中文和一条英文然后分别算 image-to-text 和 text-to-image 的 Recall1、5、10。这样能直接看出模型在两种语言上的对齐差距。def recall_at_k(sim_matrix, k1): # sim_matrix: (N, N)对角线为正样本 ranks torch.argsort(sim_matrix, dim-1, descendingTrue) targets torch.arange(sim_matrix.size(0)).unsqueeze(1) return (ranks[:, :k] targets).any(dim-1).float().mean().item()逻辑说明sim_matrix是图像和文本的相似度矩阵对角线是正样本。参数上k 取 1、5、10 分别看不同宽松度下的召回。注意中文和英文要分开算不要混在一起平均否则看不出语言差异。5.2 温度系数与学习率的联动调参对比学习里 temperature 和学习率是联动的。我试过的一个经验是temperature 从 0.07 降到 0.05 时学习率也要相应降一点否则容易震荡。下面这个表格是我在单卡 24G 上跑出来的粗略对照供参考。temperature学习率batch sizeRecall1中→图0.071e-41280.420.055e-51280.460.051e-42560.490.035e-52560.47逻辑说明temperature 越小模型对难负样本越敏感但太小会放大噪声。参数上batch size 增大时学习率可以适当提高但不要超过 2e-4。这张表只是我自己的硬件条件下的结果你的数据划分和模型结构不同数值会变但趋势可以参考。5.3 用中文标签做辅助任务提升检索一个我常用的技巧是把 image-tagging 作为辅助任务和对比学习联合训练。图像塔同时输出检索 embedding 和标签预测标签的监督信号能让图像表示更语义化。实现上就是在图像塔后面加一个分类头损失函数加权求和。# 联合损失对比损失 标签分类损失 loss contrastive_loss(img_emb, txt_emb) 0.3 * tag_loss逻辑说明0.3是标签损失的权重我一般从 0.1 到 0.5 之间试。参数上如果标签噪声大权重调低如果检索指标上不去可以适当调高让图像表示更依赖标签语义。5.4 验证时别忘了看中文特有的失败案例英文检索里常见的失败是“狗和猫混淆”中文里还会多一层“量词和修饰语”的干扰。比如“一只白色的猫”和“一只白猫”模型可能认为是两个不同的语义。我一般会在验证集里单独抽一批带量词和颜色修饰的样本看 Recall 是否明显低于整体。如果低很多说明中文文本塔对修饰语不敏感可以考虑在 tokenizer 层面保留更多字级别信息或者加一层注意力池化。从那以后我每次接中文多模态数据集都强制先跑一遍编码检查、image_id 对齐和分词覆盖率的验证这三步过了再谈调参。希望帮到你。本文还有配套的精品资源点击获取