Среднеквадратичное отклонение по результатам GAM с использованием R

Фон

База данных PostgreSQL использует PL/R для вызова функций R. Вызов R для вычисления корреляции Спирмена выглядит следующим образом:

cor( rank(x), rank(y) )

Также в R наивный расчет подобранной обобщенной аддитивной модели (GAM):

data.frame( x, fitted( gam( y ~ s(x) ) ) )

Вот x представляет годы с 1900 по 2009 год и y это среднее измерение (например, минимальная температура) за этот год.

проблема

Подходящая линия тренда (с использованием GAM) достаточно точна, как вы можете видеть на следующем рисунке:

Проблема состоит в том, что корреляции (показанные в левом нижнем углу) не точно отражают, насколько точно модель соответствует данным.

Возможное решение

Одним из способов повышения точности корреляции является использование вычисления среднеквадратичной ошибки (RMSE) для данных в двоичном виде.

Вопросы

В.1. Как бы вы реализовали расчет среднеквадратичного отклонения для связанных данных, чтобы получить корреляцию (между 0 и 1) соответствия GAM измерениям на языке R?

В.2. Есть ли лучший способ найти точность подгонки GAM к данным, и если да, то что это такое (например, среднеквадратичное отклонение)?

Попытка решения 1

  1. Вызовите функцию PL/R, используя наблюдаемые суммы и модельные (GAM) суммы:
    correlation_rmse := climate.plr_corr_rmse( v_amount, v_model );
  2. определять plr_corr_rmse следующим образом (где o а также m представляют наблюдаемые и смоделированные данные):
    CREATE OR REPLACE FUNCTION climate.plr_corr_rmse(
    o double precision[], m double precision[])
    RETURNS double precision AS
    $BODY$
    sqrt( mean( o - m ) ^ 2 )
    $BODY$
    LANGUAGE 'plr' VOLATILE STRICT
    COST 100;
    

o - m неправильно. Я хотел бы объединить оба набора данных путем расчета mean из каждых 5 точек данных (будет не более 110 точек данных). Например:

omean <- c( mean(o[1:5]), mean(o[6:10]), ... )
mmean <- c( mean(m[1:5]), mean(m[6:10]), ... )

Затем исправьте расчет RMSE следующим образом:

sqrt( mean( omean - mmean ) ^ 2 )

Как вы рассчитываете c( mean(o[1:5]), mean(o[6:10]), ... ) для вектора произвольной длины в соответствующем количестве бинов (например, 5, может быть не идеальным только для 67 измерений)?

Я не думаю hist подходит здесь, не так ли?

Попытка решения 2

Следующий код решит проблему, однако отбрасывает точки данных из конца списка (чтобы список делился на 5). Решение не идеальное, так как число "5" довольно волшебно.

while( length(o) %% 5 != 0 ) {
  o <- o[-length(o)]
}

omean <- apply( matrix(o, 5), 2, mean )

Какие еще варианты доступны?

Заранее спасибо.

1 ответ

Решение

Вы говорите, что:

Проблема состоит в том, что корреляции (показанные в левом нижнем углу) не точно отражают, насколько точно модель соответствует данным.

Вы можете рассчитать соотношение между подобранными значениями и измеренными значениями:

cor(y,fitted(gam(y ~ s(x))))

Я не понимаю, почему вы хотите скопировать ваши данные, но вы можете сделать это следующим образом:

mean.binned <- function(y,n = 5){
  apply(matrix(c(y,rep(NA,(n - (length(y) %% n)) %% n)),n),
        2,
        function(x)mean(x,na.rm = TRUE))
}

Это выглядит немного некрасиво, но должно обрабатывать векторы, длина которых не кратна длине биннинга (т.е. 5 в вашем примере).

Вы также говорите, что:

Одним из способов повышения точности корреляции является использование вычисления среднеквадратичной ошибки (RMSE) для данных в двоичном виде.

Я не понимаю, что вы имеете в виду под этим. Корреляция является фактором, определяющим среднеквадратичную ошибку - например, см. Уравнение 10 Мерфи (1988, Monthly Weather Review, v. 116, pp. 2417-2424). Но, пожалуйста, объясните, что вы имеете в виду.

Другие вопросы по тегам