欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

PointNet.pytorch程序注释点云分类

程序员文章站 2022-03-29 23:09:47
PointNet.pytorch程序注释(一)点云分类论文及程序地址运行环境训练train测试test论文及程序地址论文原文PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation源程序链接: https://github.com/fxia22/pointnet.pytorc.自己标注的程序链接: https://github.com/jiangdi1998/PointNet.pytorch.运行...

PointNet.pytorch程序注释(一)点云分类

论文及程序地址

论文原文
PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation

源程序
链接: https://github.com/fxia22/pointnet.pytorch.

自己标注的程序
链接: https://github.com/jiangdi1998/PointNet.pytorch.

运行环境

硬件:i7-6700HQ、GTX960M-2G
软件:Ubuntu18.04、Python3.6、Pytorch1.6.0、cuda10.2
训练集:ShapeNet

训练train

pointnet.pytorch/Utils/train_classification.py
由于显存只有2G,故将训练的batch_size = 8,同时在train_classification.py 71行和78行键入drop_last = True,pytorch这种动态图结构下,训练或者验证图片数不能整除batch_size是不会报错的。

运行程序命令

python3 train_classification.py --dataset '/home/jiangdi/Downloads/jiangdi1998-pointnet.pytorch-master/pointnet.pytorch/shapenetcore_partanno_segmentation_benchmark_v0' --nepoch='2' --batchSize='8'  --dataset_type 'shapenet'

注释代码

from __future__ import print_function
import argparse
import os
import random
import torch
import torch.nn.parallel
import torch.optim as optim
import torch.utils.data
from pointnet.dataset import ShapeNetDataset, ModelNetDataset
from pointnet.model import PointNetCls, feature_transform_regularizer
import torch.nn.functional as F
from tqdm import tqdm


parser = argparse.ArgumentParser()
parser.add_argument(
    '--batchSize', type=int, default=32, help='input batch size') #终端键入batchsize
parser.add_argument(
    '--num_points', type=int, default=2500, help='input batch size') #默认的数据集每个点云是2500个点
parser.add_argument(
    '--workers', type=int, help='number of data loading workers', default=4) #进程
parser.add_argument(
    '--nepoch', type=int, default=250, help='number of epochs to train for') #epoch,训练多少个权重文件
parser.add_argument('--outf', type=str, default='cls', help='output folder')
parser.add_argument('--model', type=str, default='', help='model path') #预训练模型路径
parser.add_argument('--dataset', type=str, required=True, help="dataset path") #数据集路径
parser.add_argument('--dataset_type', type=str, default='shapenet', help="dataset type shapenet|modelnet40") #数据集类型shapenet或者modelnet40
parser.add_argument('--feature_transform', action='store_true', help="use feature transform")

opt = parser.parse_args()
print(opt)

blue = lambda x: '\033[94m' + x + '\033[0m' #test设置成蓝色字体

opt.manualSeed = random.randint(1, 10000)  # fix seed #生成随机数
print("Random Seed: ", opt.manualSeed)
random.seed(opt.manualSeed)
torch.manual_seed(opt.manualSeed)

if opt.dataset_type == 'shapenet': #创建针对shapenet数据集的类对象
    dataset = ShapeNetDataset( #训练集
        root=opt.dataset,
        classification=True,  #打开分类的选项
        npoints=opt.num_points)

    test_dataset = ShapeNetDataset( #测试集
        root=opt.dataset,
        classification=True,
        split='test', #标记为测试
        npoints=opt.num_points,
        data_augmentation=False)
elif opt.dataset_type == 'modelnet40':#创建针对modelnet数据集的类对象
    dataset = ModelNetDataset(
        root=opt.dataset,
        npoints=opt.num_points,
        split='trainval')

    test_dataset = ModelNetDataset(
        root=opt.dataset,
        split='test',
        npoints=opt.num_points,
        data_augmentation=False)
else:
    exit('wrong dataset type') #如果在终端没有键入正确的数据集格式,则警告


dataloader = torch.utils.data.DataLoader( #加载数据
    dataset,
    batch_size=opt.batchSize,
    shuffle=True, #随机数
    drop_last=True, #训练的数据数不能被batch_size整除,是不会报错的
    num_workers=int(opt.workers))

testdataloader = torch.utils.data.DataLoader(
        test_dataset,
        batch_size=opt.batchSize,
        shuffle=True,
        drop_last=True,
        num_workers=int(opt.workers))

print(len(dataset), len(test_dataset)) # 12137 2874
num_classes = len(dataset.classes)
print('classes', num_classes) #classes 16

try:
    os.makedirs(opt.outf)
except OSError:
    pass

classifier = PointNetCls(k=num_classes, feature_transform=opt.feature_transform) #调用model.py的PointNetCls定义分类函数

if opt.model != '':
    classifier.load_state_dict(torch.load(opt.model)) #如果有预训练模型,将预训练模型加载


optimizer = optim.Adam(classifier.parameters(), lr=0.001, betas=(0.9, 0.999)) #优化函数,可以替换成SGD之类的
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.5)
classifier.cuda()

num_batch = len(dataset) / opt.batchSize #batch数目

