2017-09-08 2 views
7

Je suis encore débutant en tensorflow alors je suis désolé si c'est une question naïve. J'essaie d'utiliser le jeu de données inception_V4model pretrained sur ImageNet publié sur ce site. En outre, j'utilise leur réseau tel qu'il est, je veux dire celui publié sur leur site.Retrain InceptionV4 Couche finale pour les nouvelles catégories: variable locale non initialisée

Voici comment j'appelle le réseau:

def network(images_op, keep_prob): 

    width_needed_InceptionV4Net = 342 
    shape = images_op.get_shape().as_list() 
    H = int(round(width_needed_InceptionV4Net * shape[1]/shape[2], 2)) 
    resized_images = tf.image.resize_images(images_op, [width_needed_InceptionV4Net, H], tf.image.ResizeMethod.BILINEAR) 

    with slim.arg_scope(inception.inception_v4_arg_scope()): 
     logits, _ = inception.inception_v4(resized_images, num_classes=20, is_training=True, dropout_keep_prob = keep_prob) 

    return logits 

Depuis que je dois recycler la couche finale de la Inception_V4 pour mes catégories, j'ai modifié le nombre de classes à 20 comme vous pouvez le voir dans la méthode appelez le (inception.inception_v4).

Voici la méthode de train, j'ai jusqu'à présent:

def optimistic_restore(session, save_file, flags): 
reader = tf.train.NewCheckpointReader(save_file) 
saved_shapes = reader.get_variable_to_shape_map() 
var_names = sorted([(var.name, var.name.split(':')[0]) for var in tf.global_variables() 
     if var.name.split(':')[0] in saved_shapes]) 
restore_vars = [] 
name2var = dict(zip(map(lambda x:x.name.split(':')[0], tf.global_variables()), tf.global_variables())) 

if flags.checkpoint_exclude_scopes is not None: 
    exclusions = [scope.strip() for scope in flags.checkpoint_exclude_scopes.split(',')] 

with tf.variable_scope('', reuse=True): 
    variables_to_init = [] 
    for var_name, saved_var_name in var_names: 
     curr_var = name2var[saved_var_name] 
     var_shape = curr_var.get_shape().as_list() 
     if var_shape == saved_shapes[saved_var_name]: 
      print(saved_var_name) 
      excluded = False 
      for exclusion in exclusions: 
       if saved_var_name.startswith(exclusion): 
        variables_to_init.append(var) 
        excluded = True 
        break 
      if not excluded: 
       restore_vars.append(curr_var) 
saver = tf.train.Saver(restore_vars) 
saver.restore(session, save_file) 

def train(images, ids, labels, total_num_examples, batch_size, train_dir, network, flags, 
    optimizer, log_periods, resume): 
"""[email protected] Trains the network for a number of steps. 

@param images image tensor 
@param ids id tensor 
@param labels label tensor 
@param total_num_examples total number of training examples 
@param batch_size batch size 
@param train_dir directory where checkpoints should be saved 
@param network pointer to a function describing the network 
@param flags command-line arguments 
@param optimizer pointer to the optimization class 
@param log_periods list containing the step intervals at which 1) logs should be printed, 
    2) logs should be saved for TensorBoard and 3) variables should be saved 
@param resume should training be resumed (or restarted from scratch)? 

@return the number of training steps performed since the first call to 'train' 
""" 

# clearing the training directory 
if not resume: 
    if tf.gfile.Exists(train_dir): 
     tf.gfile.DeleteRecursively(train_dir) 
    tf.gfile.MakeDirs(train_dir) 

print('Training the network in directory %s...' % train_dir) 
global_step = tf.Variable(0, trainable = False) 

# creating a placeholder, set to ones, used to assess the importance of each pixel 
mask, ones = _mask(images, batch_size, flags) 

# building a Graph that computes the logits predictions from the inference model 
keep_prob = tf.placeholder_with_default(0.5, []) 
logits = network(images * mask, keep_prob) 

# creating the optimizer 
if optimizer == tf.train.MomentumOptimizer: 
    opt = optimizer(flags.learning_rate, flags.momentum) 
else: 
    opt = optimizer(flags.learning_rate) 


# calculating the semantic loss, defined as the classification or regression loss 
if flags.boosting_weights is not None and os.path.isfile(flags.boosting_weights): 
    boosting_weights_value = np.loadtxt(flags.boosting_weights, dtype = np.float32, 
             delimiter = ',') 
    boosting_weights = tf.placeholder_with_default(boosting_weights_value, 
                list(boosting_weights_value.shape), 
                name = 'boosting_weights') 
    semantic_loss = _boosting_loss(logits, ids, boosting_weights, flags) 
