龙空技术网

2022 全球人工智能技术创新大赛—算法挑战赛选手比赛方案分享(一)

中国人工智能学会 536

前言:

今天看官们对“python读取lmdb”可能比较关怀,同学们都想要了解一些“python读取lmdb”的相关资讯。那么小编同时在网摘上收集了一些关于“python读取lmdb””的相关内容,希望你们能喜欢,小伙伴们一起来学习一下吧!

由中国人工智能学会和杭州市余杭区人民政府主办,杭州未来科技城管委会和京东零售联合承办的“2022全球人工智能技术创新大赛—算法挑战赛”于5月21日结束复赛。

本次大赛从人工智能领域的技术发展与跨界应用与融合出发,开设了电商关键属性的图文匹配和商品标题实体识别两个赛道,以打造人工智能的人才交流平台和产业生态圈,促进人工智能相关领域的创新与发展。

经过激烈的复赛,大赛产生了两个赛道的7-14名获奖队伍。在征求选手的意愿后,我们将分两期对两个赛道部分选手的比赛方案进行分享,本次分享的是赛道一的选手参赛方案。

赛道一:电商关键属性的图文匹配

京东积累了电商零售场景下的海量商品的图文数据,其中商品主图和商品标题是最直观、最容易触达到用户的数据。因此,图文的一致性(即图文匹配)至关重要,要求模型根据图片和文本判断出两种模态数据传递的信息是否一致。通常,商品主图和标题包含大量的商品属性信息。在实际业务中,图片里商品的关键属性与商品标题描述的是否匹配,是影响用户体验的重要因素。本赛题要求参赛队伍利用脱敏后的京东电商平台图文数据,通过商品图片与商品标题在商品关键属性上的关联程度来判断两者是否匹配。

赛道一选手比赛方案分享

排名:第8名 队名:广工夏天无电动

分享内容:

# 代码已开源:

[LXMERT&VILT&VILBERT]()

[NEZHA-LSTM]()

# 成绩

|榜单|rank|成绩|

| -------- | :-----: | ----|

| 初赛B榜 | 4 | 0.95211401 |

| 复赛B榜 | 8 |0.95045418 |

# 技术方案

# 题目理解

判断脱敏后的图片数据与文本的属性匹配。

数据来源于电商平台上的商品信息。

特征属性13个类:

```

图文,领型,袖长,衣长,版型,裙长,穿着方式....

```

针对13个属性做二分类,只需01判断,0表示该图文对不匹配,1表示匹配。

原数据中正样本(图文=1)比例占0.85+,因此需要构造负样本。

无标签的共有10w,有标签有5w。

# 数据前处理

[1] 对无标签的10w做了属性值提取(从文本中),转成有标签,最终有标签数据达到13w+。

[2] 删除年份信息,含有年份信息的title占比0.70+,年份信息与模型任务不相关。

## 数据增强

全在**dataset.__getitem__**中增强

### 负样本生成

- 随机title替换

- 替换title中的属性值

- 隐藏属性值替换,如颜色

### 其他增广

- title重组,语义保持不变

- 脱敏特征数据点调换

# 方案

## 模型

bert一把梭

- [LXMERT]()

- [VILT]()

- [VILBERT]()

- [NEZHA-LSTM]()

- Visualbert

## Pretrain

- 任务MLM+ITM

- 13w有标签数据做‘图文’属性ITM和MLM

- 取MLM loss + ITM loss 最低的模型

- LXMERT、VILT、VILBERT、NEZHA-LSTM均无使用huggingface预训练权重

- 自定义vocab,vocab_size = 1.5k+

## Finetune

### 模型结构

- 2048的feature经过linear转成768。

- 取原模型中的bert backbone,拼接[768,13] linear作为下游进行二分类判断。

- LXMERT 下游 取text 的cross enocder 的pooler_output。

- LXMERT 的图片encoder部分去掉了position_embedding和 type_embedding。

- vilbert 下游 text 和 image两个通道 做element wise product 。

