2017-12-18 13 views
0

私はfacenet articleに記載されているようにトリプレットネットワークを訓練しようとしています。精度99%、分類が正しくない - トリプレットネットワーク

私は、正の距離(アンカー - ポジティブ)が負の距離(アンカー - ネガティブ)よりも小さいトリプレットを数えてから、トリプレットの総数で割って、バッチ。

99%の精度が得られます。しかし、モデルの埋め込みを使用して画像を分類すると(私は未知の画像を取ってそれをユークリッド距離を使ってラベル付けした画像と比較します)、たいてい20%の結果しか正しくありません。

私は間違っていますか?

私の詳細な実装は以下にあります。


トリプレット生成は

トリプレット世代前に、私は(整列し、トレーニングとDLIB(CASIAとLFW両方)を使用して、テストセットので、各顔の主要な要素との両方をトリミングしました目、鼻、唇)はほぼ同じ位置にあります。

トリプレットを生成するには、40個以上のイメージを持つCASIAフォルダをランダムに選択し、40個のアンカーを選択します。それぞれのアンカーは対応するポジティブイメージ(ランダムに選択されますがアンカーとは異なります)。次に、アンカーとポジティブのペアごとにランダムなネガティブを選択します。


トリプレット損失

ここにあります私のトリプレット損失関数:

def triplet_loss(d_pos, d_neg): 

    print("d_pos "+str(d_pos)) 
    print("d_neg "+str(d_neg)) 

    margin = 0.2 

    loss = tf.reduce_mean(tf.maximum(0., margin + d_pos - d_neg)) 


    return loss 

これらはとアンカーの間負の距離(および(アンカーと正の間に)私の正の距離です負)。

**model1** = embeddings generated for the anchor image 
**model2** = embeddings generated for the positive image 
**model3** = embeddings generated for the negative image 

可変コスト私は各ステップで計算する損失です。

d_pos_triplet = tf.reduce_sum(tf.square(model1 - model2), 1) 
    d_neg_triplet = tf.reduce_sum(tf.square(model1 - model3), 1) 

    d_pos_triplet_acc = tf.sqrt(d_pos_triplet + 1e-10) 
    d_neg_triplet_acc = tf.sqrt(d_neg_triplet + 1e-10) 

    d_pos_triplet_test = tf.reduce_sum(tf.square(model1_test - model2_test), 1) 
    d_neg_triplet_test = tf.reduce_sum(tf.square(model1_test - model3_test), 1) 

    d_pos_triplet_acc_test = tf.sqrt(d_pos_triplet_test + 1e-10) 
    d_neg_triplet_acc_test = tf.sqrt(d_neg_triplet_test + 1e-10) 


    cost = triplet_loss(d_pos_triplet, d_neg_triplet) 
    cost_test = triplet_loss(d_pos_triplet_test, d_neg_triplet_test) 

損失が正であれば、私はその後、埋め込み1 ずつ、テストを取る - 0損失は、ネットワークが学習しない意味するので(私はセミハードを選択する必要がfaceネットの記事で述べたようにこれは私のモデルである

input1,input2, input3, anchor_folder_helper, anchor_photo_helper, positive_photo_helper = training.next_batch_casia(s,e) #generate complet random 

      s = i * batch_size 
      e = (i+1) *batch_size 

     input1,input2, input3, anchor_folder_helper, anchor_photo_helper, positive_photo_helper = training.next_batch_casia(s,e) #generate complet random 


     lly = 0; 

     '''counter which helps me generate the same number of triplets each batch''' 

     while lly < len(input1): 

      input_lly1 = input1[lly:lly+1] 
      input_lly2 = input2[lly:lly+1] 
      input_lly3 = input3[lly:lly+1] 

      loss_value = sess.run([cost], feed_dict={x_anchor:input_lly1, x_positive:input_lly2, x_negative:input_lly3}) 



      while(loss_value[0]<=0): 
       ''' While the generated triplet has loss 0 (which means dpos - dneg + margin < 0) I keep generating triplets. I stop when I manage to generate a semi-hard triplet. ''' 
       input_lly1,input_lly2, input_lly3, anchor_folder_helper, anchor_photo_helper, positive_photo_helper = training.cauta_hard_negative(anchor_folder_helper, anchor_photo_helper, positive_photo_helper) 
       loss_value = sess.run([cost], feed_dict={x_anchor:input_lly1, x_positive:input_lly2, x_negative:input_lly3}) 

       if (loss_value[0] > 0): 
        _, loss_value, distance1_acc, distance2_acc, m1_acc, m2_acc, m3_acc = sess.run([accum_ops, cost, d_pos_triplet_acc, d_neg_triplet_acc, model1, model2, model3], feed_dict={x_anchor:input_lly1, x_positive:input_lly2, x_negative:input_lly3}) 
       tr_acc = compute_accuracy(distance1_acc, distance2_acc) 

       if math.isnan(tr_acc) and epoch != 0: 
        print('tr_acc %0.2f' % tr_acc) 
        pdb.set_trace() 
        avg_loss += loss_value 
        avg_acc +=tr_acc*100 

        contor_i = contor_i + 1 

        lly = lly + 1 

トリプレット) - 私はL2の正規化を適用すると、私の精度が大幅に低下することに注意してください(多分私は)間違ったことをやっている:

