Transformación de dimensión de Tensorflow

1. Introducción a la transformación de dimensiones
En el proceso de operaciones de redes neuronales, la transformación de dimensiones es la operación de tensor central. A través de la transformación de dimensiones, los datos se pueden cambiar arbitrariamente para satisfacer diferentes necesidades informáticas. Cada módulo del algoritmo tiene diferentes requisitos lógicos para el formato del tensor de datos. Cuando el formato de datos existente no cumple con los requisitos del algoritmo, es necesario ajustar los datos al formato correcto a través de la transformación de dimensión. Esta es la función de dimensión transformación.
Las funciones básicas de operación de transformación de dimensiones incluyen cambiar la forma de la vista, insertar nuevas dimensiones expand_dims, eliminar la compresión de dimensiones, intercambiar la transposición de dimensiones, copiar mosaicos de datos y otras funciones.
2. Tensor y escalar
Por ejemplo: un tensor con una forma de [4,32,32,3] puede entenderse que tiene 4 imágenes, cada imagen tiene 32 filas y 32 columnas, y cada posición tiene datos de 3 canales RGB. El almacenamiento del tensor es un área de memoria continua almacenada en la memoria. Para el mismo almacenamiento, hay diferentes formas de entenderlo. Por ejemplo, el tensor anterior se puede almacenar sin cambiar. El tensor se puede entender como 4 muestras, cada una de las cuales es un vector de longitud característica 3072 para muestras. El mismo almacenamiento, analizando datos desde diferentes ángulos, puede producir diferentes vistas.Las vistas son muy flexibles, pero también deben estar en línea con el sentido común.

import tensorflow as tf
#产生向量
x = tf.range(96)
#改变x的视图,获得四维张量,存储没有改变
x = tf.reshape(x,[2,4,4,3])
print(x)

3. Transformación de vista
Para facilitar la expresión, la dimensión relativamente a la izquierda en la lista de formas del tensor se denomina dimensión grande, y la dimensión relativamente a la derecha en la lista de formas se denomina dimensión pequeña, por ejemplo [2, 4 , 4, 3] En el tensor, en comparación con el número de canales, el número de imágenes se denomina dimensión grande y el número de canales se denomina dimensión pequeña. La transformación de la vista solo necesita satisfacer que la cantidad total de elementos de la nueva vista sea igual al tamaño del área de almacenamiento y que la cantidad de elementos de la vista sea igual a b h w * c .

La vista inicial del tensor es [b, h, w, c], escriba el diseño de la memoria y ahora cambie el tensor: (1),
[b, h w, c]: b imágenes, h w píxeles, c canales ;
(2), [b, h, w c]: b imágenes, h líneas, cada línea tiene w c características;
(3), [b, c, h, w]: b imágenes, c canales, h filas, w, columnas, cambia el orden inicial.

Cambiar la vista es una operación muy común en las redes neuronales. Se puede realizar una lógica compleja conectando en cascada múltiples operaciones de remodelación. Sin embargo, al cambiar la vista a través de la remodelación, siempre debe recordar el orden de almacenamiento de los tensores. El orden de las dimensiones de la nueva vista no puede ser el mismo que el pedido de almacenamiento. De lo contrario, el pedido de almacenamiento debe sincronizarse a través de la operación de dimensión de intercambio.

