Commit 71aaa719 authored by Pietro Morerio's avatar Pietro Morerio
Browse files

first code commit

parent 507e50e1
## Siamese network to spot pepper noise in MNIST
\ No newline at end of file
# Siamese Network Tensorflow
### A Siamese Network to spot pepper noise in MNIST
A Siamese network is a neural network that contain two or more identical subnetworks. The purpose is to find the similarity or comparing the relationship between two comparable things. Unlike classification task that uses cross entropy as the loss function, siamese network usually uses contrastive loss or triplet loss.
This project follows Hadsell-et-al.'06 [1] by computing the Euclidean distance on the output of the shared network and by optimizing the contrastive loss (see paper for more details).
[1] "Dimensionality Reduction by Learning an Invariant Mapping"
http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf
%% Cell type:code id: tags:
``` python
%matplotlib inline
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import tensorflow.contrib.slim as slim
import pandas as pd
from dataset import get_mnist
from model import *
from scipy.spatial.distance import cdist
from matplotlib import gridspec
```
%% Output
/usr/local/lib/python2.7/dist-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
from ._conv import register_converters as _register_converters
%% Cell type:code id: tags:
``` python
mnist = get_mnist()
train_images = np.array([im.reshape((28,28,1)) for im in mnist.train.images])
test_images = np.array([im.reshape((28,28,1)) for im in mnist.test.images])
len_test = len(mnist.test.images)
len_train = len(mnist.train.images)
```
%% Output
Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz
%% Cell type:code id: tags:
``` python
#helper function to plot image
def show_image(idxs, data):
if type(idxs) != np.ndarray:
idxs = np.array([idxs])
fig = plt.figure()
gs = gridspec.GridSpec(1,len(idxs))
for i in range(len(idxs)):
ax = fig.add_subplot(gs[0,i])
ax.imshow(data[idxs[i],:,:,0],cmap='gray')
ax.axis('off')
plt.show()
```
%% Cell type:markdown id: tags:
## Create the siamese net feature extraction model
%% Cell type:code id: tags:
``` python
img_placeholder = tf.placeholder(tf.float32, [None, 28, 28, 1], name='img')
net = siamese(img_placeholder, reuse=False)
```
%% Cell type:code id: tags:
``` python
offset = len(train_images)
offset = 10000
```
%% Cell type:markdown id: tags:
## Restore from checkpoint and calc the features from all of train data
%% Cell type:code id: tags:
``` python
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
ckpt = tf.train.get_checkpoint_state("model")
saver.restore(sess, "model/model.ckpt")
train_feat = sess.run(net, feed_dict={img_placeholder:train_images[:offset]})
```
%% Output
INFO:tensorflow:Restoring parameters from model/model.ckpt
%% Cell type:markdown id: tags:
## Restore from checkpoint and calc the features from all of corrupted train data
%% Cell type:code id: tags:
``` python
from syn_dataset import add_defect
train_images_noisy = np.empty((offset,28,28,1))
for i, img in enumerate(train_images[:offset]):
train_images_noisy[i]=add_defect(img)
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
ckpt = tf.train.get_checkpoint_state("model")
saver.restore(sess, "model/model.ckpt")
train_feat_noisy = sess.run(net, feed_dict={img_placeholder:train_images_noisy})
```
%% Output
INFO:tensorflow:Restoring parameters from model/model.ckpt
%% Cell type:markdown id: tags:
## Add noisy images and labels to training and test sets
%% Cell type:code id: tags:
``` python
#add noisy images & features to training set
train_feat = np.vstack([train_feat,train_feat_noisy])
train_images = np.vstack([train_images[:offset],train_images_noisy])
assert len(train_images) == len(train_feat)
#add noisy images to test set
test_images_noisy = np.empty((len(test_images),28,28,1))
for i, img in enumerate(test_images):
test_images_noisy[i]=add_defect(img)
test_images = np.vstack([test_images,test_images_noisy])
```
%% Cell type:markdown id: tags:
## Searching for similar test images from trainset based on siamese feature
%% Cell type:code id: tags:
``` python
#generate new random test image
idx = np.random.randint(0, len_test+offset)
# 2050 -> 8
# 20 -> 9
# 8644 -> 6
# idx=20
im = test_images[idx]
#show the test image
show_image(idx, test_images)
print "This is image from id:", idx
```
%% Output
This is image from id: 12286
%% Cell type:code id: tags:
``` python
#run the test image through the network to get the test features
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
ckpt = tf.train.get_checkpoint_state("model")
saver.restore(sess, "model/model.ckpt")
search_feat = sess.run(net, feed_dict={img_placeholder:[im]})
#calculate the cosine similarity and sort
dist = cdist(train_feat, search_feat, 'cosine')
rank = np.argsort(dist.ravel())
#show the top n similar image from train data
n = 10
show_image(rank[:n], train_images)
print "retrieved ids:", rank[:n]
```
%% Output
INFO:tensorflow:Restoring parameters from model/model.ckpt
retrieved ids: [15933 17369 16575 11803 12360]
%% Cell type:code id: tags:
``` python
```
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import tensorflow.contrib.slim as slim
import random
from tensorflow.examples.tutorials.mnist import input_data
from numpy.random import choice, permutation
from itertools import combinations
from syn_dataset import add_defect
flags = tf.app.flags
FLAGS = flags.FLAGS
class MyBatchGenerator():
def __init__(self, images, labels):
np.random.seed(0)
random.seed(0)
self.labels = labels
print images.shape
self.images = images.reshape((55000, 28, 28, 1))
self.tot = len(labels)
self.i = 5
self.num_idx = dict() # will contain the ids of images belonging to each key() = class number
for idx, num in enumerate(self.labels):
if num in self.num_idx:
self.num_idx[num].append(idx)
else:
self.num_idx[num] = [idx]
self.to_img = lambda x: self.images[x]
def next_batch(self, batch_size=None):
left = []
right = []
sim = []
num_classes = 5
# genuine ~1/4+1/4 of the batch
for i in range(num_classes):
l = choice(self.num_idx[i], batch_size, replace=False).tolist()
for j in range(int(batch_size/4./num_classes)):
left.append(self.to_img(l.pop()))
right.append(self.to_img(l.pop()))
sim.append([1])
left.append(add_defect(self.to_img(l.pop())))
right.append(add_defect(self.to_img(l.pop())))
sim.append([1])
#impostor ~1/2 of the batch
for i in range(num_classes):
l = choice(self.num_idx[i], batch_size, replace=False).tolist()
for j in range(int(batch_size/2./num_classes)):
left.append(self.to_img(l.pop()))
right.append(add_defect(self.to_img(l.pop())))
sim.append([0])
return np.array(left), np.array(right), np.array(sim)
class BatchGenerator():
def __init__(self, images, labels):
np.random.seed(0)
random.seed(0)
self.labels = labels
print images.shape
self.images = images.reshape((55000, 28, 28, 1))
self.tot = len(labels)
self.i = 5
self.num_idx = dict() # will contain the ids of images belonging to each key() = class number
for idx, num in enumerate(self.labels):
if num in self.num_idx:
self.num_idx[num].append(idx)
else:
self.num_idx[num] = [idx]
self.to_img = lambda x: self.images[x]
def next_batch(self, batch_size=None):
# batch_size is not used actually
left = []
right = []
sim = []
num_classes = 10
# genuine
for i in range(num_classes):
n = num_classes * (num_classes - 1)
l = choice(self.num_idx[i], n*2, replace=False).tolist()
left.append(self.to_img(l.pop()))
right.append(self.to_img(l.pop()))
sim.append([1])
#impostor
for i,j in combinations(range(num_classes), 2):
left.append(self.to_img(choice(self.num_idx[i])))
right.append(self.to_img(choice(self.num_idx[j])))
sim.append([0])
return np.array(left), np.array(right), np.array(sim)
def get_mnist():
mnist = input_data.read_data_sets("MNIST_data/")
return mnist
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import tensorflow.contrib.slim as slim
flags = tf.app.flags
FLAGS = flags.FLAGS
def siamese(input, reuse=False):
with tf.name_scope("model"):
with tf.variable_scope("conv1") as scope:
net = tf.contrib.layers.conv2d(input, 32, [7, 7], activation_fn=tf.nn.relu, padding='SAME',
weights_initializer=tf.contrib.layers.xavier_initializer_conv2d(),scope=scope,reuse=reuse)
net = tf.contrib.layers.max_pool2d(net, [2, 2], padding='SAME')
with tf.variable_scope("conv2") as scope:
net = tf.contrib.layers.conv2d(net, 64, [5, 5], activation_fn=tf.nn.relu, padding='SAME',
weights_initializer=tf.contrib.layers.xavier_initializer_conv2d(),scope=scope,reuse=reuse)
net = tf.contrib.layers.max_pool2d(net, [2, 2], padding='SAME')
with tf.variable_scope("conv3") as scope:
net = tf.contrib.layers.conv2d(net, 128, [3, 3], activation_fn=tf.nn.relu, padding='SAME',
weights_initializer=tf.contrib.layers.xavier_initializer_conv2d(),scope=scope,reuse=reuse)
net = tf.contrib.layers.max_pool2d(net, [2, 2], padding='SAME')
with tf.variable_scope("conv4") as scope:
net = tf.contrib.layers.conv2d(net, 256, [1, 1], activation_fn=tf.nn.relu, padding='SAME',