сделать карту входных характеристик из тензора расширения в keras

Я использовал расширение Тейлора в задаче классификации изображений. По сути, во-первых, вектор пикселей генерируется из изображения RGB, и значения каждого пикселя из вектора пикселей будут аппроксимированы расширением ряда Тейлора sin(x). В реализации тензорного потока я попытался закодировать это с помощью тензорного потока, и у меня все еще есть некоторые проблемы, когда я пытался создать карты функций, складывая тензор с терминами расширения. Может ли кто-нибудь предложить возможную перспективу, как я могу сделать свою текущую попытку более эффективной? Любые возможные мысли?

Вот условия расширения ряда Тейлора sin(x):

Тейлоровское расширение sin(x)

вот моя текущая попытка:

term = 2
c = tf.constant([1, -1/6])
power = tf.constant([1, 3])

x = tf.keras.Input(shape=(32, 32, 3))
res =[]
for x in range(term):
    expansion = c * tf.math.pow(tf.tile(x[..., None], [1, 1, 1, 1, term]),power)
    m_ij = tf.math.cumsum(expansion, axis=-1)
    res.append(m_i)

но это не совсем работает, потому что я хочу создать карты входных функций из каждого нейрона расширения, delta_1, delta_2 нужно сложить, что я не сделал правильно в моей предыдущей попытке, и мой код также не очень хорошо обобщен. Как я могу усовершенствовать мои вышеуказанные попытки кодирования в правильном способе реализации? Может ли кто-нибудь дать мне возможные идеи или канонический ответ, чтобы улучшить мои текущие попытки?


person jyson    schedule 13.07.2020    source источник
comment
Вы хотите суммировать или усреднять m11 и m12 или что-то еще? Потому что без него форма будет 5D - (batch_size, 3, 244, 244, 2), поэтому вам следует использовать слой Conv3D.   -  person Rahul Vishwakarma    schedule 30.07.2020
comment
Разве вы не можете использовать API стека для стека тензора? tensorflow.org/api_docs/python/tf/stack   -  person pratsbhatt    schedule 30.07.2020
comment
for x in range(term): повторно использовать одно и то же имя x. А что такое m_i? Это значит m_ij?   -  person yao99    schedule 02.08.2020
comment
Вместо стека вы можете попробовать использовать tf.Concatenate(), возможно, это поможет здесь.   -  person Rahul Vishwakarma    schedule 03.08.2020
comment
Вы ссылались на какую-либо газету/журнал? Если это так, пожалуйста, добавьте его ссылку.   -  person Rahul Vishwakarma    schedule 03.08.2020
comment
@jyson - я хотел бы попытаться ответить (и получить награду :), только что увидел вопрос, я проделал кучу работы с 3D-сетью. Было бы полезно, если бы вы разместили свой полный код (здесь или где-нибудь на github), чтобы я мог видеть, как вы вводите данные, а также как вы пытаетесь выполнить расширение.   -  person Alex I    schedule 04.08.2020
comment
@AlexI Привет, Алекс, ты пробовал состязательную попытку в своей работе? Я как бы работаю над одной новой формулировкой задачи классификации изображений. Можем ли мы подключиться, чтобы расширить возможное обсуждение с вами? Большое спасибо:)   -  person jyson    schedule 07.09.2020


Ответы (1)


При выполнении последовательного расширения, как описано, если вход имеет C каналов, а расширение имеет T членов, расширенный ввод должен иметь каналы C * T и в остальном иметь ту же форму. Таким образом, исходный вход и функция, аппроксимируемая до каждого члена, должны быть объединены по размерности канала. Это немного проще сделать с транспонированием и изменением формы, чем с конкатенацией.

Вот пример кода сверточной сети, обученной на CIFAR10:

inputs = tf.keras.Input(shape=(32, 32, 3))

x = inputs
n_terms = 2
c = tf.constant([1, -1/6])
p = tf.constant([1, 3], dtype=tf.float32)

terms = []
for i in range(n_terms):
    m = c[i] * tf.math.pow(x, p[i])
    terms.append(m)
expansion = tf.math.cumsum(terms)
expansion_terms_last = tf.transpose(expansion, perm=[1, 2, 3, 4, 0])
x = tf.reshape(expansion_terms_last, tf.constant([-1, 32, 32, 3*n_terms])) 

x = Conv2D(32, (3, 3), input_shape=(32,32,3*n_terms))(x)

Это предполагает, что исходная сеть (без расширения) будет иметь первый слой, который выглядит так:

x = Conv2D(32, (3, 3), input_shape=(32,32,3))(inputs)