#维度数和形状列表
x.ndim,x.shape
#(4, TensorShape([2, 4, 4, 3]))
#参数-1表示当前轴上长度需要根据张量总元素不变的法则自动推导
tf.reshape(x,[2,-1])
'''
<tf.Tensor: shape=(2, 48), dtype=int32, numpy=
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
        16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],
       [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
        64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
        80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95]])>
'''
tf.reshape(x,[2,4,12])
'''
<tf.Tensor: shape=(2, 4, 12), dtype=int32, numpy=
array([[[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
        [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
        [24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35],
        [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]],

       [[48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
        [60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71],
        [72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83],
        [84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95]]])>
'''
tf.reshape(x,[2,16,3])
'''
<tf.Tensor: shape=(2, 16, 3), dtype=int32, numpy=
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8],
        [ 9, 10, 11],
        [12, 13, 14],
        [15, 16, 17],
        [18, 19, 20],
        [21, 22, 23],
        [24, 25, 26],
        [27, 28, 29],
        [30, 31, 32],
        [33, 34, 35],
        [36, 37, 38],
        [39, 40, 41],
        [42, 43, 44],
        [45, 46, 47]],

       [[48, 49, 50],
        [51, 52, 53],
        [54, 55, 56],
        [57, 58, 59],
        [60, 61, 62],
        [63, 64, 65],
        [66, 67, 68],
        [69, 70, 71],
        [72, 73, 74],
        [75, 76, 77],
        [78, 79, 80],
        [81, 82, 83],
        [84, 85, 86],
        [87, 88, 89],
        [90, 91, 92],
        [93, 94, 95]]])>
'''

4. Agregar y eliminar dimensiones
Los datos de una imagen en escala de grises de 28×28 se guardan como un tensor con una forma de [28, 28], y al final se agrega una nueva dimensión al tensor, que se define como el canal dimensión numérica En este momento, la forma del tensor se convierte en [28, 28, 1]:

x = tf.random.uniform((28,28),maxval=10,dtype=tf.int32)
print('初始维度:',x.shape)
x = tf.expand_dims(x,axis=2)
print('变换后维度:',x.shape)
'''
初始维度: (28, 28)
变换后维度: (28, 28, 1)
'''

Se puede insertar una nueva dimensión en la parte delantera:

x = tf.expand_dims(x,axis=0)
x.shappe
#TensorShape([1, 28, 28, 1])
x = tf.expand_dims(x,axis=-1)
x.shape
#TensorShape([1, 28, 28, 1, 1])
x = tf.expand_dims(x,axis=-4)
x.shape
#TensorShape([1, 28, 1, 28, 1, 1])

Cuando el eje de tf.expand_dims es positivo, significa que se inserta una nueva dimensión antes de la dimensión actual, cuando es negativo, significa que se inserta una nueva dimensión después de la dimensión actual.
Eliminar dimensiones solo puede eliminar dimensiones con una longitud de 1 y no cambiará el almacenamiento de tensores.

x = tf.squeeze(x,axis=0)
x.shape
#TensorShape([28, 1, 28, 1, 1])
x = tf.squeeze(x,axis=1)
x.shape
#TensorShape([28,28, 1, 1])
#默认删除所有长度为1的维度
x =tf.squeeze(x)
x.shape
#TensorShape([28, 28])

4. Intercambiar dimensiones
La operación de intercambiar dimensiones cambia el orden de almacenamiento de los tensores y también cambia la vista de los tensores:

#[b,h,w,c]到[b,c,h,w]维度交换运算
x = tf.random.uniform((4,28,28,3),maxval=10,dtype=tf.int32)
print('初始维度:',x.shape)
x = tf.transpose(x,perm=(0,3,1,2))
print('变换后维度:',x.shape)
'''
初始维度: (4, 28, 28, 3)
变换后维度: (4, 3, 28, 28)
'''
#[b,h,w,c]交换为[b,w,h,c]
x = tf.random.uniform((4,28,28,3),maxval=10,dtype=tf.int32)
print('初始维度:',x.shape)
x = tf.transpose(x,perm=(0,2,1,3))
print('变换后维度:',x.shape)
'''
初始维度: (4, 28, 28, 3)
变换后维度: (4, 28, 28, 3)
'''

5. Copiar datos
Después de insertar una nueva dimensión agregando una operación de dimensión, es posible que desee copiar varias copias de datos en la nueva dimensión:

