该文章记录本人第一次对VQA 2.0数据集进行研究的全过程。
该过程中,感谢 某博主 的指点,帮了我不少。非常感激!
VQA任务就是给定一张图片和一个问题,模型要根据给定的输入来进行回答。
很明显,VQA任务的输入有两个(image和question),对于如何提取image的feature,这里就不在赘述, 可以使用CNN提取特征的方式,CNN可以选择Resnet、VGG等骨干网络(去除pooling和fc层)。
对于如何提取question的特征,一般的做法是,由于question本身是文字,需要转换为对应的向量形式,因为模型是不认识文字的,所以要先将每个词转换为与之对应的向量,简单的做法是使用one-hot编码,当然这里你首先是需要建立一个词典(包含你任务中所有可能出现的单词)one-hot编码例如:
初始有一个词典:['a','is','he','boy','she','dog','school','man','woman','king','queen']
那出现的单词可以用one-hot编码来表示这个单词,如’he’->[0,0,1,0,0,0,0,0,0,0,0],很明显的缺点就是当dictionary很大时,one-hot编码会特别稀疏,
这时候一般使用其它的编码方式,比如说你可以使用预训练的glove向量
当我们将单词转换为对应的向量后,此时我们要整句话对应的向量送往RNN中来提取对应的文本特征,RNN我们一般是会选择LSTM或者GRU(需要讲解LSTM和GRU的我们可以下次再说)。
得到image和question的feature后,就可以通过模型去训练,训练的方式可以使用多标签分类的形式,所以它的损失也就是一个多标签损失,也就可以使用交叉熵损失。
以上内容来自 博主 的 博文 ,该博文也值得一看
下载数据的链接:https://visualqa.org/download.html
数据集主要是有三部分:
Training:4437570
Validation:2143540
以上数据的下载链接:https://visualqa.org/download.html
Training:443757
Validation:214354
Testing:447793
另外,为了方便大家训练整个trainval split并生成result.json文件,以上传到vqa2.0在线评估服务器
前辈 合并了用于 train and validation splits的question和annotation json文件,
下载链接如下:
trainval_annotation.json
trainval_question.json
Training:82783
Validation:40504
Testing:81434
也就是说,每张图片会有5个左右的问题,每个问题会有10个左右的回答。
对于数据集的分析,看参考该博文
wget -P data http://nlp.stanford.edu/data/glove.6B.zip
unzip data/glove.6B.zip -d data/glove
rm data/glove.6B.zip
得到4种维度的词向量(例如50d文件,就是每个单词对应的50维度的向量)
后续可以根据自己的需求进行选择使用。
作用:对于先将自己任务中所有可能出现的单词,通过词向量转换为对应的向量,方便之后送往RNN中提取文本特征,因为你不可能直接将单词送往RNN中,注:可以自己训练出词向量,如果不使用别人预训练好的词向量的话。
# Questions
wget -P data https://s3.amazonaws.com/cvmlp/vqa/mscoco/vqa/v2_Questions_Train_mscoco.zip
unzip data/v2_Questions_Train_mscoco.zip -d data
rm data/v2_Questions_Train_mscoco.zip
wget -P data https://s3.amazonaws.com/cvmlp/vqa/mscoco/vqa/v2_Questions_Val_mscoco.zip
unzip data/v2_Questions_Val_mscoco.zip -d data
rm data/v2_Questions_Val_mscoco.zip
wget -P data https://s3.amazonaws.com/cvmlp/vqa/mscoco/vqa/v2_Questions_Test_mscoco.zip
unzip data/v2_Questions_Test_mscoco.zip -d data
rm data/v2_Questions_Test_mscoco.zip
# Annotations
wget -P data https://s3.amazonaws.com/cvmlp/vqa/mscoco/vqa/v2_Annotations_Train_mscoco.zip
unzip data/v2_Annotations_Train_mscoco.zip -d data
rm data/v2_Annotations_Train_mscoco.zip
wget -P data https://s3.amazonaws.com/cvmlp/vqa/mscoco/vqa/v2_Annotations_Val_mscoco.zip
unzip data/v2_Annotations_Val_mscoco.zip -d data
rm data/v2_Annotations_Val_mscoco.zip
得到6个json文件
如果想了解json文件中数据结构格式,可查看 该博文
参考链接: https://github.com/peteanderson80/bottom-up-attention#training
# Image Features # resnet101_faster_rcnn_genome
wget -P data https://imagecaption.blob.core.windows.net/imagecaption/trainval.zip
wget -P data https://imagecaption.blob.core.windows.net/imagecaption/test2014.zip
wget -P data https://imagecaption.blob.core.windows.net/imagecaption/test2015.zip
unzip data/trainval.zip -d data
unzip data/test2014.zip -d data
unzip data/test2015.zip -d data
rm data/trainval.zip
rm data/test2014.zip
rm data/test2015.zip
这里直接使用的是预训练的feature,就不再需要自己将image送往CNN中来提取特征,预训练是使用Resnet101为骨干网络,使用faster-RCNN的方式在genome上进行预训练提取的特征。
得到的文件:
所使用的代码在tool文件夹中
首先要建立一个字典,字典包含所有出现的单词,并将其转换为对应的glove词向量,通过加载question文件,取出所关注的“question”部分,再取出“question(str)”(这里有点绕,仔细看question的数据结构就可以理解,就是一层一层的去取我们所需要的部分),就获得了所有的问题,有了所有的问题,就可以取出其中的单词,然后将大写转小写等等操作,再去掉重复的单词,就得到了该任务所有可能出现的单词。
dataroot = '../data' if args.task == 'vqa' else 'data/flickr30k'
dictionary_path = os.path.join(dataroot, 'dictionary.pkl')
d = create_dictionary(dataroot, args.task) # data,vqa
#
d.dump_to_file(dictionary_path) # 字典,包含所有单词
d = Dictionary.load_from_file(dictionary_path)
这样会创建一个词典,同时可以通过词典来进行查找“单词到索引(word2idx)”和“索引到单词(idx2word)”:
print(d.idx2word) # 所有单词 ['what', 'is', 'this',..., 'pegasus', 'bebe']
print(len(d.idx2word)) # 共有19901个单词
print(d.word2idx) # {'what': 0, 'is': 1, 'this': 2,...,'pegasus': 19899, 'bebe': 19900}
光得到词典还不行,我们最终需要丢进模型中训练的一定是tensor或者说是向量形式的,文字肯定是不行的,所以需要转换为对应的词向量,其实就是为了进行word embedding做准备:
# 使用glove
glove_file = '../data/glove/glove.6B.%dd.txt' % emb_dim # 加载预训练好的data/glove/glove.6B.300d.txt
weights, word2emb = create_glove_embedding_init(d.idx2word, glove_file)
np.save(os.path.join(dataroot, 'glove6b_init_%dd.npy' % emb_dim), weights)
weights就是我们最后得到的预训练好的词典向量,我们有19901个单词,每个单词转换为300维的向量,所以weights.shape为[19901,300]:
等待更新...
等待更新...
本人初学VQA,有任何说错的地方,敬请各位伙伴指出和说明
1. dataset的下载和路径处理
将数据集放在/data/路径下
或者更改config.py中dataset的path
并且更改config.py中output_size=36
2. 数据的预处理
preprocess_features.py
preprocess_vocab.py
3. train
命令行:python train.py --trainval
4. test
命令行:python train.py --test --resume=./logs/model.pth