Aprendizaje profundo 06: Red adversarial generativa convolucional profunda (DCGAN)

Descripción general

GAN (Generative Adversarial Network) es un modelo generativo que consta de dos redes neuronales: Generador y Discriminador. La idea básica de GAN es aprender la capacidad de generar muestras reales enfrentando al generador y al discriminador entre sí.

La función del generador es tomar un vector de ruido aleatorio como entrada y transformarlo gradualmente en una salida similar a la muestra real a través de una serie de capas de red neuronal. El objetivo del generador es intentar que el discriminador confunda las muestras generadas con muestras reales, engañando así al discriminador. El objetivo de entrenamiento del generador es minimizar la diferencia entre las muestras generadas y las muestras reales.

La función del discriminador es distinguir las muestras de entrada en muestras reales y muestras generadas. El objetivo del discriminador es determinar la autenticidad de la muestra con la mayor precisión posible. El objetivo del entrenamiento del discriminador es maximizar la capacidad de distinguir entre muestras reales y muestras generadas.

El proceso de formación de GAN se puede describir brevemente en los siguientes pasos:

Inicialice los parámetros del generador y discriminador.
Se selecciona aleatoriamente un lote de muestras de muestras reales como conjunto de entrenamiento para el discriminador. Al mismo tiempo, se genera un lote de vectores de ruido aleatorio como entrada al generador.
Utilice el generador para generar un lote de muestras y mézclelas con muestras reales para formar el conjunto de entrenamiento del discriminador.
Utilice el discriminador para discriminar las muestras en el conjunto de entrenamiento y calcular la pérdida entre las muestras generadas y las muestras reales.
Actualice los parámetros del generador y el discriminador para mejorar gradualmente la calidad de las muestras generadas y, al mismo tiempo, la capacidad discriminante del discriminador también mejora gradualmente.
Repita los pasos 2 a 5 hasta que el generador pueda generar muestras similares a muestras reales.
DCGAN (Deep Convolutional GAN) es una versión mejorada de GAN, que mejora principalmente el rendimiento del generador y discriminador mediante la introducción de una red neuronal convolucional (CNN). DCGAN utiliza capas convolucionales y deconvolucionales en el generador y discriminador para permitirle procesar datos de imágenes. En comparación con la GAN tradicional, DCGAN tiene un mejor rendimiento en la generación de detalles y texturas de imágenes.

En general, GAN es un modelo generativo que aprende a generar muestras reales confrontando el generador y el discriminador entre sí, mientras que DCGAN introduce una red neuronal convolucional basada en GAN para mejorar las capacidades de procesamiento de datos de imágenes.

Introducción al principio

El trabajo pionero de GAN es el artículo clásico Generative Adversarial Networks[2] publicado en 2014 por Ian Goodfellow, conocido como el "padre de GAN", en el que propuso una red generativa de confrontación y diseñó la primera GAN. generación de números.

La aparición de GAN surgió de una idea repentina:

“Lo que no puedo crear, no lo entiendo.”
—Richard Feynman

De manera similar, si el aprendizaje profundo no puede crear imágenes, entonces realmente no las comprende. En ese momento, el aprendizaje profundo había comenzado a conquistar varios campos de la visión por computadora y logró avances en casi todas las tareas. Sin embargo, la gente siempre ha cuestionado el modelo de caja negra de las redes neuronales, por lo que cada vez más personas están explorando las características y combinaciones de características aprendidas por las redes convolucionales desde una perspectiva visual, mientras que GAN muestra las características de las redes neuronales desde una perspectiva de aprendizaje generativo. Capacidades poderosas. Las GAN resuelven un problema bien conocido en el aprendizaje no supervisado: dado un lote de muestras, entrena un sistema para generar nuevas muestras similares.

La estructura de red de la red adversarial generativa se muestra en la Figura 7-2, que incluye principalmente las dos subredes siguientes.
• Generador: ingrese un ruido aleatorio y genere una imagen.
• Discriminador: determina si la imagen de entrada es una imagen real o una imagen falsa.
Insertar descripción de la imagen aquí
Al entrenar al discriminador, es necesario utilizar imágenes falsas generadas por el generador e imágenes reales del mundo real; al entrenar al generador, solo se utiliza ruido para generar imágenes falsas. El discriminador evalúa la calidad de las imágenes falsas generadas y solicita al generador que ajuste los parámetros en consecuencia.

El objetivo del generador es generar una imagen lo más falsa posible para que el discriminador piense que es una imagen real; el objetivo del discriminador es distinguir las imágenes generadas por el generador de las imágenes del mundo real. Se puede observar que los dos tienen objetivos opuestos y compiten entre sí durante el proceso de entrenamiento, por lo que se le llama red generativa adversaria.
La descripción anterior puede ser un poco abstracta, así que usemos los ejemplos de coleccionistas de caligrafía y pintura y comerciantes de pinturas falsificadas que coleccionan las obras de Qi Baishi (las obras de Qi Baishi se muestran en la Figura 7-3). Los comerciantes de pinturas falsificadas son equivalentes a generadores. Esperan imitar las obras originales de los maestros y falsificar pinturas falsas para engañar a los coleccionistas y venderlas a precios elevados. Los coleccionistas de caligrafía y pintura esperan distinguir las obras falsas de las auténticas, para que las obras auténticas puedan ser circuló en el mundo y fue destruido.Falsificación. Las pinturas que comercializan aquí los comerciantes y coleccionistas de pinturas falsas son principalmente camarones pintados por Qi Baishi. Se puede decir que la pintura de camarones de Qi Baishi es una obra maestra en el mundo de la pintura y siempre ha sido buscada por el mundo.
Insertar descripción de la imagen aquí
En este caso, tanto el comerciante de pinturas falsificadas como el coleccionista de caligrafía y pintura eran novatos al principio y tenían un concepto vago de las obras genuinas y las falsificaciones. Las pinturas falsificadas producidas por los comerciantes de pinturas falsificadas son casi todas graffiti aleatorios, y los coleccionistas de caligrafía y pintura tienen malas habilidades de identificación. Muchas falsificaciones son consideradas genuinas por él y muchas obras auténticas son consideradas falsificaciones.

