केरस - ट्रांसफर लर्निंग - इनपुट टेंसर आकार बदलना


15

यह पोस्ट इंगित करती है कि मैं जो पूरा करना चाहता हूं वह संभव नहीं है। हालाँकि, मैं इस बारे में आश्वस्त नहीं हूँ - जो मैंने पहले ही किया है, उसे देखते हुए, मैं यह नहीं देखता कि मैं जो करना चाहता हूँ उसे हासिल नहीं किया जा सकता ...

मेरे पास दो इमेज डेटासेट हैं जहां एक में आकृति की छवियां हैं (480, 720, 3), जबकि दूसरे में आकृति की छवियां (540, 960, 3) हैं।

मैंने निम्नलिखित कोड का उपयोग करते हुए एक मॉडल शुरू किया:

input = Input(shape=(480, 720, 3), name='image_input')

initial_model = VGG16(weights='imagenet', include_top=False)

for layer in initial_model.layers:
    layer.trainable = False

x = Flatten()(initial_model(input))
x = Dense(1000, activation='relu')(x)
x = BatchNormalization()(x)
x = Dropout(0.5)(x)
x = Dense(1000, activation='relu')(x)
x = BatchNormalization()(x)
x = Dropout(0.5)(x)
x = Dense(14, activation='linear')(x)

model = Model(inputs=input, outputs=x)
model.compile(loss='mse', optimizer='adam', metrics=['mae'])

अब जब मैंने इस मॉडल को पूर्व डेटासेट पर प्रशिक्षित कर दिया है, तो मैं इनपुट टेनसर लेयर को बंद करना चाहता हूं और नए इनपुट टेंसर के साथ मॉडल को एक आकार के साथ तैयार करना चाहता हूं जो बाद के डेटासेट के छवि आयामों से मेल खाता है।

model = load_model('path/to/my/trained/model.h5')
old_input = model.pop(0)
new_input = Input(shape=(540, 960, 3), name='image_input')
x = model(new_input)
m = Model(inputs=new_input, outputs=x)
m.save('transfer_model.h5')

जो इस त्रुटि को जन्म देता है:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/aicg2/.local/lib/python2.7/site-packages/keras/engine/topology.py", line 2506, in save
    save_model(self, filepath, overwrite, include_optimizer)
  File "/home/aicg2/.local/lib/python2.7/site-packages/keras/models.py", line 106, in save_model
    'config': model.get_config()
  File "/home/aicg2/.local/lib/python2.7/site-packages/keras/engine/topology.py", line 2322, in get_config
    layer_config = layer.get_config()
  File "/home/aicg2/.local/lib/python2.7/site-packages/keras/engine/topology.py", line 2370, in get_config
    new_node_index = node_conversion_map[node_key]
KeyError: u'image_input_ib-0'

मेरे द्वारा लिंक किए गए पोस्ट में, maz बताता है कि एक आयाम बेमेल है जो एक मॉडल की इनपुट परत को बदलने से रोकता है - यदि यह मामला था, तो यह कैसे है कि मैं एक (480, 720, 3) इनपुट परत को सामने रखता हूं वीजीजी 16 मॉडल से (224, 224, 3) छवियों की उम्मीद है?

मुझे लगता है कि अधिक संभावना मुद्दा यह है कि मेरे पूर्व मॉडल का आउटपुट इस पोस्ट में fchollet क्या कह रहा है, इसके आधार पर मैं जो कुछ दे रहा हूं, उससे कुछ अलग की उम्मीद है । मैं वाक्यात्मक रूप से भ्रमित हूं, लेकिन मेरा मानना ​​है कि पूरा x = Layer()(x)खंड इनपुट-> आउटपुट से परत के टुकड़े का निर्माण कर रहा है और बस एक अलग इनपुट को सामने फेंक रहा है।

मैं वास्तव में कोई पता नहीं है, हालांकि ...

क्या कोई मुझे बता सकता है कि मैं कैसे पूरा करने की कोशिश कर रहा हूं या नहीं, अगर यह संभव नहीं है, तो मुझे समझाएं कि क्यों नहीं?


