前提
現在,こちらを参考にしてResNet50v2 + ArcFaceの実装を行っています.
ArcFaceの定義自体は上記のサイトをそのまま使用する形で実装しています.
そこで以下のような問題が発生しました.
現在の実装内容とエラー内容
1. 現在の実装内容
まずは,現在使用しているソースコードを記します.
使用しているクラス数と入力画像のshapeです.
python
1from tensorflow.keras.applications.resnet_v2 import ResNet50V2 2from keras.layers import Layer 3(他のimportは省略) 4 5num_classes = 29 6input_shape = (80, 80, 1) # 入力画像shape
次に示すのが,ArcFaceの機能を定義したものになります. こちらは先述の通り上記のサイトを参考にしています.
python
1class Arcfacelayer(Layer): 2 # s:softmaxの温度パラメータ, m:margin 3 def __init__(self, output_dim, s=30, m=0.50, easy_margin=False): 4 self.output_dim = output_dim 5 self.s = s 6 self.m = m 7 self.easy_margin = easy_margin 8 super(Arcfacelayer, self).__init__() 9 10 # 重みの作成 11 def build(self, input_shape): 12 print(f'input_shape:{input_shape}') 13 print(f"self.output_dim:{self.output_dim}") 14 # Create a trainable weight variable for this layer. 15 self.kernel = self.add_weight(name='kernel', 16 shape=(input_shape[0][1], self.output_dim), # ★ 17 initializer='uniform', 18 trainable=True) 19 super(Arcfacelayer, self).build(input_shape) 20 21 22 # mainの処理 23 def call(self, x): 24 print("call関数を読み込みました.") 25 print(f"入力x:{x}") 26 27 y = x[1] 28 x_normalize = tf.math.l2_normalize(x[0]) # x = x'/ ||x'||2 29 k_normalize = tf.math.l2_normalize(self.kernel) # Wj = Wj' / ||Wj'||2 30 31 cos_m = K.cos(self.m) 32 sin_m = K.sin(self.m) 33 th = K.cos(np.pi - self.m) 34 mm = K.sin(np.pi - self.m) * self.m 35 36 cosine = K.dot(x_normalize, k_normalize) # W.Txの内積 37 sine = K.sqrt(1.0 - K.square(cosine)) 38 39 phi = cosine * cos_m - sine * sin_m #cos(θ+m)の加法定理 40 41 if self.easy_margin: 42 phi = tf.where(cosine > 0, phi, cosine) 43 44 else: 45 phi = tf.where(cosine > th, phi, cosine - mm) 46 47 # 正解クラス:cos(θ+m) 他のクラス:cosθ 48 output = (y * phi) + ((1.0 - y) * cosine) 49 output *= self.s 50 51 return output 52 53 def compute_output_shape(self, input_shape): 54 print("compute_output_shape関数を読み込みました.") 55 56 return (input_shape[0][0], self.output_dim) #入力[x,y]のためx[0]はinput_shape[0][0]
次に示すのが,ResNet50v2をベースネットワークとしたArcFaceモデルの定義です. こちらも上記のサイトを参考にしていますが,引数やアーキテクチャを多少変更しています.
python
1# ResNet50v2 + ArcFace定義 2# 学習に使用 3def create_arcface_with_resnet50v2(num_classes, input_shape): 4 # ResNet50V2の入力層の前に独自の入力層を追加 5 input_tensor = input_shape 6 7 input_model = Sequential() 8 input_model.add(InputLayer(input_shape=input_tensor)) 9 input_model.add(Conv2D(3, (7, 7), padding='same')) 10 input_model.add(BatchNormalization()) 11 input_model.add(Activation('relu')) 12 13 resnet50v2 = ResNet50V2(include_top=False, weights=None, input_tensor=input_model.output) 14 15 flat = Flatten()(resnet50v2.layers[-1].output) 16 dense = Dense(512, activation="relu", name="hidden")(flat) 17 18 base_network = Model(input_model.inputs, dense) 19 # DLしてある重みの読み込み 20 base_network.load_weights('save_model(weights_imagenet)/weights_imagenet.hdf5', by_name=True) 21 22 yinput = Input(shape=(num_classes,)) #ArcFaceで使用 23 24 s_cos = Arcfacelayer(num_classes, 30, 0.05)([base_network,yinput]) #outputをクラス数と同じ数に 25 prediction = Activation('softmax')(s_cos) 26 27 model = Model(inputs=[base_network.input,yinput], outputs=prediction) 28 29 return model
2. エラー内容
・エラー1
上記の実装内容から以下を実行すると実行結果とともに次のようなエラーが吐かれました.
Arcfacelayerクラス内のcallメソッドが呼び出される前にbuildメソッドが呼び出されています.
python
1arcface_model = create_arcface_with_resnet50v2(num_classes, input_shape) 2 3 4(↓実行結果とエラー内容) 5 6input_shape:[None, TensorShape([None, 29])] 729 8--------------------------------------------------------------------------- 9TypeError Traceback (most recent call last) 10Input In [11], in <cell line: 1>() 11----> 1 arcface_model = create_arcface_with_resnet50v2(num_classes, input_shape) 12 13Input In [5], in create_arcface_with_resnet50v2(num_classes, input_shape) 14 22 base_network.load_weights('save_model(weights_imagenet)/weights_imagenet.hdf5', by_name=True) 15 24 yinput = Input(shape=(num_classes,)) #ArcFaceで使用 16---> 26 s_cos = Arcfacelayer(num_classes, 30, 0.05)([base_network,yinput]) #outputをクラス数と同じ数に 17 27 prediction = Activation('softmax')(s_cos) 18 29 model = Model(inputs=[base_network.input,yinput], outputs=prediction) 19 20File /usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py:67, in filter_traceback.<locals>.error_handler(*args, **kwargs) 21 65 except Exception as e: # pylint: disable=broad-except 22 66 filtered_tb = _process_traceback_frames(e.__traceback__) 23---> 67 raise e.with_traceback(filtered_tb) from None 24 68 finally: 25 69 del filtered_tb 26 27Input In [4], in Arcfacelayer.build(self, input_shape) 28 13 print(self.output_dim) 29 14 # Create a trainable weight variable for this layer. 30 15 self.kernel = self.add_weight(name='kernel', 31---> 16 shape=(input_shape[0][1], self.output_dim), # ★ 32 17 initializer='uniform', 33 18 trainable=True) 34 19 super(Arcfacelayer, self).build(input_shape) 35 36TypeError: 'NoneType' object is not subscriptable
メッセージ内の★の部分の第一要素がNoneであることがエラーの原因であったため,input_shape[0][1] (=None)をinput_shape[1][1] (=29)に変えると上記のエラーは改善されたが,次は以下のエラーが吐かれるようになってしましました.
・エラー2
こちらのエラーはbuildメソッドの後にcallメソッドが呼び出されてはいて,引数xの0番目の要素についてのエラーであることは理解できるのですが,何が原因でエラーを起こしてしまったのかが分かりません.
input_shape:[None, TensorShape([None, 29])] self.output_dim:29 call関数を読み込みました. 入力x: [<keras.engine.functional.Functional object at 0x7f2125fba580>, <tf.Tensor 'Placeholder:0' shape=(None, 29) dtype=float32>] --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Input In [11], in <cell line: 1>() ----> 1 arcface_model = create_arcface_with_resnet50v2(num_classes, input_shape) Input In [5], in create_arcface_with_resnet50v2(num_classes, input_shape) 22 base_network.load_weights('save_model(weights_imagenet)/weights_imagenet.hdf5', by_name=True) 24 yinput = Input(shape=(num_classes,)) #ArcFaceで使用 ---> 26 s_cos = Arcfacelayer(num_classes, 30, 0.05)([base_network,yinput]) #outputをクラス数と同じ数に 27 prediction = Activation('softmax')(s_cos) 29 model = Model(inputs=[base_network.input,yinput], outputs=prediction) File /usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py:67, in filter_traceback.<locals>.error_handler(*args, **kwargs) 65 except Exception as e: # pylint: disable=broad-except 66 filtered_tb = _process_traceback_frames(e.__traceback__) ---> 67 raise e.with_traceback(filtered_tb) from None 68 finally: 69 del filtered_tb File /usr/local/lib/python3.8/dist-packages/tensorflow/python/autograph/impl/api.py:692, in convert.<locals>.decorator.<locals>.wrapper(*args, **kwargs) 690 except Exception as e: # pylint:disable=broad-except 691 if hasattr(e, 'ag_error_metadata'): --> 692 raise e.ag_error_metadata.to_exception(e) 693 else: 694 raise TypeError: Exception encountered when calling layer "arcfacelayer" (type Arcfacelayer). in user code: File "/tmp/ipykernel_6559/4194376824.py", line 27, in call * x_normalize = tf.math.l2_normalize(x[0]) # x = x'/ ||x'||2 TypeError: Failed to convert elements of <keras.engine.functional.Functional object at 0x7f2125fba580> to Tensor. Consider casting elements to a supported type. See https://www.tensorflow.org/api_docs/python/tf/dtypes for supported TF dtypes. Call arguments received: • x=['<keras.engine.functional.Functional object at 0x7f2125fba580>', 'tf.Tensor(shape=(None, 29), dtype=float32)']
webサイトを参考にしているため,用いるデータの相違などによって生じたエラーか?とも考えています.
しかし,今まで使用してこなかった新たな概念が多いこともあり自力では上記の解決方法が分かりませんでした.
・エラー1の★部分のshapeにはどのような値を設定すればいいのか
・エラー2はどのようなエラーでありどのように修正するとよいか
以上お力をお貸しいただけますと幸いです.よろしくお願いします.
補足情報(FW/ツールのバージョンなど)
ubuntu 20.04
Python 3.8.10
tensorflow-gpu 2.5.3
keras 2.8.0
numpy 1.19.5
jupyter lab 2.3.2

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。