FC2カウンター FPGAの部屋 TensorFlow, Keras
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

白線間走行用CNNをKerasで学習する3(各層の重みとバイアスをCのヘッダファイルに変換)

白線間走行用CNNをKerasで学習する2(各層の重みとバイアスの統計情報)”の続き。

前回は、学習した結果の重みやバイアスの統計情報を見た。今回は、その重みやバイアスをPython コードを使用して C 言語のヘッダファイルに変換してみよう。

重みやバイアスを C のヘッダファイルに変換するPython コードは以下のブログ記事を見てほしい。

TensorFlow + Kerasを使ってみた9(畳み込み層の重みをC のヘッダに変換)
TensorFlow + Kerasを使ってみた10(バイアスをC のヘッダに変換)


これらのPython コードを使用して、畳み込み層、全結合層第1層目、全結合層第2層目の重みとバイアスを C ヘッダファイルに変換した。

畳み込み層の重みとバイアスの C ヘッダファイルを示す。
keras_mnist_zero_13_180729.png

keras_mnist_zero_14_180729.png

全結合層第1層目の重みとバイアスの C ヘッダファイルの一部を示す。
keras_mnist_zero_15_180729.png

keras_mnist_zero_16_180729.png

全結合層第2層目の重みとバイアスの C ヘッダファイルの一部を示す。
keras_mnist_zero_17_180729.png

keras_mnist_zero_18_180729.png

全結合層第2層目の重みは、最大値が 1.27 程度なのだが、ハードウェアにするときの固定小数点のビット幅は、整数部が 1 ビット、小数部が 8 ビットなので、表現できる数は、-1.0 ~ (1.0 - 1/256) なので、1.27 は飽和演算されて、1.0 - 1/256 に変更される。
  1. 2018年07月29日 05:45 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

白線間走行用CNNをKerasで学習する2(各層の重みとバイアスの統計情報)

白線間走行用CNNをKerasで学習する”の続き。

前回は、白線間走行用CNN をKeras で学習できた。今回は、学習した結果の重みやバイアスの統計情報を見ていこう。