- vilt 下游取pooler_output。

- NEZHA-LSTM:在Nezha输出添加Lstm再进行分类。

- 损失函数:BECLoss。

- 各模型其他输入操作与原文基本一致。

- 五个模型的单模成绩抖动在 $\pm 0.002$ 以内。

- 榜单成绩为5个模型融合的结果,其中LXMERT为五折参数融合。

排名:第9名 队名:圆头鲸b6zt的团队

分享内容:

主要方法:使用visualBERT结构和中文BERT的预训练参数,将文本和图像一起送入visualBERT中,得到融合特征进行二分类。

数据处理:由于数据为京东平台上的数据,因此大部分商品图片和商品标题都是对应的,这就导致了训练数据缺乏负样本。我考虑使用了关键属性替换的方法构造负样本,例如商品标题"针织衫薄款长袖",变为“针织衫薄款短袖”,就生成了负样本。

模型构建(初赛):由于初赛没有对模型大小进行限制,经过实验分析后,最终采用了双模型的方式,即将图片标题匹配任务和商品关键属性任务分为两个模型,分别进行训练和测试。

模型构建(复赛):复赛对模型大小进行了限制,需要进行模型压缩。故设计了全新的判别模型,将两个任务放在一起进行训练和测试。例如:样例"针织衫薄款长袖"+"商品图片",我将文本先进行词嵌入得到文本向量,再将图片向量拼接在文本向量后面送入visualBERT,可以得到10个特征向量,之后取‘[CLS]’对应的特征向量作为图片标题匹配任务的判别向量,“长袖”对应的特征向量取平均作为图片关键属性任务的判别向量。此外,还进行了模型结构的压缩,使用了5-7层BERT结构,比原本12层的结构,整体模型参数少了“50%”左右。

总结与展望:总体上取得了较为满意的结果,但仍有一些不足。除了官网给出的属性值外,还进行了隐藏属性的抽取,但未取得效果,可能是应用方式不对。同时由于时间问题,最后进行模型融合时未进行仔细调优,仅在B榜进行了一次模型融合。

排名:第10名 队名:aaadaptive

分享内容:

完整复赛代码

这个仓库只有复赛的代码,初赛的代码差不多,但比较混乱,暂时没有整理。

## 成绩

| | 分数 | 名次 |

|-------|:----------:|----:|

| 初赛 A | 0.94695043 | 26 |

| 初赛 B | 0.94810257 | 10 |

| 复赛 A | 0.92477171 | 34 |

| 复赛 B | 0.94935704 | 10 |

## 环境配置

主要的依赖项:

* python=3.8.8

* pytorch=1.11.0=py3.8_cuda10.2_cudnn7.6.5_0

* transformers=4.15.0=pypi_0

* python-lmdb=1.2.1=py38h2531618_1

* [Torchfast]()

* jieba=0.42.1

* [trexpark]()

其中,trexpark是有赞开源的一些预训练模型及代码,不能通过 pip 安装,线上作为数据源挂载。

## 文件说明

```{bash}

code/ # this repo

├--multilabel/ # 模型一

| ├--train.py

| └--infer.py # 推理脚本。输出概率。

├--pairwise/ # 模型二

| ├--train.py

| └--infer.py

├--prj_config.py # 一些路径配置文件

├--defs.py # 模型及所有在线增广

├--tools.py

├--preprocessing.py # 预处理脚本

└--postprocessing.py # 集成各模型输出,并生成最终提交文件

```

## 预训练模型

使用了有赞的两个已公开的预训练模型权重:

`youzanai/bert-product-title-chinese`和`youzanai/clip-product-title-chinese`。因为线上没有联网,需要做成数据集挂载,离线验证时需要手动执行一次,下载 hugging-face 文件至本地缓存目录,默认路径是`${home}/.cache/huggingface`。

所有预训练模型及下载方式:

