LoginSignup
2
1

More than 3 years have passed since last update.

TensorFlowを使うだけ使う

Last updated at Posted at 2019-09-03

はじまり

某ボードを使いこなすためにTensorFlow Liteを使う必要が出てきた。
手始めにTensorFlowのサンプルをTensorFlow Liteで変換しようとしたところ、
がっつりエラーになった。知識不足何とかしたい。

注意。

本記事はtfliteファイルを作るまでの備忘録なので、TensorFlow触った事のある人なら学びのある記事ではないです。

やる事

自分で作ったデータセットをtensorflowに食わせてtensorflow liteでコンバートする。
とりあえず作るモデルとしてはダック検出。手順をまとめるのが目的なので精度なんて二の次。

image.png

こういう画像をダックって判断するモデルが作りたい

準備

とりあえずpython3入れた後は必要なパッケージを入れてゆく

pip install tensorflow
pip install tensorflow_datasets
pip install matplotlib
pip install numpy
pip install h5py pyyaml
pip install pillow

データセットを作ろうとして失敗する

Adding a datasetを参考にデータセットを作成する。

とりあえず大事なのは

  • tensorflow_datasets.public_api.core.GeneratorBaseBuilderを継承したクラス作る
  • _info()オーバーライドする
  • _split_generator()オーバーライドする
  • _generate_example()オーバーライドする
import tensorflo_datasets.public_api as tfds

class DuckDataset(tfds.core.GeneratorBaseBuilder):

  version = tfds.core.Version('0.1.0')

  def _info(self):
    return tfds.core.DatasetInfo(
        builder=self,
        description="special greatfull duckable dataset",
        features=tfds.features.FeaturesDict({
          "image_description": tfds.features.Text(),
          "image": tfds.features.Image(),
          "label": tfds.features.ClassLabel(num_classes=5),
          }),
        supervised_keys=("image", "label"),
        urls="https://dataset-homepage.org",
        citation=r"""@article{greatfull-duckable-dataset, 
          author={miyatama},"}""",
        )

  def _split_generators(self, dl_manager):
    extract_path = "./datasets/"
    return [
        tfds.core.SplitGenerator(
          name=tfds.Split.TRAIN
          gen_kwargs={
            "image_dir_path": os.path.join(extract_path, "train"),
            "labels": os.path.join(extract_path, "train_labels.csv"),
            }
          ),
        tfds.core.SplitGenerator(
          name=tfds.Split.TEST
          gen_kwargs={
            "image_dir_path": os.path.join(extract_path, "test"),
            "labels": os.path.join(extract_path, "test_labels.csv"),
            }
          ),
        ]

  def _generate_examples(self, images_dir_path, labels):
    image_paths = sorted([os.path.join(images_dir_path, filename)
                          for filename in tf.io.gfile.listdir(images_dir_path)])

    if tf.io.gfile.exists(scenes_description_file):
      scenes_json = json.load(tf.io.gfile.GFile(scenes_description_file))
    else:
      # if annotation file does not exist, we create empty annotations
      scenes_json = {"scenes": [{"objects": []}] * len(image_paths)}

    attrs = ["image_name", "label"]
    for image_path, scene in zip(image_paths, scenes_json["scenes"]):
      objects = scene["objects"]
      fname = os.path.basename(image_path)
      record = {
          "image": image_path,
          "file_name": fname,
          "objects": [{attr: obj[attr] for attr in attrs} for obj in objects]  # pylint: disable=g-complex-comprehension
      }
      yield fname, record

何回Adding a datasetを読んでも結局gfileに食わせるものが不明だったので、何となくラベルを返すようにした。

作ったクラスをどうやって使えばいいか悩んだのち、
Follow this guide to add a dataset to TFDS.なる文言をみて心が折れる。

その他参考

データセットを作成する

とりあえず画像の用意する。

  • datasets/duckディレクトリを作る
  • Googleの画像検索開く
  • duckと打ち込んで検索
  • 適当にスクロール
  • 右クリックしてWebページの完全保存
  • できたフォルダのimage(x)ファイルをimage_x.jpgに名前変える
  • 同じ感じでjojoディレクトリと画像作る

で、画像を読み込んで学習に引き渡すまでは下記の様になる。

import tensorflow as tf
import numpy as np 
from PIL import Image 
import glob 

folder = ["datasets/duck", "datasets/jojo"] 
X = [] 
Y = [] 

def img(x): 
  y = Image.open(x) 
  y = y.convert("RGB") 
  y = y.resize((50, 50)) 
  return np.asarray(y)  

for index, name in enumerate(folder): 
  dir = "./" + name 
  files = glob.glob( dir + "/*.jpg") 
  for i, file in enumerate(files): 
    image = img(file) 
    X.append(image) 
    Y.append(index) 

X = np.array(X) / 255 
Y = np.array(Y) 

学習させる

ココはもうTensorFlowのサンプルのまま。最初のFlattenだけ違う感じ。

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(50, 50, 3)),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(2, activation=tf.nn.softmax)
])

model.compile(
  optimizer='adam',
  loss='sparse_categorical_crossentropy',
  metrics=['accuracy'])

model.fit(X, Y, epochs=5)
model.save(
  'duck_detect.h5', 
  include_optimizer=False)

tensorflow liteでコンバートする

いよいよ学習結果のモデルをコンバートしてゆく。

converter = tf.lite.TFLiteConverter.from_keras_model_file('duck_detect.h5')
tflite_model = converter.convert()
open('duck_detect.tflite', 'wb').write(tflite_model)

image.png

無事tfliteファイルが出来た

ふりかえり

TensorFlowのページ分かりやすいようで分かり辛い。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1