tensorflow實現siamese網絡(附代碼)

【轉載自 https://blog.csdn.net/qq1483661204/article/details/79039702】網絡

Learning a Similarity Metric Discriminatively, with Application to Face ide

Verification 這個siamese文章連接。 函數

本文主要講解siamese網絡,並用tensorflwo實現,在mnist數據集中,siamese網絡和其餘網絡的不一樣之處在於,首先他是兩個輸入,它輸入的不是標籤,而是是不是同一類別,若是是同一類別就是0,不然就是1,文章中是用這個網絡來作人臉識別,網絡結構圖以下: spa

 

從圖中能夠看到,他又兩個輸入,分別是下x1和x2,左右兩個的網咯結構是同樣的,而且他們共享權重,最後獲得兩個輸出,分別是Gw(x1)和Gw(x2),這個網絡的很好理解,當輸入是同一張圖片的時候,咱們但願他們呢之間的歐式距離很小,當不是一張圖片時,咱們的歐式距離很大。有了網路結構,接下來就是定義損失函數,這個很重要,而通過咱們的分析,咱們能夠知道,損失函數的特色應該是這樣的, .net

(1) 當咱們輸入同一張圖片時,他們之間的歐式距離越小,損失是越小的,距離越大,損失越大 scala

(2) 當咱們的輸入是不一樣的圖片的時候,他們之間的距離越大,損失越大 code

怎麼理解呢,很簡單,咱們就是最小化把相同類的數據之間距離,最大化不一樣類之間的距離。 orm

而後文章中定義的損失函數以下: blog

首先是定義距離,使用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

這就是損失函數,其餘的代碼以下:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
tf.reset_default_graph()
mnist = input_data.read_data_sets('./data/mnist',one_hot=True)
print(mnist.validation.num_examples)
print(mnist.train.num_examples)
print(mnist.test.num_examples)
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

def siamese(inputs,keep_prob):
        with tf.name_scope('conv1') as scope:
            w1 = tf.Variable(tf.truncated_normal(shape=[3,3,1,32],stddev=0.05),name='w1')
            b1 = tf.Variable(tf.zeros(32),name='b1')
            conv1 = tf.nn.conv2d(inputs,w1,strides=[1,1,1,1],padding='SAME',name='conv1')
        with tf.name_scope('relu1') as scope:
            relu1 = tf.nn.relu(tf.add(conv1,b1),name='relu1')
        with tf.name_scope('conv2') as scope:
            w2 = tf.Variable(tf.truncated_normal(shape=[3,3,32,64],stddev=0.05),name='w2')
            b2 = tf.Variable(tf.zeros(64),name='b2')
            conv2 = tf.nn.conv2d(relu1,w2,strides=[1,2,2,1],padding='SAME',name='conv2')
        with tf.name_scope('relu2') as scope:
            relu2 = tf.nn.relu(conv2+b2,name='relu2')

        with tf.name_scope('conv3') as scope:

            w3 = tf.Variable(tf.truncated_normal(shape=[3,3,64,128],mean=0,stddev=0.05),name='w3')
            b3 = tf.Variable(tf.zeros(128),name='b3')
            conv3 = tf.nn.conv2d(relu2,w3,strides=[1,2,2,1],padding='SAME')
        with tf.name_scope('relu3') as scope:
            relu3 = tf.nn.relu(conv3+b3,name='relu3')

        with tf.name_scope('fc1') as scope:
            x_flat = tf.reshape(relu3,shape=[-1,7*7*128])
            w_fc1=tf.Variable(tf.truncated_normal(shape=[7*7*128,1024],stddev=0.05,mean=0),name='w_fc1')
            b_fc1 = tf.Variable(tf.zeros(1024),name='b_fc1')
            fc1 = tf.add(tf.matmul(x_flat,w_fc1),b_fc1)
        with tf.name_scope('relu_fc1') as scope:
            relu_fc1 = tf.nn.relu(fc1,name='relu_fc1')



        with tf.name_scope('drop_1') as scope:

            drop_1 = tf.nn.dropout(relu_fc1,keep_prob=keep_prob,name='drop_1')
        with tf.name_scope('bn_fc1') as scope:
            bn_fc1 = tf.layers.batch_normalization(drop_1,name='bn_fc1')
        with tf.name_scope('fc2') as scope:
            w_fc2 = tf.Variable(tf.truncated_normal(shape=[1024,512],stddev=0.05,mean=0),name='w_fc2')
            b_fc2 = tf.Variable(tf.zeros(512),name='b_fc2')
            fc2 = tf.add(tf.matmul(bn_fc1,w_fc2),b_fc2)
        with tf.name_scope('relu_fc2') as scope:
            relu_fc2 = tf.nn.relu(fc2,name='relu_fc2')
        with tf.name_scope('drop_2') as scope:
            drop_2 = tf.nn.dropout(relu_fc2,keep_prob=keep_prob,name='drop_2')
        with tf.name_scope('bn_fc2') as scope:
            bn_fc2 = tf.layers.batch_normalization(drop_2,name='bn_fc2')
        with tf.name_scope('fc3') as scope:
            w_fc3 = tf.Variable(tf.truncated_normal(shape=[512,2],stddev=0.05,mean=0),name='w_fc3')
            b_fc3 = tf.Variable(tf.zeros(2),name='b_fc3')
            fc3 = tf.add(tf.matmul(bn_fc2,w_fc3),b_fc3)
        return fc3