for epoch in range(opt.nepoch): #在一个epoch下
    scheduler.step()
    for i, data in enumerate(dataloader, 0):
        points, target = data #读取待训练对象点云与标签
        target = target[:, 0]
        points = points.transpose(2, 1) #放射变换
        points, target = points.cuda(), target.cuda() #使用cuda加速
        optimizer.zero_grad() #清除梯度
        classifier = classifier.train() #训练
        pred, trans, trans_feat = classifier(points) #计算预测值
        loss = F.nll_loss(pred, target) #交叉熵函数
        if opt.feature_transform:
            loss += feature_transform_regularizer(trans_feat) * 0.001
        loss.backward() #反向传播
        optimizer.step() #优化
        pred_choice = pred.data.max(1)[1] #
        print(pred_choice) #tensor([ 0, 15,  4,  0], device='cuda:0')
        correct = pred_choice.eq(target.data).cpu().sum()
        print(correct) #tensor(1)
        print('[%d: %d/%d] train loss: %f accuracy: %f' % (epoch, i, num_batch, loss.item(), correct.item() / float(opt.batchSize))) [0: 9/3034] train loss: 2.467071 accuracy: 0.250000

        if i % 10 == 0: #每十次测试以下,过程同上
            j, data = next(enumerate(testdataloader, 0))
            points, target = data
            target = target[:, 0]
            points = points.transpose(2, 1)
            points, target = points.cuda(), target.cuda()
            classifier = classifier.eval()
            pred, _, _ = classifier(points)
            loss = F.nll_loss(pred, target)
            pred_choice = pred.data.max(1)[1]
            correct = pred_choice.eq(target.data).cpu().sum()
            print('[%d: %d/%d] %s loss: %f accuracy: %f' % (epoch, i, num_batch, blue('test'), loss.item(), correct.item()/float(opt.batchSize))) #[0: 0/3034] test loss: 2.739059 accuracy: 0.000000

    torch.save(classifier.state_dict(), '%s/cls_model_%d.pth' % (opt.outf, epoch)) #保存权重文件在cls/cls_model_1.pth

total_correct = 0
total_testset = 0
for i,data in tqdm(enumerate(testdataloader, 0)): #tqdm进度条
    points, target = data
    target = target[:, 0]
    points = points.transpose(2, 1)
    points, target = points.cuda(), target.cuda()
    classifier = classifier.eval()
    pred, _, _ = classifier(points)
    pred_choice = pred.data.max(1)[1]
    correct = pred_choice.eq(target.data).cpu().sum()
    total_correct += correct.item()
    total_testset += points.size()[0]

print("final accuracy {}".format(total_correct / float(total_testset))) #测试最终的正确率

运行过程
PointNet.pytorch程序注释点云分类

训练后的权重文件保存至

point.pytorch/utils/cls

训练权重结果
PointNet.pytorch程序注释点云分类

测试test

pointnet.pytorch/Utils/show_cls.py
1.将权重文件的路径写入到测试文件中,其中show_cls.py修改第16行的

default='/home/jiangdi/Downloads/jiangdi1998-pointnet.pytorch-master/pointnet.pytorch/utils/cls/cls_model_0.pth'

2.将第31行的修改batch_size 修改为batch_size= 8 ,第51行的float修改为float(8)

运行程序命令

python3 show_cls.py

注释代码

from __future__ import print_function
import argparse
import torch
import torch.nn.parallel
import torch.utils.data
from torch.autograd import Variable
from pointnet.dataset import ShapeNetDataset
from pointnet.model import PointNetCls
import torch.nn.functional as F


#showpoints(np.random.randn(2500,3), c1 = np.random.uniform(0,1,size = (2500)))

parser = argparse.ArgumentParser()

parser.add_argument('--model', type=str, default = '/home/jiangdi/Downloads/jiangdi1998-pointnet.pytorch-master/pointnet.pytorch/utils/cls/cls_model_0.pth',  help='model path') #加载模型
parser.add_argument('--num_points', type=int, default=2500, help='input batch size') #默认的每个点云点数2500


opt = parser.parse_args()
print(opt)

test_dataset = ShapeNetDataset( #测试集为ShapeNetDataset
    root='shapenetcore_partanno_segmentation_benchmark_v0',
    split='test',
    classification=True,
    npoints=opt.num_points,
    data_augmentation=False)

testdataloader = torch.utils.data.DataLoader( #加载测试集数据
    test_dataset, batch_size=8, shuffle=True) #显存小,修改batch_size为8或者4

classifier = PointNetCls(k=len(test_dataset.classes))
classifier.cuda()
classifier.load_state_dict(torch.load(opt.model))
classifier.eval()


for i, data in enumerate(testdataloader, 0):
    points, target = data
    points, target = Variable(points), Variable(target[:, 0])
    points = points.transpose(2, 1)
    points, target = points.cuda(), target.cuda()
    pred, _, _ = classifier(points)
    loss = F.nll_loss(pred, target)

    pred_choice = pred.data.max(1)[1]
    print(pred_choice) #预测  tensor([ 4, 12, 15,  4, 15, 15, 12,  6], device='cuda:0')
    print(target) #真值 tensor([ 4, 15, 15,  4, 15, 15, 15,  8], device='cuda:0')
    correct = pred_choice.eq(target.data).cpu().sum() #计算正确率 
    print('i:%d  loss: %f accuracy: %f' % (i, loss.data.item(), correct / float(8))) #显存小,修改batch_size为8或者4  ,i:0  loss: 0.426616 accuracy: 0.750000

运行结果
PointNet.pytorch程序注释点云分类

本文地址:https://blog.csdn.net/jd1998/article/details/112672836