一、Conv1D、Conv2D、Conv3D
1、卷积的作用
在神经网络和深度学习方面:
卷积是具有可学习参数的过滤器(矩阵/向量),用于从输入数据中提取低维特征。
它们具有保留输入数据点之间的空间或位置关系的特性。
卷积神经网络通过在相邻层的神经元之间实施局部连接模式来利用空间局部相关性。
直观地说,卷积是将滑动窗口(具有可学习权重的滤波器)概念应用于输入并产生加权和(权重和输入)作为输出的步骤。 加权和是用作下一层输入的特征空间。
例如,在人脸识别问题中,前几个卷积层学习输入图像中关键点的存在,接下来的卷积层学习边缘和形状,最后的卷积层学习人脸。 在这个例子中,输入空间首先被缩减到低维空间(表示关于点/像素的信息),然后这个空间被缩减到另一个包含(边缘/形状)的空间,最后被缩减到对图像中的人脸进行分类。 卷积可以应用于 N 维。
2、Conv1D
一维卷积,通常用于序列数据集(但也可用于其他用例)。 它们可用于从输入序列中提取局部 1D 子序列并识别卷积窗口内的局部模式。 下图显示了如何将一维卷积滤波器应用于序列以获得新特征。 一维卷积的其他常见用途见于 NLP 领域,其中每个句子都表示为单词序列。
3、Conv2D
在过去的几年里,卷积神经网络因其对机器学习或更广泛意义上的人工智能的推动而闻名。这些网络主要应用于二维数据:具有两个维度(x 和 y)的数据,例如图像。
上图中表示的是一定数量的3x3x3内核在图像上滑动, 从左到右,然后向下一点,继续从左到右,进行逐元素乘法(就是卷积),然后生成一个小于原始输入的特征图。实际上是对原始输入图像的更抽象的总结。
因此,通过堆叠多个卷积层,可以生成代表某个平均对象的某个输入的非常抽象的表示,这使得可以将它们分类。
4、 Conv3D
3D卷积层,代替输入图像中的三个维度(两个图像维度和通道维度,将拥有四个维度:两个图像维度、时间/高度维度和通道维度)。因此,特征图也是三维的。这意味着过滤器在三个维度上移动而不是两个维度:不仅从左到右和从上到下,而且还向前和向后移动。因此,就所需的计算量更大,但相对的特征提取就更丰富。
二、3D数据集
获取3D点云的方式主要以下几种:
1、RGB-D 设备:Google Tango、Microsoft Kinect等。
2、激光雷达。
3、从多个图像进行 3D 重建。
Kaggle提供的3D MNIST 数据集是对我们用来创建例如常规 CNN的原始 MNIST 数据集的改编。该数据集的作者通过点云将二维数据转换为3D,如下:
数据集下载
链接:https://pan.baidu.com/s/1y-kNJdZlyRBFqPjgkSyGLA
提取码:ow2h
三、参考代码
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Conv3D, MaxPooling3D, Dropout
from tensorflow.keras.utils import to_categorical
import h5py
import numpy as np
import matplotlib.pyplot as plt
# -- Preparatory code --
# Model configuration
batch_size = 100
no_epochs = 30
learning_rate = 0.001
no_classes = 10
validation_split = 0.2
verbosity = 1
# 将 1D 矢量转换为 3D 值
# https://www.kaggle.com/daavoo/3d-mnist
def array_to_color(array, cmap="Oranges"):
s_m = plt.cm.ScalarMappable(cmap=cmap)
return s_m.to_rgba(array)[:, :-1]
# 将数据重塑为 Conv3D 图层可以处理的格式。
def rgb_data_transform(data):
data_t = []
for i in range(data.shape[0]):
data_t.append(array_to_color(data[i]).reshape(16, 16, 16, 3))
return np.asarray(data_t, dtype=np.float32)
# Load the HDF5 data file
with h5py.File("full_dataset_vectors.h5", "r") as hf:
# Split the data into training/test features/targets
X_train = hf["X_train"][:]
targets_train = hf["y_train"][:]
X_test = hf["X_test"][:]
targets_test = hf["y_test"][:]
# Determine sample shape
sample_shape = (16, 16, 16, 3)
# Reshape data into 3D format
X_train = rgb_data_transform(X_train)
X_test = rgb_data_transform(X_test)
# 将目标向量转换为分类目标
targets_train = to_categorical(targets_train).astype(np.integer)
targets_test = to_categorical(targets_test).astype(np.integer)
# 创建模型
model = Sequential()
model.add(
Conv3D(32, kernel_size=(3, 3, 3), activation='relu', kernel_initializer='he_uniform', input_shape=sample_shape))
model.add(MaxPooling3D(pool_size=(2, 2, 2)))
model.add(Dropout(0.5))
model.add(Conv3D(64, kernel_size=(3, 3, 3), activation='relu', kernel_initializer='he_uniform'))
model.add(MaxPooling3D(pool_size=(2, 2, 2)))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(no_classes, activation='softmax'))
# Compile the model
model.compile(loss=tf.keras.losses.categorical_crossentropy,
optimizer=tf.keras.optimizers.Adam(lr=learning_rate),
metrics=['accuracy'])
# Fit data to model
history = model.fit(X_train, targets_train,
batch_size=batch_size,
epochs=no_epochs,
verbose=verbosity,
validation_split=validation_split)
model.save('3dmodel.h5')
# 生成泛化指标
score = model.evaluate(X_test, targets_test, verbose=0)
print(f'Test loss: {score[0]} / Test accuracy: {score[1]}')
# Plot history: Categorical crossentropy & Accuracy
plt.plot(history.history['loss'], label='Categorical crossentropy (training data)')
plt.plot(history.history['val_loss'], label='Categorical crossentropy (validation data)')
plt.plot(history.history['accuracy'], label='Accuracy (training data)')
plt.plot(history.history['val_accuracy'], label='Accuracy (validation data)')
plt.title('Model performance for 3D MNIST Keras Conv3D example')
plt.ylabel('Loss value')
plt.xlabel('No. epoch')
plt.legend(loc="upper left")
plt.show()
训练30 epochs的结果,准确率并不高,仅以了解Conv3D。