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()


以上