```{python}

clip.ClipChineseModel.from_pretrained('youzanai/clip-product-title-chinese') # clip使用方式见 trex 项目

AutoModel.from_pretrained("youzanai/bert-product-title-chinese")

AutoConfig.from_pretrained("uclanlp/visualbert-vqa-coco-pre")

AutoTokenizer.from_pretrained("youzanai/bert-product-title-chinese")

AutoModel.from_pretrained("bert-base-chinese")

```

## 算法

### 整体思路介绍

最终提交的结果是使用2种模型 —— pairwise-swa 和 visualbert —— 的融合结果:

前者5折bagging后与visualbert的输出取平均值,再用0.5作为分类阈值。

下面分别介绍这两种模型。

### 模型一:pairwise-swa

模型伪代码:

`Transformer(cat([img_encode(img), text_encode(text)], dim=1)) -> 0/1`

用5折预先处理好的数据,分别增广,各训练一个模型,训练时结合SWA(Stochastic Weight Average)。在推理时取5折swa权重的输出的平均值(bagging)。

#### 网络结构

![模型一](model1.svg)

#### 损失函数

二分类损失:`nn.BCEWithLogitsLoss`

#### 数据扩增

对于关键属性,用图文匹配的数据做正负样本。

如`{'img_name': 'img1', 'title': "xxx", 'key_attr': {'领型': '高领', '图文': 1}}`

会针对【领型】做一个正样本,以及其他N个取值做N个负样本。

对于标题,分别进行正增广和负增广,其中:

* 正增广

* 删除标题中出现的所有关键属性,或只保留一个

* 不增广

* 负增广

* 修改:最多把一个属性改成不匹配

* 替换成其他标题,然后删除所有与该标题不匹配的属性。

* coarse中的图文不匹配数据。

这里负样本数量最多生成 *标题中的属性个数* 个。

离线增广后,标题与关键属性的数据合并,一起训练一个0/1二分类模型。

### 模型二:visualbert

用`uclanlp/visualbert-vqa-coco-pre`初始化一个VisualBert,然后用`youzanai/bert-product-title-chinese`替换权重。

图片特征先经过

[MoEx]()、Dropout,然后与文本一起输入到VisualBert中,取``的输出,计算multilabel loss(12个属性+1个图文,共13个标记)。

这个模型用的全量fine数据,增广后直接训练,结合swa,得到一个权重文件。推理时就用这一个权重文件的输出。

训练参数可以用划分好的验证集,适当调参数。

#### 网络结构

![模型二](model2.svg)

#### 损失函数

`nn.BCEWithLogitsLoss` (权重0.7)

加一个正则化项:

属性输出的概率最小值(带mask) 与 图文输出计算KL散度,因为如果图文匹配了,说明属性输出应该较大。(权重0.3)

#### 数据扩增

训练集在线增广,方式如下:

```{python}

# 按照概率列表,互斥地选择一个变换

mutex_transform([

# 1. 序列变换

sequential_transform([

# 替换一个标题

random_replace(candidate_attr, candidate_title),

# 随机删除一个属性

random_delete(0.3),

# 随机替换一个属性

random_modify(0.3, prop)

], [0.5, 0.4, 0.5]),

# 2. 互斥变换

mutex_transform([

delete_words(), # 分词后随机选择至少一个短语,删除。相应修改 match 的字段。

replace_hidden(), # 随机换类型、颜色中的至少一个,没有这些则保持原输入。

sequential_transform([

delete_words(), # 分词后随机选择至少一个短语,删除。相应修改 match 的字段。

replace_hidden(), # 随机换类型、颜色中的至少一个,没有这些则保持原输入。

], [1., 1.])

], [0.33, 0.33, 0.34]),

# 3. 不作变换

lambda x: x

], [0.5, 0.45, 0.05])

```

### 模型集成

visualbert 与 pairwise的5折bagging,两者取平均值后,用作为分类阈值。

### NOTE

详细的训练/测试流程请参考开源仓库中的 `readme.md`;

