From 36f6d1df1cef0f19ee74a4661883bfb148ea581f Mon Sep 17 00:00:00 2001 From: Marco De Lucia Date: Wed, 10 Apr 2024 23:41:58 +0200 Subject: [PATCH] fixing doc --- Readme.md | 24 +++--- doc/Description.pdf | Bin 533494 -> 534062 bytes doc/Description.tex | 7 +- doc/Metrics.R | 189 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 205 insertions(+), 15 deletions(-) create mode 100644 doc/Metrics.R diff --git a/Readme.md b/Readme.md index b2db9e9..8991fe2 100644 --- a/Readme.md +++ b/Readme.md @@ -1,17 +1,17 @@ # TUG Benchmark -**This Readme is under construction** +**Refer to the =Description.pdf= in the =doc= folder** -This repository contains input data from POET simulations used in the NAAICE -project and is simulated with the latest version of tug with heterogeneous -alphas. +This repository contains input data from POET simulations used in the +NAAICE project and is simulated with the latest version of tug with +heterogeneous alphas. -The alpha values are randomly generated from a uniform distribution between 1e-7 -and 1e-6 and stored in according .csv files. +Benchmarks (grids, timestep, file paths, etc) are defined in the +header file `eval/bench_defs.hpp.in`. The data used by the three +benchmarks `barite_200`, `barite_large` and `surfex` are in the +corresponding subdirectories of `eval`, as `tar.gz`. Remember to +unpack them before running the executable! -You can find the three benchmarks in the `eval` directory. There is also a -header file, which describes the benchmarks with its grid shape etc. - -To write the resulting fields to a file, you can set the `BENCH_OUTPUT` -variable, e.g. `BENCH_OUTPUT=1 ./bench`. The resulting fields are written to -according .csv files. +To write the results to file, set the `BENCH_OUTPUT` environmental +variable, e.g. `BENCH_OUTPUT=1 ./bench`. The resulting fields are +written to according .csv files *in the `build` directory*. diff --git a/doc/Description.pdf b/doc/Description.pdf index 6002d6b1b2be9e6311dddd858ca6aefa3ea9458f..c4addaa80364dbc9791c12bb550fdbc87b07370e 100644 GIT binary patch delta 20129 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 Um(3#x9t$%vFgOY&B}Gq03LC+4`Tzg` delta 19543 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%0AlMUMANcs7J+bXoOF>n=nn3ghc$l) zXqGXEPC;zkzdAU&1;!?KZ5c{uT;*wVfPz5?{>m8;xLd|`omSR{z}dZ@;AI#=RF8tW zpN4U?Uij-L(0Umz{G_UGx3F|OI66Kz>b4j^)JJ;?>N-NXE@|j{Xxnc7M$4)`onq7N z=<@XL6!f_|X*)hB(+Y2P->G2oWP5+XR5JF$$g@23eVbRFYnerK3SXzA>&exfR{5&6 zrUH#2_j0I>J>``YCZwXUZf+H(P@;COs0P2Pl&VZbIvZz2i}7M()oEUsY@!D!er9nJ z07Iriv0S@TFg*EkGd?@Wh@vgVu8D#h2Uv!u`2Q!0w-R+^3QJ8^#)oDjvxk37`4?MT z*(s16jHh?w(?2G|@dcF9ErvnhqO`{-c()4|9mT|}$`#)(RUA%RE#|b=Vh_O_%FU`S z4N>Yan#B)cG>5&y$HxFd|14Oezrh{y6~5WJ!|t2=)HHP`P(1M0fgVA4dV15p(6McB zYaF9O71DQI4FM0sWSwfTCJKL_`+0*ZvWii@fz^B z_K{WX+9@GwU`TaGG}u2pIv5&6q5+X**2LkhXT~i=%IS`%_Pa?Pk$l^TN_eQS@sRF# zYQKBb@Ob1GMomiuDH{;&4yblnuLELrK+J88M8pQfx&x|Skn4E36&Y0tk8W%ajM;E@ z2-Vd~ZXJ%W;K(*O4fcP$L!7SOQR{G29S*N}eA%8^gFWvMrK=aq8XiG@ku|&$Khnmt zLyWFp+vb7iGyFWe$h3D+^Nj!;F1< zV|CiLI>~_PpA>(!hAd=wAtD+?Mw@gIMq0{{hw|Mtb^3ddX%v_W!4Ph=h~}jAf&T1m zi#T`c&q?r%swscRND{G?bSsi>NsiD4LADiiS_N}3m%&S_KV(^psA3JTX^Bj%VQ;?O zx>;ExNXtcefy7XmBgv`UW5we7jtWQg;UJ#vO;SHeKccK!M<4X368#g`C;Ewe)StDi zZmPSb)y;IbvbtU9&UmYIbKT7{%fRR1GE8fDs*}Ifk(Yl)J-w7`?I3hFx4Nb7&UJkZ z=bI$>H1k(x5H#R!;|OdaWaEhXh?J_UQ3YpgEZYN$7|ZaGnb_{z!T+hU^ctQ z=WU==mD{j&mO9JOik*rn%}_LVPI)iQTIPD_!#bE5Jv82GkG7250@j=R?L0kGG<56f zq!A$OU!Q+!0j-Q{!jPYl_vgT{TY&PNoXY{g~#COLI@9xocAUAj-bjx(lR3m`q7SdfoR^e-Y1n zS$cTQC`ITm1u;VaE#j=6e*x(bPuIa~o*1oysBa4RM0C5`e?KpD)t8YE2osmtA_!hm zG&D0oML94tF)}nYIYu})H#kKxGB-jnIWaUgMn*F*J|H|aG&4a(IWRLZGBh)i@$Ph}DExN@FEqArT=VH)(9_#7aV}Bo>57B%+Cs z5DAK?NW`no_dknIe&;d&bMCq48e=lkjxmlA?_-T2&9a0oBmoDK^fi+r;6fvP3rHUL zu!O$(qyVCS&_!PpsQ_Y72yrNe5-5ckP$s5$NcU1D=GZAsv&EPaO$nGu(K;vx3WU1J zT1JaN2P%Q0q5eZxs~}awTwvXB4%9PBa%!MbOuR#v)X7z#hr14M$DOiI)%MB z)N|^M{pp!Dh&j)c*PnHYo>i@wv8*=dfu4&V*dl0ug=R75zUY*Npsyk&?&aUw*Dmgj z0VD3cDQzx;HgT_9*XCkK!&2yk4splxI=UQIhyjhlH6=9d7q9P;rcv=uKG1YPyi0+mgW}z4(R4_>$Hkfsi}y>< zDl`%;ziq@%wrNwu&lhQO#J~1UQ$+kb{hD0ypLc5V#Q*MT@+D}zsVR^k)2%5g!RTpC z1rl6%swpPH{hX#k37%DJic9d~qLE 0) { + msg_("Removed ", length(ind)) + mean(abs(log(pred[-ind]/actual[-ind])), na.rm=TRUE) + } else { + mean(abs(log(pred/actual)), na.rm=TRUE) + } +} + +RMSElog <- function(actual, pred, eps=FALSE) { + pred[is.na(pred)] <- 0 + if (length(ind <- which(actual==0 | pred<=0)) > 0) { + msg_("Removed ", length(ind)) + sqrt(mean(log(pred[-ind]/actual[-ind])^2, na.rm=TRUE)) + } else { + sqrt(mean(log(pred/actual)^2, na.rm=TRUE)) + } +} + +GMAQabs <- function(actual, pred) { + pred[is.na(pred)] <- 0 + ind <- which(actual==0 | pred<=0) + if (length(ind) > 0) { + msg_("Removed ", length(ind)) + abs(1-exp(mean(log(abs(pred[-ind]/actual[-ind])), na.rm=TRUE))) + } else { + abs(1-exp(mean(log(abs(pred/actual)), na.rm=TRUE))) + } +} + +## Workhorse function computing the "alphas" (cfr workflows/metrics) +## for relative error measures. We first compute the alphas, then take +## care of the +Inf, -Inf, NaN cases scanning the input vectors and +## substituting 0 and 1. NAs in the predictions are preserved +Alphas <- function(actual, pred) { + alphas <- 1-pred/actual + alphas[actual==0 & pred==0] <- 0 + alphas[actual==0 & pred > 0] <- 1 + alphas[actual==0 & pred < 0] <- -1 + alphas +} + +MAPE <- function(actual, pred) { + 100*mean(abs(Alphas(actual, pred)), na.rm=TRUE) +} + +RRMSE <- function(actual, pred) { + sqrt(mean(Alphas(actual, pred)^2, na.rm=TRUE)) +} + +RMSLE <- function(actual, pred) { + sqrt(mean((log((1+pred)/(1+actual))^2), na.rm=TRUE)) +} + +MAE <- function(actual, pred) { + mean(abs(actual-pred), na.rm=TRUE) +} + +RMSE <- function(actual, pred) { + sqrt(mean((actual-pred)^2, na.rm=TRUE)) +} + +MSE <- function(actual, pred) { + mean((actual-pred)^2, na.rm=TRUE) +} + +## Function is called "R2" but it actually computes "1-R2" (note that +## "1-rss/tss" is missing) +R2 <- function(actual, pred) { + rss <- sum((actual - pred)^2, na.rm=TRUE) + tss <- sum((pred - mean(pred, na.rm=TRUE))^2, na.rm=TRUE) + rss/tss +} + +Range <- function(x) { + diff(range(x, na.rm=TRUE)) +} + +## 2024-03-08: fixed Range of actual instead of pred, thanks @Mary +Normsupnorm<- function(actual, pred) { + max(abs(actual - pred), na.rm=TRUE)/Range(actual) +} + + + +## This function computes all the measures at once in the (hopefully) +## expected right order. You need to loop this function over all +## variables. +Metrics <- function(actual, pred) { + ## MAE MSE RMSE 1-R2 NMAE NRMSE Normsupnorm MAElog RMSElog RMSLE GMAQabs MAPE RRMSE NNEG Range + alphas <- Alphas(actual, pred) + ran_pred <- Range(pred) + ran_actu <- Range(actual) ## 2024-03-08: same fix as in Normsupnorm + ret <- c( + MAE = MAE(actual, pred), + MSE = MSE(actual, pred), + RMSE = RMSE(actual, pred), + '1-R2' = R2(actual, pred), + NMAE = MAE(actual, pred)/ran_actu, + NRMSE = RMSE(actual, pred)/ran_actu, + Normsupnorm = Normsupnorm(actual, pred), + MAElog = MAElog(actual,pred), + RMSElog = RMSElog(actual,pred), + RMSLE = RMSLE(actual, pred), + GMAQabs = GMAQabs(actual, pred), + MAPE = MAPE(actual, pred), + RRMSE = RRMSE(actual, pred), + NNEG = NNEG(pred), + Range = ran_pred + ) + ret +} + +## Function applying Metrics() on all columns of two data.frames +## having the same name +DoAllMetrics <- function(vals, preds) { + ## Match column names (=variables) in both data.frames + vars <- intersect(colnames(vals), colnames(preds)) + + msg_("Going to compute metrics for: ", paste(vars, collapse=', ')) + ## Some lambda calculus combined with R ugliness + as.data.frame(t(sapply(vars, function(x) Metrics(actual = vals[[x]], pred = preds[[x]])))) +} + + +### Store the computed metrics into a .csv file. First format all +### columns with "formatC" specifying 7 digits, and then use function +### "data.table::fwrite" with option "scipen=1" to try and use the +### scientific/exponential notation as much as possible. The empty +### spaces resulting from padding are removed too. +WriteMetrics <- function(tab, fileout) { + require(data.table) + tocsv <- data.frame(Output=rownames(tab), gsub(" ", "", sapply(tab, formatC, digits = 7)), check.names = FALSE) + data.table::fwrite(tocsv, file=fileout, scipen=1) +} + +################################################################## +### ### +### Usage Example ### +### ### +################################################################## + +### We start by sourcing these functions +## source("./Metrics.R") + +### NOTE: I use the extension package data.table to read and write the +### .csv files. + +## require(data.table) + +### NOTE2: we expect named columns in the .csv - with header! + +### Example to compute all metrics at once for from a file - check colnames! +## Trues <- data.table::fread("./Trues.csv", header=TRUE, data.table = FALSE) + +### Load the simulation results dataset +## Preds <- data.table::fread("./MyPreds.csv", header=TRUE, data.table = FALSE) + +## res <- DoAllMetrics(Val, Preds) + +### Write out the metrics +## WriteMetrcs(res, file="MyMetrics.csv")