else: 
    semantic_loss = _loss(logits, labels, flags) 
tf.add_to_collection('losses', semantic_loss) 

# computing the loss gradient with respect to the mask (i.e. the insight tensor) and 
# penalizing its L1-norm 
# replace 'semantic_loss' with 'tf.reduce_sum(logits)'? 
insight = tf.gradients(semantic_loss, [mask])[0] 
insight_loss = tf.reduce_sum(tf.abs(insight)) 
if flags.insight_loss > 0.0: 
    with tf.control_dependencies([semantic_loss]): 
     tf.add_to_collection('losses', tf.multiply(flags.insight_loss, insight_loss, 
                name = 'insight_loss')) 
else: 
    tf.summary.scalar('insight_loss_raw', insight_loss) 

# summing all loss factors and computing the moving average of all individual losses and of 
# the sum 
loss = tf.add_n(tf.get_collection('losses'), name = 'total_loss') 
loss_averages_op = tf.train.ExponentialMovingAverage(0.9, name = 'avg') 
losses = tf.get_collection('losses') 
loss_averages = loss_averages_op.apply(losses + [loss]) 

# attaching a scalar summary to all individual losses and the total loss; 
# do the same for the averaged version of the losses 
for l in losses + [loss]: 
    tf.summary.scalar(l.op.name + '_raw', l) 
    tf.summary.scalar(l.op.name + '_avg', loss_averages_op.average(l)) 

# computing and applying gradients 
with tf.control_dependencies([loss_averages]): 
    grads = opt.compute_gradients(loss) 
apply_gradient = opt.apply_gradients(grads, global_step = global_step) 

# adding histograms for trainable variables and gradients 
for var in tf.trainable_variables(): 
    tf.summary.histogram(var.op.name, var) 
for grad, var in grads: 
    if grad is not None: 
     tf.summary.histogram(var.op.name + '/gradients', grad) 
tf.summary.histogram('insight', insight) 

# tracking the moving averages of all trainable variables 
variable_averages_op = tf.train.ExponentialMovingAverage(flags.moving_average_decay, 
                 global_step) 
variable_averages = variable_averages_op.apply(tf.trainable_variables()) 

# building a Graph that trains the model with one batch of examples and 
# updates the model parameters 
with tf.control_dependencies([apply_gradient, variable_averages]): 
    train_op = tf.no_op(name = 'train') 

# creating a saver 
saver = tf.train.Saver(tf.global_variables()) 

# building the summary operation based on the TF collection of Summaries 
summary_op = tf.summary.merge_all() 

# creating a session 
current_global_step = -1 
with tf.Session(config = tf.ConfigProto(log_device_placement = False, 
              inter_op_parallelism_threads = flags.num_cpus, 
              device_count = {'GPU': flags.num_gpus})) as sess: 

    # initializing variables 
    if flags.checkpoint_exclude_scopes is not None: 
      optimistic_restore(sess, os.path.join(train_dir, 'inception_V4.ckpt'), flags) 

    # starting the queue runners 
    .. 
    # creating a summary writer 
    .. 
    # training itself 
    .. 
    # saving the model checkpoint 
    checkpoint_path = os.path.join(train_dir, 'model.ckpt') 
    saver.save(sess, checkpoint_path, global_step = current_global_step) 

    # stopping the queue runners 
    .. 
return current_global_step 

J'ai ajouté un drapeau au script python appelé checkpoint_exclude_scopes où je précise que tenseurs ne devrait pas être rétablie. Ceci est nécessaire pour changer le nombre de classes dans la dernière couche du réseau. Voici comment j'appelle le script python:

./toolDetectionInceptions.py --batch_size=32 --running_mode=resume --checkpoint_exclude_scopes=InceptionV4/Logits,InceptionV4/AuxLogits 

Mes premiers essais ont été terribles parce que je suis arrivé trop de problèmes .. quelque chose comme:

tensorflow.python.framework.errors.NotFoundError: Tensor name "InceptionV4/Mixed_6b/Branch_3/Conv2d_0b_1x1/weights/read:0" not found in checkpoint files 

Après quelques googler je pouvais trouver une solution à ce site où ils proposent d'utiliser la fonction optimistic_restore présentée dans le code ci-dessus en y incluant quelques modifications.

Mais maintenant, le problème est autre chose:

W tensorflow/core/framework/op_kernel.cc:993] Failed precondition: Attempting to use uninitialized value Variable 
    [[Node: Variable/read = Identity[T=DT_INT32, _class=["loc:@Variable"], _device="/job:localhost/replica:0/task:0/cpu:0"](Variable)]] 