а в остальном сеть точно такая же, какой была бы без расширения.

terms содержит список c_i*x^p_i из оригинала; expansion содержит сумму терминов (1-й, затем 1-й и 2-й и т. д.) в одном тензоре (где T — первое измерение). expansion_terms_last перемещает размер T в последнюю очередь, а изменение формы изменяет форму с (..., C, T) на (..., C*T)

Вывод model.summary() выглядит следующим образом:

__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_4 (InputLayer)            [(None, 32, 32, 3)]  0                                            
__________________________________________________________________________________________________
tf_op_layer_Pow_6 (TensorFlowOp [(None, 32, 32, 3)]  0           input_4[0][0]                    
__________________________________________________________________________________________________
tf_op_layer_Pow_7 (TensorFlowOp [(None, 32, 32, 3)]  0           input_4[0][0]                    
__________________________________________________________________________________________________
tf_op_layer_Mul_6 (TensorFlowOp [(None, 32, 32, 3)]  0           tf_op_layer_Pow_6[0][0]          
__________________________________________________________________________________________________
tf_op_layer_Mul_7 (TensorFlowOp [(None, 32, 32, 3)]  0           tf_op_layer_Pow_7[0][0]          
__________________________________________________________________________________________________
tf_op_layer_x_3 (TensorFlowOpLa [(2, None, 32, 32, 3 0           tf_op_layer_Mul_6[0][0]          
                                                                 tf_op_layer_Mul_7[0][0]          
__________________________________________________________________________________________________
tf_op_layer_Cumsum_3 (TensorFlo [(2, None, 32, 32, 3 0           tf_op_layer_x_3[0][0]            
__________________________________________________________________________________________________
tf_op_layer_Transpose_3 (Tensor [(None, 32, 32, 3, 2 0           tf_op_layer_Cumsum_3[0][0]       
__________________________________________________________________________________________________
tf_op_layer_Reshape_3 (TensorFl [(None, 32, 32, 6)]  0           tf_op_layer_Transpose_3[0][0]    
__________________________________________________________________________________________________
conv2d_5 (Conv2D)               (None, 30, 30, 32)   1760        tf_op_layer_Reshape_3[0][0]      

На CIFAR10 эта сеть обучается немного лучше с расширением — возможно, увеличение точности на 1% (с 71 до 72%).

Пошаговое объяснение кода с использованием демонстрационных данных:

# create a sample input
x = tf.convert_to_tensor([[1,2,3],[4,5,6],[7,8,9]], dtype=tf.float32) # start with H=3, W=3
x = tf.expand_dims(x, axis=0) # add batch dimension N=1
x = tf.expand_dims(x, axis=3) # add channel dimension C=1
# x is now NHWC or (1, 3, 3, 1)

n_terms = 2 # expand to T=2
c = tf.constant([1, -1/6])
p = tf.constant([1, 3], dtype=tf.float32)

terms = []
for i in range(n_terms):
    # this simply calculates m = c_i * x ^ p_i
    m = c[i] * tf.math.pow(x, p[i])
    terms.append(m)
print(terms)
# list of two tensors with shape NHWC or (1, 3, 3, 1)

# calculate each partial sum
expansion = tf.math.cumsum(terms)
print(expansion.shape)
# tensor with shape TNHWC or (2, 1, 3, 3, 1)

# move the T dimension last
expansion_terms_last = tf.transpose(expansion, perm=[1, 2, 3, 4, 0])
print(expansion_terms_last.shape)
# tensor with shape NHWCT or (1, 3, 3, 1, 2)

# stack the last two dimensions together
x = tf.reshape(expansion_terms_last, tf.constant([-1, 3, 3, 1*2])) 
print(x.shape)
# tensor with shape NHW and C*T or (1, 3, 3, 2)
# if the input had 3 channels for example, this would be (1, 3, 3, 6)
# now use this as though it was the input

Ключевые допущения (1) c_i и p_i не являются изученными параметрами, поэтому нейроны расширения на самом деле не являются нейронами, они просто узел умножения и суммирования (хотя нейроны звучат круче :) и (2) расширение происходит для каждого входного канала независимо, таким образом, C входных каналов, расширенных до T терминов, каждый производит C*T входных признаков, но T признаков из каждого канала вычисляются полностью независимо от других каналов (это выглядит так на диаграмме), и (3) вход содержит все частичные суммы (т.е. c_1 * x ^ p_1, c_1 * x ^ p_1 + c_2 * x ^ p_2 и т. д.), но не содержит членов (опять же, выглядит так, как на диаграмме)

person Alex I    schedule 05.08.2020