def siamese_convnet(x): 

    w_conv1_1 = tf.get_variable(name='w_conv1_1', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 1, 64]) 
    w_conv1_2 = tf.get_variable(name='w_conv1_2', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 64, 64]) 

    w_conv2_1 = tf.get_variable(name='w_conv2_1', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 64, 128]) 
    w_conv2_2 = tf.get_variable(name='w_conv2_2', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 128, 128]) 

    w_conv3_1 = tf.get_variable(name='w_conv3_1', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 128, 256]) 
    w_conv3_2 = tf.get_variable(name='w_conv3_2', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 256, 256]) 
    w_conv3_3 = tf.get_variable(name='w_conv3_3', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 256, 256]) 

    w_conv4_1 = tf.get_variable(name='w_conv4_1', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 256, 512]) 
    w_conv4_2 = tf.get_variable(name='w_conv4_2', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 512, 512]) 
    w_conv4_3 = tf.get_variable(name='w_conv4_3', initializer=tf.contrib.layers.xavier_initializer(), shape=[1, 1, 512, 512]) 

    w_conv5_1 = tf.get_variable(name='w_conv5_1', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 512, 512]) 
    w_conv5_2 = tf.get_variable(name='w_conv5_2', initializer=tf.contrib.layers.xavier_initializer(), shape=[3, 3, 512, 512]) 
    w_conv5_3 = tf.get_variable(name='w_conv5_3', initializer=tf.contrib.layers.xavier_initializer(), shape=[1, 1, 512, 512]) 

    w_fc_1 = tf.get_variable(name='w_fc_1', initializer=tf.contrib.layers.xavier_initializer(), shape=[5*5*512, 2048]) 
    w_fc_2 = tf.get_variable(name='w_fc_2', initializer=tf.contrib.layers.xavier_initializer(), shape=[2048, 1024]) 

    w_out = tf.get_variable(name='w_out', initializer=tf.contrib.layers.xavier_initializer(), shape=[1024, 128]) 

    bias_conv1_1 = tf.get_variable(name='bias_conv1_1', initializer=tf.constant(0.01, shape=[64])) 
    bias_conv1_2 = tf.get_variable(name='bias_conv1_2', initializer=tf.constant(0.01, shape=[64])) 

    bias_conv2_1 = tf.get_variable(name='bias_conv2_1', initializer=tf.constant(0.01, shape=[128])) 
    bias_conv2_2 = tf.get_variable(name='bias_conv2_2', initializer=tf.constant(0.01, shape=[128])) 

    bias_conv3_1 = tf.get_variable(name='bias_conv3_1', initializer=tf.constant(0.01, shape=[256])) 
    bias_conv3_2 = tf.get_variable(name='bias_conv3_2', initializer=tf.constant(0.01, shape=[256])) 
    bias_conv3_3 = tf.get_variable(name='bias_conv3_3', initializer=tf.constant(0.01, shape=[256])) 

    bias_conv4_1 = tf.get_variable(name='bias_conv4_1', initializer=tf.constant(0.01, shape=[512])) 
    bias_conv4_2 = tf.get_variable(name='bias_conv4_2', initializer=tf.constant(0.01, shape=[512])) 
    bias_conv4_3 = tf.get_variable(name='bias_conv4_3', initializer=tf.constant(0.01, shape=[512])) 

    bias_conv5_1 = tf.get_variable(name='bias_conv5_1', initializer=tf.constant(0.01, shape=[512])) 
    bias_conv5_2 = tf.get_variable(name='bias_conv5_2', initializer=tf.constant(0.01, shape=[512])) 
    bias_conv5_3 = tf.get_variable(name='bias_conv5_3', initializer=tf.constant(0.01, shape=[512])) 

    bias_fc_1 = tf.get_variable(name='bias_fc_1', initializer=tf.constant(0.01, shape=[2048])) 
    bias_fc_2 = tf.get_variable(name='bias_fc_2', initializer=tf.constant(0.01, shape=[1024])) 

    out = tf.get_variable(name='out', initializer=tf.constant(0.01, shape=[128])) 

    x = tf.reshape(x , [-1, 160, 160, 1]); 

    conv1_1 = tf.nn.relu(conv2d(x, w_conv1_1) + bias_conv1_1); 
    conv1_2= tf.nn.relu(conv2d(conv1_1, w_conv1_2) + bias_conv1_2); 

    max_pool1 = max_pool(conv1_2); 

    conv2_1 = tf.nn.relu(conv2d(max_pool1, w_conv2_1) + bias_conv2_1); 
    conv2_2 = tf.nn.relu(conv2d(conv2_1, w_conv2_2) + bias_conv2_2); 

    max_pool2 = max_pool(conv2_2) 

    conv3_1 = tf.nn.relu(conv2d(max_pool2, w_conv3_1) + bias_conv3_1); 
    conv3_2 = tf.nn.relu(conv2d(conv3_1, w_conv3_2) + bias_conv3_2); 
    conv3_3 = tf.nn.relu(conv2d(conv3_2, w_conv3_3) + bias_conv3_3); 

    max_pool3 = max_pool(conv3_3) 

    conv4_1 = tf.nn.relu(conv2d(max_pool3, w_conv4_1) + bias_conv4_1); 
    conv4_2 = tf.nn.relu(conv2d(conv4_1, w_conv4_2) + bias_conv4_2); 
    conv4_3 = tf.nn.relu(conv2d(conv4_2, w_conv4_3) + bias_conv4_3); 

    max_pool4 = max_pool(conv4_3) 

    conv5_1 = tf.nn.relu(conv2d(max_pool4, w_conv5_1) + bias_conv5_1); 
    conv5_2 = tf.nn.relu(conv2d(conv5_1, w_conv5_2) + bias_conv5_2); 
    conv5_3 = tf.nn.relu(conv2d(conv5_2, w_conv5_3) + bias_conv5_3); 

    max_pool5 = max_pool(conv5_3) 

    fc_helper = tf.reshape(max_pool5, [-1, 5*5*512]); 
    fc_1 = tf.nn.relu(tf.matmul(fc_helper, w_fc_1) + bias_fc_1); 

    fc_2 = tf.nn.relu(tf.matmul(fc_1, w_fc_2) + bias_fc_2); 

    output = tf.matmul(fc_2, w_out) + out 
    #output = tf.nn.l2_normalize(output, 0) THIS IS COMMENTED 


    return output 
フレームワークに依存しない方法で

マイモデル:それは見本通りにあるべきとき

conv 3x3 (1, 64) 
conv 3x3 (64,64) 
max_pooling 
conv 3x3 (64, 128) 
conv 3x3 (128, 128) 
max_pooling 
conv 3x3 (128, 256) 
conv 3x3 (256, 256) 
conv 3x3 (256, 256) 
max_pooling 
conv 3x3 (256, 512) 
conv 3x3 (512, 512) 
conv 1x1 (512, 512) 
max_pooling 
conv 3x3 (256, 512) 
conv 3x3 (512, 512) 
conv 1x1 (512, 512) 
max_pooling 
fully_connected(128) 
fully_connected(128) 
output(128) 

答えて

1

あなたのL2正規化は、機能単位です。

+0

ありがとうございました!詳細を教えてください。典型的には何を意味していますか?ありがとうございました! –

+0

@HelloLiliあなたは模範的な賢明な意味を理解しましたか? –

+0

@AbhijitBalajiいいえ、私は間違っていたことを理解しました。出力= tf.nn.l2_normalize(出力、0)は出力する必要があります= tf.nn.l2_normalize(出力、軸= 1) –

関連する問題