Edge TPU Accelaratorの動作を少しでも高速化したかったのでMobileNetv2-SSD/MobileNetv1-SSD+MS-COCOをPascal VOCで転移学習して.tfliteを生成した_Docker編_その２

**Tensorflow-bin**　[![GitHub stars](https://img.shields.io/github/stars/PINTO0309/Tensorflow-bin.svg?style=social&label=Stars)](https://github.com/PINTO0309/Tensorflow-bin)
<a href="https://github.com/PINTO0309/Tensorflow-bin"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/PINTO0309/Tensorflow-bin.png" width="460px"></a>
**TPU-MobilenetSSD**　[![GitHub stars](https://img.shields.io/github/stars/PINTO0309/TPU-MobilenetSSD.svg?style=social&label=Stars)](https://github.com/PINTO0309/TPU-MobilenetSSD)
<a href="https://github.com/PINTO0309/TPU-MobilenetSSD"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/PINTO0309/TPU-MobilenetSSD.png" width="460px"></a>

# １．Introduction
前回、無謀にも非サポートのモデル MobileNetv2-SSDLite のTPUモデルを生成しようとして失敗しました。
**[【前回記事】 Edge TPU Accelaratorの動作を少しでも高速化したかったのでダメ元でMobileNetv2-SSDLite(Pascal VOC)の.tfliteを生成してTPUモデルへコンパイルしようとした_その１](https://qiita.com/PINTO/items/8368b0bc2d2d75a2f2e6)**
今回は手順を大幅に見直したうえで、再度 MobileNetv2-SSDLite のコンバートと、MobileNetv1-SSD / MobileNetv2-SSD のコンバートを実施します。 公式の手順でリトライしたところ、 **`GPUを使用できないDocker環境`** という、なかなか挑戦的な環境での作業を強要されました。 正直、転移学習でも無駄に時間が掛かりますので、公式の手順の大半を無視してリトライしました。
公式のDockerイメージを一切使用せず、なおかつ Google Colaboratory も使用しません。

環境構築を含む全ての手順を明示するため、Dockerファイルをただ貼り付けるのではなく、作成した全てのスクリプトをそのまま記載します。 どうしても Dockerファイル が必要な方は、お手数ですがご自身でImageを細かく分離するなどしてDockerファイルを生成してください。 学習用のデータセットは私の個人用Googleドライブから高速にダウンロードされるようにしてあります。 また、ショボいGPUでも比較的大きなバッチサイズでトレーニングができるように工夫してあります。

- 今回カスタマイズのポイント
  1. DockerイメージによるGPU学習対応
  2. MobileNetv1-SSD / MobileNetv2-SSD / MobileNetv2-SSDLite の転移学習への対応
  3. Pascal VOC データセット (20クラス) への対応

※ 学習時間を大幅に短縮したい方は、素直に **`Google Colaboratory`** で作業を実施してください。
※ MS-COCOデータセットに比べ、Pascal VOCデータセットでは **`１MB`** ほど.tfliteファイルのサイズが小さくなりました。
※ MS-COCO = 6.9 MB, Pascal VOC = 5.9 MB

# ２．Environment

- Ubuntu 16.04 x86_64
- Corei7 Gen8
- Geforce GTX 1070
- Tensorflow-GPU v1.12.0
- CUDA 9.0
- cuDNN 7
- Pascal VOC 2007/2012 Dataset
- Netron 2.8.1　**[here](https://github.com/lutzroeder/netron/releases)**
- Protobuf 3.7.0　**[here](https://github.com/protocolbuffers/protobuf/releases/tag/v3.7.0)**
- Nvidia-Docker version 18.09.2, build 6247962　**[here](https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(version-2.0))**
- NVIDIA Driver Version: 396.54
- [Docker Image] nvidia/cuda:9.0-cudnn7-devel-ubuntu16.04　**[here](https://hub.docker.com/r/nvidia/cuda/)**



# ３．Procedure

```console:docker_run
$ sudo docker run -it --privileged -p 6006:6006 --name="edgetpu-detect" nvidia/cuda:9.0-cudnn7-devel-ubuntu16.04 /bin/bash
```

```console:Environmental_preparation
$ apt-get update;apt-get upgrade -y
$ apt-get install -y protobuf-compiler python-pil python-lxml python-tk \
autoconf automake libtool curl make g++ unzip wget git nano \
libgflags-dev libgoogle-glog-dev liblmdb-dev libleveldb-dev \
libhdf5-10 libhdf5-serial-dev libhdf5-dev libhdf5-cpp-11 \
python3-dev python3-numpy python3-skimage gfortran libturbojpeg \
python-dev python-numpy python-skimage python3-pip python-pip \
libboost-all-dev libopenblas-dev libsnappy-dev software-properties-common \
protobuf-compiler python-pil python-lxml python-tk libfreetype6-dev pkg-config libpng12-dev

$ wget https://bootstrap.pypa.io/get-pip.py
$ python3 get-pip.py
$ pip3 install pip==18.0.0 --upgrade
$ pip3 install --user Cython contextlib2 jupyter matplotlib opencv-python lxml

$ git clone https://github.com/tensorflow/models.git
```


```console:Create_script_for_constant_definition
$ cd models/research
$ nano constants.sh
```

```bash:constants.sh
#!/bin/bash

declare -A ckpt_link_map
declare -A ckpt_name_map
declare -A config_filename_map

#ckpt_link_map["mobilenet_v1_ssd"]="http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_quantized_300x300_coco14_sync_2018_07_18.tar.gz"
ckpt_link_map["mobilenet_v1_ssd"]="http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_coco_2018_01_28.tar.gz"
#ckpt_link_map["mobilenet_v2_ssd"]="http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_quantized_300x300_coco_2019_01_03.tar.gz"
ckpt_link_map["mobilenet_v2_ssd"]="http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_coco_2018_03_29.tar.gz"
ckpt_link_map["mobilenet_v2_ssdlite"]="http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz"

#ckpt_name_map["mobilenet_v1_ssd"]="ssd_mobilenet_v1_quantized_300x300_coco14_sync_2018_07_18"
ckpt_name_map["mobilenet_v1_ssd"]="ssd_mobilenet_v1_coco_2018_01_28"
#ckpt_name_map["mobilenet_v2_ssd"]="ssd_mobilenet_v2_quantized_300x300_coco_2019_01_03"
ckpt_name_map["mobilenet_v2_ssd"]="ssd_mobilenet_v2_coco_2018_03_29"
ckpt_name_map["mobilenet_v2_ssdlite"]="ssdlite_mobilenet_v2_coco_2018_05_09"

config_filename_map["mobilenet_v1_ssd-true"]="pipeline_mobilenet_v1_ssd_retrain_whole_model.config"
config_filename_map["mobilenet_v1_ssd-false"]="pipeline_mobilenet_v1_ssd_retrain_last_few_layers.config"
config_filename_map["mobilenet_v2_ssd-true"]="pipeline_mobilenet_v2_ssd_retrain_whole_model.config"
config_filename_map["mobilenet_v2_ssd-false"]="pipeline_mobilenet_v2_ssd_retrain_last_few_layers.config"
config_filename_map["mobilenet_v2_ssdlite-true"]="pipeline_mobilenet_v2_ssdlite_retrain_whole_model.config"
config_filename_map["mobilenet_v2_ssdlite-false"]="pipeline_mobilenet_v2_ssdlite_retrain_last_few_layers.config"

INPUT_TENSORS='normalized_input_image_tensor'
OUTPUT_TENSORS='TFLite_Detection_PostProcess,TFLite_Detection_PostProcess:1,TFLite_Detection_PostProcess:2,TFLite_Detection_PostProcess:3'

OBJ_DET_DIR="$PWD"
LEARN_DIR="${OBJ_DET_DIR}/learn"
DATASET_DIR="${LEARN_DIR}/data"
CKPT_DIR="${LEARN_DIR}/ckpt"
TRAIN_DIR="${LEARN_DIR}/train"
OUTPUT_DIR="${LEARN_DIR}/models"
```

```console:Create_training_data_set_generation_script
$ nano prepare_checkpoint_and_dataset.sh
```

```bash:prepare_checkpoint_and_dataset.sh
#!/bin/bash

# Exit script on error.
set -e
# Echo each command, easier for debugging.
set -x

usage() {
  cat << END_OF_USAGE
  Downloads checkpoint and dataset needed for the tutorial.

  --network_type      Can be one of [mobilenet_v1_ssd, mobilenet_v2_ssd, mobilenet_v2_ssdlite],
                      mobilenet_v1_ssd by default.
  --train_whole_model Whether or not to train all layers of the model. false
                      by default, in which only the last few layers are trained.
  --help              Display this help.
END_OF_USAGE
}

network_type="mobilenet_v1_ssd"
train_whole_model="false"
while [[ $# -gt 0 ]]; do
  case "$1" in
    --network_type)
      network_type=$2
      shift 2 ;;
    --train_whole_model)
      train_whole_model=$2
      shift 2;;
    --help)
      usage
      exit 0 ;;
    --*)
      echo "Unknown flag $1"
      usage
      exit 1 ;;
  esac
done

export PYTHONPATH=`pwd`:`pwd`/slim:$PYTHONPATH
export PATH=/usr/local/cuda-9.0/bin:${PATH}
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64/:/usr/local/cuda-9.0/targets/x86_64-linux/lib/stubs:${LD_LIBRARY_PATH}
ldconfig

cp pipeline_mobilenet_v1_ssd_retrain_whole_model.config configs
cp pipeline_mobilenet_v1_ssd_retrain_last_few_layers.config configs
cp pipeline_mobilenet_v2_ssd_retrain_whole_model.config configs
cp pipeline_mobilenet_v2_ssd_retrain_last_few_layers.config configs
cp pipeline_mobilenet_v2_ssdlite_retrain_last_few_layers.config configs

source "$PWD/constants.sh"

echo "PREPARING checkpoint..."
mkdir -p "${LEARN_DIR}"

ckpt_link="${ckpt_link_map[${network_type}]}"
ckpt_name="${ckpt_name_map[${network_type}]}"
cd "${LEARN_DIR}"
wget -O "${ckpt_name}.tar.gz" "$ckpt_link"
tar zxvf "${ckpt_name}.tar.gz"
rm "${ckpt_name}.tar.gz"
rm -rf "${CKPT_DIR}/${ckpt_name}"
rm -rf "${CKPT_DIR}/saved_model"
mv -f ${ckpt_name}/* "${CKPT_DIR}"

echo "CHOSING config file..."
config_filename="${config_filename_map[${network_type}-${train_whole_model}]}"
cd "${OBJ_DET_DIR}"
cp "configs/${config_filename}" "${CKPT_DIR}/pipeline.config"

echo "REPLACING variables in config file..."
sed -i "s%CKPT_DIR_TO_CONFIGURE%${CKPT_DIR}%g" "${CKPT_DIR}/pipeline.config"
sed -i "s%DATASET_DIR_TO_CONFIGURE%${DATASET_DIR}%g" "${CKPT_DIR}/pipeline.config"

echo "PREPARING dataset"
rm -rf "${DATASET_DIR}"
mkdir "${DATASET_DIR}"
cd "${DATASET_DIR}"

# VOCtrainval_11-May-2012.tar <--- 1.86GB
curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=1rATNHizJdVHnaJtt-hW9MOgjxoaajzdh" > /dev/null
CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)"
curl -Lb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=1rATNHizJdVHnaJtt-hW9MOgjxoaajzdh" -o VOCtrainval_11-May-2012.tar

# VOCtrainval_06-Nov-2007.tar <--- 460MB
curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=1c8laJUn-aaWEhE5NlDwIdNv5ZdogUAcD" > /dev/null
CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)"
curl -Lb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=1c8laJUn-aaWEhE5NlDwIdNv5ZdogUAcD" -o VOCtrainval_06-Nov-2007.tar

# Extract the data.
tar -xvf VOCtrainval_11-May-2012.tar;rm VOCtrainval_11-May-2012.tar
tar -xvf VOCtrainval_06-Nov-2007.tar;rm VOCtrainval_06-Nov-2007.tar

echo "PREPARING label map..."
cd "${OBJ_DET_DIR}"
cp "object_detection/data/pascal_label_map.pbtxt" "${DATASET_DIR}"

echo "CONVERTING dataset to TF Record..."
protoc object_detection/protos/*.proto --python_out=.
python3 object_detection/dataset_tools/create_pascal_tf_record.py \
  --label_map_path="${DATASET_DIR}/pascal_label_map.pbtxt" \
  --data_dir=${DATASET_DIR}/VOCdevkit \
  --year=merged \
  --set=train \
  --output_path="${DATASET_DIR}/pascal_train.record"

python3 object_detection/dataset_tools/create_pascal_tf_record.py \
  --label_map_path="${DATASET_DIR}/pascal_label_map.pbtxt" \
  --data_dir=${DATASET_DIR}/VOCdevkit \
  --year=merged \
  --set=val \
  --output_path="${DATASET_DIR}/pascal_val.record"
```

Edit pipeline_config.
First, the MobileNet-SSD v2 config sample is shown below.
"Left side" for transfer learning. If you do not transfer learning, "Right side".

![sabun.png](https://qiita-image-store.s3.amazonaws.com/0/194769/8add3a0a-834b-a288-e936-c64c06dd47ad.png)

```console:Create_"pipeline_mobilenet_v1_ssd_retrain_whole_model.config"
$ nano pipeline_mobilenet_v1_ssd_retrain_whole_model.config
```

```config:pipeline_mobilenet_v1_ssd_retrain_whole_model.config
model {
  ssd {
    num_classes: 20
    image_resizer {
      fixed_shape_resizer {
        height: 300
        width: 300
      }
    }
    feature_extractor {
      type: "ssd_mobilenet_v1"
      depth_multiplier: 1.0
      min_depth: 16
      conv_hyperparams {
        regularizer {
          l2_regularizer {
            weight: 3.99999989895e-05
          }
        }
        initializer {
          random_normal_initializer {
            mean: 0.0
            stddev: 0.00999999977648
          }
        }
        activation: RELU_6
        batch_norm {
          decay: 0.97000002861
          center: true
          scale: true
          epsilon: 0.0010000000475
        }
      }
      override_base_feature_extractor_hyperparams: true
    }
    box_coder {
      faster_rcnn_box_coder {
        y_scale: 10.0
        x_scale: 10.0
        height_scale: 5.0
        width_scale: 5.0
      }
    }
    matcher {
      argmax_matcher {
        matched_threshold: 0.5
        unmatched_threshold: 0.5
        ignore_thresholds: false
        negatives_lower_than_unmatched: true
        force_match_for_each_row: true
        use_matmul_gather: true
      }
    }
    similarity_calculator {
      iou_similarity {
      }
    }
    box_predictor {
      convolutional_box_predictor {
        conv_hyperparams {
          regularizer {
            l2_regularizer {
              weight: 3.99999989895e-05
            }
          }
          initializer {
            random_normal_initializer {
              mean: 0.0
              stddev: 0.00999999977648
            }
          }
          activation: RELU_6
          batch_norm {
            decay: 0.97000002861
            center: true
            scale: true
            epsilon: 0.0010000000475
          }
        }
        min_depth: 0
        max_depth: 0
        num_layers_before_predictor: 0
        use_dropout: false
        dropout_keep_probability: 0.800000011921
        kernel_size: 1
        box_code_size: 4
        apply_sigmoid_to_scores: false
        class_prediction_bias_init: -4.59999990463
      }
    }
    anchor_generator {
      ssd_anchor_generator {
        num_layers: 6
        min_scale: 0.20000000298
        max_scale: 0.949999988079
        aspect_ratios: 1.0
        aspect_ratios: 2.0
        aspect_ratios: 0.5
        aspect_ratios: 3.0
        aspect_ratios: 0.333299994469
      }
    }
    post_processing {
      batch_non_max_suppression {
        score_threshold: 0.300000011921
        iou_threshold: 0.600000023842
        max_detections_per_class: 100
        max_total_detections: 100
      }
      score_converter: SIGMOID
    }
    normalize_loss_by_num_matches: true
    loss {
      localization_loss {
        weighted_smooth_l1 {
        }
      }
      classification_loss {
        weighted_sigmoid_focal {
          gamma: 2.0
          alpha: 0.75
        }
      }
      classification_weight: 1.0
      localization_weight: 1.0
    }
    encode_background_as_zeros: true
    normalize_loc_loss_by_codesize: true
    inplace_batchnorm_update: true
    freeze_batchnorm: false
  }
}
train_config {
  batch_size: 64
  data_augmentation_options {
    random_horizontal_flip {
    }
  }
  data_augmentation_options {
    ssd_random_crop {
    }
  }
  sync_replicas: true
  optimizer {
    adam_optimizer: {
      learning_rate: {
        manual_step_learning_rate {
          initial_learning_rate: .0002
          schedule {
            step: 500
            learning_rate: .00003
          }
          schedule {
            step: 1000
            learning_rate: .000003
          }
          schedule {
            step: 3000
            learning_rate: .0000003
          }
          schedule {
            step: 6000
            learning_rate: .00000003
          }
        }
      }
    }
    use_moving_average: false
  }
  fine_tune_checkpoint: "CKPT_DIR_TO_CONFIGURE/model.ckpt"
  from_detection_checkpoint: true
  load_all_detection_checkpoint_vars: true
  num_steps: 50000
  startup_delay_steps: 0.0
  replicas_to_aggregate: 8
  max_number_of_boxes: 100
  unpad_groundtruth_tensors: false
}
train_input_reader {
  label_map_path: "DATASET_DIR_TO_CONFIGURE/pascal_label_map.pbtxt"
  tf_record_input_reader {
    input_path: "DATASET_DIR_TO_CONFIGURE/pascal_train.record"
  }
}
eval_config: {
  num_examples: 10
  num_visualizations: 10
  eval_interval_secs: 0
}
eval_input_reader {
  label_map_path: "DATASET_DIR_TO_CONFIGURE/pascal_label_map.pbtxt"
  shuffle: false
  num_readers: 1
  tf_record_input_reader {
    input_path: "DATASET_DIR_TO_CONFIGURE/pascal_val.record"
  }
}
graph_rewriter {
  quantization {
    delay: 48000
    weight_bits: 8
    activation_bits: 8
  }
}
```


```console:Create_"pipeline_mobilenet_v1_ssd_retrain_last_few_layers.config"
$ nano pipeline_mobilenet_v1_ssd_retrain_last_few_layers.config
```

```config:pipeline_mobilenet_v1_ssd_retrain_last_few_layers.config
model {
  ssd {
    num_classes: 20
    image_resizer {
      fixed_shape_resizer {
        height: 300
        width: 300
      }
    }
    feature_extractor {
      type: "ssd_mobilenet_v1"
      depth_multiplier: 1.0
      min_depth: 16
      conv_hyperparams {
        regularizer {
          l2_regularizer {
            weight: 3.99999989895e-05
          }
        }
        initializer {
          random_normal_initializer {
            mean: 0.0
            stddev: 0.00999999977648
          }
        }
        activation: RELU_6
        batch_norm {
          decay: 0.97000002861
          center: true
          scale: true
          epsilon: 0.0010000000475
        }
      }
      override_base_feature_extractor_hyperparams: true
    }
    box_coder {
      faster_rcnn_box_coder {
        y_scale: 10.0
        x_scale: 10.0
        height_scale: 5.0
        width_scale: 5.0
      }
    }
    matcher {
      argmax_matcher {
        matched_threshold: 0.5
        unmatched_threshold: 0.5
        ignore_thresholds: false
        negatives_lower_than_unmatched: true
        force_match_for_each_row: true
        use_matmul_gather: true
      }
    }
    similarity_calculator {
      iou_similarity {
      }
    }
    box_predictor {
      convolutional_box_predictor {
        conv_hyperparams {
          regularizer {
            l2_regularizer {
              weight: 3.99999989895e-05
            }
          }
          initializer {
            random_normal_initializer {
              mean: 0.0
              stddev: 0.00999999977648
            }
          }
          activation: RELU_6
          batch_norm {
            decay: 0.97000002861
            center: true
            scale: true
            epsilon: 0.0010000000475
          }
        }
        min_depth: 0
        max_depth: 0
        num_layers_before_predictor: 0
        use_dropout: false
        dropout_keep_probability: 0.800000011921
        kernel_size: 1
        box_code_size: 4
        apply_sigmoid_to_scores: false
        class_prediction_bias_init: -4.59999990463
      }
    }
    anchor_generator {
      ssd_anchor_generator {
        num_layers: 6
        min_scale: 0.20000000298
        max_scale: 0.949999988079
        aspect_ratios: 1.0
        aspect_ratios: 2.0
        aspect_ratios: 0.5
        aspect_ratios: 3.0
        aspect_ratios: 0.333299994469
      }
    }
    post_processing {
      batch_non_max_suppression {
        score_threshold: 0.300000011921
        iou_threshold: 0.600000023842
        max_detections_per_class: 100
        max_total_detections: 100
      }
      score_converter: SIGMOID
    }
    normalize_loss_by_num_matches: true
    loss {
      localization_loss {
        weighted_smooth_l1 {
        }
      }
      classification_loss {
        weighted_sigmoid_focal {
          gamma: 2.0
          alpha: 0.75
        }
      }
      classification_weight: 1.0
      localization_weight: 1.0
    }
    encode_background_as_zeros: true
    normalize_loc_loss_by_codesize: true
    inplace_batchnorm_update: true
    freeze_batchnorm: false
  }
}
train_config {
  batch_size: 64
  data_augmentation_options {
    random_horizontal_flip {
    }
  }
  data_augmentation_options {
    ssd_random_crop {
    }
  }
  sync_replicas: true
  optimizer {
    adam_optimizer: {
      learning_rate: {
        manual_step_learning_rate {
          initial_learning_rate: .0002
          schedule {
            step: 500
            learning_rate: .00003
          }
          schedule {
            step: 1000
            learning_rate: .000003
          }
          schedule {
            step: 3000
            learning_rate: .0000003
          }
          schedule {
            step: 6000
            learning_rate: .00000003
          }
        }
      }
    }
    use_moving_average: false
  }
  fine_tune_checkpoint: "CKPT_DIR_TO_CONFIGURE/model.ckpt"
  from_detection_checkpoint: true
  load_all_detection_checkpoint_vars: true
  num_steps: 50000
  startup_delay_steps: 0.0
  replicas_to_aggregate: 8
  max_number_of_boxes: 100
  unpad_groundtruth_tensors: false
  freeze_variables:
        ['Conv2d_0',
          'Conv2d_1_pointwise',
          'Conv2d_1_depthwise',
          'Conv2d_2_pointwise',
          'Conv2d_2_depthwise',
          'Conv2d_3_pointwise',
          'Conv2d_3_depthwise',
          'Conv2d_4_pointwise',
          'Conv2d_4_depthwise',
          'Conv2d_5_pointwise',
          'Conv2d_5_depthwise',
          'Conv2d_6_pointwise',
          'Conv2d_6_depthwise',
          'Conv2d_7_pointwise',
          'Conv2d_7_depthwise',
          'Conv2d_8_pointwise',
          'Conv2d_8_depthwise',
          'Conv2d_9_pointwise',
          'Conv2d_9_depthwise']
}
train_input_reader {
  label_map_path: "DATASET_DIR_TO_CONFIGURE/pascal_label_map.pbtxt"
  tf_record_input_reader {
    input_path: "DATASET_DIR_TO_CONFIGURE/pascal_train.record"
  }
}
eval_config: {
  num_examples: 10
  num_visualizations: 10
  eval_interval_secs: 0
}
eval_input_reader {
  label_map_path: "DATASET_DIR_TO_CONFIGURE/pascal_label_map.pbtxt"
  shuffle: false
  num_readers: 1
  tf_record_input_reader {
    input_path: "DATASET_DIR_TO_CONFIGURE/pascal_val.record"
  }
}
graph_rewriter {
  quantization {
    delay: 48000
    weight_bits: 8
    activation_bits: 8
  }
}
```

```console:Create_"pipeline_mobilenet_v2_ssd_retrain_whole_model.config"
$ nano pipeline_mobilenet_v2_ssd_retrain_whole_model.config
```

```config:pipeline_mobilenet_v2_ssd_retrain_whole_model.config
# Quantized trained SSD with Mobilenet v2 on Pascal VOC Dataset.

model {
  ssd {
    num_classes: 20
    image_resizer {
      fixed_shape_resizer {
        height: 300
        width: 300
      }
    }
    feature_extractor {
      type: "ssd_mobilenet_v2"
      depth_multiplier: 1.0
      min_depth: 16
      conv_hyperparams {
        regularizer {
          l2_regularizer {
            weight: 3.99999989895e-05
          }
        }
        initializer {
          random_normal_initializer {
            mean: 0.0
            stddev: 0.00999999977648
          }
        }
        activation: RELU_6
        batch_norm {
          decay: 0.97000002861
          center: true
          scale: true
          epsilon: 0.0010000000475
        }
      }
      override_base_feature_extractor_hyperparams: true
    }
    box_coder {
      faster_rcnn_box_coder {
        y_scale: 10.0
        x_scale: 10.0
        height_scale: 5.0
        width_scale: 5.0
      }
    }
    matcher {
      argmax_matcher {
        matched_threshold: 0.5
        unmatched_threshold: 0.5
        ignore_thresholds: false
        negatives_lower_than_unmatched: true
        force_match_for_each_row: true
        use_matmul_gather: true
      }
    }
    similarity_calculator {
      iou_similarity {
      }
    }
    box_predictor {
      convolutional_box_predictor {
        conv_hyperparams {
          regularizer {
            l2_regularizer {
              weight: 3.99999989895e-05
            }
          }
          initializer {
            random_normal_initializer {
              mean: 0.0
              stddev: 0.00999999977648
            }
          }
          activation: RELU_6
          batch_norm {
            decay: 0.97000002861
            center: true
            scale: true
            epsilon: 0.0010000000475
          }
        }
        min_depth: 0
        max_depth: 0
        num_layers_before_predictor: 0
        use_dropout: false
        dropout_keep_probability: 0.800000011921
        kernel_size: 1
        box_code_size: 4
        apply_sigmoid_to_scores: false
        class_prediction_bias_init: -4.59999990463
      }
    }
    anchor_generator {
      ssd_anchor_generator {
        num_layers: 6
        min_scale: 0.20000000298
        max_scale: 0.949999988079
        aspect_ratios: 1.0
        aspect_ratios: 2.0
        aspect_ratios: 0.5
        aspect_ratios: 3.0
        aspect_ratios: 0.333299994469
      }
    }
    post_processing {
      batch_non_max_suppression {
        score_threshold: 0.300000011921
        iou_threshold: 0.600000023842
        max_detections_per_class: 100
        max_total_detections: 100
      }
      score_converter: SIGMOID
    }
    normalize_loss_by_num_matches: true
    loss {
      localization_loss {
        weighted_smooth_l1 {
        }
      }
      classification_loss {
        weighted_sigmoid_focal {
          gamma: 2.0
          alpha: 0.75
        }
      }
      classification_weight: 1.0
      localization_weight: 1.0
    }
    encode_background_as_zeros: true
    normalize_loc_loss_by_codesize: true
    inplace_batchnorm_update: true
    freeze_batchnorm: false
  }
}
train_config {
  batch_size: 64
  data_augmentation_options {
    random_horizontal_flip {
    }
  }
  data_augmentation_options {
    ssd_random_crop {
    }
  }
  sync_replicas: true
  optimizer {
    adam_optimizer: {
      learning_rate: {
        manual_step_learning_rate {
          initial_learning_rate: .0002
          schedule {
            step: 500
            learning_rate: .00003
          }
          schedule {
            step: 1000
            learning_rate: .000003
          }
          schedule {
            step: 3000
            learning_rate: .0000003
          }
          schedule {
            step: 6000
            learning_rate: .00000003
          }
        }
      }
    }
    use_moving_average: false
  }
  fine_tune_checkpoint: "CKPT_DIR_TO_CONFIGURE/model.ckpt"
  from_detection_checkpoint: true
  load_all_detection_checkpoint_vars: true
  num_steps: 50000
  startup_delay_steps: 0.0
  replicas_to_aggregate: 8
  max_number_of_boxes: 100
  unpad_groundtruth_tensors: false
}
train_input_reader {
  label_map_path: "DATASET_DIR_TO_CONFIGURE/pascal_label_map.pbtxt"
  tf_record_input_reader {
    input_path: "DATASET_DIR_TO_CONFIGURE/pascal_train.record"
  }
}
eval_config: {
  num_examples: 10
  num_visualizations: 10
  eval_interval_secs: 0
}
eval_input_reader {
  label_map_path: "DATASET_DIR_TO_CONFIGURE/pascal_label_map.pbtxt"
  shuffle: false
  num_readers: 1
  tf_record_input_reader {
    input_path: "DATASET_DIR_TO_CONFIGURE/pascal_train.record"
  }
}
graph_rewriter {
  quantization {
    delay: 48000
    weight_bits: 8
    activation_bits: 8
  }
}
```

```console:Create_"pipeline_mobilenet_v2_ssd_retrain_last_few_layers.config"
$ nano pipeline_mobilenet_v2_ssd_retrain_last_few_layers.config
```

```config:pipeline_mobilenet_v2_ssd_retrain_last_few_layers.config
# Quantized trained SSD with Mobilenet v2 on Pascal VOC Dataset.

model {
  ssd {
    num_classes: 20
    image_resizer {
      fixed_shape_resizer {
        height: 300
        width: 300
      }
    }
    feature_extractor {
      type: "ssd_mobilenet_v2"
      depth_multiplier: 1.0
      min_depth: 16
      conv_hyperparams {
        regularizer {
          l2_regularizer {
            weight: 3.99999989895e-05
          }
        }
        initializer {
          random_normal_initializer {
            mean: 0.0
            stddev: 0.00999999977648
          }
        }
        activation: RELU_6
        batch_norm {
          decay: 0.97000002861
          center: true
          scale: true
          epsilon: 0.0010000000475
        }
      }
      override_base_feature_extractor_hyperparams: true
    }
    box_coder {
      faster_rcnn_box_coder {
        y_scale: 10.0
        x_scale: 10.0
        height_scale: 5.0
        width_scale: 5.0
      }
    }
    matcher {
      argmax_matcher {
        matched_threshold: 0.5
        unmatched_threshold: 0.5
        ignore_thresholds: false
        negatives_lower_than_unmatched: true
        force_match_for_each_row: true
        use_matmul_gather: true
      }
    }
    similarity_calculator {
      iou_similarity {
      }
    }
    box_predictor {
      convolutional_box_predictor {
        conv_hyperparams {
          regularizer {
            l2_regularizer {
              weight: 3.99999989895e-05
            }
          }
          initializer {
            random_normal_initializer {
              mean: 0.0
              stddev: 0.00999999977648
            }
          }
          activation: RELU_6
          batch_norm {
            decay: 0.97000002861
            center: true
            scale: true
            epsilon: 0.0010000000475
          }
        }
        min_depth: 0
        max_depth: 0
        num_layers_before_predictor: 0
        use_dropout: false
        dropout_keep_probability: 0.800000011921
        kernel_size: 1
        box_code_size: 4
        apply_sigmoid_to_scores: false
        class_prediction_bias_init: -4.59999990463
      }
    }
    anchor_generator {
      ssd_anchor_generator {
        num_layers: 6
        min_scale: 0.20000000298
        max_scale: 0.949999988079
        aspect_ratios: 1.0
        aspect_ratios: 2.0
        aspect_ratios: 0.5
        aspect_ratios: 3.0
        aspect_ratios: 0.333299994469
      }
    }
    post_processing {
      batch_non_max_suppression {
        score_threshold: 0.300000011921
        iou_threshold: 0.600000023842
        max_detections_per_class: 100
        max_total_detections: 100
      }
      score_converter: SIGMOID
    }
    normalize_loss_by_num_matches: true
    loss {
      localization_loss {
        weighted_smooth_l1 {
        }
      }
      classification_loss {
        weighted_sigmoid_focal {
          gamma: 2.0
          alpha: 0.75
        }
      }
      classification_weight: 1.0
      localization_weight: 1.0
    }
    encode_background_as_zeros: true
    normalize_loc_loss_by_codesize: true
    inplace_batchnorm_update: true
    freeze_batchnorm: false
  }
}
train_config {
  batch_size: 64
  data_augmentation_options {
    random_horizontal_flip {
    }
  }
  data_augmentation_options {
    ssd_random_crop {
    }
  }
  sync_replicas: true
  optimizer {
    adam_optimizer: {
      learning_rate: {
        manual_step_learning_rate {
          initial_learning_rate: .0002
          schedule {
            step: 500
            learning_rate: .00003
          }
          schedule {
            step: 1000
            learning_rate: .000003
          }
          schedule {
            step: 3000
            learning_rate: .0000003
          }
          schedule {
            step: 6000
            learning_rate: .00000003
          }
        }
      }
    }
    use_moving_average: false
  }
  fine_tune_checkpoint: "CKPT_DIR_TO_CONFIGURE/model.ckpt"
  from_detection_checkpoint: true
  load_all_detection_checkpoint_vars: true
  num_steps: 50000
  startup_delay_steps: 0.0
  replicas_to_aggregate: 8
  max_number_of_boxes: 100
  unpad_groundtruth_tensors: false
  freeze_variables:
        [ 'FeatureExtractor/MobilenetV2/Conv/',
          'FeatureExtractor/MobilenetV2/expanded_conv/',
          'FeatureExtractor/MobilenetV2/expanded_conv_1/',
          'FeatureExtractor/MobilenetV2/expanded_conv_2/',
          'FeatureExtractor/MobilenetV2/expanded_conv_3/',
          'FeatureExtractor/MobilenetV2/expanded_conv_4/',
          'FeatureExtractor/MobilenetV2/expanded_conv_5/',
          'FeatureExtractor/MobilenetV2/expanded_conv_6/',
          'FeatureExtractor/MobilenetV2/expanded_conv_7/']
}
train_input_reader {
  label_map_path: "DATASET_DIR_TO_CONFIGURE/pascal_label_map.pbtxt"
  tf_record_input_reader {
    input_path: "DATASET_DIR_TO_CONFIGURE/pascal_train.record"
  }
}
eval_config: {
  num_examples: 10
  num_visualizations: 10
  eval_interval_secs: 0
}
eval_input_reader {
  label_map_path: "DATASET_DIR_TO_CONFIGURE/pascal_label_map.pbtxt"
  shuffle: false
  num_readers: 1
  tf_record_input_reader {
    input_path: "DATASET_DIR_TO_CONFIGURE/pascal_val.record"
  }
}
graph_rewriter {
  quantization {
    delay: 48000
    weight_bits: 8
    activation_bits: 8
  }
}
```

```console:Create_"pipeline_mobilenet_v2_ssdlite_retrain_last_few_layers.config"
$ nano pipeline_mobilenet_v2_ssdlite_retrain_last_few_layers.config
```

```config:pipeline_mobilenet_v2_ssdlite_retrain_last_few_layers.config
# SSDLite with Mobilenet v2 configuration for VOC Dataset.

model {
  ssd {
    num_classes: 20
    image_resizer {
      fixed_shape_resizer {
        height: 300
        width: 300
      }
    }
    feature_extractor {
      type: 'ssd_mobilenet_v2'
      depth_multiplier: 1.0
      min_depth: 16
      use_depthwise: true
      conv_hyperparams {
        regularizer {
          l2_regularizer {
            weight: 0.00004
          }
        }
        initializer {
          truncated_normal_initializer {
            mean: 0.0
            stddev: 0.03
          }
        }
        activation: RELU_6
        batch_norm {
          decay: 0.9997
          center: true
          scale: true
          epsilon: 0.001
        }
      }
    }
    box_coder {
      faster_rcnn_box_coder {
        y_scale: 10.0
        x_scale: 10.0
        height_scale: 5.0
        width_scale: 5.0
      }
    }
    matcher {
      argmax_matcher {
        matched_threshold: 0.5
        unmatched_threshold: 0.5
        ignore_thresholds: false
        negatives_lower_than_unmatched: true
        force_match_for_each_row: true
      }
    }
    similarity_calculator {
      iou_similarity {
      }
    }
    box_predictor {
      convolutional_box_predictor {
        conv_hyperparams {
          regularizer {
            l2_regularizer {
              weight: 0.00004
            }
          }
          initializer {
            truncated_normal_initializer {
              mean: 0.0
              stddev: 0.03
            }
          }
          activation: RELU_6
          batch_norm {
            decay: 0.9997
            center: true
            scale: true
            epsilon: 0.001
          }
        }
        min_depth: 0
        max_depth: 0
        num_layers_before_predictor: 0
        use_dropout: false
        dropout_keep_probability: 0.8
        kernel_size: 3
        box_code_size: 4
        apply_sigmoid_to_scores: false
        use_depthwise: true
      }
    }
    anchor_generator {
      ssd_anchor_generator {
        num_layers: 6
        min_scale: 0.2
        max_scale: 0.95
        aspect_ratios: 1.0
        aspect_ratios: 2.0
        aspect_ratios: 0.5
        aspect_ratios: 3.0
        aspect_ratios: 0.3333
      }
    }
    post_processing {
      batch_non_max_suppression {
        score_threshold: 1e-8
        iou_threshold: 0.6
        max_detections_per_class: 100
        max_total_detections: 100
      }
      score_converter: SIGMOID
    }
    normalize_loss_by_num_matches: true
    loss {
      localization_loss {
        weighted_smooth_l1 {
        }
      }
      classification_loss {
        weighted_sigmoid {
        }
      }
      classification_weight: 1.0
      localization_weight: 1.0
      hard_example_miner {
        num_hard_examples: 3000
        iou_threshold: 0.99
        loss_type: CLASSIFICATION
        max_negatives_per_positive: 3
        min_negatives_per_image: 3
      }
    }
  }
}
train_config: {
  batch_size: 64
  data_augmentation_options {
    random_horizontal_flip {
    }
  }
  data_augmentation_options {
    ssd_random_crop {
    }
  }
  sync_replicas: true
  optimizer {
    adam_optimizer: {
      learning_rate: {
        manual_step_learning_rate {
          initial_learning_rate: .0002
          schedule {
            step: 500
            learning_rate: .00003
          }
          schedule {
            step: 1000
            learning_rate: .000003
          }
          schedule {
            step: 3000
            learning_rate: .0000003
          }
          schedule {
            step: 6000
            learning_rate: .00000003
          }
        }
      }
    }
    use_moving_average: false
  }
  fine_tune_checkpoint: "CKPT_DIR_TO_CONFIGURE/model.ckpt"
  from_detection_checkpoint: true
  load_all_detection_checkpoint_vars: true
  num_steps: 50000
  startup_delay_steps: 0.0
  replicas_to_aggregate: 8
  max_number_of_boxes: 100
  unpad_groundtruth_tensors: false
  freeze_variables:
        [ 'FeatureExtractor/MobilenetV2/Conv/',
          'FeatureExtractor/MobilenetV2/expanded_conv/',
          'FeatureExtractor/MobilenetV2/expanded_conv_1/',
          'FeatureExtractor/MobilenetV2/expanded_conv_2/',
          'FeatureExtractor/MobilenetV2/expanded_conv_3/',
          'FeatureExtractor/MobilenetV2/expanded_conv_4/',
          'FeatureExtractor/MobilenetV2/expanded_conv_5/',
          'FeatureExtractor/MobilenetV2/expanded_conv_6/',
          'FeatureExtractor/MobilenetV2/expanded_conv_7/']
}
train_input_reader: {
  label_map_path: "DATASET_DIR_TO_CONFIGURE/pascal_label_map.pbtxt"
  tf_record_input_reader {
    input_path: "DATASET_DIR_TO_CONFIGURE/pascal_train.record"
  }
}
eval_config: {
  num_examples: 10
  num_visualizations: 10
  eval_interval_secs: 0
}
eval_input_reader: {
  label_map_path: "DATASET_DIR_TO_CONFIGURE/pascal_label_map.pbtxt"
  shuffle: false
  num_readers: 1
  tf_record_input_reader {
    input_path: "DATASET_DIR_TO_CONFIGURE/pascal_val.record"
  }
}
graph_rewriter {
  quantization {
    delay: 48000
    weight_bits: 8
    activation_bits: 8
  }
}
```

```console:
$ nano retrain_detection_model.sh
```

```bash:retrain_detection_model.sh
#!/bin/bash

# Exit script on error.
set -e
# Echo each command, easier for debugging.
set -x

usage() {
  cat << END_OF_USAGE
  Starts retraining detection model.

  --num_training_steps Number of training steps to run, 500 by default.
  --num_eval_steps     Number of evaluation steps to run, 100 by default.
  --help               Display this help.
END_OF_USAGE
}

num_training_steps=500
while [[ $# -gt 0 ]]; do
  case "$1" in
    --num_training_steps)
      num_training_steps=$2
      shift 2 ;;
    --num_eval_steps)
      num_eval_steps=$2
      shift 2 ;;
    --help)
      usage
      exit 0 ;;
    --*)
      echo "Unknown flag $1"
      usage
      exit 1 ;;
  esac
done

export PYTHONPATH=`pwd`:`pwd`/slim:$PYTHONPATH
export PATH=/usr/local/cuda-9.0/bin:${PATH}
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64/:/usr/local/cuda-9.0/targets/x86_64-linux/lib/stubs:${LD_LIBRARY_PATH}
ldconfig

source "$PWD/constants.sh"

mkdir "${TRAIN_DIR}"

python3 object_detection/model_main.py \
  --pipeline_config_path="${CKPT_DIR}/pipeline.config" \
  --model_dir="${TRAIN_DIR}" \
  --num_train_steps="${num_training_steps}" \
  --num_eval_steps="${num_eval_steps}"
```

```console:Preparation_before_data_processing
$ chmod +x constants.sh
$ chmod +x prepare_checkpoint_and_dataset.sh
$ chmod +x retrain_detection_model.sh
$ chmod +x protoc_update.sh
$ mkdir configs
$ git clone https://github.com/pdollar/coco.git
$ cd coco/PythonAPI
$ python3 setup.py install
$ cd ../..
$ pip3 install tensorflow-gpu==1.12.0 --upgrade
$ wget https://github.com/protocolbuffers/protobuf/archive/v3.7.0.zip
$ unzip v3.7.0.zip;rm v3.7.0.zip;cd protobuf-3.7.0
$ ./autogen.sh
$ ./configure
$ make -j$(($(nproc) + 1))
$ make install
$ cd python
$ export LD_LIBRARY_PATH=../src/.libs
$ python3 setup.py build --cpp_implementation
$ python3 setup.py test --cpp_implementation
$ python3 setup.py install --cpp_implementation
$ ldconfig

$ cd ../..
$ nano object_detection/utils/object_detection_evaluation.py
```

```python:object_detection/utils/object_detection_evaluation.py
# Two lines of correction are required.

#category_name = unicode(category_name, 'utf-8')
category_name = str(category_name, 'utf-8')
```

Restart Docker container.

```console:prepare_checkpoint_and_dataset,_start_training
$ cd models/research

# No sharing of weight values ​​from learned models
$ ./prepare_checkpoint_and_dataset.sh --network_type mobilenet_v1_ssd --train_whole_model true

or

# Sharing of weight value from learned model
$ ./prepare_checkpoint_and_dataset.sh --network_type mobilenet_v1_ssd --train_whole_model false

or

# No sharing of weight values ​​from learned models
$ ./prepare_checkpoint_and_dataset.sh --network_type mobilenet_v2_ssd --train_whole_model true

or

# Sharing of weight value from learned model
$ ./prepare_checkpoint_and_dataset.sh --network_type mobilenet_v2_ssd --train_whole_model false

or

# Sharing of weight value from learned model
$ ./prepare_checkpoint_and_dataset.sh --network_type mobilenet_v2_ssdlite --train_whole_model false


$ source "$PWD/constants.sh";NUM_TRAINING_STEPS=10000 && NUM_EVAL_STEPS=500;rm -rf learn/train;\
./retrain_detection_model.sh \
  --num_training_steps ${NUM_TRAINING_STEPS} \
  --num_eval_steps ${NUM_EVAL_STEPS}

or

$ source "$PWD/constants.sh";NUM_TRAINING_STEPS=500 && NUM_EVAL_STEPS=100;rm -rf learn/train;\
./retrain_detection_model.sh \
  --num_training_steps ${NUM_TRAINING_STEPS} \
  --num_eval_steps ${NUM_EVAL_STEPS}
```


```console:Check_the_progress_of_learning
$ sudo docker exec -it edgetpu-detect /bin/bash
$ cd models/research/learn/train
$ tensorboard --logdir=.
```

To check the progress of learning with Tensorboard, access "**http://localhost:6006**" from the browser of the host PC.

```console:Create_tflite_conversion_script
$ nano convert_checkpoint_to_edgetpu_tflite.sh
```

```bash:convert_checkpoint_to_edgetpu_tflite.sh
#!/bin/bash

# Exit script on error.
set -e
# Echo each command, easier for debugging.
set -x

usage() {
  cat << END_OF_USAGE
  Converts TensorFlow checkpoint to EdgeTPU-compatible TFLite file.

  --network_type    Can be one of [mobilenet_v1_ssd, mobilenet_v2_ssd, mobilenet_v2_ssdlite],
                    mobilenet_v1_ssd by default.
  --checkpoint_num  Checkpoint number, by default 0.
  --help            Display this help.
END_OF_USAGE
}

network_type="mobilenet_v1_ssd"
ckpt_number=0
while [[ $# -gt 0 ]]; do
  case "$1" in
    --network_type)
      network_type=$2
      shift 2 ;;
    --checkpoint_num)
      ckpt_number=$2
      shift 2 ;;
    --help)
      usage
      exit 0 ;;
    --*)
      echo "Unknown flag $1"
      usage
      exit 1 ;;
  esac
done

export PYTHONPATH=`pwd`:`pwd`/slim:$PYTHONPATH
export PATH=/usr/local/cuda-9.0/bin:${PATH}
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64/:/usr/local/cuda-9.0/targets/x86_64-linux/lib/stubs:${LD_LIBRARY_PATH}
ldconfig

source "$PWD/constants.sh"

rm -rf "${OUTPUT_DIR}"
mkdir "${OUTPUT_DIR}"

echo "0 aeroplane" > "${OUTPUT_DIR}/labels.txt"
echo "1 bicycle" >> "${OUTPUT_DIR}/labels.txt"
echo "2 bird" >> "${OUTPUT_DIR}/labels.txt"
echo "3 boat" >> "${OUTPUT_DIR}/labels.txt"
echo "4 bottle" >> "${OUTPUT_DIR}/labels.txt"
echo "5 bus" >> "${OUTPUT_DIR}/labels.txt"
echo "6 car" >> "${OUTPUT_DIR}/labels.txt"
echo "7 cat" >> "${OUTPUT_DIR}/labels.txt"
echo "8 chair" >> "${OUTPUT_DIR}/labels.txt"
echo "9 cow" >> "${OUTPUT_DIR}/labels.txt"
echo "10 diningtable" >> "${OUTPUT_DIR}/labels.txt"
echo "11 dog" >> "${OUTPUT_DIR}/labels.txt"
echo "12 horse" >> "${OUTPUT_DIR}/labels.txt"
echo "13 motorbike" >> "${OUTPUT_DIR}/labels.txt"
echo "14 person" >> "${OUTPUT_DIR}/labels.txt"
echo "15 pottedplant" >> "${OUTPUT_DIR}/labels.txt"
echo "16 sheep" >> "${OUTPUT_DIR}/labels.txt"
echo "17 sofa" >> "${OUTPUT_DIR}/labels.txt"
echo "18 train" >> "${OUTPUT_DIR}/labels.txt"
echo "19 tvmonitor" >> "${OUTPUT_DIR}/labels.txt"

echo "EXPORTING frozen graph from checkpoint..."
python3 object_detection/export_tflite_ssd_graph.py \
  --pipeline_config_path="${CKPT_DIR}/pipeline.config" \
  --trained_checkpoint_prefix="${TRAIN_DIR}/model.ckpt-${ckpt_number}" \
  --output_directory="${OUTPUT_DIR}" \
  --add_postprocessing_op=true

echo "CONVERTING frozen graph to TF Lite file..."
tflite_convert \
  --output_file="${OUTPUT_DIR}/output_tflite_graph.tflite" \
  --graph_def_file="${OUTPUT_DIR}/tflite_graph.pb" \
  --inference_type=QUANTIZED_UINT8 \
  --input_arrays="${INPUT_TENSORS}" \
  --output_arrays="${OUTPUT_TENSORS}" \
  --mean_values=128 \
  --std_dev_values=128 \
  --input_shapes=1,300,300,3 \
  --change_concat_input_ranges=false \
  --allow_nudging_weights_to_use_fast_gemm_kernel=true \
  --allow_custom_ops

echo "TFLite graph generated at ${OUTPUT_DIR}/output_tflite_graph.tflite"
```

```console:Execute_conversion_process_from_meta_file_to_tflite_file
$ chmod +x convert_checkpoint_to_edgetpu_tflite.sh

$ ./convert_checkpoint_to_edgetpu_tflite.sh --network_type mobilenet_v1_ssd --checkpoint_num 50000

or

$ ./convert_checkpoint_to_edgetpu_tflite.sh --network_type mobilenet_v2_ssd --checkpoint_num 50000

or

$ ./convert_checkpoint_to_edgetpu_tflite.sh --network_type mobilenet_v2_ssdlite --checkpoint_num 50000
```
![Screenshot 2019-03-24 09:40:59.png](https://qiita-image-store.s3.amazonaws.com/0/194769/de2461f7-8a05-3ed6-8270-077b397022bc.png)
**https://coral.withgoogle.com/web-compiler/**
![Screenshot 2019-03-21 16:18:27.png](https://qiita-image-store.s3.amazonaws.com/0/194769/5954ea76-1a9a-fd83-af44-988059d66a83.png)

**[Successful]　MobileNetv1-SSD / MobileNetv2-SSD**
![Screenshot 2019-03-24 16:46:05.png](https://qiita-image-store.s3.amazonaws.com/0/194769/15e5aefa-3a8d-fe69-e694-fb743d834f7f.png)

**[Failed]　MobileNetv2-SSDLite**
![Screenshot 2019-03-21 18:34:59.png](https://qiita-image-store.s3.amazonaws.com/0/194769/91e45902-d3f0-3a91-53a0-2faebf72e7e7.png)

# ４．Reference articles
**Retrain an object detection model
https://coral.withgoogle.com/tutorials/edgetpu-retrain-detection/**
**Edge TPU Model Compiler
https://coral.withgoogle.com/web-compiler/**
**Tensorflow detection model zoo
https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md**
**tensorflow/tensorflow/python/tools/freeze_graph.py
https://github.com/tensorflow/tensorflow/blob/5a74dd467f49cf44d80bd02a1979ecff45ae29e8/tensorflow/python/tools/freeze_graph.py**
**【Tensorflow】Tensorflow Object Detection API 学習させてみた
http://app.road.jp.net/?p=1985**
**Adam Optimizer
https://stackoverflow.com/questions/51915803/tensorflow-object-detection-use-adam-instead-of-rmsprop/51920195#51920195**
**Post-training quantization
https://www.tensorflow.org/lite/performance/post_training_quantization**
**Tensorflow r1.13.1 Quantization-aware training
https://github.com/tensorflow/tensorflow/tree/r1.13/tensorflow/contrib/quantize**
**nvidia-docker2のインストール（On Ubuntu 16.04 LTS）
https://qiita.com/spiderx_jp/items/32c421fd00c6ade19720**