Importar pesos existentes
LibreYOLO porta sus familias de modelos desde proyectos upstream, así que los checkpoints que estos publican ya son casi cargables. Lo que les falta son los metadatos. La autoconversión los aporta en el momento de la carga.
- Punto de entrada
LibreYOLO("path/to/upstream.pth")- Se escribe junto al origen como
<source>-<Prefix><size>[-task].pt- Conversores en script
weights/ en el repositorio
Esta página trata sobre checkpoints de otros proyectos. Si lo que estás moviendo es tu propio código desde un LibreYOLO más antiguo, consulta actualizar a 1.5.0.
Qué ocurre al cargar un archivo ajeno
LibreYOLO() carga cualquier archivo de pesos pasando primero por la ruta
restringida de solo pesos. Si el resultado lleva metadatos completos de
LibreYOLO, se usa directamente. Si no los lleva, el archivo pasa al
autoconversor antes de intentar nada más. Si la carga restringida falla del
todo, algo que ocurre cuando un checkpoint tiene un objeto de terceros
serializado dentro, se prueba el autoconversor con un cargador que neutraliza
esos objetos.
La autoconversión hace cuatro cosas. Desempaqueta el diccionario de tensores del layout que haya usado el proyecto upstream. Pregunta a cada familia registrada si reconoce las claves resultantes, remapeando nombres allí donde la nomenclatura upstream difiere de la del port de LibreYOLO. Envuelve a la ganadora en un checkpoint que cumple la versión 1.0 del esquema de metadatos, leyendo el tamaño, la tarea y el número de clases de los propios tensores. Después escribe el resultado junto al archivo de origen y carga ese.
from libreyolo import LibreYOLO # Sustituye la ruta por la de un checkpoint que ya tengas. Un layout# upstream reconocido se convierte sobre la marcha, se escribe junto# al origen y luego se carga.model = LibreYOLO("path/to/upstream-checkpoint.pth") # El número de clases y los nombres salen de los tensores y de los# metadatos del propio archivo, así que un fine-tune conserva su# conjunto de etiquetas en lugar del de COCO.print(model.family, model.size, model.task, model.nb_classes)print(model.names)libreyolo predict model=path/to/upstream-checkpoint.pth \ source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpg# El archivo convertido cumple el mismo esquema que uno publicado.libreyolo metadata path=path/to/upstream-checkpoint-LibreYOLO9t.ptLa conversión no es silenciosa. Un archivo convertido se registra en el log con la familia, el nombre de origen, el nombre de salida y el número de clases resultante, de modo que el log de una ejecución deja constancia exacta de qué se cargó.
Los layouts que desempaqueta
Los checkpoints upstream anidan sus pesos en un puñado de sitios convencionales,
y el conversor los prueba en orden hasta que uno contiene tensores: un bloque EMA
bajo ema.module o un ema plano, un ema_state_dict con su prefijo module.
eliminado, después params_ema, params, ema_net, net, model,
state_dict y, por último, el objeto en sí. Probar varios en lugar de solo el
primero implica que un bloque ema que solo contenga contadores no oculte los
pesos reales que hay debajo.
Los prefijos de envoltura también se quitan: module. del entrenamiento
distribuido, _orig_mod. de un modelo compilado y un anidamiento model.model.
que añaden algunas redistribuciones.
Qué lee, y de dónde
El tamaño, la tarea y el número de clases salen de los tensores, no del nombre
del archivo, que es la razón por la que un checkpoint con fine-tuning se
convierte con su propio número de clases en lugar de con el valor por defecto de
la arquitectura. Los nombres de las clases se toman de los metadatos del propio
checkpoint cuando están presentes, de un bloque args o hyper_parameters si
los nombres están ahí, y se recortan al número de clases detectado para que un
fine-tune que haya conservado su conjunto de etiquetas base no arrastre índices
que su cabeza ya no tiene.
Las tareas densas se tratan de forma explícita en lugar de asignarles etiquetas
inventadas. Un checkpoint de profundidad recibe una clase llamada depth; uno de
restauración, una clase llamada image. Un checkpoint de pose tiene que aportar
un número de keypoints, ya sea desde los tensores o desde la familia; si ninguno
de los dos lo produce, se rechaza la conversión en lugar de escribir un archivo
incompleto.
RF-DETR tiene su propio reconocedor, porque la detección del tamaño necesita el checkpoint entero y porque su cabeza tiene 91 salidas donde LibreYOLO usa la convención COCO de 80 clases. Un checkpoint se normaliza a 80 clases cuando lleva exactamente 80 nombres, o declara un número de clases de 80, o menciona COCO como su dataset, o no lleva ningún metadato de clases ni de dataset. Un modelo de 90 clases auténtico, identificado por sus nombres, por un número explícito distinto de 80 o por una pista de dataset que no sea COCO, se conserva tal cual.
Dónde va el archivo convertido
La salida se escribe junto al origen, con el nombre tomado de él:
<source stem>-<FilenamePrefix><size>[-<task suffix>].ptUn detector YOLOv9 tiny guardado como upstream-checkpoint.pth pasa a ser, por
tanto, upstream-checkpoint-LibreYOLO9t.pt. Nombrarlo según el origen en lugar
de según la familia implica que dos fine-tunes de la misma familia y el mismo
tamaño en un mismo directorio no se sobrescriben entre sí, y que ninguno choca
con un checkpoint oficial. El archivo se reescribe en cada carga, así que nunca
queda desfasado respecto a su origen. Si el directorio es de solo lectura, el
archivo convertido va a un directorio temporal privado y recién creado, y el log
dice dónde.
A partir de ahí es un checkpoint de LibreYOLO corriente: se carga por la ruta de
metadatos, y libreyolo metadata lo da por válido.
Casos que necesitan ayuda
Dos familias quedan fuera del reconocedor genérico. La familia de mirada (gaze) está excluida por completo: es solo de inferencia y los pesos que publica llevan restricciones de redistribución. RF-DETR está excluida porque tiene el reconocedor dedicado descrito más arriba, que es lo que se encarga de ella en su lugar.
Los checkpoints PIDNet upstream en crudo se rechazan, con un error que apunta a
weights/convert_pidnet_weights.py. Ese script escribe los metadatos semánticos
de Cityscapes que el checkpoint necesita.
D-FINE y DEIM comparten las mismas claves de arquitectura, así que los tensores
por sí solos no permiten distinguirlos. Cuando ambas reclaman un archivo y no hay
en juego ninguna familia hermana con un marcador diferenciador, decide el nombre
del archivo: un nombre con la forma de dfine_hgnetv2_n_coco.pth o
deim_hgnetv2_n_coco.pth lo zanja, y un nombre que no dice nada se rechaza con
esa explicación en lugar de adivinarlo. Instanciar LibreDFINE o LibreDEIM
directamente también lo resuelve.
Cuando varias familias reclaman legítimamente un mismo archivo, una subclase gana a la clase base que refina, y el orden del registro decide el resto, ya que ese orden codifica cuán específica es la comprobación de cada familia. El nombre del archivo solo se consulta para el empate entre D-FINE y DEIM, de modo que el nombre de un archivo nunca puede anteponer una coincidencia amplia a una precisa.
Los conversores en script
El repositorio incluye scripts de conversión por familia bajo weights/, además
de helpers compartidos para la fontanería repetida. Son la vía para un archivo
que la ruta en tiempo de ejecución rechaza, para producir un checkpoint por
adelantado en lugar de en el momento de la carga, y para las familias cuyos
metadatos hay que aportar en lugar de inferirlos de los tensores.
Esos scripts forman parte del repositorio, no del paquete instalado, así que usar uno implica clonarlo:
git clone https://github.com/LibreYOLO/libreyolo.git
cd libreyolo
python weights/convert_pidnet_weights.py --helpTodos los scripts escriben un checkpoint que cumple la versión 1.0 del esquema, que es el mismo listón que alcanza la autoconversión y el mismo que alcanzan los pesos publicados. Consulta checkpoints y pesos para saber qué contiene ese esquema.