【转载自 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 版权声明:本文为博主原创文章,转载请附上博文连接!