B Путаница со сплайнами

Я понимаю, что на этой доске есть сообщения на тему B-сплайнов, но на самом деле они меня еще больше запутали, поэтому я подумал, что кто-то может мне помочь.

Я смоделировал данные для значений x в диапазоне от 0 до 1. Я хотел бы подогнать к своим данным кубический сплайн (degree = 3) с узлами в 0, 0,1, 0,2, ..., 0,9, 1. Я бы также нравится использовать основу B-Spline и OLS для оценки параметров (я не ищу оштрафованных сплайнов).

Я думаю, что мне нужна функция bs из пакета spline, но я не совсем уверен, и я также не знаю, чем именно ее кормить.

Я также хотел бы построить полученный полиномиальный сплайн.

Спасибо!


person user2249626    schedule 05.04.2013    source источник
comment
Путаница с B-сплайнами в заголовке кажется уместной. Как у вас может быть кубический сплайн с 10 узлами и степенью = 3?   -  person IRTFM    schedule 05.04.2013
comment
@DWin Это точно то, что делает bs, не так ли? Кубические многочлены степени 3 (по умолчанию), установленные между узлами, при условии, что отдельные части плавно соединяются в узлах?   -  person Gavin Simpson    schedule 05.04.2013
comment
Я полагаю, для некоторого понимания проблемы. Я думал, что то, что просили, было кубическим полиномом, подходящим для всего диапазона данных. В противном случае простое выполнение тривиальных изменений кода примера на странице ?bs, казалось бы, полностью решит вопрос: lm(weight ~ bs(height, df = 3, knots=c(58, 62, 66, 70, 72), ), data = women)   -  person IRTFM    schedule 05.04.2013


Ответы (2)


## simulate some data - from mgcv::magic
set.seed(1)
n <- 400
x <- 0:(n-1)/(n-1)
f <- 0.2*x^11*(10*(1-x))^6+10*(10*x)^3*(1-x)^10
y <- f + rnorm(n, 0, sd = 2)

## load the splines package - comes with R
require(splines)

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

mod <- lm(y ~ bs(x, knots = seq(0.1, 0.9, by = 0.1)))

Вы можете относиться к этому так же, как к линейной модели.

> anova(mod)
Analysis of Variance Table

Response: y
                                        Df Sum Sq Mean Sq F value    Pr(>F)    
bs(x, knots = seq(0.1, 0.9, by = 0.1))  12 2997.5 249.792  65.477 < 2.2e-16 ***
Residuals                              387 1476.4   3.815                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Несколько советов по размещению узлов. bs имеет аргумент Boundary.knots, по умолчанию Boundary.knots = range(x), поэтому, когда я указал выше аргумент knots, я не включил граничные узлы.

Прочтите ?bs для получения дополнительной информации.

Создание графика подобранного сплайна

В комментариях я обсуждаю, как нарисовать подогнанный сплайн. Один из вариантов — упорядочить данные в терминах ковариаты. Это хорошо работает для одной ковариаты, но не обязательно для двух или более ковариат. Еще одна проблема заключается в том, что вы можете оценить подобранный сплайн только при наблюдаемых значениях x — это нормально, если вы произвели плотную выборку ковариаты, но в противном случае сплайн может выглядеть странно с длинными линейными участками.

Более общее решение состоит в том, чтобы использовать predict для создания прогнозов модели для новых значений ковариаты или ковариат. В приведенном ниже коде я показываю, как это сделать для приведенной выше модели, прогнозируя 100 равномерно распределенных значений в диапазоне x.

pdat <- data.frame(x = seq(min(x), max(x), length = 100))
## predict for new `x`
pdat <- transform(pdat, yhat = predict(mod, newdata = pdat))

## now plot
ylim <- range(pdat$y, y) ## not needed, but may be if plotting CIs too
plot(y ~ x)
lines(yhat ~ x, data = pdat, lwd = 2, col = "red")

Это производит

введите здесь описание изображения

