Bootstrap

cleanfid库的fid使用,及其使用CLIP模型clip_vit_b_32计算FID

cleanfid库的fid使用,及其使用CLIP模型clip_vit_b_32计算FID

本博客简介

这篇博客详细介绍了如何使用 cleanfid 库计算 Fréchet Inception Distance (FID),特别是利用 CLIP 模型 clip_vit_b_32 计算 FID 分数来评估生成图像的质量。内容涵盖了 FID 的概念和原理、cleanfid 库的安装与配置、从缓存中加载与手动加载模型的方法,以及解决可能遇到的依赖问题。通过这篇教程,可以掌握使用 cleanfid 库计算fid的完整流程,并能够解决服务器环境中遇到的联网与模型下载问题。

1. FID简介

FID(Fréchet Inception Distance)是一种用于衡量生成图像质量的评估指标,特别常用于生成对抗网络(GAN)和其他生成模型的效果评估。FID 通过量化生成图像和真实图像之间的差异来衡量生成图像的“真实感”。
在这里插入图片描述
图来自:https://github.com/GaParmar/clean-fid?tab=readme-ov-file

原理概述

FID 的计算方法主要包括以下步骤:

  1. 特征提取:首先,将真实图像和生成图像通过一个预训练的图像识别网络(如 Inception V3)提取特征,这些特征通常是图像中间层的激活值。这些激活值可以被看作是图像的特征向量。

  2. 高斯分布假设:对于真实图像和生成图像的特征向量集合,分别计算它们的均值和协方差矩阵,假设它们符合多维高斯分布。

  3. Fréchet 距离计算:将两个高斯分布之间的距离(即 Fréchet 距离)作为真实图像分布和生成图像分布之间的差异度量。Fréchet 距离计算公式如下:

    FID = ∣ ∣ μ 1 − μ 2 ∣ ∣ 2 + Tr ( Σ 1 + Σ 2 − 2 ( Σ 1 Σ 2 ) 1 / 2 ) \text{FID} = ||\mu_1 - \mu_2||^2 + \text{Tr}(\Sigma_1 + \Sigma_2 - 2(\Sigma_1 \Sigma_2)^{1/2}) FID=∣∣μ1μ22+Tr(Σ1+Σ22(Σ1Σ2)1/2)
    其中:

    • μ 1 \mu_1 μ1 μ 2 \mu_2 μ2分别是生成图像和真实图像特征分布的均值向量。
    • Σ 1 \Sigma_1 Σ1 Σ 2 \Sigma_2 Σ2 分别是生成图像和真实图像特征分布的协方差矩阵。
    • Tr \text{Tr} Tr 表示矩阵的迹(即对角线元素之和)。
  4. 结果解读:FID 的数值越小,表示生成图像和真实图像的分布越接近,生成图像的质量越好;相反,较高的 FID 值表明生成图像的质量较差。

为什么使用 FID?

相比于传统的图像评估指标(如均方误差、峰值信噪比),FID 更加关注图像的语义特征和视觉一致性,能够有效地捕捉生成图像与真实图像在内容、风格上的差异。因此,FID 已成为评估图像生成模型的重要工具。

使用场景

  • GAN 模型评估:在 GAN 训练中,通常使用 FID 来跟踪生成图像的质量。
  • 图像生成任务:例如图像修复、图像超分辨率、风格迁移等任务的生成效果评估。
  • 对比不同模型:通过 FID 分数比较不同生成模型的效果,帮助选择生成质量更好的模型。

总的来说,FID 是一种基于 Fréchet 距离的图像质量评估指标,通过特征分布的差异来衡量生成图像的“真实性”。较小的 FID 值代表生成图像与真实图像分布更接近,质量更好,因此常用于生成模型的评估。

2. 安装

虽说导入fid的代码如下:

from cleanfid import fid

但是安装该包的命令不是pip install cleanfid,我首次使用fid时候直接就使用该方式安装包,发现镜像里面没有该包,我才发现不能这么安装。正确的命令如下:

pip install clean-fid

3. 普通方法计算FID

3.1 从缓存中加载模型(默认方式)

  • 计算两个图片文件中的FID使用如下命令

    from cleanfid import fid
    score = fid.compute_fid(dir1, dir2)
    

    运行该命令首先会检查电脑缓存中是否有inception-2015-12-05.pt权重模型,如果没有,会首先下载这个文件。该方法默认是用inception_v3来计算的。

这个权重文件会下载到/tmp/目录中,下载链接如下:

inception-2015-12-05.pt链接

我在本机WSL系统中可以自动下载并运行。

但是如果你用的服务器,且不是管理员账户,同时服务器不能联网,这样不能自动下载模型。我还试了把模型移动到/tmp/文件夹下,发现依然会报如下错误:

    raise URLError(err)
urllib.error.URLError: <urlopen error [Errno -2] Name or service not known>

不知道是为为啥原因。。。

如果你在本地使用,源代码模型会自动下载到/tmp/中的。如果WSL没法联网,你手动下载之后移动到该路径下,然后运行代码大概率也没问题的。

3.2 手动加载模型

假如不能默认加载模型,那就只能手动加载模型了,代码如下:

import torch
from cleanfid import fid
from cleanfid.inception_torchscript import InceptionV3W