lr = 0.01
iterations = 20000
batch_size = 64

with tf.variable_scope('input_x1') as scope:
    x1 = tf.placeholder(tf.float32, shape=[None, 784])
    x_input_1 = tf.reshape(x1, [-1, 28, 28, 1])
with tf.variable_scope('input_x2') as scope:
    x2 = tf.placeholder(tf.float32, shape=[None, 784])
    x_input_2 = tf.reshape(x2, [-1, 28, 28, 1])
with tf.variable_scope('y') as scope:
    y = tf.placeholder(tf.float32, shape=[batch_size])

with tf.name_scope('keep_prob') as scope:
    keep_prob = tf.placeholder(tf.float32)

with tf.variable_scope('siamese') as scope:
    out1 = siamese(x_input_1,keep_prob)
    scope.reuse_variables()
    out2 = siamese(x_input_2,keep_prob)
with tf.variable_scope('metrics') as scope:
    loss = siamese_loss(out1, out2, y)
    optimizer = tf.train.AdamOptimizer(lr).minimize(loss)

loss_summary = tf.summary.scalar('loss',loss)
merged_summary = tf.summary.merge_all()

with tf.Session() as sess:

    writer = tf.summary.FileWriter('./graph/siamese',sess.graph)
    sess.run(tf.global_variables_initializer())

    for itera in range(iterations):
        xs_1, ys_1 = mnist.train.next_batch(batch_size)
        ys_1 = np.argmax(ys_1,axis=1)
        xs_2, ys_2 = mnist.train.next_batch(batch_size)
        ys_2 = np.argmax(ys_2,axis=1)
        y_s = np.array(ys_1==ys_2,dtype=np.float32)
        _,train_loss,summ = sess.run([optimizer,loss,merged_summary],feed_dict={x1:xs_1,x2:xs_2,y:y_s,keep_prob:0.6})

        writer.add_summary(summ,itera)
        if itera % 1000 == 1 :
            print('iter {},train loss {}'.format(itera,train_loss))
    embed = sess.run(out1,feed_dict={x1:mnist.test.images,keep_prob:0.6})
    test_img = mnist.test.images.reshape([-1,28,28,1])
    writer.close()

