Máy ảnh - Chuyển giao học tập - thay đổi hình dạng tenor đầu vào


14

Bài đăng này dường như chỉ ra rằng những gì tôi muốn thực hiện là không thể. Tuy nhiên, tôi không bị thuyết phục về điều này - với những gì tôi đã làm, tôi không hiểu tại sao những gì tôi muốn làm không thể đạt được ...

Tôi có hai bộ dữ liệu hình ảnh trong đó một bộ có hình ảnh có hình dạng (480, 720, 3) trong khi bộ kia có hình ảnh có hình dạng (540, 960, 3).

Tôi đã khởi tạo một mô hình bằng mã sau đây:

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'])

Bây giờ tôi đã đào tạo mô hình này trên tập dữ liệu cũ, tôi muốn tắt lớp tenxơ đầu vào và thêm vào mô hình với một tenxơ đầu vào mới có hình dạng khớp với kích thước hình ảnh của tập dữ liệu sau.

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')

dẫn đến lỗi này:

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'

Trong bài đăng mà tôi đã liên kết, maz nói rằng có một sự không phù hợp về kích thước ngăn thay đổi lớp đầu vào của một mô hình - nếu đây là trường hợp, thì làm thế nào mà tôi đặt một lớp đầu vào (480, 720, 3) ở phía trước của mô hình VGG16 dự kiến ​​hình ảnh (224, 224, 3)?

Tôi nghĩ một vấn đề có khả năng hơn là đầu ra của mô hình cũ của tôi đang mong đợi một cái gì đó khác với những gì tôi đang đưa ra dựa trên những gì fchollet đang nói trong bài viết này . Tôi bị nhầm lẫn về mặt cú pháp, nhưng tôi tin rằng toàn bộ x = Layer()(x)phân khúc đang xây dựng từng lớp từng mảnh từ đầu vào-> đầu ra và chỉ cần ném một đầu vào khác ở phía trước là phá vỡ nó.

Tôi thực sự không biết mặc dù ...

Ai đó có thể vui lòng cho tôi biết làm thế nào để hoàn thành những gì tôi đang cố gắng làm hoặc nếu không thể, giải thích cho tôi tại sao không?


bạn đã giải quyết nó chưa?
tktktk0711

Câu trả lời:


3

Bạn có thể làm điều này bằng cách tạo một thể hiện mô hình VGG16 mới với hình dạng đầu vào mới new_shapevà sao chép trên tất cả các trọng số lớp. Mã này đại khái

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())

Đã thử điều này với inceptionV3, và nó càng ngày càng chậm hơn khi vòng lặp tiếp tục
BachT

@ r-zip Tôi gặp lỗi: 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) và đó là lớp Input nên sử dụng [2:]?
mLstudent33

1

Chiều rộng và chiều cao đầu ra của kích thước đầu ra của VGGnet là một phần cố định của chiều rộng và chiều cao đầu vào vì các lớp duy nhất thay đổi các kích thước đó là các lớp gộp. Số lượng kênh trong đầu ra được cố định với số lượng bộ lọc trong lớp chập cuối cùng. Lớp làm phẳng sẽ định hình lại điều này để có được một chiều với hình dạng:

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

Trong đó x là một số thập phân <1.

Điểm chính là hình dạng của đầu vào cho các lớp Mật độ phụ thuộc vào chiều rộng và chiều cao của đầu vào cho toàn bộ mô hình. Đầu vào hình dạng cho lớp dày đặc không thể thay đổi vì điều này có nghĩa là thêm hoặc loại bỏ các nút khỏi mạng lưới thần kinh.

Một cách để tránh điều này là sử dụng lớp tổng hợp toàn cầu thay vì lớp làm phẳng (thường là GlobalAlusivePooling2D), điều này sẽ tìm mức trung bình trên mỗi kênh khiến hình dạng của đầu vào của các lớp Dense (channels,)không phụ thuộc vào hình dạng đầu vào Toàn bộ mô hình.

Một khi điều này được thực hiện, không có lớp nào trong mạng phụ thuộc vào chiều rộng và chiều cao của đầu vào để lớp đầu vào có thể được thay đổi bằng một cái gì đó như

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

0

Đây là một giải pháp khác, không dành riêng cho mô hình VGG.

Lưu ý rằng trọng lượng của lớp dày đặc không thể được sao chép (và do đó sẽ được khởi tạo mới). Điều này có ý nghĩa, bởi vì hình dạng của các trọng lượng khác nhau trong mô hình cũ và mới.

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

Điều này sẽ khá dễ dàng với kerassurgeon. Đầu tiên bạn cần cài đặt thư viện; tùy thuộc vào việc bạn đang sử dụng Keras thông qua TensorFlow (với tf 2.0 trở lên) hay Keras như một thư viện riêng biệt, nó cần được cài đặt theo nhiều cách khác nhau.

Đối với máy ảnh trong TF: pip install tfkerassurgeon( https://github.com/Raukk/tf-keras-surgeon ). Đối với máy ảnh độc lập: pip install kerassurgeon( https://github.com/BenWhetton/keras-surgeon )

Để thay thế đầu vào (ví dụ với TF 2.0; mã hiện chưa được kiểm tra):

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

Câu trả lời @ Quaybissimo làm việc cho tôi trong TF2 chỉ với những điều chỉnh nhỏ mà tôi chia sẻ dưới đây trong một chức năng duy nhất:

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

Đây là cách tôi thay đổi kích thước đầu vào trong mô hình Keras. Tôi có hai mô hình CNN, một mô hình có kích thước đầu vào [Không, Không, 3] trong khi mô hình kia có kích thước đầu vào [512,512,3]. Cả hai mô hình có trọng lượng như nhau. Bằng cách sử dụng set_weights (model.get_weights ()), trọng số của mô hình 1 có thể được chuyển sang mô hình 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())
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.