智能数字图像处理:图卷积SGN代码(pytorch)之main.py解读

1.os.environ["CUDA_VISIBLE_DEVICES"] = '0'-》目的:使用cuda的环境变量cuda_visible_Devices莱限定CUDA程序所能使用的GPU设备

2.parser = argparse.ArgumentParser(description='Skeleton-Based Action Recgnition')-》创建解析器,使用 argparse 的第一步是创建一个 ArgumentParser 对象。
fit.add_fit_args(parser)-》读入命令行参数,该调用有多个参数

3.parser.set_defaults(
    network='SGN',-》网络名称
    dataset = 'NTU',-》数据集名称
    case = 0,-》默认实例为0
    batch_size=16,-》批处理大小
    max_epochs=40,-》最大训练轮数
    monitor='val_acc',-》监视器为验证集的准确率
    lr=0.001,-》初始学习率
    weight_decay=0.0001,-》衰减权重
    lr_factor=0.1,
    workers=0,-》线程数
    print_freq = 20,
    train = 0,
    seg = 20,
    )、

4. args.num_classes = get_num_classes(args.dataset)-》调用get_num_classes得到分类数
    model = SGN(args.num_classes, args.dataset, args.seg, args)-》调用model的SGN方法得到模型

5.total = get_n_params(model)-》调用get_n_params得到model的累乘。
    print(model)-》打印模型结构哦
    print('The number of parameters: ', total)-》打印参数个数
    print('The modes is:', args.network)-》打印模式

6.if torch.cuda.is_available():-》核实显卡驱动是不是可用
        print('It is using GPU!')
        model = model.cuda()-》模型加载GPU驱动

7. criterion = LabelSmoothingLoss(args.num_classes, smoothing=0.1).cuda()-》调用LabelSmoothingLoss方法进行loss的传播。
    optimizer = optim.Adam(model.parameters(), lr=args.lr, weight_decay=args.weight_decay)-》构建一个优化器optimizer,你必须给它一个可进行迭代优化的包含了所有参数

8. if args.monitor == 'val_acc':-》若监听到验证集准确率
        mode = 'max'
        monitor_op = np.greater
        best = -np.Inf
        str_op = 'improve'-》则增加
    elif args.monitor == 'val_loss':-》若监听到验证集损失值
        mode = 'min'
        monitor_op = np.less
        best = np.Inf
        str_op = 'reduce'-》则减少

9.scheduler = MultiStepLR(optimizer, milestones=[60, 90, 110], gamma=0.1)-》根据优化器进行学习率调整
    ntu_loaders = NTUDataLoaders(args.dataset, args.case, seg=args.seg)-》加载数据
    train_loader = ntu_loaders.get_train_loader(args.batch_size, args.workers)-》加载训练数据
    val_loader = ntu_loaders.get_val_loader(args.batch_size, args.workers)-》加载验证数据
    train_size = ntu_loaders.get_train_size()-》获取训练数据大小
    val_size = ntu_loaders.get_val_size()-》获取验证数据大小

10.test_loader = ntu_loaders.get_test_loader(32, args.workers)-》加载测试数据集

    print('Train on %d samples, validate on %d samples' % (train_size, val_size))-》打印训练集大小验证集大小

    best_epoch = 0-》初始化epoch
    output_dir = make_dir(args.dataset)-》创建目录

11. save_path = os.path.join(output_dir, args.network)-》设置保存路径
    if not os.path.exists(save_path):-》如果路径不存在
        os.makedirs(save_path)-》创建路径

12.checkpoint = osp.join(save_path, '%s_best.pth' % args.case)-》设置训练完权重文件保存路径和文件名格式
    earlystop_cnt = 0
    csv_file = osp.join(save_path, '%s_log.csv' % args.case)-》设置日志文件保存路径和文件名格式
    log_res = list()

13. lable_path = osp.join(save_path, '%s_lable.txt'% args.case)-》设置标签文件保存路径和文件名格式
    pred_path = osp.join(save_path, '%s_pred.txt' % args.case)-》设置预测文件保存路径和文件名格式