En primer lugar, el coleccionista de caligrafía y pintura recopiló muchas falsificaciones en el mercado y las obras originales del Maestro Qi Baishi, las estudió y comparó cuidadosamente, e inicialmente aprendió la estructura del camarón en la pintura. la pintura tenía forma curva y un par de “quelíceros” que parecían alicates”, se filtrarán todas las pinturas falsas que no cumplan con esta condición. Cuando los coleccionistas utilizan este estándar para realizar valoraciones en el mercado, las pinturas falsas básicamente no pueden engañar a los coleccionistas y los comerciantes de pinturas falsas sufren grandes pérdidas. Sin embargo, algunas de las falsificaciones producidas por los comerciantes de pinturas falsas siguen siendo engañosas: estas falsificaciones tienen formas curvas y un par de "quelíceros" que parecen alicates. Entonces los comerciantes de pinturas falsificadas comenzaron a modificar las técnicas de imitación, agregando formas curvas y un par de "quelíceros" en forma de alicates a las obras de imitación. Aparte de estas características, otros lugares, como colores y líneas, se dibujan al azar. Aquí se muestra la primera edición de la falsificación creada por un comerciante de pinturas falsas.
Insertar descripción de la imagen aquí
Cuando los comerciantes de pinturas falsificadas ponen estas pinturas a la venta en el mercado, engañan fácilmente a los coleccionistas porque hay una criatura curva en la pintura con un par de cosas parecidas a alicates delante de la criatura, que cumple con los estándares de autenticidad reconocidos por los coleccionistas. Por eso los coleccionistas lo compraron como una pieza auténtica. Con el paso del tiempo, el coleccionista volvió a comprar cada vez más cuadros falsos y sufrió grandes pérdidas, por lo que estudió a puerta cerrada la diferencia entre cuadros falsos y auténticos. Después de repetidas comparaciones y comparaciones, descubrió que además de la forma del El camarón es curvo, los tentáculos del camarón son largos y todo el cuerpo es traslúcido, los detalles del camarón son muy ricos y cada segmento del camarón es blanco.

Una vez que los coleccionistas completaron sus estudios, volvieron a trabajar, pero las habilidades de falsificación de los comerciantes de pinturas falsas no mejoraron y los coleccionistas vieron fácilmente las falsificaciones que produjeron. Como resultado, los comerciantes de pinturas falsificadas también comenzaron a probar diferentes técnicas para pintar camarones, la mayoría de las cuales fueron en vano, pero entre los muchos intentos, algunas falsificaciones aún engañaron a los coleccionistas. Los comerciantes de pinturas falsas descubrieron que estas imitaciones tenían tentáculos largos y cuerpos translúcidos, y las pinturas de camarones eran muy detalladas, como se muestra en la Figura 7-5. Como resultado, los comerciantes de pinturas falsas comenzaron a imitarlas en grandes cantidades y a venderlas en el mercado, muchos de los cuales engañaron con éxito a los coleccionistas.
Insertar descripción de la imagen aquí
El coleccionista volvió a sufrir grandes pérdidas y se vio obligado a cerrar su tienda para estudiar la diferencia entre las obras originales de Qi Baishi y las falsificaciones, conocer las características de las obras originales de Qi Baishi y mejorar sus habilidades de identificación. De esta manera, a través del juego entre coleccionistas y comerciantes de pinturas falsas, los coleccionistas mejoraron gradualmente su capacidad para distinguir las obras auténticas de las falsificaciones desde cero, mientras que los comerciantes de pinturas falsas también mejoraron continuamente su nivel de imitación de las obras originales de Qi Baishi. Los coleccionistas utilizan las falsificaciones proporcionadas por los comerciantes de pinturas falsificadas para compararlas con las obras originales y apreciar mejor las obras originales de las pinturas de Qi Baishi; y los comerciantes de pinturas falsificadas continúan tratando de mejorar el nivel de falsificación y mejorar la calidad de las falsificaciones. pinturas, incluso si al final Lo que se produce sigue siendo falso, pero está muy cerca del original. Los coleccionistas y los comerciantes de pinturas falsificadas compiten entre sí y, al mismo tiempo, se alientan constantemente para aprender y progresar, a fin de lograr el objetivo de mejora mutua.

