image text retrieval

前置知识

识别精度主要是由召回率(recall)和精度(precision)表示的。通过绘制precision-recall 曲线,该曲线下方的面积越大,识别精度也就越高,反之越低。

在说明 recall 和 precision 计算公式之前需要先介绍几个数据定义。

  • 在一个数据集检测中,会产生四类检测结果:
    TP、TN 、FP 、FN:

​ T ——true 表示正确

​ F——false 表示错误

​ P—— positive 表示积极的,看成正例

​ N——negative 表示消极的,看成负例

我的理解:后面为预测结果,前面是预测结果的正确性。如:

T P—— 预测为 P (正例), 预测对了, 本来是正样本,检测为正样本(真阳性)。
T N—— 预测为 N (负例), 预测对了, 本来是负样本,检测为负样本(真阴性)。
F P—— 预测为 P (正例), 预测错了, 本来是负样本,检测为正样本(假阳性)。
F N—— 预测为 N (负例), 预测错了, 本来是正样本,检测为负样本(假阴性)。

TP+FP+TN+FN:样本总数。
TP+FN:实际正样本数。
TP+FP:预测结果为正样本的总数,包括预测正确的和错误的。
FP+TN:实际负样本数。
TN+FN:预测结果为负样本的总数,包括预测正确的和错误的

四种情形组成的混淆矩阵如下:

预测情况
真实情况 正例 反例
正例 TP FN
反例 FP TN

召回率(Recall)

表示的是样本中的正例有多少被预测正确了(找得全)所有正例中被正确预测出来的比例。

用途:用于评估检测器对所有待检测目标的检测覆盖率。

针对数据集中的所有正例(TP+FN)而言,模型正确判断出的正例(TP)占数据集中所有正例的比例。FN表示被模型误认为是负例但实际是正例的数据,召回率也叫查全率,以物体检测为例,我们往往把图片中的物体作为正例,此时召回率高代表着模型可以找出图片中更多的物体
$$
Recall=\frac{TP}{TP+FN}
$$

精确率(Precision)

表示的是预测为正的样本中有多少是真正的正样本(找得对)。预测结果中真正的正例的比例。

用途:用于评估检测器在检测成功基础上的正确率

针对模型判断出的所有正例(TP+FP)而言,其中真正例(TP)占的比例。精确率也叫查准率,还是以物体检测为例,精确率高表示模型检测出的物体中大部分确实是物体,只有少量不是物体的对象被当成物体

$$
Precision=\frac{TP}{TP+FP}
$$

准确率(Accuracy)

模型判断正确的数据(TP+TN)占总数据的比例
$$
Acc=\frac{TP+TN}{TP+TN+FN+FP}
$$

image to text(目前这个任务的原理就是看前k个值里面有没有真值,只要有就ok,也就是说有5个真值那么只要前1含有其中的1个那么recall@1就是1)

recall@k是用在推荐和搜索中的,对推荐或者搜索中的结果进行排序,比如对每个query都有100个搜索结果,基于这么多结果才会有recall@k,表示top-k中有正确的结果就算该次搜索正确

  • 以flickr30k_test数据集为例返回结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import mindspore.dataset as ds
from mindspore import Parameter, Tensor
import numpy as np
import PIL
import mindspore as ms
import json
import random
import random
from PIL import Image


annotations_path = '/home/ma-user/work/datasets/flickr30k/annotations/flickr30k_test.json'


class MyData:
def __init__(self, annotations_path):#这里是MSCOCO的标注文件如果是别的应该要改方式,或者把别的文件改的和MSCOCO的标注文件格式一样,annotations_path直接指向json文件,images_path直接指向图片文件夹
# 指定JSON文件路径
self.data = json.load(open(annotations_path, 'r', encoding='utf-8'))

def get_data(self):
# 在这里实现获取单个样本的逻辑
# 示例:读取数据文件中的样本
images = []
captions = []
for i in self.data:
image_path = image_path = '/home/ma-user/work/datasets/flickr30k/images' + '/' + i['image']
image = Image.open(image_path)
image = image.resize((224,224), Image.Resampling.LANCZOS)
image = PIL.ImageOps.exif_transpose(image)
image = image.convert("RGB")
images.append(image)
captions.append(i['caption'][random.randint(0, 4)])
# caption = ms.Tensor(caption, ms.string)
# image = Tensor(np.array(image))
# 示例:对样本进行预处理操作
return images, captions
  • 计算得分矩阵
1
2
import mindspore.ops as ops
logits_per_image = ops.matmul(logit_scale * image_feature, text_feature.T)
  • 计算结果矩阵前k个数值最高的纵坐标
1
2
3
4
5
6
7
8
9
10
11
12
import mindspore as ms
import numpy as np


def rc(k,logits): # 要找到每行概率最高的前 k 个值
top_k_indices = []
for row in logits:
row_num = row.asnumpy()
# 使用 ms.argsort 找到每行概率最高的前 k 个值的索引
indices = np.argsort(row_num)[-k:]
top_k_indices.append(indices)
return top_k_indices
  • 计算recall:
1
2
3
4
5
6
my_list = [i for i in range(1000)]
n = 0
for i in range(1000):
if my_list[i] in test[i]:
n += 1
print(float(n/1000))

text to image

和上面结果完全一致除了得分矩阵需要做个转置

1
logits_per_text = logits_per_image.T