一些loss和指标记录_python实现

1 L1_loss

  • 定义:计算对应位置的绝对值,求平均。又称绝对值损失函数
  • 公式:
    a = [ x 1 , x 2 , x 3 . . . x n ] 、 b = [ y 1 , y 2 , y 3 . . . y n ] a=[x_1,x_2,x_3...x_n]、b=[y_1,y_2,y_3...y_n] a=[x1,x2,x3...xn]b=[y1,y2,y3...yn]
    L 1 ( a , b ) = 1 n ∑ i = 1 n ∣ x i − y i ∣ L1(a,b)=\frac{1}{n}\sum_{i=1}^n|x_i-y_i| L1(a,b)=n1i=1nxiyi
  • 代码实现:
import torch.nn as nn
import torch.nn as nn
import torch

#loss function
loss = nn.L1Loss()

a=torch.FloatTensor([1,2,3])
b=torch.FloatTensor([1.1,2.2,2.9]) 
output = loss(a, b)
print(output)

c=torch.FloatTensor([[1,3],[2,3],[1,1]])
print(f"c_shape:{c.shape}")
d=torch.FloatTensor([[2,3.2],[2.1,3.2],[1.1,1.1]])
print(f"c_shape:{d.shape}")
out=loss(c,d)#除以6,不是除以3!
print(out)

2 Lpips_loss

感知损失,符合人眼的损失
输入网络提取特征,计算L2距离,算平均。

class LpipsLoss(nn.Module):

    def __init__(self):
        super(LpipsLoss, self).__init__()
        self.lpips_fn = lpips.LPIPS(net='vgg')#加载预训练的模型
        self.lpips_fn.net.requires_grad_(False)


    def forward(self, gt, output):
        output = output*2.-1
        gt = gt*2.
        lpips_loss = torch.mean(self.lpips_fn(output, gt))
        return lpips_loss

3 PSNR

全称:peak signal-to-Noise Ratio 峰值信噪比