En este ejemplo, el comerciante de pinturas falsas equivale a un generador y el coleccionista equivale a un discriminador. Tanto el generador como el discriminador funcionan mal al principio porque ambos se inicializan aleatoriamente. El proceso de entrenamiento se divide en dos pasos alternos. El primer paso es entrenar al discriminador (solo modifica los parámetros del discriminador y arregla el generador). El objetivo es distinguir las obras auténticas de las falsificaciones; el segundo paso es entrenar al generador. (solo modifique los parámetros del generador, discriminador fijo), para que el discriminador pueda juzgar las pinturas falsas generadas como auténticas (consideradas auténticas por los coleccionistas). Estos dos pasos se realizan alternativamente y tanto el clasificador como el discriminador alcanzan un nivel muy alto. Al final del entrenamiento, las imágenes de camarones generadas por el generador (como se muestra en la Figura 7-6) son casi indistinguibles de las imágenes reales de Qi Baishi.
Insertar descripción de la imagen aquí
A continuación, pensemos en el diseño de la estructura de la red. El objetivo del discriminador es determinar si la imagen de entrada es auténtica o falsa, por lo que puede considerarse como una red de dos clasificaciones. Podemos diseñar una red convolucional simple. El objetivo del generador es generar una imagen en color a partir del ruido. Aquí utilizamos la estructura DCGAN (Deep Convolutional Generative Adversarial Networks) ampliamente utilizada, es decir, una red totalmente convolucional, cuya estructura se muestra en la figura siguiente. La entrada de la red es un ruido de 100 dimensiones y la salida es una imagen de 3 × 64 × 64. La entrada aquí puede considerarse como una imagen de 100 × 1 × 1, que se aumenta lentamente a 4 × 4, 8 × 8, 16 × 16, 32 × 32 y 64 × 64 mediante convolución ascendente. La convolución ascendente, o convolución transpuesta, es una operación de convolución especial, similar a la operación inversa de la operación de convolución. Cuando el paso de la convolución es 2, la salida se reducirá a la mitad del tamaño de la entrada; y cuando el paso de la convolución ascendente es 2, la salida se aumentará al doble del tamaño de la entrada. Este método de muestreo ascendente puede entenderse como que la información de la imagen se almacena en 100 vectores. Con base en la información descrita por estos 100 vectores, la red neuronal primero describe información básica como contornos y tonos en los primeros pasos del muestreo ascendente. refina los detalles. Cuanto más profunda es la red, más detallados son los detalles.
Insertar descripción de la imagen aquí

Este capítulo está citado del libro "Marco de aprendizaje profundo Pytorch, introducción a la práctica".

Terminología

  • Upsample se utiliza en el campo del aprendizaje profundo en visión por computadora. Dado que la imagen de entrada extrae características a través de una red neuronal convolucional (CNN), el tamaño de la salida a menudo se vuelve más pequeño y, a veces, necesitamos restaurar la imagen a su tamaño original en Para realizar más cálculos (por ejemplo, segmentación semántica de imágenes), esta operación utiliza la expansión del tamaño de la imagen para mapear la imagen de una resolución pequeña a una resolución grande, lo que se denomina muestreo ascendente.
  • El relleno de ceros de una matriz es el proceso de agregar valores cero a los límites de una matriz. En visión por computadora y aprendizaje profundo, el relleno de ceros de matriz se usa comúnmente en el procesamiento de imágenes y redes neuronales convolucionales (CNN).
    En el procesamiento de imágenes, el relleno de ceros de matriz se puede utilizar para expandir las dimensiones de una imagen de modo que el tamaño de la imagen permanezca sin cambios al realizar una operación de convolución. Al agregar valores cero alrededor de la imagen, se asegura de que el núcleo de convolución cubra completamente los píxeles del borde de la imagen. Esto evita la pérdida de información sobre los bordes de la imagen durante las operaciones de convolución.
    En las redes neuronales convolucionales (CNN), el relleno de ceros de matriz se utiliza a menudo para ajustar el tamaño de entrada y el tamaño de salida de la capa convolucional. Al agregar valores cero a los límites de la matriz de entrada, se asegura de que las dimensiones del mapa de características producido por la operación de convolución sean consistentes con las dimensiones de la matriz de entrada. Esto es importante para construir redes neuronales profundas y procesar datos de entrada de diferentes tamaños.
    El tamaño del relleno de ceros de una matriz suele estar determinado por el número de filas y columnas rellenas. En CNN, el tamaño del relleno suele estar relacionado con el tamaño y el paso del núcleo de convolución. Al elegir correctamente el tamaño del relleno, puede controlar el tamaño del mapa de características y el tamaño del campo receptivo mientras mantiene consistentes los tamaños de entrada y salida.
  • Hay tres métodos comunes de muestreo ascendente de deconvolución (convolución transpuesta): interpolación bilineal (bilineal), deconvolución (convolución transpuesta) y desagrupación (unpooling), aquí solo analizamos la deconvolución. La deconvolución a la que se hace referencia aquí también se llama convolución transpuesta. No es el proceso inverso completo de la convolución directa. Para explicarlo en una oración: la deconvolución es una convolución directa especial. Primero sigue una cierta proporción. Expanda el tamaño de la imagen de entrada en relleno 000, luego gire el núcleo de convolución y luego realice una convolución directa.

relleno cero