x = tf.constant([1,2])
print(x.shape)
print(x)
x = tf.expand_dims(x,axis=0)
print(x.shape)
print(x)
x = tf.tile(x,multiples=[2,1])
print(x.shape)
print(x)
'''
(2,)
tf.Tensor([1 2], shape=(2,), dtype=int32)
(1, 2)
tf.Tensor([[1 2]], shape=(1, 2), dtype=int32)
(2, 2)
tf.Tensor(
[[1 2]
 [1 2]], shape=(2, 2), dtype=int32)
'''
x = tf.range(4)
print(x.shape)
print(x)
x = tf.reshape(x,(2,2))
print(x.shape)
print(x)
#在列维度复制1份数据
x = tf.tile(x,multiples=[1,2])
print(x.shape)
print(x)
#在行维度复制1份数据
x = tf.tile(x,multiples=[2,1])
print(x.shape)
print(x)
'''
(4,)
tf.Tensor([0 1 2 3], shape=(4,), dtype=int32)
(2, 2)
tf.Tensor(
[[0 1]
 [2 3]], shape=(2, 2), dtype=int32)
 (2, 4)
tf.Tensor(
[[0 1 0 1]
 [2 3 2 3]], shape=(2, 4), dtype=int32)
(4, 4)
tf.Tensor(
[[0 1 0 1]
 [2 3 2 3]
 [0 1 0 1]
 [2 3 2 3]], shape=(4, 4), dtype=int32)
'''

Mecanismo de difusión
La idea central del mecanismo de difusión es la universalidad, es decir, el mismo dato puede ser aplicable de forma general a otros lugares. Antes de verificar la universalidad, primero debe alinear la forma del tensor a la derecha y luego hacer un juicio de universalidad: para una dimensión con una longitud de 1, los datos predeterminados generalmente son adecuados para otras posiciones de la dimensión actual; para no- dimensiones existentes, luego, después de agregar una nueva dimensión, los datos actuales predeterminados también se aplican universalmente a la nueva dimensión, por lo que se pueden extender a formas de tensor con más dimensiones y longitudes arbitrarias.
Por ejemplo: un tensor cuya forma es [w, 1] debe expandirse para formar: [b, h, w, c], primero alinee las dos formas a la derecha, y para la dimensión del canal c, la longitud del tensor es 1, entonces De forma predeterminada, estos datos también son adecuados para otras posiciones en la dimensión actual, y los datos se copian lógicamente en copias c-1, y la longitud se convierte en c; para las dimensiones inexistentes b y h, a la nueva dimensión se inserta automáticamente, y la longitud de la nueva dimensión es 1, y la predeterminada Los datos actuales se generalizan a otras posiciones en la nueva dimensión, y luego las longitudes de los datos b y h se extienden automáticamente a b y h .

x = tf.random.normal([32,1])
tf.broadcast_to(x,[3,32,32,3])
'''
<tf.Tensor: shape=(3, 32, 32, 3), dtype=float32, numpy=
array([[[[-0.03420183, -0.03420183, -0.03420183],
         [-0.11337528, -0.11337528, -0.11337528],
         [ 1.3235099 ,  1.3235099 ,  1.3235099 ],
         ...,
         ...
'''
#在c维度上,张量已经有2个特征数据,当前维度上的这2个特征无法普适到其他位置,故不满足普适性原则,无法应用Broadcasting机制,将会触发错误
x = tf.random.normal([32,2])
tf.broadcast_to(x,[3,32,32,3])
'''
InvalidArgumentError: Incompatible shapes: [32,2] vs. [3,32,32,3] [Op:BroadcastTo]
'''
#自动Broadcasting机制
x = tf.random.normal([2,32,32,1])
y = tf.random.normal([32,32])
x+y,x-y,x*y,x/y
'''
(<tf.Tensor: shape=(2, 32, 32, 32), dtype=float32, numpy=
 array([[[[-2.34972119e-01, -1.32176340e+00, -8.74061882e-01, ...,
            9.48178649e-01,  7.73117542e-01, -1.03607702e+00],
          [-2.06189919e+00,  5.86489856e-01, -1.94167900e+00, ...,
            1.85062528e-01, -6.44589007e-01, -2.36011267e+00],
          [ 8.50200295e-01,  1.61495817e+00,  1.37277842e+00, ...,
            8.79180253e-01,  1.06644309e+00,  1.89374065e+00],
          ...,
'''

Supongo que te gusta

Origin blog.csdn.net/weixin_56260304/article/details/128205336
Recomendado
Clasificación