TensorFlow+Kerasでヒートマップ系のモデルを使用する場合、レイヤーの途中で画像サイズを拡大するためにlambdaを使用したBilinearフィルタが含まれるケースがあります。lambdaを扱えないハードウェアで推論する場合、この処理を規定のレイヤーに置き換える必要があります。

up2 = Lambda(
     lambda x: tf.image.resize_bilinear(
        x[0],
         x[1].shape.as_list()[1:3], 
         align_corners=True))([low3, up1])

単純に、元画像の1/2になっている場合は、UpSampling2Dに置き換えることができます。しかし、縮小時のテンソルが奇数の場合に、丸めが行われ、UpSamping2Dではテンソルサイズが合わない場合があります。たとえば、(5,5) -> (3,3)に縮小されたテンソルだと、(3,3) -> (6,6)に拡大されてしまいます。

この場合、4倍まで出力を拡大したあと、Croppingして、縮小することでサイズをあわせることができます。

from_shape=low3.shape.as_list()[1:3]
to_shape=up1.shape.as_list()[1:3]
crop_h=from_shape[0]*2-to_shape[0]
crop_w=from_shape[1]*2-to_shape[1]
common_upsample = UpSampling2D(size=(4,4), name=prefix_name+"_up_sampling2d")(low3)
common_multiple = Cropping2D((crop_h,crop_w), name=prefix_name+"_crop")(common_upsample)
up2 = AveragePooling2D(pool_size=(2,2), strides=(2,2), padding="same", name=prefix_name+"_downsampling")(common_multiple)

keras2caffeを使う場合は、UpSampling2Dの名前はup_sampling2dをつけておきます。

これで、多様なハードウェアで動作するようなネットワークを構築することができます。なお、出力はBilinearとは異なり、NearestNeighborとなるため、完全に一致はしません。

このように変更したあとに、規定の学習済みモデルを読み込むには、load_weightsでby_name=Trueを指定します。

net.load_weights("keras.h5",by_name=True)