Реализуйте ConvND в Tensorflow - PullRequest
0 голосов
/ 19 июня 2020

Итак, мне нужен сверточный слой ND, который также поддерживает комплексные числа. Поэтому я решил сам написать код.

Я тестировал этот код только на numpy, и он работал. Протестировано с несколькими каналами, 2D и 1D и сложными. Однако у меня возникают проблемы, когда я делаю это на TF.

Пока что это мой код:

def call(self, inputs):
    with tf.name_scope("ComplexConvolution_" + str(self.layer_number)) as scope:
        inputs = self._verify_inputs(inputs)            # Check inputs are of expected shape and format
        inputs = self.apply_padding(inputs)             # Add zeros if needed
        output_np = np.zeros(                           # I use np because tf does not support the assigment
            (inputs.shape[0],) +                        # Per each image
            self.output_size,                           # Image out size
            dtype=self.input_dtype                      # To support complex numbers
        )
        img_index = 0
        for image in inputs:
            for filter_index in range(self.filters):
                for i in range(int(np.prod(self.output_size[:-1]))):  # for each element in the output
                    index = np.unravel_index(i, self.output_size[:-1])
                    start_index = tuple([a * b for a, b in zip(index, self.stride_shape)])
                    end_index = tuple([a+b for a, b in zip(start_index, self.kernel_shape)])
                    # set_trace()
                    sector_slice = tuple(
                        [slice(start_index[ind], end_index[ind]) for ind in range(len(start_index))]
                    )
                    sector = image[sector_slice]
                    new_value = tf.reduce_sum(sector * self.kernels[filter_index]) + self.bias[filter_index]
                    # I use Tied Bias https://datascience.stackexchange.com/a/37748/75968
                    output_np[img_index][index][filter_index] = new_value  # The complicated line
                    img_index += 1
        output = apply_activation(self.activation, output_np)
    return output

input_size - это кортеж формы (dim1, dim2, ... , dim3, каналы). Например, двухмерный RGB-преобразователь будет (32, 32, 3), а inputs будет иметь форму (None, 32, 32, 3).

Размер вывода рассчитывается из уравнения, которое я нашел в этом paper: Руководство по арифметике свертки c для глубокого обучения

out_list = []
for i in range(len(self.input_size) - 1):   # -1 because the number of input channels is irrelevant
    out_list.append(int(np.floor((self.input_size[i] + 2 * self.padding_shape[i] - self.kernel_shape[i]) / self.stride_shape[i]) + 1))
out_list.append(self.filters)

В основном я использую np.zeros, потому что если я использую tf.zeros, я не могу назначить new_value и Я получаю: TypeError: 'Tensor' object does not support item assignment

Однако в этом текущем состоянии я получаю:
NotImplementedError: Cannot convert a symbolic Tensor (placeholder_1:0) to a numpy array.

по тому же заданию. Не вижу простого решения, думаю, мне следует полностью изменить стратегию кода.

1 Ответ

0 голосов
/ 22 июня 2020

В конце концов, я сделал это очень неэффективно на основе этого комментария , также прокомментировал здесь , но, по крайней мере, он работает:

new_value = tf.reduce_sum(sector * self.kernels[filter_index]) + self.bias[filter_index]
indices = (img_index,) + index + (filter_index,)
mask = tf.Variable(tf.fill(output_np.shape, 1))
mask = mask[indices].assign(0)
mask = tf.cast(mask, dtype=self.input_dtype)
output_np = array * mask + (1 - mask) * new_value

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

...