क्या आपने इसे हल किया है?
tktktk0711

जवाबों:


4

आप नए इनपुट आकृति के साथ एक नया वीजीजी 16 मॉडल उदाहरण new_shapeबनाकर और सभी लेयर वेट पर कॉपी करके ऐसा कर सकते हैं। कोड मोटे तौर पर है

new_model = VGG16(weights=None, input_shape=new_shape, include_top=False)
for new_layer, layer in zip(new_model.layers[1:], model.layers[1:]):
    new_layer.set_weights(layer.get_weights())

इसे स्थापना के साथ शुरू कर दिया
।3

@ r-zip मुझे एक त्रुटि मिलती है: Traceback (most recent call last): File "predict_video11.py", line 67, in <module> new_layer.set_weights(layer.get_weights()) File "/usr/local/lib/python2.7/dist-packages/keras/engine/base_layer.py", line 1057, in set_weights 'provided weight shape ' + str(w.shape)) ValueError: Layer weight shape (3, 3, 33, 64) not compatible with provided weight shape (3, 3, 9, 64) और वह इनपुट लेयर है इसलिए उपयोग करें [2:]?
mLstudent33

1

वीजीजीनेट के आउटपुट आयामों की आउटपुट चौड़ाई और ऊंचाई इनपुट चौड़ाई और ऊंचाई का एक निश्चित हिस्सा है क्योंकि उन आयामों को बदलने वाली एकमात्र परतें पूलिंग परतें हैं। आउटपुट में चैनलों की संख्या अंतिम कंसिस्टेंट लेयर में फिल्टर की संख्या के लिए तय की गई है। समतल परत आकार के साथ एक आयाम प्राप्त करने के लिए इसे फिर से खोलेगी:

((input_width * x) * (input_height * x) * channels)

जहाँ x कुछ दशमलव <1 है।

मुख्य बिंदु यह है कि घने परतों के लिए इनपुट का आकार पूरे मॉडल के इनपुट की चौड़ाई और ऊंचाई पर निर्भर है। घने परत में आकार इनपुट बदल नहीं सकता है क्योंकि इसका मतलब होगा तंत्रिका नेटवर्क से नोड्स जोड़ना या निकालना।

इससे बचने का एक तरीका यह है कि एक समतल परत के बजाय एक वैश्विक पूलिंग परत का उपयोग किया जाए (आमतौर पर GlobalApretPooling2D), यह औसत चैनल प्रति चैनल को घने परतों को इनपुट के आकार का कारण देगा (channels,)जो कि इनपुट आकार पर निर्भर नहीं है पूरा मॉडल।

एक बार जब यह किया जाता है तो नेटवर्क में कोई भी परत इनपुट की चौड़ाई और ऊंचाई पर निर्भर नहीं होती है, इसलिए इनपुट परत को कुछ के साथ बदला जा सकता है।

input_layer = InputLayer(input_shape=(480, 720, 3), name="input_1")
model.layers[0] = input_layer

model.layers[0] = input_layerTF 2.1 में मेरे लिए काम नहीं करता है। कोई त्रुटि नहीं है, लेकिन परत वास्तव में प्रतिस्थापित नहीं हुई है। ऐसा लगता है कि वेट कॉपी करना अधिक मजबूत हो सकता है (अन्य उत्तर देखें)।
z0r

0

यहां एक और समाधान है, जो वीजीजी मॉडल के लिए विशिष्ट नहीं है।

ध्यान दें, घने परत के वजन को कॉपी नहीं किया जा सकता है (और इस तरह से इसे नए सिरे से शुरू किया जाएगा)। यह समझ में आता है, क्योंकि वजन का आकार पुराने और नए मॉडल में भिन्न होता है।

import keras
import numpy as np

