zoukankan      html  css  js  c++  java
  • tensorflow实现siamese网络 (附代码)

    转载自:https://blog.csdn.net/qq1483661204/article/details/79039702

    Learning a Similarity Metric Discriminatively, with Application to Face
    Verification 这个siamese文章链接。
    本文主要讲解siamese网络,并用tensorflwo实现,在mnist数据集中,siamese网络和其他网络的不同之处在于,首先他是两个输入,它输入的不是标签,而是是否是同一类别,如果是同一类别就是0,否则就是1,文章中是用这个网络来做人脸识别,网络结构图如下:

    从图中可以看到,他又两个输入,分别是下x1和x2,左右两个的网咯结构是一样的,并且他们共享权重,最后得到两个输出,分别是Gw(x1)和Gw(x2),这个网络的很好理解,当输入是同一张图片的时候,我们希望他们呢之间的欧式距离很小,当不是一张图片时,我们的欧式距离很大。有了网路结构,接下来就是定义损失函数,这个很重要,而经过我们的分析,我们可以知道,损失函数的特点应该是这样的,
    (1) 当我们输入同一张图片时,他们之间的欧式距离越小,损失是越小的,距离越大,损失越大
    (2) 当我们的输入是不同的图片的时候,他们之间的距离越大,损失越大
    怎么理解呢,很简单,我们就是最小化把相同类的数据之间距离,最大化不同类之间的距离。
    然后文章中定义的损失函数如下:
    首先是定义距离,使用l2范数,公式如下:

    距离其实就是欧式距离,有了距离,我们的损失函数和距离的关系我上面说了,如何包证满足上面的要求呢,文章提出这样的损失函数:

    其中我们的Ew就是距离,Lg和L1相当于是一个系数,这个损失函数和交叉熵其实挺像,为了让损失函数满足上面的关系,让Lg满足单调递减,LI满足单调递增就可以。另外一个条件是:同类图片之间的距离必须比不同类之间的距离小,
    其他条件如下:

    然后作者也给出了证明,最终损失函数为:

    Q是一个常数,这个损失函数就满足上面的关系,然后我用tensoflow写了一个损失函数如下:

    需要强调的是,这个地方同一类图片是0,不同类图片是1,然后我自己用tensorflow实现的这个损失函数如下:

    def siamese_loss(out1,out2,y,Q=5):
    
        Q = tf.constant(Q, name="Q",dtype=tf.float32)
        E_w = tf.sqrt(tf.reduce_sum(tf.square(out1-out2),1))   
        pos = tf.multiply(tf.multiply(y,2/Q),tf.square(E_w))
        neg = tf.multiply(tf.multiply(1-y,2*Q),tf.exp(-2.77/Q*E_w))                
        loss = pos + neg                 
        loss = tf.reduce_mean(loss)              
        return loss


    这就是损失函数,其他的代码如下:

      1 import tensorflow as tf
      2 from tensorflow.examples.tutorials.mnist import input_data
      3 import numpy as np
      4 tf.reset_default_graph()
      5 mnist = input_data.read_data_sets('./data/mnist',one_hot=True)
      6 print(mnist.validation.num_examples)
      7 print(mnist.train.num_examples)
      8 print(mnist.test.num_examples)
      9 def siamese_loss(out1,out2,y,Q=5):
     10 
     11     Q = tf.constant(Q, name="Q",dtype=tf.float32)
     12     E_w = tf.sqrt(tf.reduce_sum(tf.square(out1-out2),1))   
     13     pos = tf.multiply(tf.multiply(y,2/Q),tf.square(E_w))
     14     neg = tf.multiply(tf.multiply(1-y,2*Q),tf.exp(-2.77/Q*E_w))                
     15     loss = pos + neg                 
     16     loss = tf.reduce_mean(loss)              
     17     return loss
     18 
     19 def siamese(inputs,keep_prob):
     20         with tf.name_scope('conv1') as scope:
     21             w1 = tf.Variable(tf.truncated_normal(shape=[3,3,1,32],stddev=0.05),name='w1')
     22             b1 = tf.Variable(tf.zeros(32),name='b1')
     23             conv1 = tf.nn.conv2d(inputs,w1,strides=[1,1,1,1],padding='SAME',name='conv1')
     24         with tf.name_scope('relu1') as scope:
     25             relu1 = tf.nn.relu(tf.add(conv1,b1),name='relu1')
     26         with tf.name_scope('conv2') as scope:
     27             w2 = tf.Variable(tf.truncated_normal(shape=[3,3,32,64],stddev=0.05),name='w2')
     28             b2 = tf.Variable(tf.zeros(64),name='b2')
     29             conv2 = tf.nn.conv2d(relu1,w2,strides=[1,2,2,1],padding='SAME',name='conv2')
     30         with tf.name_scope('relu2') as scope:
     31             relu2 = tf.nn.relu(conv2+b2,name='relu2')
     32 
     33         with tf.name_scope('conv3') as scope:
     34 
     35             w3 = tf.Variable(tf.truncated_normal(shape=[3,3,64,128],mean=0,stddev=0.05),name='w3')
     36             b3 = tf.Variable(tf.zeros(128),name='b3')
     37             conv3 = tf.nn.conv2d(relu2,w3,strides=[1,2,2,1],padding='SAME')
     38         with tf.name_scope('relu3') as scope:
     39             relu3 = tf.nn.relu(conv3+b3,name='relu3')
     40 
     41         with tf.name_scope('fc1') as scope:
     42             x_flat = tf.reshape(relu3,shape=[-1,7*7*128])
     43             w_fc1=tf.Variable(tf.truncated_normal(shape=[7*7*128,1024],stddev=0.05,mean=0),name='w_fc1')
     44             b_fc1 = tf.Variable(tf.zeros(1024),name='b_fc1')
     45             fc1 = tf.add(tf.matmul(x_flat,w_fc1),b_fc1)
     46         with tf.name_scope('relu_fc1') as scope:
     47             relu_fc1 = tf.nn.relu(fc1,name='relu_fc1')
     48 
     49 
     50 
     51         with tf.name_scope('drop_1') as scope:
     52 
     53             drop_1 = tf.nn.dropout(relu_fc1,keep_prob=keep_prob,name='drop_1')
     54         with tf.name_scope('bn_fc1') as scope:
     55             bn_fc1 = tf.layers.batch_normalization(drop_1,name='bn_fc1')
     56         with tf.name_scope('fc2') as scope:
     57             w_fc2 = tf.Variable(tf.truncated_normal(shape=[1024,512],stddev=0.05,mean=0),name='w_fc2')
     58             b_fc2 = tf.Variable(tf.zeros(512),name='b_fc2')
     59             fc2 = tf.add(tf.matmul(bn_fc1,w_fc2),b_fc2)
     60         with tf.name_scope('relu_fc2') as scope:
     61             relu_fc2 = tf.nn.relu(fc2,name='relu_fc2')
     62         with tf.name_scope('drop_2') as scope:
     63             drop_2 = tf.nn.dropout(relu_fc2,keep_prob=keep_prob,name='drop_2')
     64         with tf.name_scope('bn_fc2') as scope:
     65             bn_fc2 = tf.layers.batch_normalization(drop_2,name='bn_fc2')
     66         with tf.name_scope('fc3') as scope:
     67             w_fc3 = tf.Variable(tf.truncated_normal(shape=[512,2],stddev=0.05,mean=0),name='w_fc3')
     68             b_fc3 = tf.Variable(tf.zeros(2),name='b_fc3')
     69             fc3 = tf.add(tf.matmul(bn_fc2,w_fc3),b_fc3)
     70         return fc3
     71 
     72 lr = 0.01
     73 iterations = 20000
     74 batch_size = 64
     75 
     76 with tf.variable_scope('input_x1') as scope:
     77     x1 = tf.placeholder(tf.float32, shape=[None, 784])
     78     x_input_1 = tf.reshape(x1, [-1, 28, 28, 1])
     79 with tf.variable_scope('input_x2') as scope:
     80     x2 = tf.placeholder(tf.float32, shape=[None, 784])
     81     x_input_2 = tf.reshape(x2, [-1, 28, 28, 1])
     82 with tf.variable_scope('y') as scope:
     83     y = tf.placeholder(tf.float32, shape=[batch_size])
     84 
     85 with tf.name_scope('keep_prob') as scope:
     86     keep_prob = tf.placeholder(tf.float32)
     87 
     88 with tf.variable_scope('siamese') as scope:
     89     out1 = siamese(x_input_1,keep_prob)
     90     scope.reuse_variables()
     91     out2 = siamese(x_input_2,keep_prob)
     92 with tf.variable_scope('metrics') as scope:
     93     loss = siamese_loss(out1, out2, y)
     94     optimizer = tf.train.AdamOptimizer(lr).minimize(loss)
     95 
     96 loss_summary = tf.summary.scalar('loss',loss)
     97 merged_summary = tf.summary.merge_all()
     98 
     99 with tf.Session() as sess:
    100 
    101     writer = tf.summary.FileWriter('./graph/siamese',sess.graph)
    102     sess.run(tf.global_variables_initializer())
    103 
    104     for itera in range(iterations):
    105         xs_1, ys_1 = mnist.train.next_batch(batch_size)
    106         ys_1 = np.argmax(ys_1,axis=1)
    107         xs_2, ys_2 = mnist.train.next_batch(batch_size)
    108         ys_2 = np.argmax(ys_2,axis=1)
    109         y_s = np.array(ys_1==ys_2,dtype=np.float32)
    110         _,train_loss,summ = sess.run([optimizer,loss,merged_summary],feed_dict={x1:xs_1,x2:xs_2,y:y_s,keep_prob:0.6})
    111 
    112         writer.add_summary(summ,itera)
    113         if itera % 1000 == 1 :
    114             print('iter {},train loss {}'.format(itera,train_loss))
    115     embed = sess.run(out1,feed_dict={x1:mnist.test.images,keep_prob:0.6})
    116     test_img = mnist.test.images.reshape([-1,28,28,1])
    117     writer.close()
  • 相关阅读:
    mina:IoBuffer 常用方法(转载)
    js:对象之间的复制
    jquery与angular的交互
    javax.crypto.BadPaddingException: Given final block not properly padded
    jstree:重新加载数据集,刷新树
    TCP 握手 -> 微服务
    eclipse 中添加source
    02 IO
    为什么常用 Map<> map = new HashMap()
    自组织 Self-Orginaztion
  • 原文地址:https://www.cnblogs.com/cupleo/p/10241210.html
Copyright © 2011-2022 走看看