Среднеквадратичное отклонение по результатам GAM с использованием R - PullRequest
1 голос
/ 19 июня 2010

Фон

База данных 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) достаточно точна, как вы можете видеть на следующем рисунке:

image

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

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

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

Вопросы

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

Q.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 Ответ

2 голосов
/ 19 июня 2010

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

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

Вы можете рассчитать корреляцию между установленными значениями и измеренными значениями:

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) .Но, пожалуйста, объясните, что вы имеете в виду.

...