eval.py代码注释

#代码注释
```python
import glob
import argparse
import torch
import torchvision.transforms as transforms
import numpy as np
from PIL import Image

from networks.drn_seg import DRNSeg, DRNSub
from utils.tools import *#本地方法
from utils.visualize import *#本地方法
from sklearn.metrics import average_precision_score, accuracy_score#评价指标:accuracy_score:精度
                                                                    # average_precision_score:根据预测得分计算平均精度(AP)


def load_global_classifier(model_path, gpu_id):
    if torch.cuda.is_available() and gpu_id != -1:#判断是否存在GPU,是否存在id
        device = 'cuda:{}'.format(gpu_id)#存在GPU,device:设备名称
    else:
        device = 'cpu'#不存在
    #加载模型
    model = DRNSub(1)#DRN 扩展残差网络,通过优化和扩展池化层和卷积层来提高图像分辨率,#本地networks 封装的模型 drn_seg.py中
    state_dict = torch.load(model_path, map_location='cpu')#map_location – 函数、torch.device或者字典指明如何重新映射存储位置。这里是cpu
    model.load_state_dict(state_dict['model'])#load_state_dict 是model或optimizer之后pytorch自动具备的函数,可以直接调用,
                                                # 使用反序列化状态字典加载model’s参数字典
    model.to(device)#将模型加载到指定设备上,device=torch.device("cpu")代表的使用cpu,
                    # 而device=torch.device("cuda")则代表的使用GPU
    model.device = device
    model.eval()#测试实例化model,框架自动把BN和DropOut固定住,不会取平均,而是用训练好的值
    return model


def load_local_detector(model_path, gpu_id):
    if torch.cuda.is_available():
        device = 'cuda:{}'.format(gpu_id)
    else:
        device = 'cpu'
    #加载检测点
    model = DRNSeg(2)
    state_dict = torch.load(model_path, map_location=device)
    model.load_state_dict(state_dict['model'])
    model.to(device)
    model.device = device
    model.eval()
    return model


tf = transforms.Compose([transforms.ToTensor(),
                         transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                              std=[0.229, 0.224, 0.225])])#通过compose()将各个变换串联起来,
                                                                            # 这个类将多个变换方式结合在一起
                        #Normalize()用均值和标准差对张量图像进行标准化处理,
                         #ToTensor()将PIL图片或者numpy.ndarray转成Tensor类型的
def load_data(img_path, device):
    face = Image.open(img_path).convert('RGB')#PIL.Image.open()专接图片路径,用来直接读取该路径指向的图片,
                                            # convert('RGB')用于不同图片格式之间的转换这里将图片格式转换为RGB
    face = resize_shorter_side(face, 400)[0]#resize_shorter_side不知道怎么来的,应该是改变图像大小
    face_tens = tf(face).to(device)#将数据加载到指定设备上
    return face_tens, face


def classify_fake(model, img_path):
    img = load_data(img_path, model.device)[0].unsqueeze(0)
    # Prediction
    with torch.no_grad():#是一个上下文管理器,被该语句 wrap 起来的部分将不会track 梯度,
                        # 因为模型在训练阶段具有 requires_grad = True 的可训练参数有利于调参,但在评估阶段我们不需要梯度
        prob = model(img)[0].sigmoid().cpu().item()#sigmoid()激活函数,将模型的激活函数所得的值放在cpu上
    return prob

#计算峰值噪声比?
def calc_psnr(img0, img1, mask=None):
    return -10 * np.log10(np.mean((img0 - img1)**2) + 1e-6)#np.mean()求均值,
                                                            # np.log10()返回以10为底的输入数组的对数,按元素排序
def detect_warp(model, img_path):
    img, modified = load_data(img_path, model.device)
    # Warping field prediction
    with torch.no_grad():
        flow = model(img.unsqueeze(0))[0].cpu().numpy()
        flow = np.transpose(flow, (1, 2, 0))#transpose()简单来说,就相当于数学中的转置,在矩阵中,转置就是把行与列相互调换位置,
                                            # 初始(0,1,2),   (1,2,0)表示X,Y,Z轴都发生了变化
    # Undoing the warps
    flow = flow_resize(flow, modified.size)#改变flow形状
    modified_np = np.asarray(modified)#array和asarray都可以将结构数据转化为ndarray,
                                    # 但是主要区别就是当数据源是ndarray时,array仍然会copy出一个副本,占用新的内存,但asarray不会。
    reverse_np = warp(modified_np, flow)
    original = Image.open(img_path.replace('modified', 'reference')).convert('RGB')
    original_np = np.asarray(original.resize(modified.size, Image.BICUBIC))

    psnr_before = calc_psnr(original_np / 255, modified_np / 255)
    psnr_after = calc_psnr(original_np / 255, reverse_np / 255)
    return psnr_before, psnr_after


if __name__ == '__main__':
    parser = argparse.ArgumentParser()#通过命令行运行Python脚本时,可以通过ArgumentParser来高效地接受并解析命令行参数。
    #添加命令运行脚本
    parser.add_argument(
        "--dataroot", required=True, help='the root to the dataset')
    parser.add_argument(
        "--global_pth", required=True, help="path to the global model")
    parser.add_argument(
        "--local_pth", required=True, help="path to the local model")
    parser.add_argument(
        "--gpu_id", default='0', help="the id of the gpu to run model on")
    #把parser中设置的所有"add_argument"给返回到args子类实例当中, 那么parser中增加的属性内容都会在args实例中
    args = parser.parse_args()
    #加载模型和检测点
    glb_model = load_global_classifier(args.global_pth, args.gpu_id)
    lcl_model = load_local_detector(args.local_pth, args.gpu_id)

    pred_prob, gt_prob, psnr_before, psnr_after = [], [], [], []
    #循环读取原始图片
    for img_path in glob.glob(args.dataroot + '/original/*'):
        pred_prob.append(classify_fake(glb_model, img_path))
        gt_prob.append(0)
    #循环读取经过处理的图片
    for img_path in glob.glob(args.dataroot + '/modified/*'):
        pred_prob.append(classify_fake(glb_model, img_path))
        gt_prob.append(1)
        psnrs = detect_warp(lcl_model, img_path)
        psnr_before.append(psnrs[0])
        psnr_after.append(psnrs[1])
    #预测类别,真实类别,计算峰值噪声比前、后
    pred_prob, gt_prob, psnr_before, psnr_after = \
        np.array(pred_prob), np.array(gt_prob), np.array(psnr_before), np.array(psnr_after)
    acc = accuracy_score(gt_prob, pred_prob > 0.5)
    avg_precision = average_precision_score(gt_prob, pred_prob)
    delta_psnr = psnr_after.mean() - psnr_before.mean()

    print("Accuracy: ", acc)
    print("Average precision: ", avg_precision)
    print("PSNR increase: ", delta_psnr)

很高兴回答您的问题。根据您的要求,我为您编写了一个利用PyTorch平台实现数字图像识别任务的main.py代码,如下所示: ```python # 导入所需的库 import torch import torch.nn as nn import torch.optim as optim import torchvision.transforms as transforms import torchvision.datasets as datasets import matplotlib.pyplot as plt # 定义超参数 batch_size = 64 learning_rate = 0.001 num_epochs = 10 # 定义数据转换 transform = transforms.Compose([ transforms.ToTensor(), # 将图像转换为Tensor transforms.Normalize((0.1307,), (0.3081,)) # 标准化图像 ]) # 下载并加载训练数据集 train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True) # 加载测试数据集 test_dataset = datasets.MNIST(root='./data', train=False, transform=transform) # 创建数据加载器 train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True) test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False) # 定义深度卷积神经网络 class ConvNet(nn.Module): def __init__(self): super(ConvNet, self).__init__() self.conv1 = nn.Conv2d(1, 32, kernel_size=5, padding=2) self.conv2 = nn.Conv2d(32, 64, kernel_size=5, padding=2) self.fc1 = nn.Linear(7*7*64, 1024) self.fc2 = nn.Linear(1024, 10) def forward(self, x): x = nn.functional.relu(self.conv1(x)) x = nn.functional.max_pool2d(x, 2) x = nn.functional.relu(self.conv2(x)) x = nn.functional.max_pool2d(x, 2) x = x.view(-1, 7*7*64) x = nn.functional.relu(self.fc1(x)) x = nn.functional.dropout(x, training=self.training) x = self.fc2(x) return nn.functional.log_softmax(x, dim=1) # 创建模型 model = ConvNet() # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=learning_rate) # 训练模型 for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): images = images.requires_grad_() optimizer.zero_grad() outputs = model(images) loss = criterion(outputs, labels) loss.backward() optimizer.step() if (i+1) % 100 == 0: print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, i+1, len(train_loader), loss.item())) # 测试模型 model.eval() with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('准确率: {:.2f}%'.format(100 * correct / total)) # 画出测试图片并显示预测值和真实值 fig, axes = plt.subplots(2, 5, figsize=(10, 5)) axes = axes.flatten() for i in range(10): img = images[i].numpy().squeeze() axes[i].imshow(img, cmap='gray') axes[i].set_title('预测值: {}, 真实值: {}'.format(predicted[i].item(), labels[i].item())) axes[i].axis('off') plt.show() ``` 注释已经尽量详细了,其中包括数据集的下载、数据转换、模型的定义、损失函数和优化器的选择、模型的训练、模型的测试以及画出测试图片并显示预测值和真实值等步骤。您可以根据实际情况对其进行修改和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值