10個のオブジェクトを認識するために、事前に訓練されたネットワークで転移学習を行ったとします。トレーニング済みの10個のすべてのカテゴリも、トレーニング済みの元のモデルからの情報も失うことなく、ネットワークが分類できる11番目の項目を追加するにはどうすればよいですか?友人から、この分野で活発な研究が行われていると言われましたが、関連する論文や検索する名前が見つかりませんか?
ありがとうございました。
10個のオブジェクトを認識するために、事前に訓練されたネットワークで転移学習を行ったとします。トレーニング済みの10個のすべてのカテゴリも、トレーニング済みの元のモデルからの情報も失うことなく、ネットワークが分類できる11番目の項目を追加するにはどうすればよいですか?友人から、この分野で活発な研究が行われていると言われましたが、関連する論文や検索する名前が見つかりませんか?
ありがとうございました。
回答:
これが1回限りの場合、単純にニューラルネットワークを再トレーニングできます。頻繁に新しいクラスを追加する必要がある場合、これは悪い考えです。このような場合に行うことは、コンテンツベースの画像検索(CBIR)、または単に画像検索または視覚検索と呼ばれます。以下の回答で両方のケースを説明します。
これが一度だけ発生した場合-11番目のクラスを忘れた場合、または顧客が気が変わった場合- 再び発生しない場合は、11番目の出力ノードを最後のレイヤーに単純に追加できます。このノードの重みをランダムに初期化しますが、他の出力には既に持っている重みを使用します。その後、通常どおりトレーニングします。いくつかの重みを修正するのに役立つかもしれません。つまり、これらを訓練しないでください。
極端な場合は、新しい重みのみをトレーニングし、他のすべてを固定したままにすることです。しかし、これがうまくいくかどうかはわかりません。試してみる価値があるかもしれません。
次の例を考えてみましょう。CDストアで働いており、顧客にアルバムカバーの写真を撮ってもらいたいと考えています。アプリケーションは、オンラインストアでスキャンしたCDを表示します。その場合、ストアにある新しいCDごとにネットワークを再トレーニングする必要があります。それは毎日5枚の新しいCDになる可能性があるため、そのようにネットワークを再トレーニングすることは適切ではありません。
解決策は、画像を特徴空間にマッピングするネットワークをトレーニングすることです。各画像は記述子で表されます。記述子は、たとえば256次元のベクトルです。この記述子を計算し、記述子のデータベース(ストアにあるすべてのCDの記述子)と比較することにより、イメージを「分類」できます。データベース内の最も近い記述子が優先されます。
このような記述子ベクトルを学習するために、ニューラルネットワークをどのようにトレーニングしますか?それは活発な研究分野です。「画像検索」や「メトリック学習」などのキーワードを検索して、最近の作品を見つけることができます。
現在、人々は通常、事前に訓練されたネットワーク、たとえばVGG-16を使用してFCレイヤーを切り離し、最終的な畳み込みを記述子ベクトルとして使用します。トリプレット損失のあるシャムネットワークを使用するなどして、このネットワークをさらにトレーニングできます。
ネットワークトポロジは異なって見えるかもしれませんが、最終的には、事前に訓練されたネットワークには10個の元のクラスの認識を処理するレイヤーがあります。11番目、12番目、.. n番目のクラスを導入する最も簡単な(そして機能する)トリックは、最後に付与される前のすべてのレイヤーを使用し、追加のレイヤー(新しいモデルまたは並列レイヤー)を追加することです。最後のレイヤーを除くすべてのレイヤーの上で、10クラスレイヤー(おそらく、密なレイヤーと[len(dense layer), 10]
オプションのバイアスを持つ形状のマトリックスのマットル)に似ています。
新しいレイヤーは、shapeを持つmatmulレイヤーになります[len(dense layer), len(new classes)]
。
元のトレーニングデータにアクセスできない場合、次の2つのオプションがあります。
元のトレーニングデータにアクセスできる場合は、元のネットワークに新しいクラスを簡単に追加し、再トレーニングしてすぐに11クラスをサポートできます。
これは簡単に行えます。
最初に、これらの10クラスでモデルを構築し、モデルをbase_modelとして保存します。
base_modelをロードし、new_model as-という名前の新しいモデルも定義します
new_model = Sequential()
次に、base_modelのレイヤーをnew_modelに追加します-
# getting all the layers except the last two layers
for layer in base_model.layers[:-2]: #just exclude the last two layers from base_model
new_model.add(layer)
モデルを再度トレーニングしたくないので、新しいモデルのレイヤーをトレーニング不可にします。
# prevent the already trained layers from being trained again
for layer in new_model.layers:
layer.trainable = False
学習を転送するときに、最後のレイヤーを削除すると、モデルは10個のクラスを忘れてしまうため、base_modelの重みをnew_modelに保持する必要があります-
weights_training = base_model.layers[-2].get_weights()
new_model.layers[-2].set_weights(weights_training)
最後に密なレイヤーを追加します。この例では、この密なレイヤーのみをトレーニングします。
new_model.add(Dense(CLASSES, name = 'new_Dense', activation = 'softmax'))
ここでモデルをトレーニングすると、11のクラスすべてに適切な出力が得られることを願っています。
幸せな学習。