Загрузка частей весов моделей из ранее сохраненного файла hdf5 - PullRequest
0 голосов
/ 22 января 2019

Привет, у меня есть модель, на которой я хотел бы использовать трансферное обучение. У меня есть другая модель, которую я обучил и сохранил свои веса. Я хотел бы загрузить первые несколько весов из ранее обученной модели в эту новую модель, которая имеет те же слои, но в конце я добавил больше слоев. Как я могу загрузить веса из первых нескольких слоев в мою новую модель?

Вот что я пробовал:

def load_custom_weights(model, data, layer_indices):
  weights = [data[p] for p in layer_indices]
  print(model.weights)
  model.set_weights(weights)
  print(model.get_weights())
  return model

filename = 'unimodal_weights/best_weight_image_only_k-fold_1.hdf5'
f = h5py.File(filename, 'r')
img_data = f['model_weights']['Image_Branch']['Image_Branch_2']

img = get_img_branch()
img = load_custom_weights(img, img_data, list(img_data))

Модель, кажется, загружает веса, но моя точность очень низкая, хотя модель, которую мы снимаем с весов, хорошо набрала.

Есть ли способ проверить, действительно ли моя модель загрузила веса?

Редактировать : обе модели с несколькими графическими процессорами

РЕДАКТИРОВАТЬ 2:

Так что моя модель немного хитрая, у меня есть последовательная модель, встроенная в мою модель. Я хочу загрузить веса в одну из веток, а именно ветку изображения

Вот как выглядит моя модель:

Image_Branch:

def get_img_branch():
    Image_Branch = Sequential(name='Image_Branch')
    #block 1
    Image_Branch.add(Conv2D(64, kernel_size=(3,3), activation='relu', padding='valid', kernel_initializer='he_normal', name='block1_conv1'))
    Image_Branch.add(BatchNormalization())
    Image_Branch.add(Conv2D(64, kernel_size=(3,3), activation='relu', padding='valid', kernel_initializer='he_normal', name='block1_conv2'))
    Image_Branch.add(BatchNormalization())
    Image_Branch.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), name='block1_pool'))
...SNIP...
    #Flatten
    Image_Branch.add(Flatten())
    return Image_Branch

Инкапсулирующая модель

image_input = Input(shape, name='image_input')
#get branches
img = get_img_branch()
#set up our image branch
image_branch = (img)(image_input)
...SNIP

мы можем видеть, что мы взяли ветвь изображения, которая является последовательной моделью, и вставили ее в новую модель. Ключевым моментом здесь является то, что в формате HDF5 есть ключ с именем: ['model_weights']. В этом словаре есть еще один ключ с именем ['Image_Branch'], который соответствует моей модели.

То, что мы делаем, это просто позвоните:

load_weights(img_loc, by_name=True)

вместо:

img = get_img_branch()
img.load_weights(img_loc, by_name=True)

потому что при последнем выполнении будет пытаться найти ключ ветви изображения ['Image_Branch'], но не найдет его, потому что когда мы загружали ветку изображения в последнем примере, это ветвь изображения. Слой «Image_Branch» существует только в модели, которая его инкапсулирует.

Также, если вы хотите загрузить модель с несколькими графическими процессорами и указать веса, которые вы сделаете:

model.layers[-2].load_weights(img_loc, by_name=True)

1 Ответ

0 голосов
/ 22 января 2019

Вы можете достичь этого, осторожно назвав свои слои и используя существующую model.load_weights(filename, by_name=True) из документации :

model.load_weights(filepath, by_name=False) загружает вес модели из файла HDF5 (созданного save_weights). По умолчанию ожидается, что архитектура не изменится. Чтобы загрузить веса в другую архитектуру (с несколькими общими слоями), используйте by_name=True, чтобы загрузить только те слои с одинаковым именем.

То, к чему относится имя, например, Dense(21, ..., name='dense_layer_1') или ваша Image_Branch подмодель. Поэтому проверьте исходные имена слоев, а затем воссоздайте новую модель с совпадающими именами, в то время как новые слои имеют разные новые имена.

...