Las distribuciones son las más utilizadas, muchos datos del mundo real desafortunadamente no son normales. Cuando nos enfrentamos a datos extremadamente sesgados, es tentador utilizar transformaciones de registro para normalizar la distribución y estabilizar la varianza. Recientemente trabajé en un proyecto que analizó el consumo de energía de los modelos de IA de capacitación, utilizando datos de Epoch AI [1]. No hay datos oficiales sobre el uso de energía de cada modelo, por lo que lo calculé multiplicando el sorteo de potencia de cada modelo con su tiempo de entrenamiento. La nueva variable, Energy (en KWH), era muy sesgada derecha, junto con algunos valores atípicos extremos y sobredisperados (Fig. 1).
Para abordar esta asimetría y heterocedasticidad, mi primer instinto fue aplicar una transformación de registro a la variable de energía. La distribución de log (energía) parecía mucho más normal (Fig. 2), y una prueba de Shapiro-Wilk confirmó la normalidad límite (P ≈ 0.5).
Modelado de dilema: transformación de registro vs enlace de registro
La visualización se veía bien, pero cuando pasé al modelado, me enfrenté a un dilema: ¿debería modelar el variable de respuesta transformada log (log(Y) ~ X), o debería modelar el Variable de respuesta original usando un función de enlace de registro (Y ~ X, link = “log")? También consideré dos distribuciones: distribuciones gaussianas (normales) y gamma, y combiné cada distribución con ambos enfoques de registro. Esto me dio cuatro modelos diferentes como a continuación, todos instalados utilizando los modelos lineales generalizados de R (GLM):
all_gaussian_log_link <- glm(Energy_kWh ~ Parameters +
Training_compute_FLOP +
Training_dataset_size +
Training_time_hour +
Hardware_quantity +
Training_hardware,
family = gaussian(link = "log"), data = df)
all_gaussian_log_transform <- glm(log(Energy_kWh) ~ Parameters +
Training_compute_FLOP +
Training_dataset_size +
Training_time_hour +
Hardware_quantity +
Training_hardware,
data = df)
all_gamma_log_link <- glm(Energy_kWh ~ Parameters +
Training_compute_FLOP +
Training_dataset_size +
Training_time_hour +
Hardware_quantity +
Training_hardware + 0,
family = Gamma(link = "log"), data = df)
all_gamma_log_transform <- glm(log(Energy_kWh) ~ Parameters +
Training_compute_FLOP +
Training_dataset_size +
Training_time_hour +
Hardware_quantity +
Training_hardware + 0,
family = Gamma(), data = df)
Comparación de modelos: AIC y diagramas de diagnóstico
Comparé los cuatro modelos utilizando el Criterio de información de Akaike (AIC), que es un estimador de error de predicción. Por lo general, cuanto más bajo sea la AIC, mejor se ajusta el modelo.
AIC(all_gaussian_log_link, all_gaussian_log_transform, all_gamma_log_link, all_gamma_log_transform)
df AIC
all_gaussian_log_link 25 2005.8263
all_gaussian_log_transform 25 311.5963
all_gamma_log_link 25 1780.8524
all_gamma_log_transform 25 352.5450
Entre los cuatro modelos, los modelos que utilizan resultados transformados log tienen valores AIC mucho más bajos que los que usan enlaces de registro. Dado que la diferencia en AIC entre los modelos de enlace logarítmico y de enlace log fue sustancial (311 y 352 frente a 1780 y 2005), también examiné los gráficos de diagnóstico para validar aún más que los modelos transformados log se ajustan mejor:
Según los valores de AIC y los gráficos de diagnóstico, decidí avanzar con el modelo gamma transformado log, ya que tenía el segundo valor AIC más bajo y su trama residual vs ajustado se ve mejor que el del modelo gaussiano transformado log.
Procedí a explorar qué variables explicativas fueron útiles y qué interacciones pueden haber sido significativas. El modelo final que seleccioné fue:
glm(formula = log(Energy_kWh) ~ Training_time_hour * Hardware_quantity +
Training_hardware + 0, family = Gamma(), data = df)
Interpretando coeficientes
Sin embargo, cuando comencé a interpretar los coeficientes del modelo, algo se sentía. Dado que solo la variable de respuesta se transformó log, los efectos de los predictores son multiplicativos y necesitamos exponenciar los coeficientes para convertirlos nuevamente a la escala original. Un aumento de una unidad en 𝓍 multiplica el resultado 𝓎 por EXP (β), o cada unidad adicional en 𝓍 conduce a un cambio (EXP (β)-1) × 100 % en 𝓎 [2].
Mirando la tabla de resultados del modelo a continuación, tenemos Entrenador_time_hour, hardware_quantity, y su término de interacción Entrenador_time_hour: hardware_quantity son variables continuas, por lo que sus coeficientes representan pendientes. Mientras tanto, ya que especifiqué +0 en la fórmula del modelo, todos los niveles de la categórica Entrenador_hardware actúe como intercepciones, lo que significa que cada tipo de hardware actuó como la intercepción β₀ cuando su variable ficticia correspondiente estaba activa.
> glm(formula = log(Energy_kWh) ~ Training_time_hour * Hardware_quantity +
Training_hardware + 0, family = Gamma(), data = df)
Coefficients:
Estimate Std. Error t value Pr(>|t|)
Training_time_hour -1.587e-05 3.112e-06 -5.098 5.76e-06 ***
Hardware_quantity -5.121e-06 1.564e-06 -3.275 0.00196 **
Training_hardwareGoogle TPU v2 1.396e-01 2.297e-02 6.079 1.90e-07 ***
Training_hardwareGoogle TPU v3 1.106e-01 7.048e-03 15.696 < 2e-16 ***
Training_hardwareGoogle TPU v4 9.957e-02 7.939e-03 12.542 < 2e-16 ***
Training_hardwareHuawei Ascend 910 1.112e-01 1.862e-02 5.969 2.79e-07 ***
Training_hardwareNVIDIA A100 1.077e-01 6.993e-03 15.409 < 2e-16 ***
Training_hardwareNVIDIA A100 SXM4 40 GB 1.020e-01 1.072e-02 9.515 1.26e-12 ***
Training_hardwareNVIDIA A100 SXM4 80 GB 1.014e-01 1.018e-02 9.958 2.90e-13 ***
Training_hardwareNVIDIA GeForce GTX 285 3.202e-01 7.491e-02 4.275 9.03e-05 ***
Training_hardwareNVIDIA GeForce GTX TITAN X 1.601e-01 2.630e-02 6.088 1.84e-07 ***
Training_hardwareNVIDIA GTX Titan Black 1.498e-01 3.328e-02 4.501 4.31e-05 ***
Training_hardwareNVIDIA H100 SXM5 80GB 9.736e-02 9.840e-03 9.894 3.59e-13 ***
Training_hardwareNVIDIA P100 1.604e-01 1.922e-02 8.342 6.73e-11 ***
Training_hardwareNVIDIA Quadro P600 1.714e-01 3.756e-02 4.562 3.52e-05 ***
Training_hardwareNVIDIA Quadro RTX 4000 1.538e-01 3.263e-02 4.714 2.12e-05 ***
Training_hardwareNVIDIA Quadro RTX 5000 1.819e-01 4.021e-02 4.524 3.99e-05 ***
Training_hardwareNVIDIA Tesla K80 1.125e-01 1.608e-02 6.993 7.54e-09 ***
Training_hardwareNVIDIA Tesla V100 DGXS 32 GB 1.072e-01 1.353e-02 7.922 2.89e-10 ***
Training_hardwareNVIDIA Tesla V100S PCIe 32 GB 9.444e-02 2.030e-02 4.653 2.60e-05 ***
Training_hardwareNVIDIA V100 1.420e-01 1.201e-02 11.822 8.01e-16 ***
Training_time_hour:Hardware_quantity 2.296e-09 9.372e-10 2.450 0.01799 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for Gamma family taken to be 0.05497984)
Null deviance: NaN on 70 degrees of freedom
Residual deviance: 3.0043 on 48 degrees of freedom
AIC: 345.39
Al convertir las pendientes en porcentaje de cambio en la variable de respuesta, el efecto de cada variable continua fue casi cero, incluso ligeramente negativo:
Todas las intercepciones también se convirtieron en aproximadamente alrededor de 1 kWh en la escala original. Los resultados no tenían sentido ya que al menos una de las pistas debería crecer junto con el enorme consumo de energía. Me preguntaba si usar el modelo unido a log con los mismos predictores puede producir resultados diferentes, por lo que volveré a encajar el modelo:
glm(formula = Energy_kWh ~ Training_time_hour * Hardware_quantity +
Training_hardware + 0, family = Gamma(link = "log"), data = df)
Coefficients:
Estimate Std. Error t value Pr(>|t|)
Training_time_hour 1.818e-03 1.640e-04 11.088 7.74e-15 ***
Hardware_quantity 7.373e-04 1.008e-04 7.315 2.42e-09 ***
Training_hardwareGoogle TPU v2 7.136e+00 7.379e-01 9.670 7.51e-13 ***
Training_hardwareGoogle TPU v3 1.004e+01 3.156e-01 31.808 < 2e-16 ***
Training_hardwareGoogle TPU v4 1.014e+01 4.220e-01 24.035 < 2e-16 ***
Training_hardwareHuawei Ascend 910 9.231e+00 1.108e+00 8.331 6.98e-11 ***
Training_hardwareNVIDIA A100 1.028e+01 3.301e-01 31.144 < 2e-16 ***
Training_hardwareNVIDIA A100 SXM4 40 GB 1.057e+01 5.635e-01 18.761 < 2e-16 ***
Training_hardwareNVIDIA A100 SXM4 80 GB 1.093e+01 5.751e-01 19.005 < 2e-16 ***
Training_hardwareNVIDIA GeForce GTX 285 3.042e+00 1.043e+00 2.916 0.00538 **
Training_hardwareNVIDIA GeForce GTX TITAN X 6.322e+00 7.379e-01 8.568 3.09e-11 ***
Training_hardwareNVIDIA GTX Titan Black 6.135e+00 1.047e+00 5.862 4.07e-07 ***
Training_hardwareNVIDIA H100 SXM5 80GB 1.115e+01 6.614e-01 16.865 < 2e-16 ***
Training_hardwareNVIDIA P100 5.715e+00 6.864e-01 8.326 7.12e-11 ***
Training_hardwareNVIDIA Quadro P600 4.940e+00 1.050e+00 4.705 2.18e-05 ***
Training_hardwareNVIDIA Quadro RTX 4000 5.469e+00 1.055e+00 5.184 4.30e-06 ***
Training_hardwareNVIDIA Quadro RTX 5000 4.617e+00 1.049e+00 4.401 5.98e-05 ***
Training_hardwareNVIDIA Tesla K80 8.631e+00 7.587e-01 11.376 3.16e-15 ***
Training_hardwareNVIDIA Tesla V100 DGXS 32 GB 9.994e+00 6.920e-01 14.443 < 2e-16 ***
Training_hardwareNVIDIA Tesla V100S PCIe 32 GB 1.058e+01 1.047e+00 10.105 1.80e-13 ***
Training_hardwareNVIDIA V100 9.208e+00 3.998e-01 23.030 < 2e-16 ***
Training_time_hour:Hardware_quantity -2.651e-07 6.130e-08 -4.324 7.70e-05 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for Gamma family taken to be 1.088522)
Null deviance: 2.7045e+08 on 70 degrees of freedom
Residual deviance: 1.0593e+02 on 48 degrees of freedom
AIC: 1775
Esta vez, Entrenamiento_time y Hardware_Quantity Aumentaría el consumo total de energía en un 0.18% por hora adicional y 0.07% por chip adicional, respectivamente. Mientras tanto, su interacción disminuiría el uso de energía en un 2 × 10 °%. Estos resultados tenían más sentido como Entrenamiento_time puede alcanzar hasta 7000 horas y Hardware_Quantity hasta 16000 unidades.
Para visualizar mejor las diferencias, creé dos gráficos que comparan las predicciones (que se muestran como líneas discontinuas) de ambos modelos. El panel izquierdo utilizó el modelo GAMMA GLM transformado log, donde las líneas discontinuas eran casi planas y cerca de cero, en ningún lugar cerca de las líneas continuas ajustadas de datos sin procesar. Por otro lado, el panel derecho utilizaba el modelo GAMMA GAMMA ligado, donde las líneas discontinuas se alineaban mucho más estrechamente con las líneas ajustadas reales.
test_data <- df[, c("Training_time_hour", "Hardware_quantity", "Training_hardware")]
prediction_data <- df %>%
mutate(
pred_energy1 = exp(predict(glm3, newdata = test_data)),
pred_energy2 = predict(glm3_alt, newdata = test_data, type = "response"),
)
y_limits <- c(min(df$Energy_KWh, prediction_data$pred_energy1, prediction_data$pred_energy2),
max(df$Energy_KWh, prediction_data$pred_energy1, prediction_data$pred_energy2))
p1 <- ggplot(df, aes(x = Hardware_quantity, y = Energy_kWh, color = Training_time_group)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE) +
geom_smooth(data = prediction_data, aes(y = pred_energy1), method = "lm", se = FALSE,
linetype = "dashed", size = 1) +
scale_y_log10(limits = y_limits) +
labs(x="Hardware Quantity", y = "log of Energy (kWh)") +
theme_minimal() +
theme(legend.position = "none")
p2 <- ggplot(df, aes(x = Hardware_quantity, y = Energy_kWh, color = Training_time_group)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE) +
geom_smooth(data = prediction_data, aes(y = pred_energy2), method = "lm", se = FALSE,
linetype = "dashed", size = 1) +
scale_y_log10(limits = y_limits) +
labs(x="Hardware Quantity", color = "Training Time Level") +
theme_minimal() +
theme(axis.title.y = element_blank())
p1 + p2
Por qué falla la transformación del registro
Para comprender la razón por la cual el modelo transformado logarítmicamente no puede capturar los efectos subyacentes como el de los registros, caminemos por lo que sucede cuando aplicamos una transformación de registro a la variable de respuesta:
Digamos que Y es igual a alguna función de x más el término de error:
Cuando aplicamos un registro que se transforma en Y, en realidad estamos comprimiendo F (x) y el error:
Eso significa que estamos modelando una variable de respuesta completamente nueva, log (y). Cuando conectamos nuestra propia función G (x) – en mi caso g (x) = entrenador_time_hour*hardware_quantity + entrenador_hardware– Está tratando de capturar los efectos combinados del término “encogido” F (x) y de error.
Por el contrario, cuando usamos un enlace de registro, todavía estamos modelando la Y original, no la versión transformada. En cambio, el modelo expone nuestra propia función G (x) para predecir Y.
El modelo luego minimiza la diferencia entre la Y y la Y. de esa manera, los términos de error permanecen intactos en la escala original:
Conclusión
La transformación de registro Una variable no es lo mismo que usar un enlace de registro, y puede no siempre dar resultados confiables. Debajo del capó, una transformación de registro altera la variable misma y distorsiona tanto la variación como el ruido. Comprender esta sutil diferencia matemática detrás de sus modelos es tan importante como tratar de encontrar el modelo mejor ajustado.
[1] Época ai. Datos sobre modelos de IA notables . Recuperado de https://epoch.ai/data/notable-ai-models
[2] Biblioteca de la Universidad de Virginia. Interpretación de transformaciones de registro en un modelo lineal.Recuperado de https://library.virginia.edu/data/articles/interpreting-log-transformations-in-a-linear-model