FC2カウンター FPGAの部屋 自作の白線間走行用 CNN を Vitis-AI の Custom OP WorkFlow で実行する1
fc2ブログ

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

FPGAの部屋

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

自作の白線間走行用 CNN を Vitis-AI の Custom OP WorkFlow で実行する1

白線間走行用CNNをKerasで学習する”で学習した白線間走行用 CNN を Vitis-AI のカスタム OP ワークフローで動作させてみたいということで、今回は、修正した train_eval_line.py と quntize_curve_line.py を貼っておく。更に、train_curve_run_image、train_curve_run_label、test_curve_run_image、test_curve_run_label、学習用データとテスト・データを読み込む curve_dataset.py を Vitis-AI/tf2_custom_op_demo ディレクトリにコピーした。

(2022/11/11:追記) train_eval_line.py と quntize_curve_line.py を 12/11 に変更した。詳しくは、”自作の白線間走行用 CNN を Vitis-AI の Custom OP Flow で実行する5”を参照のこと。

Vitis-AI/tf2_custom_op_demo の tran_eval.py と quntize.py をコピーして名前を train_eval_line.py と quntize_curve_line.py に変更した。そして、train_eval_line.py と quntize_curve_line.py の内容を一部変更した。

train_eval_line.py を示す。

# Copyright 2019 Xilinx Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# train_eval_line.py
# 2022/12/05 : modified by marsee
# 2022/12/08 : modified by marsee

import os, sys
import numpy as np
import tensorflow as tf
import argparse

print(tf.__version__)

os.environ["CUDA_VISIBLE_DEVICES"] = "0"

from curve_dataset import load_mnist
from tensorflow.keras import utils as np_utils

parser = argparse.ArgumentParser(description='tensorflow 2 custom op example.')
parser.add_argument('--eval_only', type=bool, default=False, help='if only evaluate model')
parser.add_argument('--quant', type=bool, default=False, help='if evluate quantized model')

args = parser.parse_args()


class Mylayer(tf.keras.layers.Layer):
  def __init__(self, name="custom_layer", **kwargs):
    super().__init__(name=name, **kwargs)
    self.prelu = tf.keras.layers.PReLU()

  def call(self, inputs, training=None, mask=None):
    x = self.prelu(inputs)
    return x

custom_objects = {"Mylayer": Mylayer}

def build_model():
  inputs = tf.keras.Input((10, 56, 1))
  x = tf.keras.layers.Conv2D(2, (5, 5), activation='relu')(inputs)

  x = tf.keras.layers.MaxPooling2D((2, 2), (2, 2))(x)

  my_model = Mylayer()
  x = my_model(x)

  x = tf.keras.layers.Flatten()(x)
  x = tf.keras.layers.Dense(100, activation='relu')(x)
  x = tf.keras.layers.Dense(3, activation='softmax')(x)

  model = tf.keras.Model(inputs=inputs, outputs=x)
  return model

def main():
  #################################
  ###### build dataset
  #################################
  (x_train, y_train), (x_test, y_test) = load_mnist(normalize=False, flatten=False)
  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)
  x_train = np.transpose(x_train,(0,2,3,1))

  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)
  x_test = np.transpose(x_test,(0,2,3,1))

  x_train = x_train.astype('float32')
  x_test = x_test.astype('float32')
  x_train /= 255
  x_test /= 255

  y_train = y_train.astype('int32')
  y_test = y_test.astype('int32')
  y_train = np_utils.to_categorical(y_train, 3)
  y_test =  np_utils.to_categorical(y_test, 3)

  #################################
  ##### evaluate model
  #################################
  if args.eval_only:
    if args.quant:
      from tensorflow_model_optimization.quantization.keras import vitis_quantize
      # quantized_model = tf.keras.models.load_model("./quantized/quantized.h5",
      #         custom_objects=custom_objects)
      with vitis_quantize.quantize_scope():
        quantized_model = tf.keras.models.load_model("./quantized/quantized_curve_line.h5",
                custom_objects=custom_objects)
        quantized_model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
        eval_results = quantized_model.evaluate(x_test, y_test)
        print("\n***************** Summary *****************")
        print("Quantized model accuracy: ", eval_results[1])
      return
    loaded_model = tf.keras.models.load_model("./keras_curve_cnn2_line.h5",
            custom_objects=custom_objects)
    eval_results = loaded_model.evaluate(x_test, y_test)
    print("\n***************** Summary *****************")
    print("Float model accuracy: ", eval_results[1])
    return
  #################################
  ##### build model
  #################################
  model = build_model()
  model.summary()
  #################################
  ##### compile train
  #################################
  model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
  model.fit(x_train, y_train, epochs=20, shuffle=True)
  eval_results = model.evaluate(x_test, y_test)
  print("\n***************** Summary *****************")
  print("Trained float model accuracy: ", eval_results[1])
  save_path = "./keras_curve_cnn2_line.h5"
  print("Trained float model is saved in ", save_path)
  model.save(save_path)

if __name__ == '__main__':
  main()


quntize_curve_line.py を示す。

# Copyright 2019 Xilinx Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# quantize_curve_line.py
# 2022/12/05 : modified by marsee

import os, sys
import numpy as np
import tensorflow as tf

from curve_dataset import load_mnist
from train_eval_line import custom_objects

print(tf.__version__)
os.environ["CUDA_VISIBLE_DEVICES"] = "0"


