Algorithms often break down when forced to make predictions about data for which little supervised information is available. 对于样本量很少的类别, 现有的分类算法在分类时, 表现很差, 我们希望在不需要扩充样本的情况下, 能够有效的将算法的能力在少数类中得到提升.
from keras.layers import Input, Conv2D, Lambda, merge, Dense, Flatten,MaxPooling2Dfrom keras.models import Model, Sequentialfrom keras.regularizers import l2from keras import backend as Kfrom keras.optimizers import SGD,Adamfrom keras.losses import binary_crossentropyimport numpy.random as rngimport numpy as npimport osimport dill as pickleimport matplotlib.pyplot as pltfrom sklearn.utils import shuffledefW_init(shape,name=None):"""Initialize weights as in paper""" values = rng.normal(loc=0,scale=1e-2,size=shape)return K.variable(values,name=name)#//TODO: figure out how to initialize layer biases in keras.defb_init(shape,name=None):"""Initialize bias as in paper""" values=rng.normal(loc=0.5,scale=1e-2,size=shape)return K.variable(values,name=name)input_shape = (105,105,1)left_input =Input(input_shape)right_input =Input(input_shape)#build convnet to use in each siamese 'leg'convnet =Sequential()convnet.add(Conv2D(64,(10,10),activation='relu',input_shape=input_shape, kernel_initializer=W_init,kernel_regularizer=l2(2e-4)))convnet.add(MaxPooling2D())convnet.add(Conv2D(128,(7,7),activation='relu', kernel_regularizer=l2(2e-4),kernel_initializer=W_init,bias_initializer=b_init))convnet.add(MaxPooling2D())convnet.add(Conv2D(128,(4,4),activation='relu',kernel_initializer=W_init,kernel_regularizer=l2(2e-4),bias_initializer=b_init))convnet.add(MaxPooling2D())convnet.add(Conv2D(256,(4,4),activation='relu',kernel_initializer=W_init,kernel_regularizer=l2(2e-4),bias_initializer=b_init))convnet.add(Flatten())convnet.add(Dense(4096,activation="sigmoid",kernel_regularizer=l2(1e-3),kernel_initializer=W_init,bias_initializer=b_init))#encode each of the two inputs into a vector with the convnetencoded_l =convnet(left_input)encoded_r =convnet(right_input)#merge two encoded inputs with the l1 distance between themL1_distance =lambdax: K.abs(x[0]-x[1])both =merge([encoded_l,encoded_r], mode = L1_distance, output_shape=lambdax: x[0])prediction =Dense(1,activation='sigmoid',bias_initializer=b_init)(both)siamese_net =Model(input=[left_input,right_input],output=prediction)optimizer =Adam(0.00006)# TODO: get layerwise learning rates and momentum annealing scheme described in paperworkingsiamese_net.compile(loss="binary_crossentropy",optimizer=optimizer)siamese_net.count_params()
classSiamese_Loader:"""For loading batches and testing tasks to a siamese net"""def__init__(self,Xtrain,Xval): self.Xval = Xval self.Xtrain = Xtrain self.n_classes,self.n_examples,self.w,self.h = Xtrain.shape self.n_val,self.n_ex_val,_,_ = Xval.shapedefget_batch(self,n):"""Create batch of n pairs, half same class, half different class""" categories = rng.choice(self.n_classes,size=(n,),replace=False) pairs=[np.zeros((n, self.h, self.w,1))for i inrange(2)] targets=np.zeros((n,)) targets[n//2:]=1for i inrange(n): category = categories[i] idx_1 = rng.randint(0,self.n_examples) pairs[0][i,:,:,:] = self.Xtrain[category,idx_1].reshape(self.w,self.h,1) idx_2 = rng.randint(0,self.n_examples)#pick images of same class for 1st half, different for 2nd category_2 = category if i >= n//2else (category + rng.randint(1,self.n_classes)) % self.n_classes pairs[1][i,:,:,:] = self.Xtrain[category_2,idx_2].reshape(self.w,self.h,1)return pairs, targetsdefmake_oneshot_task(self,N):"""Create pairs of test image, support set for testing N way one-shot learning. """ categories = rng.choice(self.n_val,size=(N,),replace=False) indices = rng.randint(0,self.n_ex_val,size=(N,)) true_category = categories[0] ex1, ex2 = rng.choice(self.n_examples,replace=False,size=(2,)) test_image = np.asarray([self.Xval[true_category,ex1,:,:]]*N).reshape(N,self.w,self.h,1) support_set = self.Xval[categories,indices,:,:] support_set[0,:,:]= self.Xval[true_category,ex2] support_set = support_set.reshape(N,self.w,self.h,1) pairs = [test_image,support_set] targets = np.zeros((N,)) targets[0]=1return pairs, targetsdeftest_oneshot(self,model,N,k,verbose=0):"""Test average N way oneshot learning accuracy of a siamese neural net over k one-shot tasks"""pass n_correct =0if verbose:print("Evaluating model on {} unique {} way one-shot learning tasks ...".format(k,N))for i inrange(k): inputs, targets = self.make_oneshot_task(N) probs = model.predict(inputs)if np.argmax(probs)==0: n_correct+=1 percent_correct = (100.0*n_correct / k)if verbose:print("Got an average of {}% {} way one-shot learning accuracy".format(percent_correct,N))return percent_correct