划分训练/验证集时注意,不要把同一个图片的N个不同的增广分散在训练集和验证集中,否则很容易过拟合,验证集上的分数不可靠;

主要的提升点在于 SWA 及模型融合。

由于复赛限制了模型参数及文件大小,使用的 bert 只取前6层。

Model1

Model2

排名:第11名 队名:美人鱼wp45的团队

分享内容:

## 数据分析

#### 1. 原始数据处理

原始数据分为有标签(5万)和无标签(10万)

通过从有标签数据的title中检索属性,将原本的正样本无标签数据构造成有标签数据

#### 2. 数据增强

数据本身正负样本比例为8:2,需要构造负样本

• 将属性随机替换

• 随机交换标题中关键属性的位置

• 删除部分关键属性

经实验证明,当正负样本比例为1:2,效果最佳,实验数据约40万

## 模型

#### 1. CNN

在一位大佬分享的baseline上做了一些改动,初赛单模效果能到0.93+,最终CNN是跑了五折再进行投票融合,成绩能到0.94+

• 调整了正则化参数

• 融合了最大池化和平均池化来提取更多信息

• 在文字和图片特征concat后添加了attention模块

#### 2. BERT

使用ChineseBert在全部title上使用MLM任务预训练。文字输入Bert得到的Embedding结果与图片特征(经过降维处理)concat做13分类,初赛A榜分数0.93

• concat后处理结构与CNN相同

#### 3. Visual Bert

直接将图片向量降维到1024后与文字向量一同输入visualbert, 使用Huggface预训练权重,复赛A榜分数0.909

• 使用transform结构6层结果与12层结果相差不大

• 对图片向量的输入方式进行了探索,发现复制图片向量并单独经过处理后进行输入,有小幅的结果提升

## 一些尝试

• 使用jieba 分词,对字典根据数据集进行了调整(有提升)

• 分析数据发现图文、版型、领型预测效果不好,单独对其进行二分类(没提升)

• 复赛将训练数据分布设置成测试数据(没提升)

## 总结

总体来说我们组这次比赛开始使用的CNN网络,对这个网络进行了一系列的实验,

单模五折到0.94+后,再做调整效果就不明显了,但因为CNN这个模型非常小,只有12M,所以不用考虑模型大小的限制,最后方案融合了BERT,Visual BERT模型。

## 最后

BERT,Visual BERT这两个模型我们也尝试了很多种改进,效果不太理想,也希望可以看看别人的方案学习一下。

第一次打比赛,还有很多需要改进的地方,继续加油

代码:

排名:第12名 队名:limzero

分享内容:

1 方案总览

图文和属性分别进行建模,图文直接作为2分类任务(bert),属性的12个二分类任务放在一起当作多标签分类来做(CNN/Bi_LSTM)。

初赛A:18

初赛B:8

复赛A:25

复赛B:12

2 数据方面

(1)对coarse进行属性提取,对于 “裤门襟 闭合方式 衣门襟(隐藏属性)” 需要重点处理,因为这仨属性的value有些重复;

(2)根据属性的不同取值来制作负样本,针对fine和coarse都进行负样本制作;注意制作的时候要依一定概率进行属性替换,比如一个标题中出现了三个属性,可以替换一个属性或两个或三个进行负样本制作,不要全部都换掉,这样会导致制作的负样本太简单;

(3)数据增强:

a.根据属性的同义词进行正样本增强,标题中替换同义词后标签不变;

b.通过删除进行图文正样本增强,标题中删除某个属性后图文依然匹配;

c.通过shuffle title进行数据增强,但这里需要根据属性的所有可能取值进行手动分词(使用正则表达式实现)再shuffle,不能使用jieba分词再shuffle。

(4)属性采用了12个多标签分类这种建模方式,所以负样本来自于两部分:

a.一部分是这个标题中压根没有这个属性(easy negative,大量存在)

b.另一部分是我们自己替换后生成的负样本(hard negative,比如“修身型”被替换为了“宽松型”),可以在训练过程中手动书写loss计算过程,通过自定义权重忽略easy neg,实现挺麻烦,但是效果不大。