まずは、層の構成から見ていく。
_________________________________________________________________

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_22 (Conv2D)           (None, 6, 52, 2)          52        
_________________________________________________________________
activation_64 (Activation)   (None, 6, 52, 2)          0         
_________________________________________________________________
max_pooling2d_22 (MaxPooling (None, 3, 26, 2)          0         
_________________________________________________________________
flatten_22 (Flatten)         (None, 156)               0         
_________________________________________________________________
dense_43 (Dense)             (None, 100)               15700     
_________________________________________________________________
activation_65 (Activation)   (None, 100)               0         
_________________________________________________________________
dense_44 (Dense)             (None, 3)                 303       
_________________________________________________________________
activation_66 (Activation)   (None, 3)                 0         
=================================================================
Total params: 16,055
Trainable params: 16,055
Non-trainable params: 0


畳み込み層の統計情報を見ていく。

conv_layer_bias = [-0.3386867 -0.5459513]
np.max(conv_layer_weight) = 0.6478661894798279
np.min(conv_layer_weight) = -0.44461962580680847
np.max(abs_conv_layer_weight) = 0.6478661894798279
np.min(abs_conv_layer_weight) = 0.01398547738790512
np.max(conv_layer_bias) = -0.3386867046356201
np.min(conv_layer_bias) = -0.5459513068199158
np.max(abs_conv_layer_bias) = 0.5459513068199158
np.min(abs_conv_layer_bias) = 0.3386867046356201
conv_output = (26550, 6, 52, 2)
np.std(conv_output) = 0.2930081784725189
np.max(conv_output) = 1.9703364372253418
np.min(conv_output) = -0.6579744815826416
np.max(abs_conv) = 1.9703364372253418
np.min(abs_conv) = 7.748603820800781e-07


畳み込み層の重みの最大値は約 0.65 で、最小値は約 -0.44 だった。(この下からは約を外します)
重みの絶対値の最小値は 0.014 程度だった。
バイアスの最大値は -0.34 で、最小値は -0.55 だった。バイアスの絶対値の最小値は 0.34 だった。
畳み込み層の出力の最大値は 1.97 で、最小値は -0.66 だった。
畳み込み層の重みとバイアスのグラフを示す。
keras_mnist_zero_10_180729.png

次に、全結合層第1層目の統計情報を見ていく。

np.max(dence_layer1_weight) = 0.6284171938896179
np.min(dence_layer1_weight) = -0.452088862657547
np.max(abs_dence_layer1_weight) = 0.6284171938896179
np.min(abs_dence_layer1_weight) = 2.8568319976329803e-07
np.max(dence_layer1_bias) = 0.11784756183624268
np.min(dence_layer1_bias) = -0.08143308758735657
np.max(abs_dence_layer1_bias) = 0.11784756183624268
np.min(abs_dence_layer1_bias) = 0.0
dence_layer1_output = (26550, 100)
np.std(dence_layer1_output) = 0.9401099681854248
np.max(dence_layer1_output) = 5.256106853485107
np.min(dence_layer1_output) = -5.39329195022583
np.max(abs_dence_layer1_output) = 5.39329195022583
np.min(abs_dence_layer1_output) = 8.740462362766266e-07


全結合層第1層目の重みの最大値は 0.63 、最小値は -0.45 だった。バイアスの最大値は 0.12 、最小値は -0.08 だった。
全結合層第1層目の出力の最大値は 5.26 、最小値は -5.39 だった。
全結合層第1層目の重みとバイアスのグラフを示す。
keras_mnist_zero_11_180729.png

最後に全結合層第2層目の統計情報を見ていく。

np.max(dence_layer2_weight) = 1.2727510929107666
np.min(dence_layer2_weight) = -1.23631751537323
np.max(abs_dence_layer2_weight) = 1.2727510929107666
np.min(abs_dence_layer2_weight) = 0.002743939170613885
np.max(dence_layer2_bias) = 0.009167053736746311
np.min(dence_layer2_bias) = -0.028219975531101227
np.max(abs_dence_layer2_bias) = 0.028219975531101227
np.min(abs_dence_layer2_bias) = 0.007371054962277412
dence_layer2_output = (26550, 3)
np.std(dence_layer2_output) = 5.037158012390137
np.max(dence_layer2_output) = 17.514923095703125
np.min(dence_layer2_output) = -16.942663192749023
np.max(abs_dence_layer2_output) = 17.514923095703125
np.min(abs_dence_layer2_output) = 0.00031781941652297974


全結合層第2層目の重みの最大値は 1.27 で、最小値は 0.003 だった。バイアスの最大値は 0.009 で、最小値は -0.03 だった。
全結合層第2層目の出力の最大値は 17.51 で、最小値は -16.94 だった。
全結合層第2層目の重みとバイアスのグラフを示す。
keras_mnist_zero_12_180729.png
  1. 2018年07月28日 05:15 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

白線間走行用CNNをKerasで学習する

「ゼロから作るDeep Learning」のMNISTデータを使用してKerasで学習する”で「ゼロから作るDeep Learning」のMNISTデータを使用してKerasで学習した。今回は、白線間走行用CNN をKeras で学習する。

まずは、白線間走行用CNN の学習データはデータのシャッフルができていないので、今回 Keras で学習するときにデータをシャッフルしたい。ミニバッチで学習するときに不利だと思うからだ。
Python でトレーニングデータをシャッフルするのだが、トレーニング用のラベルデータも同時にシャッフルする必要がある。どうやるか考えながら検索していると、”zip()を使って複数配列(array, list)をshuffleする-python”を見つけた。これはやりたいことにぴったりだった。
実際に使用したPython コードを示す。

(x_train, y_train), (x_test, y_test) = load_mnist(normalize=False, flatten=False)
print('x_train shape:', x_train.shape)
print('y_train shape:', y_train.shape)

# トレーニングデータとテストデータをシャッフル
trainzip = list(zip(y_train, x_train))
np.random.shuffle(trainzip)
y_train, x_train = zip(*trainzip)
x_train = np.asarray(x_train)
y_train = np.asarray(y_train)

testzip = list(zip(y_test, x_test))
np.random.shuffle(testzip)
y_test, x_test = zip(*testzip)
x_test = np.asarray(x_test)
y_test = np.asarray(y_test)


結果を示す。
keras_mnist_zero_6_180727.png
keras_mnist_zero_7_180727.png
keras_mnist_zero_8_180727.png

x_train shape: (34650, 1, 10, 56)
y_train shape: (34650,)
x_train shape: (34650, 10, 56, 1)
34650 train samples
26550 test samples
Train on 34650 samples, validate on 26550 samples
Epoch 1/8
34650/34650 [==============================] - 6s 170us/step - loss: 0.5659 - acc: 0.7551 - val_loss: 0.4968 - val_acc: 0.7847
Epoch 2/8
34650/34650 [==============================] - 5s 152us/step - loss: 0.2709 - acc: 0.8988 - val_loss: 0.2481 - val_acc: 0.9006
Epoch 3/8
34650/34650 [==============================] - 5s 152us/step - loss: 0.1726 - acc: 0.9386 - val_loss: 0.1631 - val_acc: 0.9456
Epoch 4/8
34650/34650 [==============================] - 5s 158us/step - loss: 0.1273 - acc: 0.9540 - val_loss: 0.2028 - val_acc: 0.9261
Epoch 5/8
34650/34650 [==============================] - 5s 158us/step - loss: 0.1025 - acc: 0.9616 - val_loss: 0.1651 - val_acc: 0.9376
Epoch 6/8
34650/34650 [==============================] - 6s 163us/step - loss: 0.0861 - acc: 0.9673 - val_loss: 0.1170 - val_acc: 0.9532
Epoch 7/8
34650/34650 [==============================] - 5s 154us/step - loss: 0.0760 - acc: 0.9705 - val_loss: 0.1007 - val_acc: 0.9618
Epoch 8/8
34650/34650 [==============================] - 5s 153us/step - loss: 0.0672 - acc: 0.9733 - val_loss: 0.0957 - val_acc: 0.9647


テストデータでの精度は 0.9647 だった。
この白線間走行用CNN の学習は、うまく行かないことも多い。何度もトライして一番良さそうな値を採用した。
epochs ごとの精度のグラフを示す。
keras_mnist_zero_9_180727.png

テストデータがあばれているのが分かる。
最後にPython コードを貼っておく。

# My Mnist CNN (Convolution layerの特徴マップは5個)
# Conv2D - ReLU - MaxPooling - Dence - ReLU - Dence
# 2018/05/25 by marsee
# Keras / Tensorflowで始めるディープラーニング入門 https://qiita.com/yampy/items/706d44417c433e68db0d
# のPythonコードを再利用させて頂いている

import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
from dataset_curve.curve_dataset import load_mnist
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D, Activation
from keras import backend as K

import numpy as np

batch_size = 128
num_classes = 3
epochs = 8

img_rows, img_cols = 10, 56

(x_train, y_train), (x_test, y_test) = load_mnist(normalize=False, flatten=False)
print('x_train shape:', x_train.shape)
print('y_train shape:', y_train.shape)

# トレーニングデータとテストデータをシャッフル
trainzip = list(zip(y_train, x_train))
np.random.shuffle(trainzip)
y_train, x_train = zip(*trainzip)
x_train = np.asarray(x_train)
y_train = np.asarray(y_train)

testzip = list(zip(y_test, x_test))
np.random.shuffle(testzip)
y_test, x_test = zip(*testzip)
x_test = np.asarray(x_test)
y_test = np.asarray(y_test)

#Kerasのバックエンドで動くTensorFlowとTheanoでは入力チャンネルの順番が違うので場合分けして書いています
if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

y_train = y_train.astype('int32')
y_test = y_test.astype('int32')
y_train = keras.utils.np_utils.to_categorical(y_train, num_classes)
y_test =  keras.utils.np_utils.to_categorical(y_test, num_classes)

model = Sequential()
model.add(Conv2D(2, kernel_size=(5, 5),
                 input_shape=input_shape))
model.add(Activation(activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(100))
model.add(Activation(activation='relu'))
model.add(Dense(num_classes))
model.add(Activation(activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs,
          verbose=1, validation_data=(x_test, y_test))

  1. 2018年07月27日 04:32 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

「ゼロから作るDeep Learning」のMNISTデータを使用してKerasで学習する

「ゼロから作るDeep Learning」のMNISTデータを使用してKerasで学習してみた。これができると、「ゼロから作るDeep Learning」のMNISTデータの形にした白線間走行用CNNをKerasで学習させることができる。

まずは、「ゼロから作るDeep Learning」の mnist.py を使用するのだが、そのPython ファイルの入ったフォルダ dataset は、Jupyter Notebook ファイルの入った keras_mnist_zero フォルダと同じフォルダに置いてある。
keras_mnist_zero_1_180726.png

TensorFlow + Kerasを使ってみた3(以前使用したCNNを使った学習)”で使ったPython コードを使用して、(x_train, y_train), (x_test, y_test) にデータをロードする部分だけ、「ゼロから作るDeep Learning」の mnist.py を使ったコードに置き換えた。

(x_train, y_train), (x_test, y_test) = load_mnist(normalize=False, flatten=False)
print('x_train shape:', x_train.shape)
print('x_train shape:', y_train.shape)

load_mnist() の引数で、normalize=False は下のPython コードで 0 ~ 1.0 に正規化しているので、0 ~ 255 の値とした。flatten=False は、(28, 28) の手書き数字画像が必要なので指定している。
x_train, x_test にロードしたタプルの次元だが、

x_train shape: (60000, 1, 28, 28)

だったのだが、下の if 文の中の reshape で配列の形を変えている。最後が 1 次元なので、形を変えても問題無いようだ。
Python コードと学習結果を示す。
keras_mnist_zero_2_180726.png
keras_mnist_zero_3_180726.png
keras_mnist_zero_4_180726.png
keras_mnist_zero_5_180726.png
  1. 2018年07月26日 04:54 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

TensorFlow + Kerasを使ってみた22(Linux版とWindows版のVivado HLSでの違い)

TensorFlow + Kerasを使ってみた21(特徴マップ数が3個、5個、10個のMNIST用CNNをC/RTLコシムとIP化)”の続き。

前回は、特徴マップ数が 3 個、 5 個、10 個のMNIST用CNNをC/RTL 強調シミュレーションと、Export RTL を行って、結果を比較した。今回は、前回はLinux 版のVivado HLS 2017.4 の結果だったが、Windows版のVivado HLS 2017.4 の結果も比較した。また、Vivado HLS 2018.1 で特徴マップが 3 個の場合をやってみたので比較した。

Windows版のVivado HLS 2017.4 の特徴マップ 3 個、5 個、10 個のC コードの合成とExport RTLを行った。結果は下表に示す。

特徴マップが 3 個の場合のWindows版Vivado HLS 2018.1 の C コードの合成の結果を示す。
tensorflow_keras_111_180618.png

特徴マップが 3 個の場合のWindows版Vivado HLS 2018.1 の Export RTLの結果を示す。
tensorflow_keras_112_180618.png

Vivado HLSの特徴マップ 3 個、5 個、10 個のC コードの合成とExport RTLの結果を下表に示す。
tensorflow_keras_113_180618.png

Vivado HLS 2017.4 のLinux 版とWindows版のC コードの合成結果は同じだったが、Export RTLの結果は異なっている。これは、Vivado 2017.4 が Linux 版とWindows版で異なっているのかもしれない?
Vivado HLS 2018.1 のC コードの合成結果は、2017.4 の結果よりも FF と LUT のリソース使用量が少なった。Export RTLの結果は、FF は Vivado HLS 2018.1 の方がリソース使用量が少なかったが、LUT は Vivado HLS 2017.4 の方がリソース使用量が少なかった。
  1. 2018年06月18日 05:30 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

TensorFlow + Kerasを使ってみた21(特徴マップ数が3個、5個、10個のMNIST用CNNをC/RTLコシムとIP化)

TensorFlow + Kerasを使ってみた20(特徴マップ3個のMNIST用CNNをVivado HLSで実装)”の続き。

前回は、MNIST 用のCNN で特徴マップ数が 3 個の場合をVivado HLS で実装した。今回は、特徴マップ数が 3 個、 5 個、10 個のMNIST用CNNをC/RTL 強調シミュレーションと、Export RTL を行う。

まずは、特徴マップ数が 3 個の時のMNIST 用CNN をC/RTL 強調シミュレーションと、Export RTL を行ってみよう。
最初に、テストベンチの mnist_conv_nn_hlss_tb.cpp の 「#define NUM_ITERATIONS 1000」をコメントアウトして、「#define NUM_ITERATIONS 2」のコメントアウトを削除した。これは、C/RTL 強調シミュレーションを行うにあたって、1000 個推論を実行するのは時間がかかりすぎると思ったからだ。波形を見るだけなので、少ない推論数でも十分なわけだ。
tensorflow_keras_104_180616.png

これで、C/RTL 強調シミュレーションを行ったところ、エラーだった。
tensorflow_keras_105_180616.png

次に、Export RTL を行った。なお、Vivado synthesis, place and route にチェックを入れてある。結果を示す。
tensorflow_keras_103_180616.png

LUT は 2794 個、FF は 3195 個、DSP は 62 個、BRAM 34 個、SRL 73 個使用している。
合成時のリソース使用量はBRAM_18K が 34 個、DSP48E が 62 個、FF が 5284 個、LUT が 9137 個だった。DSP と BRAM の個数は同じで、FF は約 60.5 % 、LUT は約 31.4 % になった(LUT はLUT とSRL をLUT として計算した)。


次に、特徴マップ数が 5 個の時のMNIST 用CNN をC/RTL 強調シミュレーションと、Export RTL を行ってみよう。
同様に、テストベンチの mnist_conv_nn_hlss_tb.cpp の 「#define NUM_ITERATIONS 1000」をコメントアウトして、「#define NUM_ITERATIONS 2」のコメントアウトを削除した。
C/RTL 強調シミュレーションを実行したところ、同様にエラーだった。
tensorflow_keras_106_180616.png

Export RTL を行った。なお、Vivado synthesis, place and route にチェックを入れてある。結果を示す。
tensorflow_keras_107_180617.png

LUT は 3605 個、FF は 3811 個、DSP は 93 個、BRAM 66 個、SRL 63 個使用している。
合成時のリソース使用量はBRAM_18K が 66 個、DSP48E が 93 個、FF が 6215 個、LUT が 11144 個だった。DSP と BRAM の個数は同じで、FF は約 61.3 % 、LUT は約 32.9 % になった(LUT はLUT とSRL をLUT として計算した)。


最後に、特徴マップ数が 5 個の時のMNIST 用CNN をC/RTL 強調シミュレーションと、Export RTL を行ってみよう。
同様に、テストベンチの mnist_conv_nn_hlss_tb.cpp の 「#define NUM_ITERATIONS 1000」をコメントアウトして、「#define NUM_ITERATIONS 2」のコメントアウトを削除した。
C/RTL 強調シミュレーションを実行したところ、同様にエラーだった。
tensorflow_keras_109_180617.png

Export RTL を行った。なお、Vivado synthesis, place and route にチェックを入れてある。結果を示す。
tensorflow_keras_108_180617.png

LUT は 5708 個、FF は 5681 個、DSP は 175 個、BRAM 130 個、SRL 73 個使用している。
合成時のリソース使用量はBRAM_18K が 130 個、DSP48E が 175 個、FF が 9005 個、LUT が 16391 個だった。DSP と BRAM の個数は同じで、FF は約 63.1 % 、LUT は約 35.3 % になった(LUT はLUT とSRL をLUT として計算した)。

Export RTL 時の特徴マップ数によるリソース使用量の違いを表に追加した。
tensorflow_keras_110_180617.png
  1. 2018年06月17日 05:36 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

TensorFlow + Kerasを使ってみた20(特徴マップ3個のMNIST用CNNをVivado HLSで実装)

TensorFlow + Kerasを使ってみた19(特徴マップ3個と2個のMNIST用CNNをテスト)”の続き。

前回は、MNIST 用のCNN で特徴マップが 3 個と 2 個の時について学習を行ったところ、3 個の場合の精度が 98.54 % で使い物になるようだった。特徴マップが 2 個の場合は、98.02 % で少し低くなっていた。今回は、MNIST 用のCNN で特徴マップが 3 個の場合をVivado HLS で実装してみよう。

まずは、畳み込み層と全結合層の重みとバイアスをKeras からC のヘッダファイルとして取得した。
そして、MNIST のデータの1000 個分をC のヘッダファイルとして出力した mnist_data.h を使用する。
これらのヘッダファイルの取得方法は、”TensorFlow + Kerasを使ってみた18(特徴マップ5個のMNIST用CNNをVivado HLSで実装)”をご覧あれ。。。

Vivado HLS 2017.4 の mnist_conv_nn5_hlss_org を作成した。
各層の演算精度が書いてある mnist_conv_nn5_hlss.h を示す。ここの値を変更すると演算精度を変更することができる。
tensorflow_keras_99_180615.png

幾度と無く mnist_conv_nn5_hlss.h のパラメータを変更して、C シミュレーションを行った結果、「特徴マップが 5 個の時」のパラメータの中で、 CONV_BIT_LENGTH を 10 から 11 ビットに変更したところ、ハードウェア化する固定小数点演算の精度が改善した。これで行くことにする。

C シミュレーションを行った。結果を示す。
tensorflow_keras_98_180615.png

1000 個のMNIST のデータのうちでハードウェアの固定小数点演算ではエラーが 15 個、ソフトウェアの浮動小数点演算ではエラーが 16 個だった。
よって、ハードウェアの固定小数点演算での精度は、98.5 % となった。
ソフトウェアの浮動小数点演算での精度は、98.4 % となった。

C コードの合成を行った。結果を示す。
tensorflow_keras_100_180615.png
tensorflow_keras_101_180615.png

Latency は min が 101701 クロックで、max は 102133 クロックだった。100 MHz 動作だと約 1.02 ms だった。fpsにすると約 979 fps となった。
リソース使用量はBRAM_18K が 34 個、DSP48E が 62 個、FF が 5284 個、LUT が 9137 個だった。

特徴マップ数が 10 個の場合と 5 個の場合と 3 個の場合のリソース使用量を表にした。
tensorflow_keras_102_180615.png

この表を見ると、特に BRAM_18K の減りが激しいようだ。BRAM_18K の特徴マップ数が 10 個の時を基準とした時の 3 個の時のパーセンテージは 26.15 % だったが、DSP48E は 35.43 % で、FF は 58.68 % 、 LUT は 55.74 % だった。

なお、あくまで C コードの合成でのリソース使用量の見積もりであることに注意してほしい。
特に、パラメータ数が多いテンプレートを使っていると C コードの合成時のレポートと実際にExport RTL した時のVivado での概算とのリソース使用量の違いが多い気がする。
  1. 2018年06月15日 05:33 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0