#tensorflow
Вопрос:
Проблема
После копирования весов из предварительно подготовленной модели я не получаю тот же результат.
Описание
tf2cv
репозиторий предоставляет предварительно обученные модели в TF2 для различных базовых костей. К сожалению, кодовая база имеет для меня ограниченное применение, потому что они используют подклассы tf.keras.Model
, что очень затрудняет извлечение промежуточных результатов и градиентов по желанию. Поэтому я приступил к переписыванию кодов для магистралей с использованием функционального API. После переписывания кодов архитектуры resnet я скопировал их веса в свою модель и сохранил их в SavedModel
формате. Чтобы проверить, правильно ли это сделано, я ввел данные в свой экземпляр модели и их, и результаты были разными.
Мои подходы к отладке проблемы
- Я проверил количество обучаемых и необучаемых параметров, и они одинаковы между моим экземпляром модели и их экземплярами.
- Я проверил, были ли скопированы все обучаемые веса, которые у них есть.
Мой нынешний образ мыслей
Я думаю, возможно, что веса не были скопированы в правильные слои. Например :- Слой X и слой Y могут иметь веса одинаковой формы, но во время копирования веса веса слоя Y могли попасть в слой X и наоборот. Это возможно только в том случае, если я неправильно сопоставил имена слоев между двумя моделями. Однако я тщательно проверил и до сих пор не нашел ни одной ошибки.
Код
Мой код прилагается ниже. Их tfcv
код () для resnet можно найти здесь
Пожалуйста, обратите внимание, что resnet_orig
в следующем фрагменте кода то же самое, что и здесь
Мой преобразованный код можно найти здесь
from vision.image import resnet as myresnet
from glob import glob
from loguru import logger
import tensorflow as tf
import resnet_orig
import re
import os
import numpy as np
from time import time
from copy import deepcopy
tf.random.set_seed(time())
models = [
'resnet10',
'resnet12',
'resnet14',
'resnetbc14b',
'resnet16',
'resnet18_wd4',
'resnet18_wd2',
'resnet18_w3d4',
'resnet18',
'resnet26',
'resnetbc26b',
'resnet34',
'resnetbc38b',
'resnet50',
'resnet50b',
'resnet101',
'resnet101b',
'resnet152',
'resnet152b',
'resnet200',
'resnet200b',
]
def zipdir(path, ziph):
# ziph is zipfile handle
for root, dirs, files in os.walk(path):
for file in files:
ziph.write(os.path.join(root, file),
os.path.relpath(os.path.join(root, file),
os.path.join(path, '..')))
def find_model_file(model_type):
model_files = glob('*.h5')
for m in model_files:
if '{}-'.format(model_type) in m:
return m
return None
def remap_our_model_variables(our_variables, model_name):
remapped = list()
reg = re.compile(r'(staged )')
for var in our_variables:
newvar = var.replace(model_name, 'features/features')
stage_search = re.search(reg, newvar)
if stage_search is not None:
stage_search = stage_search[0]
newvar = newvar.replace(stage_search, '{}/{}'.format(stage_search,
stage_search))
newvar = newvar.replace('conv_preact', 'conv/conv')
newvar = newvar.replace('conv_bn','bn')
newvar = newvar.replace('logits','output1')
remapped.append(newvar)
remap_dict = dict([(x,y) for x,y in zip(our_variables, remapped)])
return remap_dict
def get_correct_variable(variable_name, trainable_variable_names):
for i, var in enumerate(trainable_variable_names):
if variable_name == var:
return i
logger.info('Uffff.....')
return None
layer_regexp_compiled = re.compile(r'(.*)/.*')
model_files = glob('*.h5')
a = np.ones(shape=(1,224,224,3), dtype=np.float32)
inp = tf.constant(a, dtype=tf.float32)
for model_type in models:
logger.info('Model is {}.'.format(model_type))
model = eval('myresnet.{}(input_height=224,input_width=224,'
'num_classes=1000,data_format="channels_last")'.format(
model_type))
model2 = eval('resnet_orig.{}(data_format="channels_last")'.format(
model_type))
model2.build(input_shape=(None,224, 224,3))
model_name=find_model_file(model_type)
logger.info('Model file is {}.'.format(model_name))
original_weights = deepcopy(model2.weights)
if model_name is not None:
e = model2.load_weights(model_name, by_name=True, skip_mismatch=False)
print(e)
loaded_weights = deepcopy(model2.weights)
else:
logger.info('Pretrained model is not available for {}.'.format(
model_type))
continue
diff = [np.mean(x.numpy()-y.numpy()) for x,y in zip(original_weights,
loaded_weights)]
our_model_weights = model.weights
their_model_weights = model2.weights
assert (len(our_model_weights) == len(their_model_weights))
our_variable_names = [x.name for x in model.weights]
their_variable_names = [x.name for x in model2.weights]
remap_dict = remap_our_model_variables(our_variable_names, model_type)
new_weights = list()
for i in range(len(our_model_weights)):
our_name = model.weights[i].name
remapped_name = remap_dict[our_name]
source_index = get_correct_variable(remapped_name, their_variable_names)
new_weights.append(
model2.weights[source_index].value())
logger.debug('Copying from {} ({}) to {} ({}).'.format(
model2.weights[
source_index].name,
model2.weights[source_index].value().shape,
model.weights[
i].name,
model.weights[i].value().shape))
logger.info(len(new_weights))
logger.info('Setting new weights')
model.set_weights(new_weights)
logger.info('Finished setting new weights.')
their_output = model2(inp)
our_output = model(inp)
logger.info(np.max(their_output.numpy() - our_output.numpy()))
logger.info(diff) # This must be 0.0
break
Комментарии:
1. Можете ли вы попробовать использовать
Pre-Trained Models
отtf.keras.applications
, tensorflow.org/api_docs/python/tf/keras/applications . Это будет намного проще.