定义:
给定大小为 n ∗ m n*m nm的标签图片 I I I和模型输出图片 K K K

  1. 计算均方误差 M S E = 1 m ∗ n ∑ i = 0 n − 1 ∑ j = 0 m − 1 [ I ( i , j ) − K ( i , j ) ] 2 MSE=\frac{1}{m*n}\sum_{i=0}^{n-1}\sum_{j=0}^{m-1}[I(i,j)-K(i,j)]^2 MSE=mn1i=0n1j=0m1[I(i,j)K(i,j)]2
  2. P S N R = 10 ∗ l o g 10 M A X 2 M S E PSNR=10*log_{10}^{\frac{MAX^2}{MSE}} PSNR=10log10MSEMAX2 M A X MAX MAX是指图片的最可能的最大像素值(比如范围是0~255,那 M A X = 255 MAX=255 MAX=255

rgb情况下计算PSNR的代码:

import lpips
def calculate_psnr(img1, img2, normalized=False):
    if not normalized:
        img1 = img1.astype(np.float32)/255.
        img2 = img2.astype(np.float32)/255.
    MSE = np.mean((img1-img2)**2)
    
    #psnr= 10 * log10 (1^2 / MSE)
    if MSE == 0:
        psnr = 100
    else:
        psnr = -10*math.log10(MSE)
    return psnr

4 SSIM

全称:Structural Similarity 结构相似性

5 GAN_loss

5.1 softplus函数

  • 公式: s o f t p l u s ( x ) = l o g ( 1 + e x ) softplus(x)=log^{(1+e^x)} softplus(x)=log(1+ex)
  • 分析:
    1. 当输入 x = 0 x=0 x=0时,函数输出为 l o g 2 log^2 log2
    2. 当输入 x x x 无限趋近于负无穷时,函数输出无限接近于0
    3. 当输入 x x x 无限趋近于正无穷时,函数输出无限接近于正无穷

5.2 生成器的Loss

  • 分析:生成器希望自己生成的“假”图片,能被判别器识别为真。即我们判别器模型的输入是fake_img,希望判别器输出为正数。
  • 思路:判别器结果越趋近于正数,计算获得的Loss就应该越小。将输出转负后输入softplus函数,获得小loss
#G_loss
def cal_adv_loss(fake_g_pred):
    adv_loss = F.softplus(-fake_g_pred).mean()
    return adv_loss

5.3 判别器的loss

注意,计算判别器的loss,由有部分组成。两个输入,real_img和fake_img。

  • 分析:我们希望判别器能识别出real_img为真,输出正数,fake_img为假,为负数。
  • 思路:
    • real_img_pred越靠近正数,越符合期望,那我们的loss就应该越小;
    • 同理fake_img_pred越靠近负数,越符合期望,我们的loss就应该越小。
    • 而soft_plus是输入越靠近负无穷,loss越小,因此代码中,real_img_pred应该加负号
#D_loss
def cal_adv_d_loss(fake_d_pred, real_d_pred):
    real_loss = F.softplus(-real_d_pred).mean()
    fake_loss = F.softplus(fake_d_pred).mean()
    D_loss = real_loss + fake_loss
    return D_loss

6 FID指标

FID指标:用于衡量生成图像的多样性和质量,FID越小,则图像多样性越好,质量越好。
操作:

  1. 用inception network网络对两个数据集的图片都进行特征提取(最后一层输出图像的类别被去除),因此一张图片就会得到一个2048维度的特征。
  2. 所有真实图片的提取的向量是服从一个分布的;对于用GAN生成的图片对应的高位向量特征也是服从一个分布的。如果两个分布相同,那么意味着GAN生成图片的真实程度很高。那怎么去衡量分布呢?——计算两个多维变量分布之间的距离。
    • 公式为: F I D ( x , g ) = ∣ ∣ u x − u g ∣ ∣ 2 2 + T r ( ∑ x + ∑ g − 2 ( ∑ x ∑ g ) 0.5 ) FID(x,g)=||u_x-u_g||^2_2+Tr(\sum_x+\sum_g-2(\sum_x\sum_g)^{0.5}) FID(x,g)=∣∣uxug22+Tr(x+g2(xg)0.5)
    • T r Tr Tr是指矩阵中的迹,也就是对角线上元素之和
    • x 、 g x、g xg表示真实图片、生成图片
    • u 、 s i g m a u、sigma usigma表示均值、协方差

代码:

import torch
import os
import pathlib
from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser

import numpy as np
import torch
import torchvision.transforms as TF
from PIL import Image
from scipy import linalg
from torch.nn.functional import adaptive_avg_pool2d

try:
    from tqdm import tqdm
except ImportError:
    # If tqdm is not available, provide a mock version of it
    def tqdm(x):
        return x

from pytorch_fid.inception import InceptionV3

parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
parser.add_argument('--batch-size', type=int, 
                    default=50,
                    help='Batch size to use')
parser.add_argument('--num-workers', type=int, 
                    default=8,
                    help=('Number of processes to use for data loading. '
                          'Defaults to `min(8, num_cpus)`'))
parser.add_argument('--device', type=str, 
                    default="cuda:6",
                    help='Device to use. Like cuda, cuda:0 or cpu')

parser.add_argument('--dims', type=int, 
                    default=2048,
                    choices=list(InceptionV3.BLOCK_INDEX_BY_DIM),
                    help=('Dimensionality of Inception features to use. '
                          'By default, uses pool3 features'))
parser.add_argument('--save-stats', action='store_true',
                    help=('Generate an npz archive from a directory of samples. '
                          'The first path is used as input and the second as output.'))
#path dataset of the fake imgs from GAN and target 
parser.add_argument('path', type=str, nargs='*', 
                    default=[
                    '/mnt/Datasets/CelebAMask-HQ/CelebAMask-HQ', #gt dataset
                    '/home/my_GAN_dataset/'],
                    help=('Paths to the generated images or to .npz statistic files'))

IMAGE_EXTENSIONS = {'bmp', 'jpg', 'jpeg', 'pgm', 'png', 'ppm',
                    'tif', 'tiff', 'webp'}



class ImagePathDataset(torch.utils.data.Dataset):
    def __init__(self, files, transforms=None):
        self.files = files
        self.transforms = transforms

    def __len__(self):
        return len(self.files)

    def __getitem__(self, i):
        path = self.files[i]
        img = Image.open(path).convert('RGB')
        if self.transforms is not None:
            img = self.transforms(img)
        return img


def get_activations(files, model, batch_size=50, dims=2048, device='cpu',
                    num_workers=1):
    """Calculates the activations of the pool_3 layer for all images.

    Params:
    -- files       : List of image files paths
    -- model       : Instance of inception model
    -- batch_size  : Batch size of images for the model to process at once.
                     Make sure that the number of samples is a multiple of
                     the batch size, otherwise some samples are ignored. This
                     behavior is retained to match the original FID score
                     implementation.
    -- dims        : Dimensionality of features returned by Inception
    -- device      : Device to run calculations
    -- num_workers : Number of parallel dataloader workers

    Returns:
    -- A numpy array of dimension (num images, dims) that contains the
       activations of the given tensor when feeding inception with the
       query tensor.
    """
    model.eval()

    if batch_size > len(files):
        print(('Warning: batch size is bigger than the data size. '
               'Setting batch size to data size'))
        batch_size = len(files)

    dataset = ImagePathDataset(files, transforms=TF.ToTensor())
    dataloader = torch.utils.data.DataLoader(dataset,
                                             batch_size=batch_size,
                                             shuffle=False,
                                             drop_last=False,
                                             num_workers=num_workers)

    pred_arr = np.empty((len(files), dims))

    start_idx = 0

    #把数据集中图片的特征都放入pred_arr
    for batch in tqdm(dataloader):
        batch = batch.to(device)

        with torch.no_grad():
            pred = model(batch)[0]

        # If model output is not scalar, apply global spatial average pooling.
        # This happens if you choose a dimensionality not equal 2048.
        if pred.size(2) != 1 or pred.size(3) != 1:
            pred = adaptive_avg_pool2d(pred, output_size=(1, 1))

        pred = pred.squeeze(3).squeeze(2).cpu().numpy()

        pred_arr[start_idx:start_idx + pred.shape[0]] = pred

        start_idx = start_idx + pred.shape[0]

    return pred_arr


def calculate_frechet_distance(mu1, sigma1, mu2, sigma2, eps=1e-6):
    """Numpy implementation of the Frechet Distance.
    The Frechet distance between two multivariate Gaussians X_1 ~ N(mu_1, C_1)
    and X_2 ~ N(mu_2, C_2) is
            d^2 = ||mu_1 - mu_2||^2 + Tr(C_1 + C_2 - 2*sqrt(C_1*C_2)).

    Stable version by Dougal J. Sutherland.

    Params:
    -- mu1   : Numpy array containing the activations of a layer of the
               inception net (like returned by the function 'get_predictions')
               for generated samples.
    -- mu2   : The sample mean over activations, precalculated on an
               representative data set.
    -- sigma1: The covariance matrix over activations for generated samples.
    -- sigma2: The covariance matrix over activations, precalculated on an
               representative data set.

    Returns:
    --   : The Frechet Distance.
    """
    #转换为numpy
    mu1 = np.atleast_1d(mu1)
    mu2 = np.atleast_1d(mu2)
    
    #转换为至少两维
    sigma1 = np.atleast_2d(sigma1)
    sigma2 = np.atleast_2d(sigma2)

    assert mu1.shape == mu2.shape, \
        'Training and test mean vectors have different lengths'
    assert sigma1.shape == sigma2.shape, \
        'Training and test covariances have different dimensions'

    diff = mu1 - mu2

    # Product might be almost singular
    covmean, _ = linalg.sqrtm(sigma1.dot(sigma2), disp=False)#整体开平方 
    
    #数据是否都是有限的
    if not np.isfinite(covmean).all():
        msg = ('fid calculation produces singular product; '
               'adding %s to diagonal of cov estimates') % eps
        print(msg)
        offset = np.eye(sigma1.shape[0]) * eps#生成对角矩阵
        covmean = linalg.sqrtm((sigma1 + offset).dot(sigma2 + offset))

    # Numerical error might give slight imaginary component
    if np.iscomplexobj(covmean):#判断是否为复数
        #获得矩阵对角线上的虚数部分,判断是否接近0,允许误差1e-3,如果误差过大,报错
        if not np.allclose(np.diagonal(covmean).imag, 0, atol=1e-3):
            m = np.max(np.abs(covmean.imag))
            raise ValueError('Imaginary component {}'.format(m))
        covmean = covmean.real#取实数部分

    tr_covmean = np.trace(covmean)#算矩阵的迹

    return (diff.dot(diff) + np.trace(sigma1)
            + np.trace(sigma2) - 2 * tr_covmean)


def calculate_activation_statistics(files, model, batch_size=50, dims=2048,
                                    device='cpu', num_workers=1):
    """Calculation of the statistics used by the FID.
    Params:
    -- files       : List of image files paths
    -- model       : Instance of inception model
    -- batch_size  : The images numpy array is split into batches with
                     batch size batch_size. A reasonable batch size
                     depends on the hardware.
    -- dims        : Dimensionality of features returned by Inception
    -- device      : Device to run calculations
    -- num_workers : Number of parallel dataloader workers

    Returns:
    -- mu    : The mean over samples of the activations of the pool_3 layer of
               the inception model.
    -- sigma : The covariance matrix of the activations of the pool_3 layer of
               the inception model.
    """
    act = get_activations(files, model, batch_size, dims, device, num_workers)
    mu = np.mean(act, axis=0)
    sigma = np.cov(act, rowvar=False)
    return mu, sigma


def compute_statistics_of_path(path, model, batch_size, dims, device,
                               num_workers=1):
    #如果以.npz结尾
    if path.endswith('.npz'):
        with np.load(path) as f:
            m, s = f['mu'][:], f['sigma'][:]
    else:
        path = pathlib.Path(path)
        files = sorted([file #有序
                        for ext in IMAGE_EXTENSIONS#make sure what we get is img
                       for file in path.glob('*.{}'.format(ext))])
        m, s = calculate_activation_statistics(files, model, batch_size,
                                               dims, device, num_workers)

    return m, s


def calculate_fid_given_paths(paths, batch_size, device, dims, num_workers=1):
    """Calculates the FID of two paths"""
    #chech path
    for p in paths:
        if not os.path.exists(p):
            raise RuntimeError('Invalid path: %s' % p)

    block_idx = InceptionV3.BLOCK_INDEX_BY_DIM[dims]

    model = InceptionV3([block_idx]).to(device)

    #get the mean and conv of the dateset
    m1, s1 = compute_statistics_of_path(paths[0], model, batch_size,
                                        dims, device, num_workers)
    m2, s2 = compute_statistics_of_path(paths[1], model, batch_size,
                                        dims, device, num_workers)
    #compute
    fid_value = calculate_frechet_distance(m1, s1, m2, s2)

    return fid_value


def save_fid_stats(paths, batch_size, device, dims, num_workers=1):
    """Calculates the FID of two paths"""
    if not os.path.exists(paths[0]):
        raise RuntimeError('Invalid path: %s' % paths[0])

    if os.path.exists(paths[1]):
        raise RuntimeError('Existing output file: %s' % paths[1])

    block_idx = InceptionV3.BLOCK_INDEX_BY_DIM[dims]

    model = InceptionV3([block_idx]).to(device)

    print(f"Saving statistics for {paths[0]}")

    m1, s1 = compute_statistics_of_path(paths[0], model, batch_size,
                                        dims, device, num_workers)

    np.savez_compressed(paths[1], mu=m1, sigma=s1)


def main():
    args = parser.parse_args()
    print(args.path)

    if args.device is None:
        device = torch.device('cuda' if (torch.cuda.is_available()) else 'cpu')
    else:
        device = torch.device(args.device)

    if args.num_workers is None:
        try:
            num_cpus = len(os.sched_getaffinity(0))#get the number of CPUs
        except AttributeError:
            # os.sched_getaffinity is not available under Windows, use
            # os.cpu_count instead (which may not return the *available* number
            # of CPUs).
            num_cpus = os.cpu_count()

        num_workers = min(num_cpus, 8) if num_cpus is not None else 0
    else:
        num_workers = args.num_workers

    if args.save_stats:
        save_fid_stats(args.path, args.batch_size, device, args.dims, num_workers)
        return
    fid_value = calculate_fid_given_paths(paths=args.path,
                                          batch_size=args.batch_size,
                                          device=device,
                                          dims=args.dims,
                                          num_workers=num_workers)
    print('FID: ', fid_value)


if __name__ == '__main__':
    main()
  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 可以使用 Matplotlib 库在 Python 中绘制 loss 和 epoch 曲线。首先,需要在代码中导入 Matplotlib,然后通过记录 loss 和 epoch 的数值并将其作为 Matplotlib 的输入数据,最后调用 plot 函数绘制曲线。例如: ``` import matplotlib.pyplot as plt epochs = [1, 2, 3, 4, 5] loss = [0.2, 0.15, 0.1, 0.05, 0.01] plt.plot(epochs, loss, 'r') plt.xlabel('Epochs') plt.ylabel('Loss') plt.title('Loss vs. Epochs') plt.show() ``` 这将绘制红色的 loss 和 epoch 曲线。 ### 回答2: Python是一种高级的编程语言,适用于各种领域,包括机器学习深度学习。当我们训练模型时,我们通常需要了解模型的性能如何随时间推移而变化。为了实现这一目标,我们在代码中添加了可视化损失和epoch曲线的功能。下面将详细介绍如何使用Python绘制loss和epoch曲线。 首先,我们需要从训练模型的程序中获取损失和epoch数据。我们可以使用Python的numpy库来存储这些数据。在训练期间,我们可以将损失和epoch数据发送到numpy数组中。通常,我们将损失和epoch数据保存在csv文件中,以备将来使用。 接下来,我们需要将损失和epoch数据可视化。我们可以使用Python的matplotlib库来实现可视化。对于简单的可视化,我们可以使用plt.plot()函数将损失和epoch数据传递给Matplotlib。在图表上,将显示损失和epoch的变化趋势。 如果我们想更加详细地研究模型的性能,并将损失和epoch图表细化到数据点级别,我们可以使用Seaborn库。Seaborn库建立在Matplotlib库之上,并提供了更加高效和美观的可视化效果。 一些其他的Python库,如Plotly和Bokeh,提供了交互式的数据可视化,使用户能够从数据中获取更多信息。 总的来说,Python的numpy,Matplotlib,Seaborn等开源库可以帮助我们对机器学习深度学习的模型进行可视化,以进一步优化模型性能。可视化数据可以帮助我们更好地理解模型的运行和优化,以便在竞争激烈的数据科学和机器学习领域中保持竞争优势。 ### 回答3: Python是一种高级编程语言,其简单易学、易于阅读和有效地处理数据,使其成为机器学习深度学习领域的流行语言。在训练深度学习模型时,监控模型表现的指标非常重要。通常,人们使用loss和accuracy来监测模型的表现,其中loss表示在一次迭代中预测值与实际值之间的误差。 在机器学习中,模型的loss通常会在每个epoch中被计算并记录下来。这些数据需要可视化来更好地理解模型表现。Python提供了一种简单而有效的方法来绘制loss和epoch曲线,这是使用matplotlib库。 首先,我们需要在训练过程中记录每个epoch中的loss。 这可以通过以下方式实现: history = model.fit(X_train, y_train, epochs=10, validation_data=(X_val, y_val)) loss = history.history['loss'] val_loss = history.history['val_loss'] 其中,history是模型训练的历史记录,而loss和val_loss分别是训练集和验证集中的loss。 接下来,我们可以使用matplotlib库来绘制loss和epoch曲线,并添加必要的标签和标题。示例代码如下所示: import matplotlib.pyplot as plt epochs = range(1, len(loss) + 1) plt.plot(epochs, loss, 'bo', label='Training loss') plt.plot(epochs, val_loss, 'b', label='Validation loss') plt.title('Training and Validation Loss') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() plt.show() 此代码将绘制一个图表,其中包含两个曲线:蓝色圆点表示训练集的loss,而蓝色线表示验证集的loss。通过图表,我们可以看出模型是否过度拟合,以及我们需要对其进行调整。 总之,通过Python和matplotlib库,绘制loss和epoch曲线是一项简单而重要的任务,它可以帮助我们监视和优化机器学习模型的性能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MORE_77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值