Keras 2 : examples : PointNet によるポイントクラウド分類 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 12/06/2021 (keras 2.7.0)
* 本ページは、Keras の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
- Code examples : Computer Vision : Point cloud classification with PointNet (Author: David Griffiths)
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- 人工知能研究開発支援
- 人工知能研修サービス(経営者層向けオンサイト研修)
- テクニカルコンサルティングサービス
- 実証実験(プロトタイプ構築)
- アプリケーションへの実装
- 人工知能研修サービス
- PoC(概念実証)を失敗させないための支援
- テレワーク & オンライン授業を支援
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
- 株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
- E-Mail:sales-info@classcat.com ; WebSite: www.classcat.com ; Facebook
Keras 2 : examples : PointNet によるポイントクラウド分類
Description: ModelNet10 分類のための PoinetNet の実装。
イントロダクション
順序付けられていない 3D ポイントセット i.e. ポイントクラウドの分類、検出とセグメンテーションはコンピュータビジョンの中核的な問題です。このサンプルは将来性のあるポイントクラウドの深層学習論文 PointNet (Qi et al., 2017) を実装します。PointNet の詳細な紹介は このブログ投稿 を見てください。
セットアップ
colab を使用しているのであれば、最初に “!pip install trimesh” で trimesh をインストールしてください。
import os
import glob
import trimesh
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from matplotlib import pyplot as plt
tf.random.set_seed(1234)
データセットのロード
ModelNet10 モデルデータセットを使用します、これは ModelNet40 の小さい 10 クラス版です。最初にデータをダウンロードします :
DATA_DIR = tf.keras.utils.get_file(
"modelnet.zip",
"http://3dvision.princeton.edu/projects/2014/3DShapeNets/ModelNet10.zip",
extract=True,
)
DATA_DIR = os.path.join(os.path.dirname(DATA_DIR), "ModelNet10")
Downloading data from http://3dvision.princeton.edu/projects/2014/3DShapeNets/ModelNet10.zip 473407488/473402300 [==============================] - 13s 0us/step
.off メッシュファイルを読んで可視化するために trimesh パッケージを使用できます。
mesh = trimesh.load(os.path.join(DATA_DIR, "chair/train/chair_0001.off"))
mesh.show()
メッシュファイルをポイントクラウドに変換するには最初にメッシュサーフェス上のポイントからサンプリングする必要があります。.sample() は一様なランダムサンプリングを実行します。ここでは 2048 の位置でサンプリングして matplotlib で可視化します。
points = mesh.sample(2048)
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111, projection="3d")
ax.scatter(points[:, 0], points[:, 1], points[:, 2])
ax.set_axis_off()
plt.show()
tf.data.Dataset() を生成するためには、最初に ModelNet データフォルダをパースする必要があります。各メッシュはロードされてポイントクラウドにサンプリングされた後、標準 python リストに追加されて numpy 配列に変換されます。また、現在のインデックス列挙 (= enumerate) 値をオブジェクトラベルとしてストアしてこれを後で recall するために辞書を使用します。
def parse_dataset(num_points=2048):
train_points = []
train_labels = []
test_points = []
test_labels = []
class_map = {}
folders = glob.glob(os.path.join(DATA_DIR, "[!README]*"))
for i, folder in enumerate(folders):
print("processing class: {}".format(os.path.basename(folder)))
# store folder name with ID so we can retrieve later
class_map[i] = folder.split("/")[-1]
# gather all files
train_files = glob.glob(os.path.join(folder, "train/*"))
test_files = glob.glob(os.path.join(folder, "test/*"))
for f in train_files:
train_points.append(trimesh.load(f).sample(num_points))
train_labels.append(i)
for f in test_files:
test_points.append(trimesh.load(f).sample(num_points))
test_labels.append(i)
return (
np.array(train_points),
np.array(test_points),
np.array(train_labels),
np.array(test_labels),
class_map,
)
サンプリングするポイント数とバッチサイズを設定してデータセットをパースします。これは完了まで ~5 分かかる可能性があります。
NUM_POINTS = 2048
NUM_CLASSES = 10
BATCH_SIZE = 32
train_points, test_points, train_labels, test_labels, CLASS_MAP = parse_dataset(
NUM_POINTS
)
processing class: bathtub processing class: desk processing class: monitor processing class: sofa processing class: chair processing class: toilet processing class: dresser processing class: table processing class: bed processing class: night_stand
データは tf.data.Dataset() オブジェクトに読み込むことができます。shuffle buffer size をデータセット全体のサイズに設定します、この前にデータはクラスで順序付けられているからです。ポイントクラウド・データを処理するときデータ増強は重要です。訓練データセットを jitter してシャッフルするために増強関数を作成します。
def augment(points, label):
# jitter points
points += tf.random.uniform(points.shape, -0.005, 0.005, dtype=tf.float64)
# shuffle points
points = tf.random.shuffle(points)
return points, label
train_dataset = tf.data.Dataset.from_tensor_slices((train_points, train_labels))
test_dataset = tf.data.Dataset.from_tensor_slices((test_points, test_labels))
train_dataset = train_dataset.shuffle(len(train_points)).map(augment).batch(BATCH_SIZE)
test_dataset = test_dataset.shuffle(len(test_points)).batch(BATCH_SIZE)
モデルの構築
各畳み込みと (最終層を例外として) 完全結合層は Convolution / Dense -> バッチ正規化 -> ReLU 活性から構成されます。
def conv_bn(x, filters):
x = layers.Conv1D(filters, kernel_size=1, padding="valid")(x)
x = layers.BatchNormalization(momentum=0.0)(x)
return layers.Activation("relu")(x)
def dense_bn(x, filters):
x = layers.Dense(filters)(x)
x = layers.BatchNormalization(momentum=0.0)(x)
return layers.Activation("relu")(x)
PointNet は 2 つの中核コンポーネントから構成されます。プライマリ MLP ネットワーク、そして transformer ネット (T-net) です。T-net は自身のミニネットワークによりアフィン変換行列を学習することが目的です。T-net は 2 回使用されます。1 度目は入力特徴 (n, 3) を基準の (= canonical) 表現に変換します。2 番目は特徴空間 (n, 3) のアラインメントのためのアフィン変換です。原論文のように、変換を直交行列 (i.e. ||X*X^T – I|| = 0) に近くなるように制約します (i.e. ||X*X^T – I|| = 0)。
class OrthogonalRegularizer(keras.regularizers.Regularizer):
def __init__(self, num_features, l2reg=0.001):
self.num_features = num_features
self.l2reg = l2reg
self.eye = tf.eye(num_features)
def __call__(self, x):
x = tf.reshape(x, (-1, self.num_features, self.num_features))
xxt = tf.tensordot(x, x, axes=(2, 2))
xxt = tf.reshape(xxt, (-1, self.num_features, self.num_features))
return tf.reduce_sum(self.l2reg * tf.square(xxt - self.eye))
そして T-net 層を構築する一般的な関数を定義できます。
def tnet(inputs, num_features):
# Initalise bias as the indentity matrix
bias = keras.initializers.Constant(np.eye(num_features).flatten())
reg = OrthogonalRegularizer(num_features)
x = conv_bn(inputs, 32)
x = conv_bn(x, 64)
x = conv_bn(x, 512)
x = layers.GlobalMaxPooling1D()(x)
x = dense_bn(x, 256)
x = dense_bn(x, 128)
x = layers.Dense(
num_features * num_features,
kernel_initializer="zeros",
bias_initializer=bias,
activity_regularizer=reg,
)(x)
feat_T = layers.Reshape((num_features, num_features))(x)
# Apply affine transformation to input features
return layers.Dot(axes=(2, 1))([inputs, feat_T])
次に主要ネットワークが同じように実装できます、そこでは t-net ミニモデルはグラフの層内でドロップできます。ここでは原論文で公開されているネットワークを再現しますが、小さい 10 クラス ModelNet データセットを使用していますので、各層での重みの数が半分です。
inputs = keras.Input(shape=(NUM_POINTS, 3))
x = tnet(inputs, 3)
x = conv_bn(x, 32)
x = conv_bn(x, 32)
x = tnet(x, 32)
x = conv_bn(x, 32)
x = conv_bn(x, 64)
x = conv_bn(x, 512)
x = layers.GlobalMaxPooling1D()(x)
x = dense_bn(x, 256)
x = layers.Dropout(0.3)(x)
x = dense_bn(x, 128)
x = layers.Dropout(0.3)(x)
outputs = layers.Dense(NUM_CLASSES, activation="softmax")(x)
model = keras.Model(inputs=inputs, outputs=outputs, name="pointnet")
model.summary()
Model: "pointnet" __________________________________________________________________________________________________ Layer (type) Output Shape Param # Connected to ================================================================================================== input_1 (InputLayer) [(None, 2048, 3)] 0 __________________________________________________________________________________________________ conv1d (Conv1D) (None, 2048, 32) 128 input_1[0][0] __________________________________________________________________________________________________ batch_normalization (BatchNorma (None, 2048, 32) 128 conv1d[0][0] __________________________________________________________________________________________________ activation (Activation) (None, 2048, 32) 0 batch_normalization[0][0] __________________________________________________________________________________________________ conv1d_1 (Conv1D) (None, 2048, 64) 2112 activation[0][0] __________________________________________________________________________________________________ batch_normalization_1 (BatchNor (None, 2048, 64) 256 conv1d_1[0][0] __________________________________________________________________________________________________ activation_1 (Activation) (None, 2048, 64) 0 batch_normalization_1[0][0] __________________________________________________________________________________________________ conv1d_2 (Conv1D) (None, 2048, 512) 33280 activation_1[0][0] __________________________________________________________________________________________________ batch_normalization_2 (BatchNor (None, 2048, 512) 2048 conv1d_2[0][0] __________________________________________________________________________________________________ activation_2 (Activation) (None, 2048, 512) 0 batch_normalization_2[0][0] __________________________________________________________________________________________________ global_max_pooling1d (GlobalMax (None, 512) 0 activation_2[0][0] __________________________________________________________________________________________________ dense (Dense) (None, 256) 131328 global_max_pooling1d[0][0] __________________________________________________________________________________________________ batch_normalization_3 (BatchNor (None, 256) 1024 dense[0][0] __________________________________________________________________________________________________ activation_3 (Activation) (None, 256) 0 batch_normalization_3[0][0] __________________________________________________________________________________________________ dense_1 (Dense) (None, 128) 32896 activation_3[0][0] __________________________________________________________________________________________________ batch_normalization_4 (BatchNor (None, 128) 512 dense_1[0][0] __________________________________________________________________________________________________ activation_4 (Activation) (None, 128) 0 batch_normalization_4[0][0] __________________________________________________________________________________________________ dense_2 (Dense) (None, 9) 1161 activation_4[0][0] __________________________________________________________________________________________________ reshape (Reshape) (None, 3, 3) 0 dense_2[0][0] __________________________________________________________________________________________________ dot (Dot) (None, 2048, 3) 0 input_1[0][0] reshape[0][0] __________________________________________________________________________________________________ conv1d_3 (Conv1D) (None, 2048, 32) 128 dot[0][0] __________________________________________________________________________________________________ batch_normalization_5 (BatchNor (None, 2048, 32) 128 conv1d_3[0][0] __________________________________________________________________________________________________ activation_5 (Activation) (None, 2048, 32) 0 batch_normalization_5[0][0] __________________________________________________________________________________________________ conv1d_4 (Conv1D) (None, 2048, 32) 1056 activation_5[0][0] __________________________________________________________________________________________________ batch_normalization_6 (BatchNor (None, 2048, 32) 128 conv1d_4[0][0] __________________________________________________________________________________________________ activation_6 (Activation) (None, 2048, 32) 0 batch_normalization_6[0][0] __________________________________________________________________________________________________ conv1d_5 (Conv1D) (None, 2048, 32) 1056 activation_6[0][0] __________________________________________________________________________________________________ batch_normalization_7 (BatchNor (None, 2048, 32) 128 conv1d_5[0][0] __________________________________________________________________________________________________ activation_7 (Activation) (None, 2048, 32) 0 batch_normalization_7[0][0] __________________________________________________________________________________________________ conv1d_6 (Conv1D) (None, 2048, 64) 2112 activation_7[0][0] __________________________________________________________________________________________________ batch_normalization_8 (BatchNor (None, 2048, 64) 256 conv1d_6[0][0] __________________________________________________________________________________________________ activation_8 (Activation) (None, 2048, 64) 0 batch_normalization_8[0][0] __________________________________________________________________________________________________ conv1d_7 (Conv1D) (None, 2048, 512) 33280 activation_8[0][0] __________________________________________________________________________________________________ batch_normalization_9 (BatchNor (None, 2048, 512) 2048 conv1d_7[0][0] __________________________________________________________________________________________________ activation_9 (Activation) (None, 2048, 512) 0 batch_normalization_9[0][0] __________________________________________________________________________________________________ global_max_pooling1d_1 (GlobalM (None, 512) 0 activation_9[0][0] __________________________________________________________________________________________________ dense_3 (Dense) (None, 256) 131328 global_max_pooling1d_1[0][0] __________________________________________________________________________________________________ batch_normalization_10 (BatchNo (None, 256) 1024 dense_3[0][0] __________________________________________________________________________________________________ activation_10 (Activation) (None, 256) 0 batch_normalization_10[0][0] __________________________________________________________________________________________________ dense_4 (Dense) (None, 128) 32896 activation_10[0][0] __________________________________________________________________________________________________ batch_normalization_11 (BatchNo (None, 128) 512 dense_4[0][0] __________________________________________________________________________________________________ activation_11 (Activation) (None, 128) 0 batch_normalization_11[0][0] __________________________________________________________________________________________________ dense_5 (Dense) (None, 1024) 132096 activation_11[0][0] __________________________________________________________________________________________________ reshape_1 (Reshape) (None, 32, 32) 0 dense_5[0][0] __________________________________________________________________________________________________ dot_1 (Dot) (None, 2048, 32) 0 activation_6[0][0] reshape_1[0][0] __________________________________________________________________________________________________ conv1d_8 (Conv1D) (None, 2048, 32) 1056 dot_1[0][0] __________________________________________________________________________________________________ batch_normalization_12 (BatchNo (None, 2048, 32) 128 conv1d_8[0][0] __________________________________________________________________________________________________ activation_12 (Activation) (None, 2048, 32) 0 batch_normalization_12[0][0] __________________________________________________________________________________________________ conv1d_9 (Conv1D) (None, 2048, 64) 2112 activation_12[0][0] __________________________________________________________________________________________________ batch_normalization_13 (BatchNo (None, 2048, 64) 256 conv1d_9[0][0] __________________________________________________________________________________________________ activation_13 (Activation) (None, 2048, 64) 0 batch_normalization_13[0][0] __________________________________________________________________________________________________ conv1d_10 (Conv1D) (None, 2048, 512) 33280 activation_13[0][0] __________________________________________________________________________________________________ batch_normalization_14 (BatchNo (None, 2048, 512) 2048 conv1d_10[0][0] __________________________________________________________________________________________________ activation_14 (Activation) (None, 2048, 512) 0 batch_normalization_14[0][0] __________________________________________________________________________________________________ global_max_pooling1d_2 (GlobalM (None, 512) 0 activation_14[0][0] __________________________________________________________________________________________________ dense_6 (Dense) (None, 256) 131328 global_max_pooling1d_2[0][0] __________________________________________________________________________________________________ batch_normalization_15 (BatchNo (None, 256) 1024 dense_6[0][0] __________________________________________________________________________________________________ activation_15 (Activation) (None, 256) 0 batch_normalization_15[0][0] __________________________________________________________________________________________________ dropout (Dropout) (None, 256) 0 activation_15[0][0] __________________________________________________________________________________________________ dense_7 (Dense) (None, 128) 32896 dropout[0][0] __________________________________________________________________________________________________ batch_normalization_16 (BatchNo (None, 128) 512 dense_7[0][0] __________________________________________________________________________________________________ activation_16 (Activation) (None, 128) 0 batch_normalization_16[0][0] __________________________________________________________________________________________________ dropout_1 (Dropout) (None, 128) 0 activation_16[0][0] __________________________________________________________________________________________________ dense_8 (Dense) (None, 10) 1290 dropout_1[0][0] ================================================================================================== Total params: 748,979 Trainable params: 742,899 Non-trainable params: 6,080
モデルの訓練
モデルが定義されたので .compile() と .fit() を使用して他の標準的な分類モデルのように訓練できます。
model.compile(
loss="sparse_categorical_crossentropy",
optimizer=keras.optimizers.Adam(learning_rate=0.001),
metrics=["sparse_categorical_accuracy"],
)
model.fit(train_dataset, epochs=20, validation_data=test_dataset)
Epoch 1/20 125/125 [==============================] - 28s 221ms/step - loss: 3.5897 - sparse_categorical_accuracy: 0.2724 - val_loss: 5804697916006203392.0000 - val_sparse_categorical_accuracy: 0.3073 Epoch 2/20 125/125 [==============================] - 27s 215ms/step - loss: 3.1970 - sparse_categorical_accuracy: 0.3443 - val_loss: 836343949164544.0000 - val_sparse_categorical_accuracy: 0.3425 Epoch 3/20 125/125 [==============================] - 27s 215ms/step - loss: 2.8959 - sparse_categorical_accuracy: 0.4260 - val_loss: 15107376738729984.0000 - val_sparse_categorical_accuracy: 0.3084 Epoch 4/20 125/125 [==============================] - 27s 215ms/step - loss: 2.7148 - sparse_categorical_accuracy: 0.4939 - val_loss: 6823221.0000 - val_sparse_categorical_accuracy: 0.3304 Epoch 5/20 125/125 [==============================] - 27s 215ms/step - loss: 2.5500 - sparse_categorical_accuracy: 0.5560 - val_loss: 675110905872323182592.0000 - val_sparse_categorical_accuracy: 0.4493 Epoch 6/20 125/125 [==============================] - 27s 215ms/step - loss: 2.3595 - sparse_categorical_accuracy: 0.6081 - val_loss: 600389124096.0000 - val_sparse_categorical_accuracy: 0.5749 Epoch 7/20 125/125 [==============================] - 27s 215ms/step - loss: 2.2485 - sparse_categorical_accuracy: 0.6394 - val_loss: 680423464582760103936.0000 - val_sparse_categorical_accuracy: 0.4912 Epoch 8/20 125/125 [==============================] - 27s 215ms/step - loss: 2.1945 - sparse_categorical_accuracy: 0.6575 - val_loss: 44108689408.0000 - val_sparse_categorical_accuracy: 0.6410 Epoch 9/20 125/125 [==============================] - 27s 215ms/step - loss: 2.1318 - sparse_categorical_accuracy: 0.6725 - val_loss: 873314112.0000 - val_sparse_categorical_accuracy: 0.6112 Epoch 10/20 125/125 [==============================] - 27s 215ms/step - loss: 2.0140 - sparse_categorical_accuracy: 0.7018 - val_loss: 13168980992.0000 - val_sparse_categorical_accuracy: 0.6784 Epoch 11/20 125/125 [==============================] - 27s 215ms/step - loss: 1.9929 - sparse_categorical_accuracy: 0.7056 - val_loss: 36888236785664.0000 - val_sparse_categorical_accuracy: 0.6586 Epoch 12/20 125/125 [==============================] - 27s 215ms/step - loss: 1.9542 - sparse_categorical_accuracy: 0.7166 - val_loss: 85375.9844 - val_sparse_categorical_accuracy: 0.7026 Epoch 13/20 125/125 [==============================] - 27s 215ms/step - loss: 1.8648 - sparse_categorical_accuracy: 0.7447 - val_loss: 7.7962 - val_sparse_categorical_accuracy: 0.5441 Epoch 14/20 125/125 [==============================] - 27s 215ms/step - loss: 1.9016 - sparse_categorical_accuracy: 0.7444 - val_loss: 66469.9062 - val_sparse_categorical_accuracy: 0.6134 Epoch 15/20 125/125 [==============================] - 27s 215ms/step - loss: 1.8003 - sparse_categorical_accuracy: 0.7695 - val_loss: 519227186348032.0000 - val_sparse_categorical_accuracy: 0.6949 Epoch 16/20 125/125 [==============================] - 27s 215ms/step - loss: 1.8019 - sparse_categorical_accuracy: 0.7702 - val_loss: 5263462156149188460544.0000 - val_sparse_categorical_accuracy: 0.6520 Epoch 17/20 125/125 [==============================] - 27s 215ms/step - loss: 1.7177 - sparse_categorical_accuracy: 0.7903 - val_loss: 142240048.0000 - val_sparse_categorical_accuracy: 0.7941 Epoch 18/20 125/125 [==============================] - 27s 216ms/step - loss: 1.7548 - sparse_categorical_accuracy: 0.7855 - val_loss: 2.6049 - val_sparse_categorical_accuracy: 0.5022 Epoch 19/20 125/125 [==============================] - 27s 215ms/step - loss: 1.7101 - sparse_categorical_accuracy: 0.8003 - val_loss: 1152819181305987072.0000 - val_sparse_categorical_accuracy: 0.7753 Epoch 20/20 125/125 [==============================] - 27s 215ms/step - loss: 1.6812 - sparse_categorical_accuracy: 0.8176 - val_loss: 12854714433536.0000 - val_sparse_categorical_accuracy: 0.7390 <tensorflow.python.keras.callbacks.History at 0x7f07e5dd3940>
(訳者注: 実験結果)
Epoch 1/20 125/125 [==============================] - 22s 70ms/step - loss: 3.5277 - sparse_categorical_accuracy: 0.2819 - val_loss: 6368364.5000 - val_sparse_categorical_accuracy: 0.2070 Epoch 2/20 125/125 [==============================] - 8s 66ms/step - loss: 3.0239 - sparse_categorical_accuracy: 0.3926 - val_loss: 349888905216.0000 - val_sparse_categorical_accuracy: 0.2919 Epoch 3/20 125/125 [==============================] - 8s 65ms/step - loss: 2.9007 - sparse_categorical_accuracy: 0.4520 - val_loss: 426501728645414912.0000 - val_sparse_categorical_accuracy: 0.4769 Epoch 4/20 125/125 [==============================] - 8s 65ms/step - loss: 2.6231 - sparse_categorical_accuracy: 0.5350 - val_loss: 365586408275968.0000 - val_sparse_categorical_accuracy: 0.5518 Epoch 5/20 125/125 [==============================] - 8s 65ms/step - loss: 2.4360 - sparse_categorical_accuracy: 0.5873 - val_loss: 8039983893970944.0000 - val_sparse_categorical_accuracy: 0.5297 Epoch 6/20 125/125 [==============================] - 8s 66ms/step - loss: 2.2732 - sparse_categorical_accuracy: 0.6352 - val_loss: 67042457550482189582336.0000 - val_sparse_categorical_accuracy: 0.5253 Epoch 7/20 125/125 [==============================] - 8s 65ms/step - loss: 2.2531 - sparse_categorical_accuracy: 0.6412 - val_loss: 6522547994624.0000 - val_sparse_categorical_accuracy: 0.4824 Epoch 8/20 125/125 [==============================] - 8s 65ms/step - loss: 2.1496 - sparse_categorical_accuracy: 0.6765 - val_loss: 448372045714030592000.0000 - val_sparse_categorical_accuracy: 0.5727 Epoch 9/20 125/125 [==============================] - 8s 65ms/step - loss: 2.1125 - sparse_categorical_accuracy: 0.6723 - val_loss: 129756599156736.0000 - val_sparse_categorical_accuracy: 0.6024 Epoch 10/20 125/125 [==============================] - 8s 65ms/step - loss: 2.0435 - sparse_categorical_accuracy: 0.6953 - val_loss: 1085065035513856.0000 - val_sparse_categorical_accuracy: 0.5980 Epoch 11/20 125/125 [==============================] - 8s 65ms/step - loss: 1.8759 - sparse_categorical_accuracy: 0.7469 - val_loss: 4563005440.0000 - val_sparse_categorical_accuracy: 0.6377 Epoch 12/20 125/125 [==============================] - 8s 65ms/step - loss: 1.9058 - sparse_categorical_accuracy: 0.7497 - val_loss: 2.7094 - val_sparse_categorical_accuracy: 0.4581 Epoch 13/20 125/125 [==============================] - 8s 65ms/step - loss: 1.8625 - sparse_categorical_accuracy: 0.7582 - val_loss: 226794225664.0000 - val_sparse_categorical_accuracy: 0.7577 Epoch 14/20 125/125 [==============================] - 8s 65ms/step - loss: 1.7204 - sparse_categorical_accuracy: 0.7975 - val_loss: 3.1878 - val_sparse_categorical_accuracy: 0.4692 Epoch 15/20 125/125 [==============================] - 8s 65ms/step - loss: 1.7921 - sparse_categorical_accuracy: 0.7785 - val_loss: 92965546511902441472.0000 - val_sparse_categorical_accuracy: 0.6806 Epoch 16/20 125/125 [==============================] - 8s 65ms/step - loss: 1.7961 - sparse_categorical_accuracy: 0.7900 - val_loss: 2.6489 - val_sparse_categorical_accuracy: 0.6839 Epoch 17/20 125/125 [==============================] - 8s 65ms/step - loss: 1.7213 - sparse_categorical_accuracy: 0.8028 - val_loss: 1773427039053488848896.0000 - val_sparse_categorical_accuracy: 0.7236 Epoch 18/20 125/125 [==============================] - 8s 64ms/step - loss: 1.7182 - sparse_categorical_accuracy: 0.7950 - val_loss: 309250944.0000 - val_sparse_categorical_accuracy: 0.7643 Epoch 19/20 125/125 [==============================] - 8s 65ms/step - loss: 1.6680 - sparse_categorical_accuracy: 0.8153 - val_loss: 1098322592923648.0000 - val_sparse_categorical_accuracy: 0.8315 Epoch 20/20 125/125 [==============================] - 8s 64ms/step - loss: 1.6444 - sparse_categorical_accuracy: 0.8218 - val_loss: 17504475136.0000 - val_sparse_categorical_accuracy: 0.8370 CPU times: user 2min 56s, sys: 8.36 s, total: 3min 5s Wall time: 3min 19s
予測の可視化
訓練済みモデル性能を可視化するために matplotlib を使用できます。
data = test_dataset.take(1)
points, labels = list(data)[0]
points = points[:8, ...]
labels = labels[:8, ...]
# run test data through model
preds = model.predict(points)
preds = tf.math.argmax(preds, -1)
points = points.numpy()
# plot points with predicted class and label
fig = plt.figure(figsize=(15, 10))
for i in range(8):
ax = fig.add_subplot(2, 4, i + 1, projection="3d")
ax.scatter(points[i, :, 0], points[i, :, 1], points[i, :, 2])
ax.set_title(
"pred: {:}, label: {:}".format(
CLASS_MAP[preds[i].numpy()], CLASS_MAP[labels.numpy()[i]]
)
)
ax.set_axis_off()
plt.show()
以上