改进的双线性池

时间:2019-05-02 19:53:22

标签: python-3.x tensorflow keras deep-learning jupyter-notebook

我正在实现一种称为“改进的双线性填充”的算法。它包括不带FC层的VGG或ResNet。在结果特征图中执行每个向量的外积。然后执行矩阵平方根,元素明智平方根,L2范数,最后将结果馈入softmax层。

以下是论文: https://arxiv.org/abs/1707.06772

我试图以这种方式重新实现它: 我使用了在imagenet上保留的没有FC层的keras VGG 16模型

vgg_16 = keras.applications.vgg16.VGG16(weights='imagenet',include_top=False, input_shape=(224, 224, 3))

vgg_16.layers.pop()

My_Model = Sequential()
for layer in vgg_16.layers:
    My_Model.add(layer)

for layer in My_Model.layers:
    layer.trainable = False

然后我在每个位置取每个向量,并将乘积做一个矩阵

Batch_Size=16

def BILINEAR_POOLING(Feature_Map):
    Height = Feature_Map.shape[1]
    Width = Feature_Map.shape[2]
    Channel = Feature_Map.shape[3]
    Epsilon = (tf.scalar_mul( tf.keras.backend.epsilon(), tf.ones([Batch_Size, Channel, Channel],tf.float32)))
    A = tf.zeros([Batch_Size, Channel, Channel],tf.float32)
    for i in range (Height):
        for j in range (Width):
            A = A + tf.matmul(Feature_Map[:,i,j,:],Feature_Map[:,i,j,:], transpose_a=True)
    N = tf.cast((Height*Width), tf.float32)
    A = tf.add(tf.div(A,N) ,Epsilon)
    return A

然后是模糊部分,具有SVD分解和Lyapunov方程的矩阵平方根

#Forward + Backward via SVD
def Sqrt_Root_SVD_Lyapunov(A):
    BatchSize = A.shape[0]
    Dim = A.shape[1]
    #dlda = tf.zeros([BatchSize,Dim,Dim],tf.float32)
    sA = tf.zeros([BatchSize,Dim,Dim],tf.float32)
    output_list = []
    for i in range(BatchSize):
        S,U,V = tf.svd(A[i,:,:],compute_uv = True)
        S = tf.where(tf.less(S, 1e-10), S, tf.sqrt(S))
        SQRT = tf.matmul(U,(tf.matmul(tf.diag(tf.sqrt(S)),V, transpose_b = True)))
        output_list.append(SQRT)
        #S = tf.matmul(tf.diag(tf.sqrt(S)), (tf.ones([Dim,Dim],Type)))
        #IU = tf.transpose(U)
        #X = tf.matmul(tf.matmul(-U,(tf.matmul((tf.matmul(dldz,IU)),U)/(S+tf.transpose(S)))),IU)
        #dlda [i,:,:] = X
    sA= tf.stack(output_list)
    return sA

pytorch中的原始代码如下

# Forward + Backward via SVD decomposition
def sqrt_svd_lyap(A, dldz, dtype):
  batchSize = A.data.shape[0]
  dim = A.data.shape[1]
  dlda = torch.zeros(batchSize, dim, dim).type(dtype)
  sA = torch.zeros(batchSize, dim, dim).type(dtype)
  for i in range(batchSize):
    U, S, V = (A[i,:,:].data).svd()
    sA[i,:,:] = (U.mm(S.diag().sqrt())).mm(V.t())
    S = S.diag().sqrt().mm(torch.ones(dim, dim).type(dtype))
    IU = U.t()
    X = -U.mm(
            ((IU.mm(dldz[i,:,:].data)).mm(IU.t()))
            /(S+S.t())
            ).mm(U.t());
    dlda[i,:,:] = X
  return sA, dlda, compute_error(A, Variable(sA, requires_grad=False))

然后我将这些功能添加到模型中

My_Model.add(Lambda(BILINEAR_POOLING,output_shape=[512,512]))
My_Model.add(Lambda(Sqrt_Root_SVD_Lyapunov,output_shape=[512,512]))
My_Model.add(Lambda(lambda x: tf.sign(x)* tf.sqrt(tf.abs(x))))
My_Model.add(Lambda(lambda x: tf.math.l2_normalize(x,axis=None, epsilon=1e-12, name=None,dim=None)))
My_Model.add(Flatten())
My_Model.add(Dense(7, activation='softmax'))

My_Model.compile(SGD(lr=.001), loss='categorical_crossentropy', metrics=['accuracy'])

My_Model.fit_generator(train_batches, steps_per_epoch=49, validation_data=valid_batches, validation_steps=16,epochs=10,
                       verbose=1)

问题是它确实给出了很好的结果。而且它停留在30%,所以我认为它并没有结束学习的目的

你能告诉我问题吗?

0 个答案:

没有答案