MinkowskiEngine demo ModelNet40分类

本文将看一个简单的演示示例,该示例训练用于分类的3D卷积神经网络。输入是稀疏张量,卷积也定义在稀疏张量上。该网络是以下体系结构的扩展,但具有剩余的块和更多的层。

创建ModelNet40数据加载器

首先,需要创建一个数据加载器,以返回网格的稀疏张量表示。如果仅使用顶点,则3D模型的网格表示可能会稀疏。

首先以相同的密度采样点。

def resample_mesh(mesh_cad, density=1):

'''

    https://chrischoy.github.io/research/barycentric-coordinate-for-mesh-sampling/

    Samples point cloud on the surface of the model defined as vectices and

    faces. This function uses vectorized operations so fast at the cost of some

    memory.

    param mesh_cad: low-polygon triangle mesh in o3d.geometry.TriangleMesh

    param density: density of the point cloud per unit area

    param return_numpy: return numpy format or open3d pointcloud format

    return resampled point cloud

    Reference :

      [1] Barycentric coordinate system

      \begin{align}

        P = (1 - \sqrt{r_1})A + \sqrt{r_1} (1 - r_2) B + \sqrt{r_1} r_2 C

      \end{align}

    '''

faces = np.array(mesh_cad.triangles).astype(int)

vertices = np.array(mesh_cad.vertices)

vec_cross = np.cross(vertices[faces[:, 0], :] - vertices[faces[:, 2], :],

vertices[faces[:, 1], :] - vertices[faces[:, 2], :])

face_areas = np.sqrt(np.sum(vec_cross**2, 1))

n_samples = (np.sum(face_areas) * density).astype(int)

n_samples_per_face = np.ceil(density * face_areas).astype(int)

floor_num = np.sum(n_samples_per_face) - n_samples

if floor_num > 0:

indices = np.where(n_samples_per_face > 0)[0]

floor_indices = np.random.choice(indices, floor_num, replace=True)

n_samples_per_face[floor_indices] -= 1

n_samples = np.sum(n_samples_per_face)

# Create a vector that contains the face indices

sample_face_idx = np.zeros((n_samples,), dtype=int)

acc = 0

for face_idx, _n_sample in enumerate(n_samples_per_face):

sample_face_idx[acc:acc + _n_sample] = face_idx

acc += _n_sample

r = np.random.rand(n_samples, 2)

A = vertices[faces[sample_face_idx, 0], :]

B = vertices[faces[sample_face_idx, 1], :]

C = vertices[faces[sample_face_idx, 2], :]

P = (1 - np.sqrt(r[:, 0:1])) * A + \

np.sqrt(r[:, 0:1]) * (1 - r[:, 1:]) * B + \

np.sqrt(r[:, 0:1]) * r[:, 1:] * C

return P

上面的函数将以相同的密度对网格上的点进行采样。接下来,在量化步骤之前经历了一系列数据扩充步骤。

数据扩充

稀疏张量由两个部分组成:1)坐标和2)与这些坐标关联的特征。必须对这两个组件都应用数据增强,以最大化固定数据集的效用,并使网络对噪声具有鲁棒性。

这在图像数据增强中并不是什么新鲜事。对图像应用随机平移,剪切,缩放,所有这些都是坐标数据扩充。颜色失真(例如色平移,颜色通道上的高斯噪声,色相饱和度增强)都具有数据增强功能。

由于在ModelNet40数据集中只有坐标作为数据,将仅应用坐标数据增强。

class RandomRotation:

def _M(self, axis, theta):

return expm(np.cross(np.eye(3), axis / norm(axis) * theta))

def __call__(self, coords, feats):

R = self._M(

np.random.rand(3) - 0.5, 2 * np.pi * (np.random.rand(1) - 0.5))

return coords @ R, feats

class RandomScale:

def __init__(self, min, max):

self.scale = max - min

self.bias = min

def __call__(self, coords, feats):

s = self.scale * np.random.rand(1) + self.bias

return coords * s, feats

class RandomShear:

def __call__(self, coords, feats):

T = np.eye(3) + np.random.randn(3, 3)

return coords @ T, feats

class RandomTranslation:

def __call__(self, coords, feats):

trans = 0.05 * np.random.randn(1, 3)

return coords + trans, feats

训练ResNet进行ModelNet40分类

主要训练功能很简单。没有使用基于时间的训练,而是使用了基于迭代的训练。与基于时间的训练相比,基于迭代的训练的一个优势在于,训练逻辑独立于批处理大小。

def train(net, device, config):

optimizer = optim.SGD(

net.parameters(),

lr=config.lr,

momentum=config.momentum,

weight_decay=config.weight_decay)

scheduler = optim.lr_scheduler.ExponentialLR(optimizer, 0.95)

crit = torch.nn.CrossEntropyLoss()

...

net.train()

train_iter = iter(train_dataloader)

val_iter = iter(val_dataloader)

logging.info(f'LR: {scheduler.get_lr()}')

for i in range(curr_iter, config.max_iter):

s = time()

data_dict = train_iter.next()

d = time() - s

optimizer.zero_grad()

sin = ME.SparseTensor(data_dict['feats'],

data_dict['coords'].int()).to(device)

sout = net(sin)

loss = crit(sout.F, data_dict['labels'].to(device))

loss.backward()

optimizer.step()

t = time() - s

...

运行示例

集成所有代码块时,可以运行自主ModelNet40分类网络。

python -m examples.modelnet40 --batch_size 128 --stat_freq 100

完整的代码可以在example / modelnet40.py找到。

https://github.com/NVIDIA/MinkowskiEngine/blob/master/examples/modelnet40.py

警告

ModelNet40数据加载和体素化是训练中最耗时的部分。因此,该示例将所有ModelNet40数据缓存到内存中,这将占用大约10G的内存。

最新文章

  1. 【前端】使用CSS使元素居中的几种方式
  2. linux编译安装MySQL
  3. Linux学习笔记---【1】
  4. WPF 显示初始化界面
  5. MQTT之 Mosquitto hello world的使用
  6. Android权限安全(7)binder,service,zygote安全相关简介
  7. MYSQL的分区字段,必须包含在主键字段内
  8. python字符串操作2
  9. CF_Lucky Sum
  10. hbase 单机模式安装
  11. IOS 创建一张有颜色的UIImage
  12. WCF 采用net.tcp协议
  13. 【SICP练习】151 练习4.7
  14. 我的长大app开发教程第一弹:Fragment布局
  15. windows7安装MySQL-python遇到的坑
  16. day 10函数二
  17. PCB布局布线
  18. 对numpy中shape的理解
  19. RocketMQ源码分析:(一)安装与案例演示
  20. Oracle使用技巧及PL/SQL Developer配置

热门文章

  1. The 2014 ACM-ICPC Asia Mudanjiang Regional First Round J
  2. W32Dasm缓冲区溢出分析【转载】
  3. R3抹掉加载的DLL
  4. Vip视频解析端口
  5. 【python】Leetcode每日一题-颠倒二进制位
  6. Git 系列教程(5)- 记录每次更新到仓库
  7. MySQL备份脚本,应该这么写
  8. JWT 基本使用
  9. IOC随笔小记录
  10. Vue | 指令实现自动翻译填充英文名功能