Implementación de un Pequeño Proyecto de Clasificación de Imágenes con el Framework CANN

Introducción al Proyecto y Selección de Componentes

Este proyecto desarrolla un sistema de clasificación de imágenes para frutas comunes (manzana, plátano, naranja) aprovechando la aceleración de cómputo heterogéneo que ofrece la arquitectura CANN (Compute Architecture for Neural Networks) de Huawei. El objetivo principal es guiar al desarrollador a través de un flujo de trabajo completo y simplificado, familiarizándolo con los pasos esenciales de adaptación de modelos, conversión de formatos e implementación de la inferencia en hardware Ascend. El sistema acepta una imagen de entrada y devuelve la categoría predicha con su nivel de confianza.

Las decisiones técnicas clave para un proyecto de esta escala se resumen en la siguiente tabla:

Componente Elección Justificación
Plataforma de Desarrollo CANN 7.x Entorno de toolkit estable con documentación madura y buenas herramientas de depuración.
Hardware Objetivo Ascend 310B (ej. Atlas 200I DK A2) Una unidad de procesamiento neuronal (NPU) de nivel de entrada, ideal para experimentación y aplicaciones de borde ligeras.
Arquitectura del Modelo MobileNetV2 Modelo pre-entrenado y ligero, excelente para el despliegue en dispositivos con recursos limitados y fácil de adaptar.
Conjunto de Datos Datos propios de frutas (3 clases) Control total sobre los datos, simplificando el preprocesamiento. Un tamaño reducido (p.ej., 600 imágenes) permite iteraciones rápidas.
Precisión Esperada >90% Meta realista para una demostración funcional con un conjunto de datos pequeño y un modelo base.

Configuración del Entorno de Desarrollo y Ejecución

La preparación del entorno es un paso crítico. Se requieren dos configuraciones principales: el host de desarrollo (PC) y el dispositivo objetivo (tarjeta Ascend). A continuación se detallan las dependencias core y los comandos de verificación:

Entorno Instalación Principal Verificación Salida Esperada
Host de Desarrollo 1. Instalar Python 3.8+. 2. Instalar el driver de Ascend. 3. Instalar el toolkit de CANN. python3 -c "import acl; print(acl.__version__)" Número de versión del toolkit (ej. 7.0.RC1)
Dispositivo Objetivo 1. Grabar la imagen oficial del firmware. 2. Instalar el driver y el runtime de CANN. npu-smi info El estado de la NPU se muestra como "OK".

Para las dependencias del proyecto, se recomienda usar un entorno virtual. Las librerías esenciales incluyen torch, torchvision y el toolkit de CANN.

# Crear y activar el entorno virtual
python3 -m venv cann_project_env
source cann_project_env/bin/activate

# Instalar librerías necesarias
pip install torch==1.12.1 torchvision==0.13.1 opencv-python-headless numpy ascend-cann-toolkit

Preparación de los Datos para la Inferencia

Los datos deben organizarse en una estructura de directorios que permita su carga sencilla. La jerarquía es:

dataset_frutas/
├── entrenamiento/
│   ├── manzana/
│   ├── platano/
│   └── naranja/
├── validacion/
│   ├── manzana/
│   ├── platano/
│   └── naranja/
└── prueba/
    ├── manzana/
    ├── platano/
    └── naranja/

El preprocesamiento es idéntico para todas las imágenes: convertir a RGB, redimensionar a 224x224 píxeles y normalizar los valores de los canales con la media y desviación estándar de ImageNet. Una función que encapsula estos pasos podría verse así:

import cv2
import numpy as np
from torchvision import transforms

def preparar_imagen_para_modelo(ruta_imagen):
    # Cargar imagen en formato BGR de OpenCV y convertir a RGB
    img_bgr = cv2.imread(ruta_imagen)
    img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
    
    # Definir la cadena de transformaciones
    transformaciones = transforms.Compose([
        transforms.ToPILImage(),
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])
    
    # Aplicar transformaciones y obtener tensor
    tensor_img = transformaciones(img_rgb)
    
    # Añadir dimensión de lote (batch) y convertir a numpy array
    array_np = tensor_img.unsqueeze(0).numpy()
    return array_np.astype(np.float32)

Adaptación, Entrenamiento y Conversión del Modelo