Il semble qu'il y ait une variable locale que ce n'est pas initialisé, mais je ne pouvais pas trouver. Pouvez-vous s'il vous plaît aider?

ÉDITÉ:

Pour déboguer ce problème, j'ai vérifié le nombre de variables qui doivent être initialisées et remis en état en ajoutant des journaux dans la fonction optimistic_restore. Voici un bref:

# saved_shapes 609 
    # var_names 608 
    # name2var 1519 
    # variables_to_init: 7 
    # restore_vars: 596 
    # global_variables: 1519 

Pour votre information, CheckpointReader.get_variable_to_shape_map(): retourne un nom de tenseur de cartographie dict aux listes de ints, ce qui représente la forme du tenseur correspondant dans le poste de contrôle. Cela signifie que le nombre de variables dans ce point de contrôle est 609 et le nombre total de variables nécessaires pour la restauration est 1519.

Il semble qu'il y ait un énorme écart entre les tenseurs de point de contrôle préalables et les variables utilisées par l'architecture réseau (c'est aussi leur réseau). Existe-t-il une sorte de compression sur le point de contrôle? Est-ce exact ce que je dis? Je sais maintenant ce qui manque: c'est juste l'initialisation des variables qui n'ont pas été restaurées. Pourtant, j'ai besoin de savoir pourquoi il y a une énorme différence entre leur architecture réseau InceptionV4 et le point de contrôle pré-entraîné?

+0

Est-ce que 'sess.run (tf.global_variables_initializer())' résoudre votre problème? – rvinas

+0

Merci @rvinas. Si je comprends bien, il initialise toutes les variables et ne conserve pas les valeurs des poids restaurés. Cela signifie: en utilisant cette méthode, nous brisons le concept de finetuning. Ai-je tort? BTW, je l'ai essayé et ça marche mais je pense que ça ne fait pas vraiment ce dont j'ai besoin. – Maystro

+0

Vous êtes les bienvenus. Si c'est le cas, ma réponse résoudra probablement votre problème. – rvinas

Répondre

2

Voici comment je définir la fonction optimistic_restore pour le faire fonctionner comme prévu:

def optimistic_restore(session, save_file, flags): 

if flags.checkpoint_exclude_scopes is not None: 
    exclusions = [scope.strip() for scope in flags.checkpoint_exclude_scopes.split(',')] 

reader = tf.train.NewCheckpointReader(save_file) 
saved_shapes = reader.get_variable_to_shape_map() 
print ('saved_shapes %d' % len(saved_shapes)) 
var_names = sorted([(var.name, var.name.split(':')[0]) for var in tf.global_variables() 
        if var.name.split(':')[0] in saved_shapes]) 

var_names_to_be_initialized = sorted([(var.name, var.name.split(':')[0]) for var in tf.global_variables() 
        if var.name.split(':')[0] not in saved_shapes]) 
print('var_names %d' % len(var_names)) 
print('var_names_to_be_initialized %d' % len(var_names_to_be_initialized)) 
restore_vars = [] 
name2var = dict(zip(map(lambda x: x.name.split(':')[0], tf.global_variables()), tf.global_variables())) 
print('name2var %d' % len(name2var)) 

with tf.variable_scope('', reuse=True): 
    variables_to_init = [] 
    for var_name, saved_var_name in var_names: 
     curr_var = name2var[saved_var_name] 
     var_shape = curr_var.get_shape().as_list() 
     if var_shape == saved_shapes[saved_var_name]: 
      excluded = False 
      for exclusion in exclusions: 
       if saved_var_name.startswith(exclusion): 
        variables_to_init.append(curr_var) 
        excluded = True 
        break 
      if not excluded: 
       restore_vars.append(curr_var) 
     else: 
      variables2_to_init.append(curr_var) 
    for var_name, saved_var_name in var_names_to_be_initialized: 
     curr_var = name2var[saved_var_name] 
     variables2_to_init.append(curr_var) 

print('variables2_to_init : %d ' % len(variables_to_init)) 
print('global_variables: %d ' % len(tf.global_variables())) 
print('restore_vars: %d ' % len(restore_vars)) 
saver = tf.train.Saver(restore_vars) 
saver.restore(session, save_file) 
session.run(tf.variables_initializer(variables_to_init)) 
3

Les variables qui ne sont pas restaurées avec l'économiseur doivent être initialisées. À cette fin, vous pouvez exécuter v.initializer.run() pour chaque variable v que vous ne restaurez pas.

+0

Merci pour votre réponse. C'est le concept que je devrais appliquer à mon code, donc je vais upvote votre réponse – Maystro