VQA官网上提供了数据集文件:VQA_v2数据集
大致理解一下就是:
根据官网的解释可知,question被保存为JSON文件的格式,其具有数据结构如下:
{
"info" : info,
"task_type" : str,
"data_type": str,
"data_subtype": str,
"questions" : [question],
"license" : license
}
--------------------------取出所关注的question部分
question{
"question_id" : int,
"image_id" : int,
"question" : str
}
从它的关键部分可以看出,
在这里可以解释的一下就是,一张图片是包含多个问题的,一个问题也可能出现在多张图片当中,在数据集当中对于id混乱这一点来说是不会出现的。因为“image_id”是固定的,同一个问题出现在不同的图像当中会有不同的“question_id”。
根据官网的解释可知,Annotation也被保存为JSON文件的格式,其具有数据结如下:
{
"info" : info,
"data_type": str,
"data_subtype": str,
"annotations" : [annotation],
"license" : license
}
------------------------取出所关注的annotation部分
annotation{
"question_id" : int,
"image_id" : int,
"question_type" : str,
"answer_type" : str,
"answers" : [answer],
"multiple_choice_answer" : str
}
----------------------具体的answer部分
answer{
"answer_id" : int,
"answer" : str,
"answer_confidence": str
}
可以细看一下其中的几个参数:
“question_type”:这是由问题的前几个词所决定的问题类型
“answe_type”:这是答案的类型,包含’yes/no’、'number’和’other’三种
“multiple_choice_answer”:最常见的ground-truth
“question_id”:可以理解为答案的置信度
至此,官方提供的数据文件就介绍结束了
代码参考链接
目的是获取一个由所有question的word构成的一个list,有了这个list之后,就可以使用例如Glove来进行word embedding。
当然,如果是使用Bert的话可以忽略2.1.1.2,因为Bert的输入是原始的句子,而不是embedding后的向量。
self.stat_ques_list = \
json.load(open(__C.QUESTION_PATH['train'], 'r'))['questions'] + \
json.load(open(__C.QUESTION_PATH['val'], 'r'))['questions'] + \
json.load(open(__C.QUESTION_PATH['test'], 'r'))['questions']
结合1.2可以看出,这里取出的是所有的question的information,每一个information包含了question_id、iamge_id和question。
具体实现如下:
self.token_to_ix, self.pretrained_emb = tokenize(self.stat_ques_list, __C.USE_GLOVE)
------------------------------------------
def tokenize(stat_ques_list, use_glove):
token_to_ix = {
'PAD': 0,
'UNK': 1,
}
spacy_tool = None
pretrained_emb = []
if use_glove:
spacy_tool = en_vectors_web_lg.load()
pretrained_emb.append(spacy_tool('PAD').vector)
pretrained_emb.append(spacy_tool('UNK').vector)
for ques in stat_ques_list:
words = re.sub(
r"([.,'!?\"()*#:;])",
'',
ques['question'].lower()
).replace('-', ' ').replace('/', ' ').split()
for word in words:
if word not in token_to_ix:
token_to_ix[word] = len(token_to_ix)
if use_glove:
pretrained_emb.append(spacy_tool(word).vector)
pretrained_emb = np.array(pretrained_emb)
return token_to_ix, pretrained_emb
代码还是比较容易理解的,tokenize()
输入的是前一步得到的所有question information(并且默认是使用Glove的)。由于所需要的只是具体的question,所以要将其取出并且大写转小写,再去除标点符号和特殊字符,获取所有的单个word,利用这些word来构建一个token_to_ix{}
的字典和一个对应的pretrained_emb[]
的list。
token_to_ix{}
的含义是通过token可以找到其对应的索引pretrained_emb[]
的含义是根据索引可以获取对应token的embedding结果(Glove是300维的)token_to_ix{}
的大小是可以得到Question token vocabulary size的self.qid_to_ques = {} # -----问题信息(['image_id','question','question_id'])
for ques in self.stat_ques_list:
qid = str(ques['question_id'])
self.qid_to_ques[qid] = ques
通过获取question information中的question_id,构建了一个qid_to_ques{}
的字典,他的作用就是通过question_id来找到对应的question information。
至此,处理Question的所有步骤就结束了!!!
self.ans_list = \
json.load(open(__C.ANSWER_PATH['train'], 'r'))['annotations'] + \
json.load(open(__C.ANSWER_PATH['val'], 'r'))['annotations']
结合1.3可以看出,这里取出的是annotation的information,每一个information包含了question_id、iamge_id、question_type、answer_type、answers和multiple_choice_answer。
注意:这的answers是一个list,还包含着10个具体answer的信息,并且是没有test的annotation
self.ans_to_ix, self.ix_to_ans = json.load(open('answer_dict.json', 'r'))
获取到通过answer_ix(索引)找到answer和通过answer找到answer_ix(索引)的两个字典。因为候选答案一共是3129和,所以answer_ix是从 0 ~ 3128 的。
至于这个answer_dict.json文件应该是别人生成好的,目的是可以在每次训练的过程中都为answer选择固定的索引,而不是每次都随机创建,其部分内容如下:
[{"net": 0, "pitcher": 1, "orange": 2, "yes": 3, "white": 4, "skiing": 5, "red": 6, "frisbee": 7, "brushing teeth": 8, "no": 9, "black and white": 10, "skateboard": 11, "1": 12, "blue": 13, "green": 14, "motorcycle": 15, "gray": 16, "2": 17, "purse": 18, "skis": 19, "poles": 20, "surfboard": 21,....., "100 year party ct": 3120, "hispanic": 3121, "in cabbage town": 3122, "opponent": 3123, "woodpecker": 3124, "visilab": 3125, "mt airy": 3126, "crosstown": 3127, "freightliner": 3128}, {"0": "net", "1": "pitcher", "2": "orange", "3": "yes", "4": "white", "5": "skiing", "6": "red", "7": "frisbee", "8": "brushing teeth", "9": "no", "10": "black and white", "11": "skateboard", "12": "1", "13": "blue", "14": "green", "15": "motorcycle", "16": "gray", "17": "2", "18": "purse", "19": "skis", "20": "poles", "21": "surfboard", "22": "dog", "23": "on", "24": "office", "25": "large", "26": "very big", "27": "laptop", "28": "vent",..., "3115": "beads", "3116": "cosmo", "3117": "10:08", "3118": "jal", "3119": "6:30", "3120": "100 year party ct", "3121": "hispanic", "3122": "in cabbage town", "3123": "opponent", "3124": "woodpecker", "3125": "visilab", "3126": "mt airy", "3127": "crosstown", "3128": "freightliner"}]
至此,处理Answer的步骤暂时结束,后续还会有相应的处理。
以常使用bottom up所提取的image feature来举例,这是一种region feature,包含有object feature和对应的bounding box。对于feature file来说一般是有两种格式:
接下来将对分别对如何读取这两种格式feature file进行介绍。