def get_model():
    old_input_shape = (20, 20, 3)
    model = keras.models.Sequential()
    model.add(keras.layers.Conv2D(9, (3, 3), padding="same", input_shape=old_input_shape))
    model.add(keras.layers.MaxPooling2D((2, 2)))
    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(1, activation="sigmoid"))
    model.compile(loss='binary_crossentropy', optimizer=keras.optimizers.Adam(lr=0.0001), metrics=['acc'], )
    model.summary()
    return model

def change_model(model, new_input_shape=(None, 40, 40, 3)):
    # replace input shape of first layer
    model._layers[1].batch_input_shape = new_input_shape

    # feel free to modify additional parameters of other layers, for example...
    model._layers[2].pool_size = (8, 8)
    model._layers[2].strides = (8, 8)

    # rebuild model architecture by exporting and importing via json
    new_model = keras.models.model_from_json(model.to_json())
    new_model.summary()

    # copy weights from old model to new one
    for layer in new_model.layers:
        try:
            layer.set_weights(model.get_layer(name=layer.name).get_weights())
        except:
            print("Could not transfer weights for layer {}".format(layer.name))

    # test new model on a random input image
    X = np.random.rand(10, 40, 40, 3)
    y_pred = new_model.predict(X)
    print(y_pred)

    return new_model

if __name__ == '__main__':
    model = get_model()
    new_model = change_model(model)

0

यह बहुत आसान होना चाहिए kerassurgeon। पहले आपको पुस्तकालय स्थापित करने की आवश्यकता है; इस पर निर्भर करते हुए कि क्या आप केरस का उपयोग टेनसोरफ्लो (टीएफ 2.0 और अप के साथ) या केरस के माध्यम से एक अलग पुस्तकालय के रूप में कर रहे हैं, इसे अलग-अलग तरीकों से स्थापित करने की आवश्यकता है।

टीएआरएस में केरस के लिए: pip install tfkerassurgeon( https://github.com/Raukk/tf-keras-surgeon )। स्टैंडअलोन केर के लिए: pip install kerassurgeon( https://github.com/BenWhetton/keras-surgeon )

इनपुट को बदलने के लिए (उदाहरण के लिए TF 2.0; वर्तमान में बिना कोड के)

from tensorflow import keras  # or import keras for standalone version
from tensorflow.keras.layers import Input

model = load_model('path/to/my/trained/model.h5')
new_input = Input(shape=(540, 960, 3), name='image_input')

# or kerassurgeon for standalone Keras
from tfkerassurgeon import delete_layer, insert_layer

model = delete_layer(model.layers[0])
# inserts before layer 0
model = insert_layer(model.layers[0], new_input)

0

@gebbissimo उत्तर ने मेरे लिए TF2 में काम किया जो कि केवल एक ही फंक्शन में नीचे दिए गए छोटे रूपांतरणों के साथ काम करता है:

def change_input_size(model,h,w,ch=3):
   model._layers[0]._batch_input_shape = (None,h,w,ch)
   new_model = keras.models.model_from_json(model.to_json())
   new_model.summary()
   for layer,new_layer in zip(model.layers,new_model.layers):
      new_layer.set_weights(layer.get_weights())
   return new_model

0

यह मैं केरस मॉडल में इनपुट आकार कैसे बदल सकता हूं। मेरे पास दो सीएनएन मॉडल हैं, एक इनपुट आकार [कोई नहीं, कोई नहीं, 3] जबकि दूसरे का इनपुट आकार [512,512,3] है। दोनों मॉडल में समान वजन है। Set_weights (model.get_weights ()) का उपयोग करके, मॉडल 1 के वजन को मॉडल 2 में स्थानांतरित किया जा सकता है

inputs = Input((None, None, 3))
.....
model = Model(inputs=[inputs], outputs=[outputs])
model.compile(optimizer='adam', loss='mean_squared_error')
model.load_weights('my_model_name.h5')

inputs2 = Input((512, 512, 3))
....
model2 = Model(inputs=[inputs2], outputs=[outputs])
model2.compile(optimizer='adam', loss='mean_squared_error')
model2.set_weights(model.get_weights())
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.