Para algunos procesos en el procesamiento de imágenes, necesito expandir el tamaño de la matriz numérica leída. Por ejemplo, la matriz que originalmente era (4, 6) ahora necesita expandirse en 3 filas en la parte superior, inferior, izquierda y derecha. y para no afectar el cálculo numérico, utilice relleno 0.
Por ejemplo, en la imagen a continuación, tengo una matriz de 4x5 de todos 1, pero ahora necesito agregar 3 filas de 0 alrededor para expandir el tamaño. Después de la expansión, todavía necesito operar en el área original.

  1. Si la matriz original tiene forma (m, n) y está llena con valores de p filas y q columnas en cada borde, entonces la forma de la matriz llena será (m + 2p, n + 2q)
  2. Si la forma de la matriz original es (m, n) y se inserta un cero entre cada elemento, entonces la nueva matriz es (m+m-1,n,n-1)=(2m-1, 2n-1)

Insertar descripción de la imagen aquí
Numpy ha encapsulado una función, que es pad

 #%%
import numpy as np
oneArry=np.ones((4,5))
print(oneArry)
print("周围",np.pad(oneArry,3))  #等价于print(np.pad(oneArry,(3,3)))
#注意元组0是左上角补充3行 ,元组1表示右小角
print("左上角",np.pad(oneArry,(3,0)))
print("右下角",np.pad(oneArry,(0,3)))

producción