14.开始训练
    if args.train ==1:-》第一轮
        for epoch in range(args.start_epoch, args.max_epochs):-》循环,范围在第一轮到最后一轮(40)之间

            print(epoch, optimizer.param_groups[0]['lr'])-》打印训练轮数,优化器的参数

15. t_start = time.time()-》记录开始时间
     train_loss, train_acc = train(train_loader, model, criterion, optimizer, epoch)-》计算训练损失和准确率
     val_loss, val_acc = validate(val_loader, model, criterion)-》计算验证集损失和准确率
     log_res += [[train_loss, train_acc.cpu().numpy(),\
                         val_loss, val_acc.cpu().numpy()]]-》更新日志

16.

print('Epoch-{:<3d} {:.1f}s\t'
                  'Train: loss {:.4f}\taccu {:.4f}\tValid: loss {:.4f}\taccu {:.4f}'
                  .format(epoch + 1, time.time() - t_start, train_loss, train_acc, val_loss, val_acc))-》打印当前训练信息

            current = val_loss if mode == 'min' else val_acc-》-》如果验证集准确率打破了记录则更新准确率

17.cpu存储张量
            current = current.cpu()

18.if monitor_op(current, best):-》 监视器监视准确率
                print('Epoch %d: %s %sd from %.4f to %.4f, '
                      'saving model to %s'
                      % (epoch + 1, args.monitor, str_op, best, current, checkpoint))-》-》打印保存信息
                best = current-》更新历史最佳准确率
                best_epoch = epoch + 1-》更新epoch
                save_checkpoint({
                    'epoch': epoch + 1,
                    'state_dict': model.state_dict(),
                    'best': best,
                    'monitor': args.monitor,
                    'optimizer': optimizer.state_dict(),
                }, checkpoint)-》保存更新参数
                earlystop_cnt = 0

19. else:
                print('Epoch %d: %s did not %s' % (epoch + 1, args.monitor, str_op))-》打印提示信息
                earlystop_cnt += 1-》更新earlystop_cnt

            scheduler.step()-》步长

20.print('Best %s: %.4f from epoch-%d' % (args.monitor, best, best_epoch))-》打印最佳轮数信息
        with open(csv_file, 'w') as fw:-》打开csv文件
            cw = csv.writer(fw)-》写入fw信息
            cw.writerow(['loss', 'acc', 'val_loss', 'val_acc'])-》写入列名loss,acc,val_loss,val_acc
            cw.writerows(log_res)-》写入日志信息
        print('Save train and validation log into into %s' % csv_file)-》打印完成信息

21 测试
    args.train = 0
    model = SGN(args.num_classes, args.dataset, args.seg, args)-》调用SGN模型
    model = model.cuda()-》调用GPU
    test(test_loader, model, checkpoint, lable_path, pred_path)-》调用测试函数进行测试

解读train方法

1. losses = AverageMeter()-》损失值
    acces = AverageMeter()-》进程
    model.train()

2.for i, (inputs, target) in enumerate(train_loader):-》遍历训练标签

        output = model(inputs.cuda())-》传入输入参数到model函数
        target = target.cuda(device=None, non_blocking=False) -》使用Python写CUDA程序
        loss = criterion(output, target)-》计算输出与真实标签之间的误差损失值loss
        acc = accuracy(output.data, target)-》测量精度
        losses.update(loss.item(), inputs.size(0))-》更新损失
        acces.update(acc[0], inputs.size(0))-》更新精度
        optimizer.zero_grad() -》梯度初始化
        loss.backward()-》损失反向传播
        optimizer.step()-》优化器反向优化参数

3. if (i + 1) % args.print_freq == 0:
            print('Epoch-{:<3d} {:3d} batches\t'
                  'loss {loss.val:.4f} ({loss.avg:.4f})\t'
                  'accu {acc.val:.3f} ({acc.avg:.3f})'.format(
                   epoch + 1, i + 1, loss=losses, acc=acces))-》打印损失值和准确率

    return losses.avg, acces.avg-》返回平均损失值和平均准确率

