En la Parte 1 de esta serie, -2, un modelo básico de series de tiempo. Nos ensuciamos las manos analizando un caso de estudio real y vimos lo que Chronos-2 puede hacer nada más sacarlo de la caja, sin necesidad de formación.
Pero como señalamos al final de la Parte 1, el disparo cero no siempre es suficiente.
En los casos en que:
Es posible que sus datos no se parezcan a nada de la combinación previa al entrenamiento. El modelo sigue cometiendo errores sistemáticos. Tiene abundantes datos históricos que pueden aprovecharse. Su objetivo posterior puede estar desalineado con el objetivo para el cual se optimiza el entrenamiento de Chronos-2.
El siguiente paso natural es el ajuste fino.
En esta publicación, continuaremos con el mismo estudio de caso de demanda de electricidad en edificios de la Parte 1 y analizaremos cinco escenarios de ajuste de Chronos-2:
Adaptación de un solo edificio: cómo realizar ajustes en un solo activo. Ajuste de la cartera: cómo agrupar el historial de toda la flota para un adaptador compartido. Ajuste fino basado en covariables: cómo ajustar con señales futuras conocidas. Portafolio + covariables: cómo aprovechar la información tanto de covariables como de flota. Transferencia retenida: cómo adaptarse una vez y luego implementar en activos que el modelo nunca vio durante el ajuste.
Al final, tendrá una plantilla de trabajo para ajustar un TSFM que esté listo para adaptarse a sus propios datos.
La parte 1 de esta serie presenta cómo realizar pronósticos de Chronos-2 para escenarios univariados, multivariados, basados en covariables y de aprendizaje cruzado. Si desea utilizar Chronos-2 de fábrica, consulte la publicación aquí.
1. El estudio de caso, resumido
Repasemos rápidamente la configuración de la Parte 1.
Disponemos de un conjunto de datos sintéticos de ocho edificios comerciales que registra la demanda de electricidad por hora. La tarea que pretendemos resolver es pronosticar la carga eléctrica total con una semana de antelación, es decir, 168 horas. Contamos con un simulador físico para generar el conjunto de datos, donde la carga total se descompone en cargas de base, enchufe, iluminación y HVAC. Físicamente, las cargas de enchufes e iluminación están determinadas por los patrones de ocupación entre semana, mientras que la carga de HVAC está determinada por la temperatura exterior.
Ahora, la novedad de la Parte 2 es que simulamos un lapso de tiempo más largo para que podamos tener datos para realizar ajustes. Y mantenemos una clara separación entre los datos de ajuste y los datos de inferencia. En concreto, dividimos la línea de tiempo en cuatro ventanas contiguas:
Tren (12 semanas): 2025-03-01 a 2025-05-22, la única ventana que ve es el ajuste. Validación (1 semana): 2025-05-23 al 2025-05-29, utilizada para la selección de puntos de control y parada anticipada. Contexto de inferencia (45 días): 2025-05-30 al 2025-07-13, ventana utilizada como contexto al realizar pronósticos. El proceso de disparo cero de la Parte 1 también consumió 45 días de contexto. Prueba (1 semana): 2025-07-14 a 2025-07-20, el horizonte de pronóstico para probar el modelo ajustado.
Tenga en cuenta que el proceso de ajuste solo verá datos en el conjunto de capacitación y validación, por lo que no hay fugas en el análisis.
2. Resumen sobre ajustes y LoRA
Antes de nuestro recorrido, primero analicemos brevemente el concepto de ajuste fino y una de sus tecnologías específicas, es decir, LoRA.
2.1 ¿Qué es el ajuste fino?
El ajuste fino significa que continuamos entrenando un modelo previamente entrenado con nuestros propios datos. Efectivamente, estamos adaptando los pesos del modelo previamente entrenado de modo que comprenda y siga los patrones específicos de nuestro problema.
Específicamente para Chronos-2, es un transformador de parámetros de 120M que ya ha aprendido mucha estructura genérica de series de tiempo. Un ajuste fino nos permitiría orientar aún más su comportamiento en la dirección de nuestros datos.
¿Pero deberíamos actualizar todos los parámetros de 120M?
Probablemente no.
Esto puede resultar costoso tanto en computación como en almacenamiento. Además, en la práctica, es posible que no tengamos datos suficientes para permitir el ajuste de todos los parámetros de 120M.
Necesitamos una manera más eficiente de hacer el ajuste. Una de esas soluciones es LoRA.
2.2 ¿Qué es LoRA?
LoRA significa Adaptación de bajo rango[1]. Su idea central es simple: en lugar de actualizar las matrices de peso completo, congelamos el modelo original previamente entrenado y solo aprendemos un pequeño conjunto de parámetros adicionales que modifican ligeramente su comportamiento.
Para dar un ejemplo, supongamos que una capa en el modelo previamente entrenado contiene una matriz de peso W, con una forma de d_out x d_in, donde d_out=d_in=1024.
La actualización de la matriz de pesos implicaría:
Entonces, el tamaño de ΔW también debería ser 1024 x 1024. Si queremos realizar una actualización completa, eso significaría que actualizaremos más de un millón de parámetros entrenables.
El truco que adopta LoRA es que ΔW no se aprende como una matriz completa. En cambio, LoRA lo representa como el producto de dos matrices mucho más pequeñas:
donde A tiene una forma de rx d_in y B tiene una forma de d_out x r. Y r es el rango del adaptador. La razón por la que se le llama método de rango bajo es que r suele ser bastante pequeño, como 4, 8, 16 o 32.
Lo que esto implica es que LoRA no permite que el ajuste fino realice un cambio arbitrario de dimensión completa en W. Las actualizaciones están restringidas a un subespacio de dimensiones inferiores. Y de esa restricción es exactamente de donde proviene la eficiencia.
Esto funciona en la práctica porque muchas adaptaciones posteriores realmente no requieren cambiar el modelo en todas las direcciones posibles. A menudo, el cambio útil reside en un subespacio mucho más pequeño. LoRA explota directamente esta suposición.
En la práctica, esto nos aporta varias ventajas. Dado que tenemos muchos menos parámetros entrenables, el uso de memoria de la GPU, que es consumido por los gradientes y los estados del optimizador, se puede reducir mucho. También tenemos puntos de control más pequeños, porque no necesitamos guardar una copia completa del modelo de parámetros 120M para cada experimento; Solo guardamos el adaptador. Y reduce el riesgo de sobreajuste, especialmente cuando el conjunto de datos posteriores no es grande.
3. ¿Cómo hacer LoRA para Chronos-2?
Para hacer LoRA para el modelo Chronos-2, lo primero que debemos decidir es qué capas de Chronos-2 queremos adaptar.
Para responder a esta pregunta, primero debemos observar cómo se construye el modelo.
En la Parte 1, explicamos que Chronos-2 es un codificador Transformer organizado en torno a tres bloques de construcción:
Incorporación de un parche de entrada. Una pila de capas de atención, que alternan entre atención temporal y atención grupal. Una incrustación de parche de salida.
Nuestra configuración LoRA adapta dos de estos tres bloques:
Las proyecciones Q, K, V y O en cada capa de atención. Aquí es donde podemos ajustar cómo atiende el modelo tanto temporalmente dentro de cada serie como entre series dentro de un grupo.
En Chronos-2, cada capa de atención implica cuatro proyecciones lineales para mapear desde la entrada de la capa hasta la salida. La consulta (Q), la clave (K) y el valor (V) producen tres vistas diferentes de la entrada, luego el mecanismo de atención calcula una puntuación de similitud entre cada consulta y cada clave, y utiliza esas puntuaciones para calcular la agregación ponderada de los valores. Luego, el resultado pasa a través de la proyección de salida (O), que combina información a través de las cabezas de atención y la reforma para que coincida con las dimensiones de salida estándar de la capa.
La incorporación del parche de salida. Esto nos permite ajustar la forma en que el modelo proyecta sus estados internos en los pronósticos finales.
En código tenemos:
LORA_CONFIG = { "r": 8, "lora_alpha": 16, "target_modules": [ "self_attention.q", "self_attention.v", "self_attention.k", "self_attention.o", "output_patch_embedding.output_layer", ], }
donde lora_alpha es un factor de escala. Controla la fuerza con la que se aplica la actualización de LoRA, donde una α mayor significa una adaptación más agresiva.
En nuestro estudio actual, utilizamos la biblioteca Hugging Face peft para ajustar Chronos-2.
Ahora estamos listos para ponernos manos a la obra.
4. Cinco escenarios de ajuste
Para los siguientes experimentos, también partimos del mismo modelo base, es decir, punto de control amazon/chronos-2, con la misma configuración LoRA. Lo que cambia son los datos que exponemos a ajustes.
La métrica principal que usaremos es el error porcentual absoluto ponderado:
Con esa configuración, repasemos los cinco escenarios uno por uno.
Si aún no ha configurado el entorno Chronos adecuado, consulte la Parte 1: 4.1 Configuración del modelo Chronos-2.
4.1 Adaptación de un solo edificio
¿Podemos realizar ajustes en un activo?
Supongamos que solo nos importa un edificio, digamos el Edificio 03. Tenemos sus datos de carga históricos y queremos adaptar Chronos-2 a los patrones de este edificio en particular.
Esta sería la configuración de ajuste más sencilla. Sin covariables, sin información de cartera, solo una serie de objetivos.
Como se mencionó anteriormente, comenzamos desde el punto de control de amazon/chronos-2, dejamos el modelo base congelado y solo aprendemos un pequeño adaptador LoRA encima de él.
La API de ajuste fino de Chronos-2 espera datos de entrenamiento como una lista de diccionarios de tareas. Para nuestra tarea univariada actual de solo destino, cada diccionario solo necesita una clave: destino.
Para el Edificio 03, podemos preparar la entrada de ajuste fino de esta manera:
story_building = "Edificio 03" train_df = full_df[full_df["marca de tiempo"] < "2025-05-23"] single_building_train = train_df[ train_df["edificio"].eq(story_building) ].sort_values("marca de tiempo") train_inputs = [ { "target": single_building_train[["total_load_kw"]] .to_numpy(dtype="float32") .T } ]
La razón por la que necesitamos una "transposición" arriba es que Chronos-2 espera que la matriz objetivo tenga forma:
(num_target_series, time_steps)
Como solo tenemos un objetivo univariado, tenemos:
(1,T)
Además de los datos de entrenamiento, debemos preparar datos de validación en el mismo formato:
validation_df = full_df[full_df["marca de tiempo"] < "2025-05-30"] single_building_validation = validation_df[ validation_df["building"].eq(story_building) ].sort_values("timestamp") validation_inputs = [ { "target": single_building_validation[["total_load_kw"]] .to_numpy(dtype="float32") .T } ]
Hay dos cosas que vale la pena mencionar aquí:
En primer lugar, sólo un recordatorio: los datos de validación aquí no se utilizan para actualizar el adaptador LoRA; se utiliza para decidir qué punto de control del adaptador conservar. Es el mismo patrón que normalmente usarías para entrenar un modelo de red neuronal.
Entonces, podrás notar que validation_df no solo es del 23 al 29 de mayo, sino que también contiene todo lo anterior. Lo necesitamos porque, para hacer pronósticos, Chronos-2 necesita contexto. Según el conjunto de predicción_longitud, Chronos trata internamente las últimas horas de predicción_longitud de validation_df como el verdadero objetivo de pronóstico de validación. Los valores anteriores son el contexto.
En el caso actual, solo configuramos una tarea de validación en validation_inputs. Esto significa que efectivamente solo tenemos una ventana de pronóstico de validación, porque internamente Chronos-2 siempre usa los últimos pasos de longitud_predicción del marco de datos como ventana de destino y los pasos de longitud_contexto anteriores como contexto, SIN IMPORTAR cuántos pasos más introduzca en ese marco de datos. En otras palabras, simplemente alimentar un marco de datos de validación más largo no crea automáticamente más ventanas de validación.
En la práctica, si desea más ventanas de pronóstico de validación, por ejemplo, realizar una validación basada en ventanas móviles, necesitaríamos crear múltiples tareas de validación, cada una de las cuales finalizará en una fecha límite diferente. De esta forma, Chronos-2 validaría las últimas 168 horas de cada tarea.
Para el entrenamiento, sin embargo, realmente no necesitamos ningún tratamiento especial, ya que simplemente podemos pasarle a Chronos-2 una larga serie histórica y dejarle probar muchas ventanas de entrenamiento internamente.
Ahora podemos ajustar:
fine_tuned_model = base_model.fit( train_inputs, predict_length=168, validation_inputs=validation_inputs, finetune_mode="lora", lora_config=LORA_CONFIG, context_length=1080, # tasa de aprendizaje de ventana de contexto de 45 días = 2e-5, num_steps=1000, tamaño de lote = 32, output_dir="finetuned_models/fine_tuning_modes/single_target", finetuned_ckpt_name="punto de control", callbacks=[EarlyStoppingCallback(early_stopping_patience=6)], save_steps=25, eval_steps=25,)
Aquí, configuramos predict_length=168, de modo que el modelo esté entrenado para la misma tarea que nos interesa en el momento de la prueba, es decir, pronósticos por hora con una semana de anticipación. Además, configuramos context_length=45 * 24, que representa una ventana de contexto de 45 días. Esta es la misma longitud de contexto que usamos en la Parte 1. Finalmente, como hemos usado validation_inputs, la selección del punto de control está activada. Cada 25 pasos de entrenamiento, Chronos-2 evalúa la pérdida de validación y, si la pérdida de validación deja de mejorar durante 6 comprobaciones de validación seguidas (early_stopping_patience=6), se activará la parada anticipada y se detendrá el ajuste.
Ejecuté el trabajo de ajuste en una GPU para computadora portátil NVIDIA RTX 2000 Ada con 8 GB de VRAM. Esta carrera terminó en unos 42 segundos.
Una vez que se entrena al adaptador, la inferencia se ve casi igual que el pronóstico de tiro cero:
contexto_único = test_context_df[ test_context_df["edificio"].eq(story_building) ][["edificio", "marca de tiempo", "total_load_kw"]] pred_single_finetuned = fine_tuned_model.predict_df( contexto_único, longitud_predicción=168, niveles_cuantiles=[0.025, 0.5, 0.975], id_column="edificio", timestamp_column="timestamp", target="total_load_kw", )
Para el Edificio 03, la línea de base de tiro cero solo al objetivo tiene una WAPE del 8,3%. Después de realizar ajustes únicamente en el Edificio 03, WAPE se reduce al 7,6%. Vemos que el ajuste ha traído algunas mejoras.
4.2 Ajuste de la cartera
¿Podemos agrupar el historial de toda la flota para un adaptador compartido?
En la práctica, a menudo tenemos varios activos relacionados en una cartera.
En nuestro caso, eso significa ocho edificios. No son idénticos, pero siguen patrones de demanda diarios y semanales similares.
Entonces, la siguiente pregunta natural es: ¿podemos ajustar un adaptador en toda la cartera de edificios, en lugar de solo un edificio a la vez?
Aquí, todavía pronosticamos solo total_load_kw, esto significa que la configuración es casi la misma que antes:
target_column = "total_load_kw" train_inputs = [ { "target": building_df[[target_column]].to_numpy(dtype="float32").T, } para _, building_df en train_df.groupby("building", sort=True) ] validation_inputs = [ { "target": building_df[[target_column]].to_numpy(dtype="float32").T, } para _, building_df en validation_df.groupby("building", sort=True) ]
Efectivamente, cada edificio se convierte en una tarea de formación. Luego ajustamos Chronos-2 con la misma configuración LoRA que antes:
modelo_afinado = modelo_base.fit( entradas = entradas_entrenamiento, entradas_validación = entradas_validación, longitud_predicción = 168, longitud_contexto = 1080, lora_config = LORA_CONFIG, tasa_de_aprendizaje = 2e-5, pasos_max = 1000,)
Vale la pena enfatizar que aquí no estamos entrenando ocho adaptadores separados. En cambio, le pedimos a Chronos-2 que aprenda una adaptación compartida que funcione en toda la flota. En la práctica, si hay patrones recurrentes en los edificios, el adaptador podría tener más posibilidades de aprenderlos. Sin embargo, si cada edificio es completamente independiente, esta estrategia puede no ayudar mucho.
Las razones del ajuste se muestran a continuación, donde comparamos la calidad de pronóstico entre el Chronos-2 de disparo cero y el afinado:
Edificio WAPE de disparo cero WAPE ajustado Edificio 01 8,0% 7,4% Edificio 02 12,2% 11,3% Edificio 03 8,3% 7,5% Edificio 04 8,0% 7,6% Edificio 05 7,2% 6,8% Edificio 06 10,9% 9,9% Edificio 07 7,7% 7,2% Edificio 08 6,6% 6,3%
Vemos mejoras en todos los edificios, lo cual es una buena señal de que todos los edificios se benefician del adaptador compartido.
4.3 Ajuste fino basado en covariables
¿Podemos darle a Chronos-2 las covariables conocidas durante el ajuste fino?
Hasta ahora, Chronos-2 sólo ve la serie objetivo en sí, es decir, total_load_kw histórico.
Pero en nuestro caso de demanda de edificios, sí conocemos o podemos pronosticar razonablemente bien los factores determinantes subyacentes, incluida la temperatura exterior, el patrón de ocupación, la irradiancia solar y el indicador de fin de semana. Son las covariables que impulsan el cambio de total_load_kw.
Por lo tanto, en este escenario de ajuste, nos gustaría saber si podemos ajustar Chronos-2 no solo en el historial del objetivo, sino también en la relación entre el objetivo y las covariables futuras conocidas.
Aquí es donde se debe cambiar la entrada de ajuste fino. En lugar de solo pasar el objetivo, cada tarea de entrenamiento ahora también debería contener covariables_pasadas y covariables_futuras:
known_future_columns = [ "outdoor_temp_c", "ocupación", "solar_irradiance", "is_weekend", ] single_building_train = train_df[ train_df["building"].eq(story_building) ].sort_values("timestamp") train_inputs = [ { "target": single_building_train[["total_load_kw"]] .to_numpy(dtype="float32") .T, "past_covariates": { columna: single_building_train[columna].to_numpy(dtype="float32") para la columna enknown_future_columns }, "future_covariates": {columna: Ninguna para la columna enknown_future_columns }, } ]
La parte past_covariates contiene los valores históricos de la serie de covariables. Durante el ajuste, Chronos-2 puede ver cómo las covariables de temperatura, ocupación, irradiancia solar y fines de semana cambian la carga.
La parte Future_covariates le dice a Chronos-2 que estas covariables también están disponibles en el horizonte de pronóstico. Aquí los configuramos en Ninguno porque Chronos-2 construye las ventanas futuras internamente a partir de la misma serie histórica. Más adelante, en el momento de la inferencia, proporcionaremos los valores de covariables futuros reales a través de Future_df, tal como lo hicimos en la Parte 1.
La llamada de ajuste en sí sigue siendo casi la misma:
fine_tuned_model = base_model.fit( train_inputs, predict_length=168, validation_inputs=validation_inputs, finetune_mode="lora", lora_config=LORA_CONFIG, context_length=1080, learning_rate=2e-5, num_steps=1000, lote_size=32, salida_dir="finetuned_models/fine_tuning_modes/single_covariate", finetuned_ckpt_name="punto de control", callbacks=[EarlyStoppingCallback(early_stopping_patience=6)], save_steps=25, eval_steps=25,)
Una vez realizado el ajuste, en el momento de la inferencia, pasamos tanto el contexto histórico como las covariables futuras conocidas:
context_with_covariates = test_context_df[ ["edificio", "marca de tiempo", "carga_total_kw"] + columnas_futuras_conocidas ] futuro_covariates_df = test_truth_df[ ["edificio", "marca de tiempo"] + columnas_futuras_conocidas ] pred_single_covariate = fine_tuned_model.predict_df( contexto_con_covariables, futuro_df=future_covariates_df, predicción_longitud=168, quantile_levels=[0.025, 0.5, 0.975], id_column="edificio", timestamp_column="timestamp", target="total_load_kw", )
Para el Edificio 03, el WAPE de tiro cero informado por covariables es del 4,0%. Después de ajustar el adaptador basado en covariables en el Edificio 03, WAPE cae al 2,8%, lo que lleva a una reducción relativa del 30,7%.
Esta es una ganancia mucho mayor que el ajuste fino solo de objetivos.
Esta es también una interesante lección práctica: a veces la mayor ganancia no es el “ajuste” en sí mismo. Es afinar el modelo con la información correcta.
4.4 Cartera + covariables
¿Podemos aprovechar la información de covariables y de flota para realizar ajustes?
Los dos escenarios anteriores agregaron el ingrediente “Cartera” y el ingrediente “covariable” por separado. Naturalmente, queremos utilizar ambos.
Esta es la configuración que creo que es más relevante en muchos casos de uso reales, porque en la práctica, rara vez tenemos un solo activo y, en la mayoría de los casos, tenemos señales externas conocidas o predecibles que pueden respaldar el pronóstico de series objetivo. Usar ambos para realizar ajustes no sólo es lógico, sino que probablemente también sea preferible.
Concretamente, para nuestro caso actual, ajustamos los ocho edificios y, para cada edificio, proporcionamos total_load_kw como objetivo y outdoor_temp_c, ocupación, irradiancia solar e is_weekend como covariables futuras conocidas:
entradas_tren =[]para construir, building_df en train_df.groupby("building", sort=True): building_df = building_df.sort_values("timestamp") train_inputs.append( { "target": building_df[["total_load_kw"]] .to_numpy(dtype="float32") .T, "past_covariates": { columna: building_df[column].to_numpy(dtype="float32") para la columna enknown_future_columns }, "future_covariates": {columna: Ninguno para la columna enknown_future_columns }, })
En el fragmento de código anterior, creamos una tarea por edificio. La misma idea se aplica también a los datos de validación. Cada edificio está asociado con una tarea de validación y Chronos-2 utiliza las últimas 168 horas de cada tarea como ventana de pronóstico de validación.
La llamada de ajuste sigue siendo la misma:
fine_tuned_model = base_model.fit( train_inputs, predict_length=168, validation_inputs=validation_inputs, finetune_mode="lora", lora_config=LORA_CONFIG, context_length=1080, learning_rate=2e-5, num_steps=1000, lote_size=32, salida_dir="finetuned_models/fine_tuning_modes/portfolio_covariate", finetuned_ckpt_name="punto de control", callbacks=[EarlyStoppingCallback(early_stopping_patience=6)], save_steps=25, eval_steps=25,)
A modo de inferencia, pasamos por el contexto histórico de 45 días, así como por las covariables futuras conocidas para la semana de pronóstico:
context_with_covariates = test_context_df[ ["edificio", "marca de tiempo", "carga_total_kw"] + columnas_futuras_conocidas ] futuro_covariates_df = test_truth_df[ ["edificio", "marca de tiempo"] + columnas_futuras_conocidas ] pred_portfolio_covariate = fine_tuned_model.predict_df( contexto_con_covariables, futuro_df=future_covariates_df, predicción_longitud=168, quantile_levels=[0.025, 0.5, 0.975], id_column="edificio", timestamp_column="timestamp", target="total_load_kw", )
La siguiente figura muestra los resultados del ajuste para el Edificio 03, donde podemos ver claramente la mejora aportada por el ajuste:
En los ocho edificios, la línea de base simple de tiro cero tiene una WAPE del 8,4%. Después del ajuste de cartera + covariables, WAPE cae al 2,8%, una reducción relativa del 66,8%.
4.5 Transferencia retenida
¿Podemos adaptarnos una vez y luego implementar activos que el modelo nunca vio durante el ajuste?
Hasta ahora, cada escenario de ajuste ha utilizado los mismos edificios que aparecen más tarde en el momento de la inferencia.
Pero hay una pregunta más importante: ¿Qué pasa si un nuevo edificio entra en funcionamiento hace muy poco tiempo?
Entonces, en este escenario final, mantenemos el Edificio 06 durante el ajuste fino, para que Chronos-2 nunca vea sus datos mientras aprende el adaptador LoRA. Realizamos ajustes en los otros siete edificios, utilizando tanto historias de objetivos como covariables de futuro conocido. Luego, en el momento de la inferencia, aplicamos el adaptador al Edificio 06.
El cambio de código es pequeño:
Held_out_building = "Edificio 06" train_buildings = [ edificio para construir en sorted(train_df["edificio"].unique()) if edificio !=held_out_building ] train_inputs =[]para construir en train_buildings: building_df = train_df[ train_df["building"].eq(building) ].sort_values("timestamp") train_inputs.append( { "target": building_df[["total_load_kw"]] .to_numpy(dtype="float32") .T, "past_covariates": { columna: building_df[column].to_numpy(dtype="float32") para la columna enknown_future_columns }, "future_covariates": {columna: Ninguno para la columna enknown_future_columns }, })
Luego, en el momento de la inferencia, apuntamos al Edificio 06 para realizar pronósticos:
building_06_context = test_context_df[ test_context_df["building"].eq(held_out_building) ][["building", "timestamp", "total_load_kw"] +known_future_columns] building_06_future_covariates = test_truth_df[ test_truth_df["building"].eq(held_out_building) ][["building", "marca de tiempo"] + columnas_futuras_conocidas] pred_heldout = fine_tuned_model.predict_df( edificio_06_context, futuro_df=edificio_06_future_covariates, predicción_longitud=168, quantile_levels=[0.025, 0.5, 0.975], id_column="edificio", marca de tiempo_column="marca de tiempo", objetivo="carga_total_kw", )
Para el Edificio 06, la línea de base de tiro cero informada por covariables tiene una WAPE del 4,2%. Después de aplicar el adaptador ajustado en los otros siete edificios, WAPE cae al 3,1%. Esa es una reducción relativa del 26,8%.
Para una implementación real, nuestra investigación actual del quinto trimestre representa un patrón más escalable, es decir, ajustamos un adaptador en una cartera representativa y luego lo implementamos en activos relacionados a medida que se conectan. Para cada nuevo activo, todavía proporcionamos su contexto reciente y sus covariables futuras conocidas, pero no tenemos que volver a realizar ajustes inmediatamente. De todos modos, no tendremos suficientes datos para eso.
5. ¿Qué aprendimos?
Después de analizar los cinco escenarios uno por uno, pongamos los resultados uno al lado del otro.
Para cada fila, comparo el modelo ajustado con la línea de base de tiro cero correspondiente. Concretamente, eso significa que el ajuste fino de solo objetivo se compara con el disparo cero solo de objetivo, y el ajuste fino informado por covariables se compara con el disparo cero informado por covariables:
El patrón es bastante claro. El ajuste fino del objetivo ayuda hasta cierto punto, pero sólo modestamente. Las mayores ganancias aparecen cuando le damos a Chronos-2 las covariables futuras conocidas y luego ajustamos el adaptador en torno a eso. El resultado de la transferencia retenida también es alentador: incluso para un edificio excluido del ajuste fino, el adaptador puede aprender de los edificios relacionados y aun así mejorar con respecto a la línea de base de tiro cero informada por covariables.
Puede encontrar el cuaderno completo aquí: https://github.com/ShuaiGuo16/chronos-2-forecasting/blob/main/02_chronos2_fine_tuning_building_demand.ipynb
Referencia
[1]LoRA: adaptación de bajo rango de modelos de lenguaje grandes. arXiv, 2021.