本文主要介绍怎么用keras实现你自己的3D卷积网络。
首先要介绍什么是3D卷积网络,然后3D和2D卷积网络的不同点。最后一步一步使用keras去实现自己的3D卷积网络。
什么是3D卷积网络 3D卷积网络不管怎么说和2D卷积网络都是非常相似的。以下是它们的不同点。
3D卷积层
下图是2D卷积的方式,输入层是一个4x4矩阵,滤波器是一个3x3的矩阵,卷积操作是滤波器对输入层每一项进行相乘。然后得到一个2x2矩阵。
2d卷积
3D卷积
填充选项和 slides 选项的工作方式相同。
3d MaxPool Layers
2d Maxpool Layers (2x2 filter) 是取一个小的2x2矩阵的最大元素,我们把它从输入中取出来。
最大池化
现在3D的最大池化 Maxpool (2x2x2) , 我们在宽度为2的立方体中寻找最大元素。此多维数据集表示由输入的2x2x2区域分隔的空格
注意,操作的数量(与2d CNN层相比)乘以所使用的过滤器的大小(不管该层是Maxpool还是卷积),也乘以输入本身的大小。
三维数据集
3维点云数据是什么样子的,下面是从数据集中显示的其中一个。
数据
数据集的下载可以通过以下网址进行下载。
预处理与实现
可以自己尝试使用的Kaggle数据集上的代码:
需要导入的库如下:
import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" #if like me you do not have a lot of memory in your GPU
os.environ["CUDA_VISIBLE_DEVICES"] = "" #then these two lines force keras to use your CPU
import keras
from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv3D, MaxPooling3D, Dropout, BatchNormalization
from keras.utils import to_categorical
import numpy as np
import matplotlib.pyplot as plt
import h5py
首先对数据集进行预处理,下面代码是对数据集进行处理:
def array_to_color(array, cmap="Oranges"):
s_m = plt.cm.ScalarMappable(cmap=cmap)
return s_m.to_rgba(array)[:,:-1]
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)
数据集存储为h5文件,因此要提取实际的数据点,需要从h5文件中读取数据,并使用 to_categorical函数将其转换为向量。在这一步中,我们也为交叉验证做准备
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)
# Convert target vectors to categorical targets
targets_train = to_categorical(targets_train).astype(np.integer)
targets_test = to_categorical(targets_test).astype(np.integer)
下面是3D模型的构建,其代码如下,使用的是比较简单的网络:
# Create the model
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(BatchNormalization(center=True, scale=True))
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(BatchNormalization(center=True, scale=True))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(10, activation='softmax'))
# Compile the model
model.compile(loss='categorical_crossentropy',
optimizer=keras.optimizers.Adam(lr=0.001),
metrics=['accuracy'])
model.summary()
# Fit data to model
history = model.fit(X_train, targets_train,
batch_size=128,
epochs=40,
verbose=1,
validation_split=0.3)
注意,与2d cnn相比,相同层数的参数数要高得多。
下面是经过一段时间的train,得到了一个小样本的训练结果。
结果
3D用来干什么
有很多3D cnn的应用程序
到此结束。不同的观点可以讨论,下面是代码的地址