def main():
  #################################
  ###### build dataset
  #################################
  (x_train, y_train), (x_test, y_test) = load_mnist(normalize=False, flatten=False)
  
  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)
  x_test = np.transpose(x_test,(0,2,3,1))
  x_test = x_test.astype('float32')
  x_test /= 255

  #################################
  ##### quantize model
  #################################
  loaded_model = tf.keras.models.load_model("./keras_curve_cnn2_line.h5",
          custom_objects=custom_objects)
  loaded_model.summary()
  from tensorflow_model_optimization.quantization.keras import vitis_quantize
  # do quantization
  calib_dataset = x_test
  quant_model = vitis_quantize.VitisQuantizer(loaded_model, custom_objects=custom_objects).quantize_model(
      calib_dataset=calib_dataset,
      add_shape_info=True)
  # quant_model.summary()
  q_save_path = os.path.join('./quantized', 'quantized_curve_line.h5')
  quant_model.save(q_save_path)
  print("\n***************** Summary *****************")
  print("Quantized model is saved in ", q_save_path)

if __name__ == '__main__':
  main()


学習用データ・セットをコピーした。
カーブ、直線用白線間走行用畳み込みニューラルネットワーク5(トレーニング用データの生成)”で生成した train_curve_run_image と train_curve_run_label を Vitis-AI/tf2_custom_op_demo ディレクトリにコピーした。
カーブ、直線用白線間走行用畳み込みニューラルネットワーク7(テスト用データの作成)”で生成した test_curve_run_image のテスト用画像ファイルと test_curve_run_label のテスト用ラベル・ファイルを Vitis-AI/tf2_custom_op_demo ディレクトリにコピーした。

これらの学習用データとテスト・データを読み込む curve_dataset.py を貼っておく。

# curve_dataset.py
# 2017/12/18 白線追従走行用CNNに変更 by marsee
# 元になったコードは、https://github.com/oreilly-japan/deep-learning-from-scratch の mnist.py です
# 改変したコードもMITライセンスとします。 2017/12/18 by marsee

# coding: utf-8
try:
    import urllib.request
except ImportError:
    raise ImportError('You should use Python 3.x')
import os.path
import gzip
import pickle
import os
import numpy as np


key_file = {
    'train_img':'train_curve_run_image',
    'train_label':'train_curve_run_label',
    'test_img':'test_curve_run_image',
    'test_label':'test_curve_run_label'
}

dataset_dir = os.path.dirname(os.path.abspath(__file__))
save_file = dataset_dir + "/mnist.pkl"

train_num = 34650
test_num = 26550
img_dim = (1, 10, 56)
img_size = 560


def _load_label(file_name):
    file_path = dataset_dir + "/" + file_name
    
    print("Converting " + file_name + " to NumPy Array ...")
    with open(file_path, 'rb') as f:
            labels = np.frombuffer(f.read(), np.uint8, offset=8)
    print("Done")
    
    return labels

def _load_img(file_name):
    file_path = dataset_dir + "/" + file_name
    
    print("Converting " + file_name + " to NumPy Array ...")    
    with open(file_path, 'rb') as f:
            data = np.frombuffer(f.read(), np.uint8, offset=16)
    data = data.reshape(-1, img_size)
    print("Done")
    
    return data
    
def _convert_numpy():
    dataset = {}
    dataset['train_img'] =  _load_img(key_file['train_img'])
    dataset['train_label'] = _load_label(key_file['train_label'])    
    dataset['test_img'] = _load_img(key_file['test_img'])
    dataset['test_label'] = _load_label(key_file['test_label'])
    
    return dataset

def init_mnist():
    dataset = _convert_numpy()
    print("Creating pickle file ...")
    with open(save_file, 'wb') as f:
        pickle.dump(dataset, f, -1)
    print("Done!")

def _change_one_hot_label(X):
    T = np.zeros((X.size, 3))
    for idx, row in enumerate(T):
        row[X[idx]] = 1
        
    return T
    

def load_mnist(normalize=True, flatten=True, one_hot_label=False):
    """MNISTデータセットの読み込み
    
    Parameters
    ----------
    normalize : 画像のピクセル値を0.0~1.0に正規化する
    one_hot_label : 
        one_hot_labelがTrueの場合、ラベルはone-hot配列として返す
        one-hot配列とは、たとえば[0,0,1,0,0,0,0,0,0,0]のような配列
    flatten : 画像を一次元配列に平にするかどうか 
    
    Returns
    -------
    (訓練画像, 訓練ラベル), (テスト画像, テストラベル)
    """
    if not os.path.exists(save_file):
        init_mnist()
        
    with open(save_file, 'rb') as f:
        dataset = pickle.load(f)
    
    if normalize:
        for key in ('train_img', 'test_img'):
            dataset[key] = dataset[key].astype(np.float32)
            dataset[key] /= 255.0
            
    if one_hot_label:
        dataset['train_label'] = _change_one_hot_label(dataset['train_label'])
        dataset['test_label'] = _change_one_hot_label(dataset['test_label'])
    
    if not flatten:
         for key in ('train_img', 'test_img'):
            dataset[key] = dataset[key].reshape(-1, 1, 10, 56)

    return (dataset['train_img'], dataset['train_label']), (dataset['test_img'], dataset['test_label']) 


if __name__ == '__main__':
    init_mnist()


Custom_OP_Workflow_37_221207.png
  1. 2022年12月07日 04:23 |
  2. Vitis-AI
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/5786-9caf479a
この記事にトラックバックする(FC2ブログユーザー)