(5)制作样本有两种方式(效果差不多)

a.在线数据增强(对于pytorch,在__getitem__()的时候,对输入的一条正样本进行随机正样本增强,制作负样本),需要很多轮才能收敛!

b.离线数据增强(设置需要制作多少倍的正负样本,离线做好所有的样本)

3 模型方面

(1)大量实验表明,使用简单几层CNN或者Bi_LSTM来建模属性,使用bert来建模图文是最优的选择。

(2)image feature和text feature的交互方式:concat起来经过简单几层全连接层进行交互即可,各种花式交互操作作用并不大。

(3)使用CNN或LSTM来处理属性的时候,word embedding随机初始化的效果要显著好于用bert预训练好的embedding,至于原因嘛,不懂!(个人猜测,bert预训练的词向量虽然好,但是它需要适配bert的架构,搞成CNN或者RNN来学,可能反倒不如Kaiming随机初始化,而且属性的分类模式太简单,bert动辄768维的embedding太容易过拟合!)。

chinese-roberta-wwm-ext;chinese-macbert-base;roberta-base-word-chinese-cluecorpussmall;三种在图文上的表现旗鼓相当,macbert略胜,分字还是分词影响不大。

(4)使用warmup学习率预热策略可以显著提升bert的收敛表现。

(5)五折、多模型融合都可以显著提升线上分数(仅限于初赛!)模型融合的时候使用的是经过Sigmoid()后的概率。

(6)图文需要单独训练,而属性需要和图文一起训练,也就是13个标签的多标签训练属性,然后预测的时候只取属性的12个位置即可。

(7)属性里面“版型”的权重(数量)是很大的,而且难度是最大的,队友尝试将“版型”单独拿出来进行建模,可以显著提升线上/线下表现。

排名:第14名 队名:ready&bling

分享内容:

## 模型方面

### 创新点

我们利用Roberta作为主体模型(试过很多的bert模型,Roberta效果最好)。因为我们观察到若是使用bert作为backbone模型,图像只有一个token(将图像2048维度均分成多个tokens效果不好)也就是说bert只能针对文本信息进行交互,为了增强图像信息利用,我们主要创新点是将图像和文本两种模态数据融合了两次,第一次是在Robert输入端,第二次是在Roberta的输出端,最后我们将融合的特征映射成匹配得分,通过计算BCEloss进行反向传播优化,这样可以取得很好的效果。下面是具体的模型结构:

### 网络结构

![img](C:\Users\LiaoYu\AppData\Local\YNote\data\qq9D3340BEC3355DA2158281B6AEE67C22\73073d98295445e08015ea402e5bd74d\clipboard.png)

   整个网络架构分为特征提取、两模态特征融合、Roberta特征交互、特征融合输出得分和计算Loss

**1.特征提取**

   该部分由两部分组成,第一部分输入关键属性和title进行正负样本的增强(在下面的“数据增强”部分具体介绍),然后经过Tokenizer模块对每一个汉字进行编码,之后进行embedding对一句话中的每一个词生成一个768维度的向量并添加一个CLS的768维的向量,生成一个(n+1)*768的向量(一句话假设有n个汉字);第二部分是将原始的图像2048维的特征进行特征映射768维的向量,然后进行重复扩充形成与文本token数量一致的向量组。

**2.两模态特征融合**

   对上述得到的文本和图像特征进行相加融合,生成一个(n+1)*768的向量

**3.Roberta特征交互**

   将上述的融合特征输入Roberta模型中进行交互,最后输出CLS位置对应的768维的向量

**4.特征融合输出得分、计算Loss**

   将图像特征与Roberta的CLS位置输出进行融合,然后通过全连接映射输出匹配得分s。计算BCE loss,进行整个模型的优化。

## 数据方面

### 数据增强

**文本正负样本增强**

