深度学习中的 PointNet 是什么?
PointNet 通过直接使用原始数据来分析点云,而无需体素化或其他预处理步骤。斯坦福大学的一位研究人员在 2016 年提出了这种新颖的架构,用于对图像的 3D 表示进行分类和分割。
关键属性
在点云中,PointNet 考虑了点集的几个关键属性。
点云由非结构化的点集组成,单个点云中可能存在多个排列。如果我们有 N 个点,就有 N 个!有几种方法可以对它们进行排序。使用排列不变性,PointNet 可确保分析与不同的排列保持独立。因此,无论点如何排序,网络都应该产生一致的结果。 PointNet 的设计尊重了这一特性,可以应对点云中的不规则性并捕捉基本特征,而不受点的顺序影响。
在旋转和平移等不同变换下,PointNet 的分类和分割结果应保持一致。网络应该能够识别和分类点云中的对象或片段,而不管它们的位置、方向或位置如何。PointNet 通过结合变换不变性来确保学习到的特征和表示的稳健性。即使存在几何变换,网络也能很好地概括并做出准确的预测。
点之间的相互作用
虽然点云中的每个点都包含有价值的信息,但相邻点之间的关系和连接在理解底层结构方面也起着关键作用。特别是,PointNet 认识到这些相互作用的重要性。考虑到局部环境和相邻点之间的关系,网络能够通过考虑局部环境来准确地分割点云的不同部分。通过利用点局部邻域中存在的丰富信息,PointNet 可以实现卓越的分割结果。
点网架构
通过结合这些属性,PointNet 为分析点云提供了强大的架构。通过这样做,它克服了需要体素化或其他中间表示的传统方法的局限性。PointNet 处理无序集的能力、其变换不变性以及对点交互的依赖,实现了对 3D 表示进行分类和分割的统一而有效的方法。
PointNet 使研究人员和从业者能够直接处理原始点云数据,并在各种 3D 识别任务中实现最先进的性能。除了增强我们对 3D 形状和物体的理解之外,这一突破还为机器人、计算机辅助设计和增强现实等领域开辟了新的可能性。未来,PointNet 将在点云分析方面取得令人兴奋的进步。 PointNet 的一个基本方面是它使用称为最大池化的对称函数来处理无序输入集。为了让网络从点云中学习并从中提取有价值的信息,此功能至关重要。
最大池化允许 PointNet 通过学习一组优化函数来识别点云中有趣且信息丰富的点。正是这些选定的点使网络能够通过编码其重要性的原因来捕获 3D 形状或对象的基本特征。PointNet 架构的最终全连接层将这些学习到的最优值聚合成一个全局描述符。可以从这个全局描述符中获得对形状的整体理解,该描述符可用于形状分类。此外,相同的聚合特征还可用于预测单个点的标签,从而促进形状分割。
数据可以在 PointNet 的输入格式中进行刚性或仿射转换。可以独立转换每个点,从而轻松进行操作和预处理。可以利用此特性引入依赖于数据的空间变换器网络。在 PointNet 处理数据之前,这个空间变换器网络会一致地对齐数据以使其规范化。添加此步骤可进一步增强网络结果的准确性和稳健性。
下图是 PointNet 架构的直观表示。分类网络的输入中有 n 个点。它在应用输入和特征转换后使用最大池化聚合点特征。作为此过程的结果,m 个预定义类将获得分类分数。该架构通过连接全局和局部特征来扩展分割任务。多层感知器用符号"mlp"表示,其中层大小用括号表示。对于最终的多层感知器,使用整流线性单元 (ReLU) 将批量归一化应用于所有层。
Python 示例
以下是在自定义数据集上训练 PointNet 模型的示例代码片段 −
import numpy as np import tensorflow as tf from tensorflow import keras from tensorflow.keras import layer # 定义点和类的数量 NUM_POINTS = 2048 NUM_CLASSES = 10 # 定义数据集和标签 train_points = np.random.randn(NUM_POINTS, 3) train_labels = np.random.randint(NUM_CLASSES, size=NUM_POINTS) test_points = np.random.randn(NUM_POINTS, 3) test_labels = np.random.randint(NUM_CLASSES, size=NUM_POINTS) # 定义 PointNet 模型架构 inputs = keras.Input(shape=(NUM_POINTS, 3)) x = layer.Conv1D(64, kernel_size=1,activation="relu")(inputs) x = layer.BatchNormalization()(x) x = layer.Conv1D(64, kernel_size=1,activation="relu")(x) x = layer.BatchNormalization()(x) # 应用最大池化来聚合点特征 x = layers.GlobalMaxPooling1D()(x) x = layers.Dense(256, activation="relu")(x) x = layers.Dropout(0.4)(x) x = layers.Dense(128, activation="relu")(x) x = layers.Dropout(0.4)(x) outputs = layers.Dense(NUM_CLASSES, activation="softmax")(x) model = keras.Model(inputs=inputs, outputs=outputs, name="pointnet") model.summary() # 编译并训练模型 model.compile( loss="sparse_categorical_crossentropy", optimizer=keras.optimizers.Adam(learning_rate=0.001), metrics=["accuracy"], ) model.fit( train_points, train_labels, batch_size=32, epochs=10, validation_data=(test_points, test_labels) )
实际场景需要预处理数据集并将其加载到 train_points、train_labels、test_points 和 test_labels 变量中。根据您的具体问题和数据特征,您可能需要调整模型架构和超参数。