[[1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1.]]
周围 [[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 0.]
 [0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 0.]
 [0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 0.]
 [0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
左上角 [[0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 1. 1. 1. 1.]
 [0. 0. 0. 1. 1. 1. 1. 1.]
 [0. 0. 0. 1. 1. 1. 1. 1.]
 [0. 0. 0. 1. 1. 1. 1. 1.]]
右下角 [[1. 1. 1. 1. 1. 0. 0. 0.]
 [1. 1. 1. 1. 1. 0. 0. 0.]
 [1. 1. 1. 1. 1. 0. 0. 0.]
 [1. 1. 1. 1. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]]

El relleno dentro de un elemento se refiere a llenar hacia arriba, abajo, izquierda y derecha dentro del elemento,
por ejemplo

[[1, 1],
 [1, 1]]

Lleno:

[[1, 0, 1], 
[0, 0, 0],
 [1, 0, 1]]

Código

import numpy as np

matrix = [[1, 1],
          [1, 1]]

zero_inserted_matrix = np.zeros((2*len(matrix)-1, 2*len(matrix[0])-1))

for i in range(len(matrix)):
    for j in range(len(matrix[0])):
        zero_inserted_matrix[2*i][2*j] = matrix[i][j]

print(zero_inserted_matrix)

producción

[[1. 0. 1.]
 [0. 0. 0.]
 [1. 0. 1.]]

convolución transpuesta

Referencia: https://www.zhihu.com/question/48279880
Convolución transpuesta o convolución de microzancada. Sin embargo, cabe señalar que el nombre deconvolución no es muy apropiado, porque la convolución transpuesta no es una verdadera deconvolución tal como se define en el campo de procesamiento de señales/imágenes. Técnicamente hablando, la deconvolución en el procesamiento de señales es la operación inversa de la convolución. Pero este no es el caso aquí. Más adelante explicaremos por qué es más natural y apropiado llamar a esta operación convolución transpuesta.

Podemos usar convoluciones comunes para implementar convoluciones transpuestas. Aquí usamos un ejemplo simple para ilustrar. La capa de entrada es 2 * 2 (la parte azul a continuación). Primero, el valor de relleno Padding es relleno cero con un paso unitario de 2 * 2 (lo siguiente se llena con 2 filas de 2 arriba, abajo, izquierda y derecha en la columna azul), y luego use un núcleo de convolución 3 * 3 con un paso de 1 para realizar una operación de convolución (la convolución obtiene un valor a la vez) para lograr un muestreo superior y el tamaño de la salida de muestreo superior es 4*4, que es (6-3 +1,6-3+1)

Insertar descripción de la imagen aquí
Vale la pena mencionar que con varios rellenos y zancadas, podemos asignar la misma entrada 2*2 a diferentes tamaños de imagen. En la siguiente figura, la convolución transpuesta se aplica a la misma entrada 2*2 (se inserta un cero entre las entradas y se agrega un relleno de ceros de un paso unitario de 2*2 alrededor de ella), y se aplica una convolución 3*3. aplicado. Kernel, el resultado resultante (es decir, el resultado del muestreo superior) tiene un tamaño de 5 * 5.
Insertar descripción de la imagen aquí
Observar la convolución transpuesta en el ejemplo anterior puede ayudarnos a desarrollar una comprensión intuitiva. Pero para aplicar aún más la convolución transpuesta, también debemos comprender cómo se implementa la multiplicación de matrices por computadora . Desde la perspectiva del proceso de implementación, podemos entender por qué convolución transpuesta es el nombre más apropiado.

En convolución, lo definimos así: C representa el núcleo de convolución, la entrada es la imagen de entrada y la salida es la imagen de salida. Después de la convolución (multiplicación de matrices), reducimos la muestra de la entrada de la imagen grande a la salida de una imagen pequeña. Esta implementación de multiplicación de matrices sigue C*entrada=salida.

El siguiente ejemplo muestra cómo funciona esta operación en una computadora. Aplana la matriz de entrada (16*1) y convierte el núcleo de convolución en una matriz dispersa (4*16). Luego, use la multiplicación de matrices entre la matriz dispersa y la entrada aplanada. Después de eso, la matriz obtenida (4*1) se convierte en 2*2 y se genera.
Insertar descripción de la imagen aquí
En este momento, si se utiliza el núcleo de convolución para corresponder al CTC^T transpuesto de la matriz dispersaCMultiplicar T (16*4) por el aplanamiento de la salida (4*1) da como resultado un resultado (16*1) que tiene la misma forma que la entrada (16*1).


Sin embargo, vale la pena señalar que las dos operaciones anteriores no son reversibles: para el mismo núcleo de convolución (debido a que su matriz dispersa no es una matriz ortogonal), el resultado no se puede restaurar al valor original después de la operación de transposición, solo se conserva el valor original. Forma , por lo que el nombre de convolución transpuesta proviene de esto. Y para responder a la pregunta mencionada anteriormente, la convolución transpuesta es más precisa que la convolución inversa.

Generar imágenes animadas

Utilice DCGAN para entrenar un modelo para generar imágenes de animación de 64 * 64 y utilice este ejemplo para planificar la organización de la estructura de directorios de la red neuronal. La mayoría de los proyectos de código abierto tienen estructuras de directorios similares y será más fácil analizar el modelo de código abierto en el futuro.

Selección de potencia informática

Dado que el entrenamiento gan requiere grandes recursos y lleva mucho tiempo, se recomienda utilizar un servidor gpu.
Hay muchos modelos de GPU proporcionados en la plataforma en la nube gpt. Podemos dividirlo aproximadamente en cinco categorías según la arquitectura de la GPU (se recomienda autodl o inscode, que se pueden facturar a tiempo y liberar cuando se agote):

  1. GPU de arquitectura NVIDIA Pascal, como TitanXp, serie GTX 10, etc. Este tipo de GPU carece de capacidades de aceleración de hardware de baja precisión, pero tiene una potencia informática moderada de precisión simple. Debido a que es económico, es adecuado para practicar el entrenamiento de modelos pequeños (como Cifar10) o depurar código de modelo.
  2. GPU de arquitectura NVIDIA Volta/Turing, como la serie GTX 20, Tesla V100, etc. Este tipo de GPU está equipada con TensorCore, que está diseñado para acelerar cálculos de baja precisión (int8/float16), pero la potencia de cálculo de precisión simple no ha mejorado mucho en comparación con la generación anterior. Recomendamos habilitar el entrenamiento de precisión mixta de marcos de aprendizaje profundo en la instancia para acelerar el cálculo del modelo. En comparación con el entrenamiento de precisión simple, el entrenamiento de precisión mixta generalmente puede proporcionar más del doble de aceleración del entrenamiento.
  3. GPU con arquitectura NVIDIA Ampere, como la serie GTX 30, Tesla A40/A100, etc. Este tipo de GPU está equipada con TensorCore de tercera generación. En comparación con la generación anterior, admite el formato TensorFloat32, que puede acelerar directamente el entrenamiento de precisión simple (PyTorch está habilitado de forma predeterminada). Sin embargo, todavía recomendamos utilizar el modelo de entrenamiento de media precisión float16 con potencia informática ultra alta, que puede lograr mejoras de rendimiento más significativas que la generación anterior de GPU.
  4. Tarjetas aceleradoras Cambrian serie MLU 200. El entrenamiento de modelos aún no es compatible. La inferencia del modelo que utiliza esta serie de tarjetas aceleradoras debe cuantificarse en int8 para su cálculo. Y debe instalar el marco de aprendizaje profundo adaptado a Cambrian MLU.
  5. Tarjetas aceleradoras de la serie Huawei Ascend. Soporte de entrenamiento e inferencia de modelos. Sin embargo, es necesario instalar el marco MindSpore para realizar el cálculo.

Elegir un modelo de GPU no es difícil. Para los modelos de aprendizaje profundo comúnmente utilizados, el rendimiento del modelo de entrenamiento de GPU se puede estimar aproximadamente en función de la potencia informática de la GPU correspondiente a la precisión. La plataforma AutoDL marca y clasifica la potencia informática de cada tipo de GPU para que todos puedan elegir la GPU que más les convenga.

La cantidad de GPU seleccionadas está relacionada con la tarea de capacitación. Generalmente, creemos que una sesión de entrenamiento del modelo debe completarse dentro de las 24 horas, para que el modelo mejorado pueda entrenarse al día siguiente. A continuación se ofrecen algunas sugerencias para elegir varias GPU:

  • 1 GPU. Adecuado para algunas tareas de entrenamiento con conjuntos de datos más pequeños, como Pascal VOC, etc.
  • 2 GPU. Lo mismo que una sola GPU, pero puede ejecutar dos conjuntos de parámetros a la vez o expandir el tamaño del lote.
  • 4 GPU. Adecuado para tareas de entrenamiento con algunos conjuntos de datos medianos, como MS COCO, etc.
  • 8 GPU. ¡Una configuración clásica que durará para siempre! Es adecuado para diversas tareas de formación y también es muy conveniente para reproducir los resultados del trabajo.
  • ¡Quiero más! Se utiliza para entrenar modelos de parámetros grandes, ajustar parámetros a gran escala o completar el entrenamiento de modelos ultrarrápidamente.

Mis GPU de uso común están clasificadas en orden de alto a bajo rendimiento. La potencia informática de GPU de estas máquinas se clasifica de la siguiente manera, junto con su información de configuración básica:

  1. A100:
    • Número de núcleos CUDA: 6912
    • Número de núcleos tensoriales: 432
    • Capacidad de memoria de vídeo: 40 GB
    • Ancho de banda de memoria: 1555 GB/s
    • Arquitectura: amperio
  2. V100:
    • Número de núcleos CUDA: 5120
    • Número de núcleos tensoriales: 640
    • Capacidad de memoria de vídeo: 16 GB / 32 GB / 32 GB HBM2
    • Ancho de banda de memoria: 900 GB/s / 1134 GB/s / 1134 GB/s
    • Arquitectura: Volta
  3. P100:
    • Número de núcleos CUDA: 3584
    • Número de núcleos tensoriales: 0
    • Capacidad de memoria de vídeo: 16 GB / 12 GB HBM2
    • Ancho de banda de memoria: 732 GB/s / 549 GB/s
    • Arquitectura: Pascal
  4. Tesla T4:
    • Número de núcleos CUDA: 2560
    • Número de núcleos tensoriales: 320
    • Capacidad de memoria de vídeo: 16 GB
    • Ancho de banda de memoria: 320 GB/s
    • Arquitectura: Turing
  5. RTX A4000:
    • Número de núcleos CUDA: 6144
    • Número de núcleos tensoriales: 192
    • Capacidad de memoria de vídeo: 16 GB
    • Ancho de banda de memoria: 448 GB/s
    • Arquitectura: Ampere
      utiliza P100 para completar el entrenamiento en aproximadamente 1 hora (3831,2 s)

conjunto de datos

En kagle: https://www.kaggle.com/code/splcher/starter-anime-face-dataset
Registre una cuenta por correo electrónico y podrá descargarla. Debajo del conjunto de datos, hay diferentes códigos de entrenamiento de usuarios y resultados basados en el conjunto de datos.
Código de referencia: https://www.kaggle.com/code/splcher/starter-anime-face-dataset

Planificación de directorios

Insertar descripción de la imagen aquí
Los principales contenidos y funciones de cada archivo son los siguientes.

• puntos de control/: se utiliza para guardar el modelo entrenado, de modo que el programa aún pueda recargar el modelo y reanudar el entrenamiento después de una salida anormal.
• data/: Operaciones relacionadas con datos, incluido el preprocesamiento de datos, la implementación de conjuntos de datos, etc.
• modelos/: Definición del modelo, puede haber varios modelos, como AlexNet y ResNet34 anteriores, un modelo corresponde a un archivo.
• utils/: Funciones de utilidad que se pueden utilizar. En este experimento, las herramientas de visualización están principalmente encapsuladas.
• config.py: Archivo de configuración, aquí se concentran todas las variables configurables y se proporcionan los valores predeterminados.
• main.py: El archivo principal es la entrada a los programas de entrenamiento y pruebas, se pueden especificar diferentes operaciones y parámetros a través de diferentes comandos.
• requisitos.txt: bibliotecas de terceros de las que depende el programa.
• README.md: Proporciona las instrucciones necesarias para el programa.

código fuente

Carga de fuente de datos

Agregue el AnimeFaceDataset descargado al directorio de datos y cree un nuevo dataset.py para cargar el conjunto de datos.

from torch.utils.data import Dataset,DataLoader
from torchvision import datasets, transforms
class AtomicDataset(Dataset):
    def __init__(self,root,image_size):
        Dataset.__init__(self)
        self.dataset=datasets.ImageFolder(root,
                           transform=transforms.Compose([
                               transforms.Resize(image_size),
                               transforms.CenterCrop(image_size),
                               transforms.ToTensor(),
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
                           ]))
    def __getitem__(self,index):
        return self.dataset[index]
    def __len__(self):
        return len(self.dataset)

    def toBatchLoader(self,batch_size):
        return DataLoader(self,batch_size=batch_size, shuffle=False)

Definir clase de configuración

config.py define la clase de configuración

class Config:
    #定义转换后图像的大小
    img_size=64
    #训练图片所在目录,目录必须是有子目录,子目录名称就是分类名
    img_root="./data/AnimeFaceDataset"
    #每次加载的批次数
    batch_size=64
    """
    在卷积神经网络中,这些缩写通常表示以下含义:
        nz:表示输入噪声向量的维度。全称为"noise dimension",即噪声维度。
        ngf:表示生成器网络中特征图的通道数。全称为"number of generator features",即生成器特征图通道数。
        nc:表示输入图像的通道数。全称为"number of image channels",即图像通道数。
    """
    #表示噪声的维度,一般是(100,1,1)
    nz=100
    #表示生成特征图的维度,64*64的图片
    ngf=64
    #生成或者传入图片的通道数
    nc=3
    # 表示判别器输入特征图的维度,64*64的图片
    ndf = 64
    # 优化器的学习率
    lr = 0.0002
    # Beta1 hyperparam for Adam optimizers
    beta1 = 0.5
    # epochs的次数
    num_epochs=50
    def __init__(self,kv):
        for key, value in kv.items():
            setattr(self, key, value)

Dado que estas configuraciones son estáticas de forma predeterminada, puede usar fire para definir parámetros en la línea de comando, a través de

python main.py 函数名 --参数值1=值1 --参数值2=值2的方式传入到**kwargs

main.py define el método de tren

def train(**kwargs):
	print(kwargs)
if __name__ == "__main__":
    # 将main.py中所有的函数映射成  python main.py 方法名 --参数1=参数值 --参数2=参数值的形式,这些参数以keyvalue字典的形式传入kwargs
    fire.Fire()

Definir modelo

Cree un nuevo models.py en el directorio de modelos para definir los modelos G y D

import torch.nn as nn
"""
nn.ConvTranspose2d的参数包括:
    in_channels:输入通道数
    out_channels:输出通道数
    kernel_size:卷积核大小
    stride:步长
    padding:填充大小
    output_padding:输出填充大小
    groups:分组卷积数量,默认为1
    bias:是否使用偏置,默认为True
  生成器的目标是从一个随机噪声向量生成逼真的图像。在生成器中,通道数从大到小可以理解为从抽象的特征逐渐转化为具体的图像细节。通过逐层转置卷积(ConvTranspose2d)操作,
将低维度的特征逐渐转化为高维度的图像。通道数的减少可以理解为对特征进行提取和压缩,以生成更具细节和逼真度的图像。
"""
#生成网络
class Generator(nn.Module):
    def __init__(self, nz,ngf,nc):
        super(Generator, self).__init__()
        self.main = nn.Sequential(
            # nz表示噪声的维度,一般是(100,1,1)
            # ngf表示生成特征图的维度
            # nc表示输入或者输出图像的维度
            #输出尺寸 = (输入尺寸(高度) - 1) * stride - 2 * padding + kernel_size + output_padding
            #如果(卷积核,步长,填充)=(4, 1, 0)表示图像的维度是卷积核的大小(卷积核高,卷积核宽)
            #如果(卷积核,步长,填充)=(4, 2, 1)表示图像的维度是是上一个图像的2被(输入图像高度*2,输入图像宽度*2)
            nn.ConvTranspose2d(nz, ngf * 8, 4, 1, 0, bias=False),
            nn.BatchNorm2d(ngf * 8),
            nn.ReLU(True),
            # state size. (ngf*8) x 4 x 4
            nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 4),
            nn.ReLU(True),
            # state size. (ngf*4) x 8 x 8
            nn.ConvTranspose2d(ngf * 4, ngf * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 2),
            nn.ReLU(True),
            # state size. (ngf*2) x 16 x 16
            nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf),
            nn.ReLU(True),
            # state size. (ngf) x 32 x 32
            nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False),
            nn.Tanh()
            # state size. (nc) x 64 x 64
        )

    def forward(self, input):
        return self.main(input)

