কেরাস - স্থানান্তর শিখন - ইনপুট টেনসরের আকার পরিবর্তন করা


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'

আমি যে পোস্টটি লিঙ্ক করেছি তাতে ম্যাজ জানিয়েছে যে একটি মাত্রার অমিল রয়েছে যা কোনও মডেলের ইনপুট স্তর পরিবর্তন করা রোধ করে - যদি এটি হয় তবে আমি কীভাবে সামনে একটি (480, 720, 3) ইনপুট স্তর রেখেছি (224, 224, 3) চিত্রগুলি প্রত্যাশিত ভিজিজি 16 মডেলটির কী?

আমার মনে হয় আরও সম্ভাব্য সমস্যাটি হ'ল আমার প্রাক্তন মডেলের আউটপুটটি এই পোস্টে 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())

InceptionV3 সঙ্গে এই চেষ্টা, এবং এটি হিসাবে লুপ চলতে ধীর এবং ধীর পায়
BachT

@ আর-জিপ আমি একটি ত্রুটি পেয়েছি: 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)

যেখানে এক্স কিছু দশমিক <1।

মূল বিষয়টি হ'ল ঘন স্তরগুলিতে ইনপুটটির আকার পুরো মডেলের ইনপুটটির প্রস্থ এবং উচ্চতার উপর নির্ভর করে। ঘন স্তরে আকৃতির ইনপুট পরিবর্তন করতে পারে না কারণ এর অর্থ নিউরাল নেটওয়ার্ক থেকে নোড যুক্ত করা বা অপসারণ করা হবে।

এটি এড়ানোর এক উপায় হ'ল ফ্ল্যাট স্তর (সাধারণত গ্লোবালএভারেজপুলিং ২ ডি) এর পরিবর্তে গ্লোবাল পুলিং স্তর ব্যবহার করা এটি ঘন স্তরগুলিতে ইনপুটটির আকারের কারণ হিসাবে প্রতি চ্যানেল গড় খুঁজে পাবে (channels,)যা ইনপুট আকারের উপর নির্ভর করে না পুরো মডেল।

একবার এটি হয়ে গেলে নেটওয়ার্কের কোনও স্তরই ইনপুটটির প্রস্থ এবং উচ্চতার উপর নির্ভর করে না তাই ইনপুট স্তরটিকে এমন কিছু দিয়ে পরিবর্তন করা যায়

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

model.layers[0] = input_layerটিএফ ২.১-এ আমার পক্ষে কাজ করে না। কোনও ত্রুটি নেই, তবে স্তরটি বাস্তবে প্রতিস্থাপন করা হয়নি। দেখে মনে হচ্ছে ওজনগুলি অনুলিপি করা আরও মজবুত হতে পারে (অন্যান্য উত্তর দেখুন)।
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। প্রথমে আপনার গ্রন্থাগারটি ইনস্টল করা প্রয়োজন; আপনি যদি টেনসরফ্লো (টিএফ ২.০ এবং এর সাথে) বা কেরাসকে পৃথক গ্রন্থাগার হিসাবে ব্যবহার করছেন তবে তার উপর নির্ভর করে এটি বিভিন্ন উপায়ে ইনস্টল করা প্রয়োজন।

টিএফ-এ কেরাসের জন্য: pip install tfkerassurgeon( https://github.com/Raukk/tf-keras-surgeon )। স্বতন্ত্র কেরাসের জন্য: pip install kerassurgeon( https://github.com/BenWhetton/keras-surgeon )

ইনপুটটি প্রতিস্থাপন করতে (উদাহরণস্বরূপ টিএফ ২.০ সহ; বর্তমানে অনির্ধারিত কোড):

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

@ জিবিবিসিমো উত্তর টিএফ 2 এ আমার জন্য কেবলমাত্র একটি ছোট ফাংশন যা আমি নীচে ভাগ করে নিয়েছি তা দিয়ে ছোট ছোট অভিযোজন নিয়ে কাজ করেছে:

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] রয়েছে। উভয় মডেল একই ওজন আছে। সেট_ওয়েটস (মডেল.জেট_ওয়েটস) ব্যবহার করে, মডেল 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())
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.