解读validate方法:同train方法大同小异

解读test方法:

1. acces = AverageMeter()-》调用AverageMeter获取模型准确率
    model.load_state_dict(torch.load(checkpoint)['state_dict'])-》在验证集上获得最佳性能的加载学习模型
    model.eval() -》调用model的验证方法eval

2. label_output = list()->创建输出列表
    pred_output = list()-》创建预测列表

3.t_start = time.time()
    for i, (inputs, target) in enumerate(test_loader):
        with torch.no_grad():-》不属于梯度下降
            output = model(inputs.cuda())-》获取模型输出
            output = output.view((-1, inputs.size(0)//target.size(0), output.size(1)))-》输出维度
            output = output.mean(1)-》取均值

        label_output.append(target.cpu().numpy())-》添加输出标签到numpy数组
        pred_output.append(output.cpu().numpy())-》添加预测输出到numpy数组

        acc = accuracy(output.data, target.cuda(device=None, non_blocking=False) )-》计算输出与预测之间的准确率
        acces.update(acc[0], inputs.size(0))-》更新准确率

 4.label_output = np.concatenate(label_output, axis=0)-》输出标签
    np.savetxt(lable_path, label_output, fmt='%d')-》保存到txt文件
    pred_output = np.concatenate(pred_output, axis=0)-》能够一次完成多个数组的拼接
    np.savetxt(pred_path, pred_output, fmt='%f')-》保存在txt文件

    print('Test: accuracy {:.3f}, time: {:.2f}s'
          .format(acces.avg, time.time() - t_start))-》打印准确率,完成完成时间,开始时间信息

解读accuracy方法

1. batch_size = target.size(0)-》获取批大小
    _, pred = output.topk(1, 1, True, True)-》求最大和最小值
    pred = pred.t()-》转置
    correct = pred.eq(target.view(1, -1).expand_as(pred))-》判断相等
    correct = correct.view(-1).float().sum(0, keepdim=True)-》输出准确率和的维度

解读save_checkpoint方法:

    torch.save(state, filename)-》保存文件名和最佳权重模型参数的文件
    if is_best:
        shutil.copyfile(filename, 'model_best.pth.tar')  

解读get_n_params方法:
1.pp=0
    for p in list(model.parameters()):
        nn=1
        for s in list(p.size()):
            nn = nn*s
        pp += nn-》计算pp参数的累乘

解读LabelSmoothingLoss 类

1.pred = pred.log_softmax(dim=self.dim)-》softmax分类日志
        with torch.no_grad():
            true_dist = torch.zeros_like(pred):预测归0初始化
            true_dist.fill_(self.smoothing / (self.cls - 1))-》一块单元赋成指定的值
            true_dist.scatter_(1, target.data.unsqueeze(1), self.confidence)-》绘制散点图
        return torch.mean(torch.sum(-true_dist * pred, dim=self.dim)) -》返回预测值的和的均值

附上完整代码:

# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import argparse
import time
import shutil
import os
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
import os.path as osp
import csv
import numpy as np

np.random.seed(1337)

import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim.lr_scheduler import ReduceLROnPlateau, MultiStepLR
from model import SGN
from data import NTUDataLoaders, AverageMeter
import fit
from util import make_dir, get_num_classes

parser = argparse.ArgumentParser(description='Skeleton-Based Action Recgnition')
fit.add_fit_args(parser)
parser.set_defaults(
    network='SGN',
    dataset = 'NTU',
    case = 0,
    batch_size=16,
    max_epochs=40,
    monitor='val_acc',
    lr=0.001,
    weight_decay=0.0001,
    lr_factor=0.1,
    workers=0,
    print_freq = 20,
    train = 0,
    seg = 20,
    )
args = parser.parse_args()

def main():

    args.num_classes = get_num_classes(args.dataset)
    model = SGN(args.num_classes, args.dataset, args.seg, args)

    total = get_n_params(model)
    print(model)
    print('The number of parameters: ', total)
    print('The modes is:', args.network)

    if torch.cuda.is_available():
        print('It is using GPU!')
        model = model.cuda()

    criterion = LabelSmoothingLoss(args.num_classes, smoothing=0.1).cuda()
    optimizer = optim.Adam(model.parameters(), lr=args.lr, weight_decay=args.weight_decay)

    if args.monitor == 'val_acc':
        mode = 'max'
        monitor_op = np.greater
        best = -np.Inf
        str_op = 'improve'
    elif args.monitor == 'val_loss':
        mode = 'min'
        monitor_op = np.less
        best = np.Inf
        str_op = 'reduce'

    scheduler = MultiStepLR(optimizer, milestones=[60, 90, 110], gamma=0.1)
    # Data loading
    ntu_loaders = NTUDataLoaders(args.dataset, args.case, seg=args.seg)
    train_loader = ntu_loaders.get_train_loader(args.batch_size, args.workers)
    val_loader = ntu_loaders.get_val_loader(args.batch_size, args.workers)
    train_size = ntu_loaders.get_train_size()
    val_size = ntu_loaders.get_val_size()


    test_loader = ntu_loaders.get_test_loader(32, args.workers)

    print('Train on %d samples, validate on %d samples' % (train_size, val_size))

    best_epoch = 0
    output_dir = make_dir(args.dataset)

    save_path = os.path.join(output_dir, args.network)
    if not os.path.exists(save_path):
        os.makedirs(save_path)

    checkpoint = osp.join(save_path, '%s_best.pth' % args.case)
    earlystop_cnt = 0
    csv_file = osp.join(save_path, '%s_log.csv' % args.case)
    log_res = list()

    lable_path = osp.join(save_path, '%s_lable.txt'% args.case)
    pred_path = osp.join(save_path, '%s_pred.txt' % args.case)

    # Training
    if args.train ==1:
        for epoch in range(args.start_epoch, args.max_epochs):

            print(epoch, optimizer.param_groups[0]['lr'])

            t_start = time.time()
            train_loss, train_acc = train(train_loader, model, criterion, optimizer, epoch)
            val_loss, val_acc = validate(val_loader, model, criterion)
            log_res += [[train_loss, train_acc.cpu().numpy(),\
                         val_loss, val_acc.cpu().numpy()]]

            print('Epoch-{:<3d} {:.1f}s\t'
                  'Train: loss {:.4f}\taccu {:.4f}\tValid: loss {:.4f}\taccu {:.4f}'
                  .format(epoch + 1, time.time() - t_start, train_loss, train_acc, val_loss, val_acc))

            current = val_loss if mode == 'min' else val_acc

            ####### store tensor in cpu
            current = current.cpu()

            if monitor_op(current, best):
                print('Epoch %d: %s %sd from %.4f to %.4f, '
                      'saving model to %s'
                      % (epoch + 1, args.monitor, str_op, best, current, checkpoint))
                best = current
                best_epoch = epoch + 1
                save_checkpoint({
                    'epoch': epoch + 1,
                    'state_dict': model.state_dict(),
                    'best': best,
                    'monitor': args.monitor,
                    'optimizer': optimizer.state_dict(),
                }, checkpoint)
                earlystop_cnt = 0
            else:
                print('Epoch %d: %s did not %s' % (epoch + 1, args.monitor, str_op))
                earlystop_cnt += 1

            scheduler.step()

        print('Best %s: %.4f from epoch-%d' % (args.monitor, best, best_epoch))
        with open(csv_file, 'w') as fw:
            cw = csv.writer(fw)
            cw.writerow(['loss', 'acc', 'val_loss', 'val_acc'])
            cw.writerows(log_res)
        print('Save train and validation log into into %s' % csv_file)

    ### Test
    args.train = 0
    model = SGN(args.num_classes, args.dataset, args.seg, args)
    model = model.cuda()
    test(test_loader, model, checkpoint, lable_path, pred_path)


def train(train_loader, model, criterion, optimizer, epoch):
    losses = AverageMeter()
    acces = AverageMeter()
    model.train()

    for i, (inputs, target) in enumerate(train_loader):

        output = model(inputs.cuda())
        target = target.cuda(device=None, non_blocking=False) 
        loss = criterion(output, target)

        # measure accuracy and record loss
        acc = accuracy(output.data, target)
        losses.update(loss.item(), inputs.size(0))
        acces.update(acc[0], inputs.size(0))

        # backward
        optimizer.zero_grad()  # clear gradients out before each mini-batch
        loss.backward()
        optimizer.step()

        if (i + 1) % args.print_freq == 0:
            print('Epoch-{:<3d} {:3d} batches\t'
                  'loss {loss.val:.4f} ({loss.avg:.4f})\t'
                  'accu {acc.val:.3f} ({acc.avg:.3f})'.format(
                   epoch + 1, i + 1, loss=losses, acc=acces))

    return losses.avg, acces.avg


def validate(val_loader, model, criterion):
    losses = AverageMeter()
    acces = AverageMeter()
    model.eval()

    for i, (inputs, target) in enumerate(val_loader):
        with torch.no_grad():
            output = model(inputs.cuda())
        target = target.cuda(device=None, non_blocking=False) 
        with torch.no_grad():
            loss = criterion(output, target)

        # measure accuracy and record loss
        acc = accuracy(output.data, target)
        losses.update(loss.item(), inputs.size(0))
        acces.update(acc[0], inputs.size(0))

    return losses.avg, acces.avg


def test(test_loader, model, checkpoint, lable_path, pred_path):
    acces = AverageMeter()
    # load learnt model that obtained best performance on validation set
    model.load_state_dict(torch.load(checkpoint)['state_dict'])
    model.eval()

    label_output = list()
    pred_output = list()

    t_start = time.time()
    for i, (inputs, target) in enumerate(test_loader):
        with torch.no_grad():
            output = model(inputs.cuda())
            output = output.view((-1, inputs.size(0)//target.size(0), output.size(1)))
            output = output.mean(1)

        label_output.append(target.cpu().numpy())
        pred_output.append(output.cpu().numpy())

        acc = accuracy(output.data, target.cuda(device=None, non_blocking=False) )
        acces.update(acc[0], inputs.size(0))


    label_output = np.concatenate(label_output, axis=0)
    np.savetxt(lable_path, label_output, fmt='%d')
    pred_output = np.concatenate(pred_output, axis=0)
    np.savetxt(pred_path, pred_output, fmt='%f')

    print('Test: accuracy {:.3f}, time: {:.2f}s'
          .format(acces.avg, time.time() - t_start))


def accuracy(output, target):
    batch_size = target.size(0)
    _, pred = output.topk(1, 1, True, True)
    pred = pred.t()
    correct = pred.eq(target.view(1, -1).expand_as(pred))
    correct = correct.view(-1).float().sum(0, keepdim=True)

    return correct.mul_(100.0 / batch_size)

def save_checkpoint(state, filename='checkpoint.pth.tar', is_best=False):
    torch.save(state, filename)
    if is_best:
        shutil.copyfile(filename, 'model_best.pth.tar')

def get_n_params(model):
    pp=0
    for p in list(model.parameters()):
        nn=1
        for s in list(p.size()):
            nn = nn*s
        pp += nn
    return pp

class LabelSmoothingLoss(nn.Module):
    def __init__(self, classes, smoothing=0.0, dim=-1):
        super(LabelSmoothingLoss, self).__init__()
        self.confidence = 1.0 - smoothing
        self.smoothing = smoothing
        self.cls = classes
        self.dim = dim

    def forward(self, pred, target):
        pred = pred.log_softmax(dim=self.dim)
        with torch.no_grad():
            true_dist = torch.zeros_like(pred)
            true_dist.fill_(self.smoothing / (self.cls - 1))
            true_dist.scatter_(1, target.data.unsqueeze(1), self.confidence)
        return torch.mean(torch.sum(-true_dist * pred, dim=self.dim))

if __name__ == '__main__':
    main()
    

 

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页