"""
    和转置卷积相反的是(4,2,1)会让维度2倍降低
    卷积过程是height-kerel+1
"""
class Discriminator(nn.Module):
    def __init__(self, nc,ndf):
        super(Discriminator, self).__init__()
        self.main = nn.Sequential(
            # input is (nc) x 64 x 64
            nn.Conv2d(nc, ndf, 4, 2, 1, bias=False),
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf) x 32 x 32
            nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ndf * 2),
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf*2) x 16 x 16
            nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ndf * 4),
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf*4) x 8 x 8
            nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ndf * 8),
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf*8) x 4 x 4
            nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False),
            nn.Sigmoid()
            # state size (1,1,1)
        )

    def forward(self, input):
        return self.main(input)

tren

Entrene el modelo D y compare los datos de salida con 1 para calcular la pérdida y minimizar la pérdida. Utilice la predicción del modelo D para comparar los datos generados por G con 0 (no se puede engañar) para calcular la pérdida y minimizar la pérdida.
Entrene el modelo G, genere imágenes, use el modelo D para predecir y compare la pérdida con 1 (engañe al modelo D) para minimizar la pérdida.

def train(**kwargs):
    # 通过传入的参数初始化Config
    defaultConfig = Config(kwargs)
    # 通过给定的目录和图像大小转换成数据集
    dataset = AtomicDataset(defaultConfig.img_root, defaultConfig.img_size)
    # 转换为可迭代的批次为defaultConfig.batch_size的数据集
    dataloader = dataset.toBatchLoader(defaultConfig.batch_size)
    # 创建生成网络模型
    netG = Generator(defaultConfig.nz, defaultConfig.ngf, defaultConfig.nc).to(device)
    # 创建分类器模型
    netD = Discriminator(defaultConfig.nc, defaultConfig.ndf).to(device)
    # 使用criterion = nn.BCELoss()
    criterion = nn.BCELoss()
    # Setup Adam optimizers for both G and D
    optimizerD = optim.Adam(netD.parameters(), lr=defaultConfig.lr, betas=(defaultConfig.beta1, 0.999))
    optimizerG = optim.Adam(netG.parameters(), lr=defaultConfig.lr, betas=(defaultConfig.beta1, 0.999))
    # 如果是真的图片label=1,伪造的图片为0
    real_label = 1
    fake_label = 0
    # Lists to keep track of progress
    img_list = []
    G_losses = []
    D_losses = []
    iters = 0
    #生成一个64批次100*1*1的噪声
    fixed_noise = torch.randn(64, defaultConfig.nz, 1, 1, device=device)

    print("Starting Training Loop...")
    # For each epoch
    for epoch in range(defaultConfig.num_epochs):
        # For each batch in the dataloader
        for i, data in enumerate(dataloader, 0):

            ############################
            # (1) Update D network: maximize log(D(x)) + log(1 - D(G(z)))
            # 对于真实传入的图片进行判断器训练,label肯定是1
            # 对于噪声传入的图片进行判断器训练,label肯定是0
            ###########################
            ## 通过真实图片训练D网络
            netD.zero_grad()
            # 将64批次数据转换为gpu设备
            real_cpu = data[0].to(device)
            # 获取批次的个数
            b_size = real_cpu.size(0)
            # 生成的是一个一维的张量,其中包含64个元素,每个元素的值为1。
            label = torch.full((b_size,), real_label, device=device).float()
            # 分类器捲積后最后产生一个64个批次的1*1,转换成1维数组。
            output = netD(real_cpu).view(-1)
            # 计算和真实数据的损失
            errD_real = criterion(output, label)
            # 反向传播计算梯度
            errD_real.backward()
            # D_x的值表示判别器对真实样本的平均预测概率
            D_x = output.mean().item()

            ## 通过噪声训练生成器模型
            # 生成噪声的变量 也是64批次,噪声的通道数是100
            noise = torch.randn(b_size, defaultConfig.nz, 1, 1, device=device)
            # 传入到生成网络中,生成一张64*3*64*64的图片
            fake = netG(noise)
            # 生成器生成的图片对应的真实的label应该是0
            label.fill_(fake_label)
            # detach()是PyTorch中的一个函数,它用于从计算图中分离出一个Tensor。当我们调用detach()函数时,它会返回一个新的Tensor,该Tensor与原始Tensor共享相同的底层数据,但不会有梯度信息。
            # 使用判别器网络来判断通过噪声生成的图片,转换为1维
            output = netD(fake.detach()).view(-1)
            # 进行损失函数计算
            errD_fake = criterion(output, label)
            # 反向传播计算梯度
            errD_fake.backward()
            # 表示判别器对虚假样本的平均预测概率
            D_G_z1 = output.mean().item()
            # 将真实图片和虚假图片的损失求和获取所有的损失
            errD = errD_real + errD_fake
            # 更新权重参数
            optimizerD.step()

            ############################
            # (2) Update G network: maximize log(D(G(z)))
            # 对于G网络来说,对于虚假传入的图片进行判断器训练,尽量让判别器认为是真1,生成的图片才够真实
            ###########################
            netG.zero_grad()
            label.fill_(real_label)  # fake labels are real for generator cost
            # 使用之前的G网络生成的图片64*3*64*64,传入D网络
            output = netD(fake).view(-1)
            # 计算G网路的损失
            errG = criterion(output, label)
            # 反向计算梯度
            errG.backward()
            #表示判别器对虚假样本判断为真的的平均预测概率
            D_G_z2 = output.mean().item()
            # 更新G的权重
            optimizerG.step()

            # 输出训练统计,每1000批次
            if i % 1000 == 0:
                print('[%d/%d][%d/%d]\tLoss_D: %.4f\tLoss_G: %.4f\tD(x): %.4f\tD(G(z)): %.4f / %.4f'
                      % (epoch, defaultConfig.num_epochs, i, len(dataloader),
                         errD.item(), errG.item(), D_x, D_G_z1, D_G_z2))

            # Save Losses for plotting later
            G_losses.append(errG.item())
            D_losses.append(errD.item())

            # 即每经过一定数量的迭代(iters % 250 == 0)或者是训练的最后一个epoch的最后一个batch((epoch == defaultConfig.num_epochs - 1) and (i == len(dataloader) - 1)),
            # 就会使用G网络通过噪声生成64批次3通道64*64的图像,并且加入到img_list去做可视化,看看效果
            if (iters % 250 == 0) or ((epoch == defaultConfig.num_epochs - 1) and (i == len(dataloader) - 1)):
                with torch.no_grad():
                    fake = netG(fixed_noise).detach().cpu()
                img_list.append(vutils.make_grid(fake, padding=2, normalize=True))

            iters += 1
    #保存生成器的网络到checkpoints目录
    torch.save(netG.state_dict(), "./checkpoints/optimizerG.pt")

Visualización

perder empate

    #绘制G和D的损失函数图像
    plt.figure(figsize=(10, 5))
    plt.title("Generator and Discriminator Loss During Training")
    #一维数组的索引值是x坐标也就是批次索引
    plt.plot(G_losses, label="G")
    plt.plot(D_losses, label="D")
    plt.xlabel("iterations")
    plt.ylabel("Loss")
    plt.legend()
    plt.show()

Insertar descripción de la imagen aquí

Dibujar cambios de imagen del generador

    #创建一个8*8的画布
    fig = plt.figure(figsize=(8, 8))
    plt.axis("off")
    ims = [[plt.imshow(np.transpose(i, (1, 2, 0)), animated=True)] for i in img_list]
    ani = animation.ArtistAnimation(fig, ims, interval=1000, repeat_delay=1000, blit=True)
    HTML(ani.to_jshtml())

Cada 250 iteraciones, se generan 64 imágenes a través de G, y se descubre que las imágenes se vuelven más claras hacia atrás.
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí

otros proyectos

CicloGAN

Dirección de referencia: https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix

stargan

Dirección de referencia: https://github.com/yunjey/stargan

Supongo que te gusta

Origin blog.csdn.net/liaomin416100569/article/details/131620536
Recomendado
Clasificación