這裏多說一句,siamese能夠用來降維,由於最後他的輸出是二維的,這樣直接把維度降下來了。

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 loss123456789這就是損失函數,其餘的代碼以下:import tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_dataimport numpy as nptf.reset_default_graph()mnist = input_data.read_data_sets('./data/mnist',one_hot=True)print(mnist.validation.num_examples)print(mnist.train.num_examples)print(mnist.test.num_examples)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 lossdef siamese(inputs,keep_prob):        with tf.name_scope('conv1') as scope:            w1 = tf.Variable(tf.truncated_normal(shape=[3,3,1,32],stddev=0.05),name='w1')            b1 = tf.Variable(tf.zeros(32),name='b1')            conv1 = tf.nn.conv2d(inputs,w1,strides=[1,1,1,1],padding='SAME',name='conv1')        with tf.name_scope('relu1') as scope:            relu1 = tf.nn.relu(tf.add(conv1,b1),name='relu1')        with tf.name_scope('conv2') as scope:            w2 = tf.Variable(tf.truncated_normal(shape=[3,3,32,64],stddev=0.05),name='w2')            b2 = tf.Variable(tf.zeros(64),name='b2')            conv2 = tf.nn.conv2d(relu1,w2,strides=[1,2,2,1],padding='SAME',name='conv2')        with tf.name_scope('relu2') as scope:            relu2 = tf.nn.relu(conv2+b2,name='relu2')        with tf.name_scope('conv3') as scope:            w3 = tf.Variable(tf.truncated_normal(shape=[3,3,64,128],mean=0,stddev=0.05),name='w3')            b3 = tf.Variable(tf.zeros(128),name='b3')            conv3 = tf.nn.conv2d(relu2,w3,strides=[1,2,2,1],padding='SAME')        with tf.name_scope('relu3') as scope:            relu3 = tf.nn.relu(conv3+b3,name='relu3')        with tf.name_scope('fc1') as scope:            x_flat = tf.reshape(relu3,shape=[-1,7*7*128])            w_fc1=tf.Variable(tf.truncated_normal(shape=[7*7*128,1024],stddev=0.05,mean=0),name='w_fc1')            b_fc1 = tf.Variable(tf.zeros(1024),name='b_fc1')            fc1 = tf.add(tf.matmul(x_flat,w_fc1),b_fc1)        with tf.name_scope('relu_fc1') as scope:            relu_fc1 = tf.nn.relu(fc1,name='relu_fc1')        with tf.name_scope('drop_1') as scope:            drop_1 = tf.nn.dropout(relu_fc1,keep_prob=keep_prob,name='drop_1')        with tf.name_scope('bn_fc1') as scope:            bn_fc1 = tf.layers.batch_normalization(drop_1,name='bn_fc1')        with tf.name_scope('fc2') as scope:            w_fc2 = tf.Variable(tf.truncated_normal(shape=[1024,512],stddev=0.05,mean=0),name='w_fc2')            b_fc2 = tf.Variable(tf.zeros(512),name='b_fc2')            fc2 = tf.add(tf.matmul(bn_fc1,w_fc2),b_fc2)        with tf.name_scope('relu_fc2') as scope:            relu_fc2 = tf.nn.relu(fc2,name='relu_fc2')        with tf.name_scope('drop_2') as scope:            drop_2 = tf.nn.dropout(relu_fc2,keep_prob=keep_prob,name='drop_2')        with tf.name_scope('bn_fc2') as scope:            bn_fc2 = tf.layers.batch_normalization(drop_2,name='bn_fc2')        with tf.name_scope('fc3') as scope:            w_fc3 = tf.Variable(tf.truncated_normal(shape=[512,2],stddev=0.05,mean=0),name='w_fc3')            b_fc3 = tf.Variable(tf.zeros(2),name='b_fc3')            fc3 = tf.add(tf.matmul(bn_fc2,w_fc3),b_fc3)        return fc3lr = 0.01iterations = 20000batch_size = 64with tf.variable_scope('input_x1') as scope:    x1 = tf.placeholder(tf.float32, shape=[None, 784])    x_input_1 = tf.reshape(x1, [-1, 28, 28, 1])with tf.variable_scope('input_x2') as scope:    x2 = tf.placeholder(tf.float32, shape=[None, 784])    x_input_2 = tf.reshape(x2, [-1, 28, 28, 1])with tf.variable_scope('y') as scope:    y = tf.placeholder(tf.float32, shape=[batch_size])with tf.name_scope('keep_prob') as scope:    keep_prob = tf.placeholder(tf.float32)with tf.variable_scope('siamese') as scope:    out1 = siamese(x_input_1,keep_prob)    scope.reuse_variables()    out2 = siamese(x_input_2,keep_prob)with tf.variable_scope('metrics') as scope:    loss = siamese_loss(out1, out2, y)    optimizer = tf.train.AdamOptimizer(lr).minimize(loss)loss_summary = tf.summary.scalar('loss',loss)merged_summary = tf.summary.merge_all()with tf.Session() as sess:    writer = tf.summary.FileWriter('./graph/siamese',sess.graph)    sess.run(tf.global_variables_initializer())    for itera in range(iterations):        xs_1, ys_1 = mnist.train.next_batch(batch_size)        ys_1 = np.argmax(ys_1,axis=1)        xs_2, ys_2 = mnist.train.next_batch(batch_size)        ys_2 = np.argmax(ys_2,axis=1)        y_s = np.array(ys_1==ys_2,dtype=np.float32)        _,train_loss,summ = sess.run([optimizer,loss,merged_summary],feed_dict={x1:xs_1,x2:xs_2,y:y_s,keep_prob:0.6})        writer.add_summary(summ,itera)        if itera % 1000 == 1 :            print('iter {},train loss {}'.format(itera,train_loss))    embed = sess.run(out1,feed_dict={x1:mnist.test.images,keep_prob:0.6})    test_img = mnist.test.images.reshape([-1,28,28,1])    writer.close()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117這裏多說一句,siamese能夠用來降維,由於最後他的輸出是二維的,這樣直接把維度降下來了。--------------------- 做者:ML_BOY 來源:CSDN 原文:https://blog.csdn.net/qq1483661204/article/details/79039702 版權聲明:本文爲博主原創文章,轉載請附上博文連接!

相關文章
相關標籤/搜索