El modelo base (MobileNetV2) se adapta reemplazando su capa final de clasificación por una adecuada para nuestras 3 clases. Durante el entrenamiento, solo se ajustan los parámetros de esta nueva capa, manteniendo el "backbone" (extracción de características) congelado.

import torch
import torch.nn as nn
from torchvision import models

# Cargar modelo pre-entrenado y modificar la capa de clasificación
modelo_base = models.mobilenet_v2(pretrained=True)

# Congelar los parámetros de todas las capas excepto la nueva
for nombre, parametro in modelo_base.named_parameters():
    parametro.requires_grad = False

# Reemplazar la última capa densa
num_clases = 3
capa_clasificador = modelo_base.classifier[1]
modelo_base.classifier[1] = nn.Linear(capa_clasificador.in_features, num_clases)

# Configurar optimizador (solo para los parámetros de la nueva capa)
optimizador = torch.optim.Adam(modelo_base.classifier[1].parameters(), lr=0.001)
funcion_perdida = nn.CrossEntropyLoss()

El flujo de conversión del modelo requiere dos pasos:

  1. Exportar a formato ONNX: Se crea un tensor de entrada ficticio y se utiliza torch.onnx.export para generar el archivo modelo_frutas.onnx.
  2. Convertir a formato OM: Se usa la herramianta de línea de comandos ATC (Ascend Tensor Compiler). Es crucial especificar correctamente la versión del SoC (System on Chip) de la NPU objetivo.
# Ejemplo de comando de conversión con ATC
atc --model=modelo_frutas.onnx \
    --framework=5 \
    --output=modelo_frutas_convertido \
    --soc_version=Ascend310B \
    --input_format=NCHW \
    --input_shape="input:1,3,224,224" \
    --log=info

Este proceso genera el archivo modelo_frutas_convertido.om, que es el binario ejecutable en la NPU.

Implementación del Motor de Inferencia con AscendCL

La inferencia se gestiona mediante la API de bajo nivel de AscendCL. El flujo de ejecución implica gestionar el ciclo de vida del contexto, los buffers de memoria en el dispositivo y los flujos de datos entre el host (CPU) y el dispositivo (NPU).

Los pasos fundamentales en el código de inferencia son:

  1. Inicialización: Inicializar la librería AscendCL y crear un contexto de ejecución para un dispositivo específico.
  2. Carga del Modelo: Cargar el archivo OM en memoria y crear una instancia del modelo lista para ejecutarse.
  3. Preparación de Datos: Asignar memoria en el dispositivo (NPU) para los tensores de entrada y salida, y copiar los datos preprocesados desde la memoria del host.
  4. Ejecución: Invocar la función de inferencia del modelo con los datasets de entrada y salida preparados.
  5. Post-procesamiento: Copiar los resultados de vuelta a la memoria del host, aplicar la función softmax para obtener probabilidades e identificar la clase con mayor puntuación.
  6. Limpieza: Liberar todos los recursos asignados (memoria del dispositivo, instancias del modelo, contexto).

La gestión de memoria es crucial para la estabilidad. Una estrategia de reutilización de bufffers para las entradas y salidas puede mejorar el rendimiento en escenarios de inferencia continua.

Validación y Opciones de Optimización

La validación inicial se realiza con un subconjunto de imágenes de prueba. Un resultado típico para un modelo bien ajustado con datos limitados es una precisión del 90%. Los errores comunes suelen deberse a imágenes ambiguas, lo que sugiere que se podría mejorar mediante un aumento de datos más agresivo o la recopilación de más ejemplos representativos.

Para optimizar el rendimiento de inferencia en este contexto pequeño, se pueden considerar las siguientes tácticas:

  • Inferencia por Lotes (Batch): Procesar múltiples imágenes simultáneamente en lugar de una por una, amortizando así el costo de la carga del modelo y la asignación de memoria.
  • Cuantización: Convertir el modelo de precisión flotante (FP32) a entero de 8 bits (INT8) usando las herramientas de cuantización de CANN. Esto generalmente acelera la inferencia y reduce el consumo de memoria, a costa de una ligera posible pérdida de precisión que debe evaluarse.

Este proyecto proporciona una base sólida. Los próximos pasos podrían incluir la integración con un framwork web para crear una API, o el despliegue directo en dispositivos de borde más potentes como los de la serie Atlas.

Etiquetas: CANN AscendCL MobileNetV2 HUAWEI Ascend ONNX

Publicado el 7-16 10:56