有4种正样本构造方式和3种负样本构造方式,具体如下

   例如有一个样本的title:薄款拉链修身型短款方领皮外套女装长袖2021年冬季

1.构造正样本title:随机减少title中的一个关键属性

   如:薄款拉链短款方领皮外套女装长袖2021年冬季(减少了修身型)

2.构造负样本title1:随机增加一个关键属性到title中

   如:薄款拉链修身型短款方领皮外套女装长袖鞋帮高度高帮2021年冬季(增加了“鞋帮高度高帮”)

2(改).构造负样本title1:随机增加一个关键属性到title中

   如:薄款拉链修身型短款方领皮外套女装长袖高帮2021年冬季(增加了“高帮”)

3.构造负样本title2:在训练集中全局随机选择一个title

   如:春秋季开衫男士纯色圆领毛衣宽松型灰色

4.构造负样本title3:将title中的每一个关键属性用其所在大类中的其它关键属性代替

   如:薄款系带宽松型长款圆领皮外套女装短袖2021年冬季(“拉链”用“系带”代替,“修身型”用“宽松型”代替,“短款型”用“长款”代替,“方领”用“圆领”代替,“长袖”用“短袖”代替)

4(改).构造负样本title3:将title中的一个同义词关键属性用其同义关键属性代替

   如:薄款拉链修身型短款方领皮外套女装九分袖2021年冬季(“长袖”用“九分袖”代替)

5.构造正样本title:随机选择title中的一个同义词进行替换

  如:薄款拉链修身型短款方领皮外套女装九分袖2021年冬季(“长袖”用“九分袖”代替)

6.构造正样本title:以关键属性分割句子,然后打乱

  原句:薄款系带宽松型长款圆领皮外套女装短袖2021年冬季

  打乱后:长款宽松型薄款系带短袖皮外套女装圆领2021年冬季

7.构造正样本title:使用jieba(精准模式、添加自定义词典)分割句子,然后打乱

  原句:薄款系带宽松型长款圆领皮外套女装短袖2021年冬季

  分割:薄款、系带、宽松型、长款、圆领、皮外套、女装、短袖、2021年、冬季

  拼接:薄款长款宽松型系带短袖女装圆领皮外套2021年冬季

**关键属性负样本增强**

例如一个样本的keys是:版型修身型、款式短款、袖长长袖

1.构造正样本keys:在**所有的关键属性**中进行全局随机选择

   例如:领型半高领、裙长短长裙、裤型五分裤

2.构造负样本keys:在**关键属性所在的大类**中进行随机选择

   例如:版型型宽松型、款式长款、袖长短袖

3.构造正样本keys:添加同义词

   例如:版型标准型、衣长常规款、袖长九分袖

**注意:在以上的数据增强的策略中我们都考虑到了同义词,在构造负样本时,对同义词进行了规避**

### 数据数量增加

   训练数据集有以下两个部分构成:第一部分:将原本10万coarse数据中图文匹配的89样本转化进行关键属性提取转换成fine数据;第二部分:原本5万fine中除去1000验证集的49000样本。两个部分加起来则一共有89588+49000的细粒度训练样本。

**注意:在对coarse数据进行fine数据转换的时候,有些的关键属性比如“系带”只是鞋子和靴子的关键属性,不能作为裤子,衣服的关键属性,也就是说只有文本中有“鞋”,“靴”两个字的时候才对“系带”关键属性进行提取。还有其它的一些关键属性也有相同的问题。**

## 算法的其他细节

   我们在训练的过程中,每2个epoch重置随机种子并重新加载数据,以此生成不一样的正负样本。

   我们在测试时,假设我们测试关键属性“袖长长袖”与图像是否匹配,我们会计算“袖长长袖”和“袖长九分袖”(因为长袖和九分袖是同义词)与图像的匹配分数,若是有一个超过阈值就认为匹配成功。并在我们在测试过程中,考虑了**图文匹配则关键属性一定匹配**。

下期我们将进行赛道二的选手方案分享,敬请期待~

标签: #python读取lmdb