person Gavin Simpson    schedule 05.04.2013
comment
Это очень помогает спасибо! Теперь, если я построю соответствующие значения, используя точки (x, fitted (mod)) я получаю то, что ищу. Однако использование lines(x,fitted(mod)) не соединяет точки для отображения полиномиального сплайна. Как мне построить получившийся сплайн? - person user2249626; 05.04.2013
comment
@user2249626 user2249626, если ваши данные не расположены в порядке x, тогда соответствующие значения не будут в порядке x, и, следовательно, то, что выглядит нормально при построении с помощью points, представляет собой беспорядок спагетти при построении с использованием lines. Два варианта; i) проще всего просто отсортировать данные перед подгонкой модели или ii) использовать predict в модели, предоставляя новые значения x как seq(min(x), max(x), length = 100). Тогда постройте это. - person Gavin Simpson; 05.04.2013
comment
Извините, я новый пользователь R. Что именно вы подразумеваете под сортировкой? Поместите пары x, y в матрицу и отсортируйте эту матрицу по столбцу x? - person user2249626; 05.04.2013
comment
@user2249626 user2249626 да, хорошо во фрейме данных и отсортируй пары. Я покажу вам это после обеда... Вернитесь к редактированию через 30 минут или около того. - person Gavin Simpson; 05.04.2013
comment
Я немного подумал об этом. Я сортирую фрейм данных следующим образом: df ‹- data.frame(x,y) df_ordered ‹- df[order(df$x),]. Затем я подогнал модель следующим образом: mod ‹- lm(df_ordered$y~bs(df_ordered$x,knots=seq(0.1,0.9, by=0.1))). Затем я добавляю сплайн к своей диаграмме рассеяния: lines(df_ordered$x,fitted(mod)) Будет ли это правильным способом подбора и отображения полиномиального сплайна? - person user2249626; 06.04.2013
comment
@user2249626 user2249626 ну, это было бы в одну сторону. Лучше использовать predict в диапазоне ковариаты. - person Gavin Simpson; 06.04.2013
comment
@ user2249626 Я добавил пример построения сплайна. - person Gavin Simpson; 06.04.2013
comment
Спасибо за редактирование! Еще один вопрос: когда я использую подход прогнозирования для построения графика и длина = 250 (поскольку у меня есть 250 (x_i, y_i) наблюдений), построенный сплайн выглядит намного грубее, чем когда я использую свой первоначальный подход к построению графика (применяя порядок данных Рамка). Есть ли способ получить такой же гладкий сплайн с помощью метода прогнозирования? Спасибо! - person user2249626; 07.04.2013
comment
@user2249626 user2249626 да, увеличьте количество точек, на которые вы прогнозируете. Найдите length = 100 в обновленном примере, который я добавил вчера. Увеличьте это до желаемого, чтобы получить плавную функцию при построении графика. - person Gavin Simpson; 07.04.2013

Основываясь на примере в ответе, более простым способом построения подогнанного сплайна было бы использование пакета effects.

## simulate some data - from mgcv::magic
set.seed(1)
n <- 400
x <- 0:(n-1)/(n-1)
f <- 0.2*x^11*(10*(1-x))^6+10*(10*x)^3*(1-x)^10
y <- f + rnorm(n, 0, sd = 2)

## load the splines package - comes with R
require(splines)
require(car)
require(effects)

## estimate model
mod <- lm(y ~ bs(x, knots = seq(0.1, 0.9, by = 0.1)))

Затем вы можете использовать Anova из car:

> Anova(mod)
Anova Table (Type II tests)

Response: y
                                       Sum Sq  Df F value    Pr(>F)    
bs(x, knots = seq(0.1, 0.9, by = 0.1)) 2997.5  12  65.477 < 2.2e-16 ***
Residuals                              1476.4 387                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

И вы можете легко построить подогнанный сплайн, используя пакет effects.

plot(allEffects(mod))

Что выведет это:

введите здесь описание изображения

Смотрите также:

person landroni    schedule 06.04.2015