8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TensorFlowAdvent Calendar 2020

Day 3

tf.image.resizeを含むFull Integer Quantization (.tflite)モデルのEdgeTPUモデルへの変換後の推論時に発生する "main.ERROR - Only float32 and uint8 are supported currently, got -xxx.Node number n (op name) failed to invoke" エラーの回避方法

Last updated at Posted at 2020-12-02

1. はじめに

2020年11月時点の TFLite Converter あるいは edgetpu compiler のどちらかにバグがあり、 TensorFlow v2.xtf.image.resize オペレーションを含むモデルを量子化すると構造が壊れます。 下記に問題提起されています。

  1. issue : Resize Nearest Neighbor does not convert #187 - google-coral/edgetpu
  2. issue : Yolov4-Tiny EdgeTPU Missing Leaky Relu #51 - PINTO0309/PINTO_model_zoo
  3. issue : RESIZE_NEAREST_NEIGHBOR Operation version not supported #42024 - tensorflow/tensorflow

具体的には、下図の一例のようにEdgeTPUモデルへ変換した際の仕様不備により、 ResizeNearestNeighbor あるいは ResizeBilinear 以降の変換が正しく行われないばかりか、推論実行時に edgetpu_runtime が動作不安定になりエラーを出力します。 これは TensorFlow v1.x の頃には発生していなかった事象です。 half_pixel_centerstrue の状態のモデルを量子化して生成すると発生します。 また、 EdgeTPUモデルへ変換せず INT8量子化 を行っただけのモデルの挙動も不安定になるなど、問題が多いです。
Screenshot 2020-11-29 20:27:28.png

エラーの発生例は下記のとおりですが、 ResizeNearestNeighborResizeBilinear の部分でエラーになるわけではなく、その後ろのどこかのレイヤーで仕様アンマッチによるエラーを引き起こしますので、問題の所在がとてもわかりくいバグです。

エラー例1
main.ERROR - Only float32 and uint8 is supported currently, got INT8.Node number 404 (LEAKY_RELU) failed to invoke.
エラー例2
main.ERROR - Only float32 and uint8 are supported currently, got -1695564548.Node number 5 (PRELU) failed to invoke.

2. 回避方法

下記は Cloud TPU を使用した場合に発生する類似の問題を回避する方法をご説明いただいている記事です。 今回は下記2種類の対処を同時に実施します。

  1. TPUでアップサンプリングする際にエラーを出さない方法 - Shikoan's ML Blog - @koshian2さん
  2. Colab TPUでもtensorflow.kerasでBilinear法のアップサンプリングを行う方法 - Qiita - @fwattyさん

TensorFlow v1.x 世代の resize オペレーションへ置き換えることにより問題を回避します。 Lamda を経由してコールしないと Numpy 変換は対応していない、という旨のエラーが発生してしまいます。 Lamda でラップして定義した v1.x ベースの resize オペレーションは、正常に v2.x ベースの ResizeNearestNeighborResizeBilinear へ変換されることを確認済みです。

Lamdaを使用したupsamplingの実装例
### 呼び出し先の関数定義 ############################################################
def upsampling2d_bilinear(x, upsampling_factor_height, upsampling_factor_width):
    w = x.shape[2] * upsampling_factor_width
    h = x.shape[1] * upsampling_factor_height
    return tf.compat.v1.image.resize_bilinear(x, (h, w))

def upsampling2d_nearest(x, upsampling_factor_height, upsampling_factor_width):
    w = x.shape[2] * upsampling_factor_width
    h = x.shape[1] * upsampling_factor_height
    return tf.compat.v1.image.resize_nearest_neighbor(x, (h, w))

### 呼び出し元のメインロジック #######################################################
# height方向に2倍、width方向に2倍のupsamplingを行います。整数のみ指定可能です。
x = Lambda(upsampling2d_bilinear,
           arguments={'upsampling_factor_height': 2,
                      'upsampling_factor_width':  2})(x)

# height方向に4倍、width方向に4倍のupsamplingを行います。整数のみ指定可能です。
x = Lambda(upsampling2d_nearest,
           arguments={'upsampling_factor_height': 4,
                      'upsampling_factor_width':  4})(x)

下図のように v1.x ベースの resize オペレーションを使用していても v2.x ベースの resize オペレーションへ正常に変換されていることが分かります。 更に half_pixel_centersfalse に設定されていることが分かります。
Screenshot 2020-11-29 21:12:55.png

edgetpu_compiler を通して.tfliteをコンバートすると、下図のように全てのオペレーションが EdgeTPU 対応のカスタムオペレータに変換されたことが分かります。 これで EdgeTPU 上で推論を実行してもエラーになることはありません。
Screenshot 2020-11-29 20:46:53.png
今回の問題を発生させる標準オペレーションは下記です。 そもそも half_pixel_centers を設定するパラメータがありませんので外から制御することができません。

TF2.x_Resize_images_to_size_using_the_specified_method
tf.image.resize(
    images, size, method=ResizeMethod.BILINEAR, preserve_aspect_ratio=False,
    antialias=False, name=None
)
Args Overview
images 4-D Tensor of shape [batch, height, width, channels] or 3-D Tensor of shape [height, width, channels].
size A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images.
method An image.ResizeMethod, or string equivalent. Defaults to bilinear.
preserve_aspect_ratio Whether to preserve the aspect ratio. If this is set, then images will be resized to a size that fits in size while preserving the aspect ratio of the original image. Scales up the image if size is bigger than the current size of the image. Defaults to False.
antialias Whether to use an anti-aliasing filter when downsampling an image.
name A name for this operation (optional).

3. おわりに

以上です。 それでは皆さん、 良いTensorFlowライフを満喫してください! ちなにみに私お手製の PyTorch(NCHW) to TensoFlow(NHWC) 変換ツール openvino2tensorflow はツールレベルで対処済みです。

8
3
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
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?