dir1 = "datasets/blur"
dir2 = "datasets/sharp"

class CustomInceptionExtractor(torch.nn.Module):
    def __init__(self, device='cuda'):
        super().__init__()
        path = "metrics/pre_trained"  ### 写绝对路径
        self.model = InceptionV3W(path, download=False).to(device)

    def forward(self, x):
        return self.model(x)

custom_extractor = CustomInceptionExtractor(device='cuda')

score = fid.compute_fid(
    dir1,
    dir2,
    custom_feat_extractor=custom_extractor
)

# 打印 FID 分数
print("FID score:", score)

这样即使联网有问题,也可以从本地加载模型进行测试,输出大概如下所示:

compute FID between two folders
Found 2 images in the folder datasets/blur
FID blur : 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:03<00:00,  3.02s/it]
Found 2 images in the folder datasets/sharp
FID sharp : 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:03<00:00,  3.00s/it]
FID score: 136.3556460685012
  • 计算图像文件夹和预先计算的数据集统计之间的FID(例如:FFHQ)

    from cleanfid import fid
    score = fid_compute_fid(dir1, dataset_name="FFHQ", dataset_res=1024, dataset_split="trainval170k")
    
  • 使用生成模型和预先计算的数据集统计信息计算FID

    from cleanfid import fid
    # function that accepts a latent and returns an image in range[0,255]
    gen = lambda z: GAN(latent=z, ... , <other_flags>)
    score = fid.compute_fid(gen=gen, dataset_name="FFHQ",
            dataset_res=256, num_gen=50_000, dataset_split="trainval70k")
    

4.使用clip计算FID

4.1 代码示例

代码如下:

from cleanfid import fid

score = fid.compute_fid(dir1, dir2, mode="clean", model_name="clip_vit_b_32")

print("FID score:", score)

如果一切没有问题,输出如下:

compute FID between two folders
Found 2 images in the folder datasets/blur
FID blur : 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:04<00:00,  4.37s/it]
Found 2 images in the folder datasets/sharp
FID sharp : 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00,  1.10it/s]
FID score: 23.74481030293663

4.2 各种问题解决方法

1. 缺少clip库

如果直接运行,大概率会缺少clip库,通过如下命令安装:

pip install git+https://github.com/openai/CLIP.git

如果链接不到github,记得使用清华镜像,设置全局pip安装镜像如下:

pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple

设置镜像之后再次安装。如果清华镜像不能使用,就使用阿里云镜像,中科大镜像,哪个能用哪个吧。

2. 缺少ViT-B-32.pt模型文件

之后运行代码,如果出现大概如下错误:

Traceback (most recent call last):
  File "/store_statistics.py", line 27, in <module>
    fid.make_custom_stats(custom_name, dataset_path, mode="clean", model_name="clip_vit_b_32")
  File "lib/python3.9/site-packages/cleanfid/fid.py", line 355, in make_custom_stats
    clip_fx = CLIP_fx("ViT-B/32")
  File "/lib/python3.9/site-packages/cleanfid/clip_features.py", line 22, in __init__
    self.model, _ = clip.load(name, device=device)
  File "/lib/python3.9/site-packages/clip/clip.py", line 120, in load
    model_path = _download(_MODELS[name], download_root or os.path.expanduser("~/.cache/clip"))
  File "/lib/python3.9/site-packages/clip/clip.py", line 59, in _download
    with urllib.request.urlopen(url) as source, open(download_target, "wb") as output:
  File "/lib/python3.9/urllib/request.py", line 214, in urlopen
    return opener.open(url, data, timeout)
  File "/lib/python3.9/urllib/request.py", line 517, in open
    response = self._open(req, data)
  File "/lib/python3.9/urllib/request.py", line 534, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "lib/python3.9/urllib/request.py", line 494, in _call_chain
    result = func(*args)
  File "/lib/python3.9/urllib/request.py", line 1389, in https_open
    return self.do_open(http.client.HTTPSConnection, req,
  File "/lib/python3.9/urllib/request.py", line 1349, in do_open
raise URLError(err)
urllib.error.URLError: <urlopen error [Errno -2] Name or service not known>

大概率是没有下载ViT-B-32.pt,如果你没有vit模型,那就通过如下代码下载

from huggingface_hub import hf_hub_download
import os

####################使用clip_vit_b_32需要下载的权重文件########################
###设置目标路径
save_dir = os.path.expanduser("~/.cache/clip")
os.makedirs(save_dir, exist_ok=True)

#### 下载模型文件并保存到指定目录
model_path = hf_hub_download(repo_id="jinaai/clip-models", filename="ViT-B-32.pt", local_dir=save_dir)

print(f"Model downloaded and saved to: {model_path}")

大概率huggingface也连接不上,依然使用镜像,在命令行中运行:

export HF_ENDPOINT="https://hf-mirror.com"

设置huggingface镜像之后,再次通过上述代码下载vit模型。

至此,所有准备工作完成,运行命令就可大功告成,输出依旧如下:

compute FID between two folders
Found 2 images in the folder datasets/blur
FID blur : 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:04<00:00,  4.37s/it]
Found 2 images in the folder datasets/sharp
FID sharp : 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00,  1.10it/s]
FID score: 23.74481030293663

参考链接

https://github.com/GaParmar/clean-fid

;