Пользовательский лямбда-слой для продукта Kronecker в Keras - проблемы с размером, зарезервированным для batch_size - PullRequest
0 голосов
/ 14 мая 2018

Я использую Keras 2.1.5 с бэкэндом Tensorflow для создания модели для классификации изображений. В моей модели я хотел бы объединить вход и выход слоя свертки, посчитав произведение Кронекера . Я написал функции, которые подсчитывают произведение Кронекера двух трехмерных тензоров, используя бэкэнд-функции Keras.

def kronecker_product(mat1, mat2):
    #Computes the Kronecker product of two matrices.
    m1, n1 = mat1.get_shape().as_list()
    mat1_rsh = K.reshape(mat1, [m1, 1, n1, 1])
    m2, n2 = mat2.get_shape().as_list()
    mat2_rsh = K.reshape(mat2, [1, m2, 1, n2])
    return K.reshape(mat1_rsh * mat2_rsh, [m1 * m2, n1 * n2])

def kronecker_product3D(tensors):
    tensor1 = tensors[0]
    tensor2 = tensors[1]
    #Separete slices of tensor and computes appropriate matrice kronecker product
    m1, n1, o1 = tensor1.get_shape().as_list()
    m2, n2, o2 = tensor2.get_shape().as_list()
    x_list = []
    for ind1 in range(o1):
        for ind2 in range(o2):
            x_list.append(DenseNetKTC.kronecker_product(tensor1[:,:,ind1], tensor2[:,:,ind2]))
    return K.reshape(Concatenate()(x_list), [m1 * m2, n1 * n2, o1 * o2])

Затем я попытался использовать слой Lambda, чтобы обернуть операцию в слой Keras:

cb = Convolution2D(12, (3,3), padding='same')(x)
x = Lambda(kronecker_product3D)([x, cb])

но получено сообщение об ошибке " ValueError: слишком много значений для распаковки (ожидается 3) ". Я ожидаю, что вход будет тензором трех измерений, но на самом деле он имеет четыре измерения - первое измерение, зарезервированное для batch_size в Keras. Я не знаю, как справиться с этим четвертым измерением с динамическим размером.

Я много искал, но не могу найти ни одного примера функции, которая бы справлялась вручную с измерением для партий.

Буду рад любым советам или помощи. Большое спасибо!

1 Ответ

0 голосов
/ 14 мая 2018

Простое решение:

Просто добавьте размер партии в свои кальки и измените форму

def kronecker_product(mat1, mat2):
    #Computes the Kronecker product of two matrices.
    batch, m1, n1 = mat1.get_shape().as_list()
    mat1_rsh = K.reshape(mat1, [-1, m1, 1, n1, 1])
    batch, m2, n2 = mat2.get_shape().as_list()
    mat2_rsh = K.reshape(mat2, [-1, 1, m2, 1, n2])
    return K.reshape(mat1_rsh * mat2_rsh, [-1, m1 * m2, n1 * n2])

def kronecker_product3D(tensors):
    tensor1 = tensors[0]
    tensor2 = tensors[1]
    #Separete slices of tensor and computes appropriate matrice kronecker product
    batch, m1, n1, o1 = tensor1.get_shape().as_list()
    batch, m2, n2, o2 = tensor2.get_shape().as_list()
    x_list = []
    for ind1 in range(o1):
        for ind2 in range(o2):
            x_list.append(kronecker_product(tensor1[:,:,:,ind1], tensor2[:,:,:,ind2]))
    return K.reshape(Concatenate()(x_list), [-1, m1 * m2, n1 * n2, o1 * o2])

Для сложного решения я бы попытался найти способчтобы избежать итерации, но это может быть гораздо сложнее, чем я думал ....

...