О пакете BinSeqBstrap

Постановка задачи

Допустим, у нас есть какая кусочно-гладкая функция f(x), к который прибавлен некий случайный шум, соответствующий условиям Гаусса-Маркова. И все хорошо, только эта самая функция f(x) – функция с неустранимым(-и)  разрывом(-ами) первого рода, то есть в какой-то точке левый и правый предел этой функции равны разным числам, а у функции есть скачок. Задача – как-то нужно научить алгоритм распознавать этот скачок.

Минутка теории

Теоретические основы изложены в виньетке, написанной Кэти МакДэйд и Флориана Пэйна из Кэмбриджа, опубликованной вот тут.

Если вкратце, то функционал пакета позволяет решить 4 разные подзадачи, базовая из которых - определение места и размера единственного скачка функции при известной ширине окна h

Основа: вот эта вот длинная формула

Результат этой формулы используется для вычисления места скачка

n – общее количество точек
n – общее количество точек

Сам метод основан на идеях непараметрической регрессии. Для определения местоположения точек разрыва выбирается окно из некоторого количества точек, и считается разница между суммами значений слева и справа. Для определения размера скачка используется разница значений сглаженной функции в определенной точек разрыва.

Практика

В коде это выглядит так:

library(BinSegBstrap)
## Часть 1
set.seed(1)
n <- 1:100
signal <- 0.1*n-5
signal[51:100] <- signal[51:100] + 5 
y <- rnorm(n) + signal # Придумываем искусственные данные
est <- estimateSingleCp(y = y, bandwidth = 0.1)
est$cp # определяем точку разрыва
est$size # определяем скачок функции
plot(y, pch = 16, col = "grey30")
lines(signal)
lines(est$est, col = "red") # est$est - подогнанные значения
Местоположение скачка точно установлено, его размер – примерно.
Местоположение скачка точно установлено, его размер – примерно.
А вот графика. Красная линия - это сглаженная регрессия, черная - подобранные линии уравнений
А вот графика. Красная линия - это сглаженная регрессия, черная - подобранные линии уравнений

Часть 2. Определение параметров скачка при неизвестной величине

Собственно, к исходной формуле достраивается только алгоритм кросс-валидации, который позволяет найти лучший размер окна, в котором искать скачок.

Зададим алгоритму задачку посложнее:

set.seed(1)
n <- 1:100
signal1 <- 5-0.1*n
signal2 <- 0.01*n^2-20
signal<-c(signal1[1:50],signal2[51:100])
y <- rnorm(n) + signal
est <- estimateSingleCp(y = y)
est$bandwidth # подобранная ширина окна
est$cp # определяем точку разрыва
est$size # определяем скачок функции
plot(y, pch = 16, col = "grey30") # plot of observations, true and estimated signal
lines(signal)
lines(est$est, col = "red")
Снова все определено верно
Снова все определено верно

Часть 3. Проверка статистической гипотезы о наличии скачка

Объявляем нулевую гипотезу о том, что размер скачка К равен 0 (альтернативная – не равен).

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

В коде это выглядит так:

test <- BstrapTest(y = y)
test$outcome # Результат проверки гипотезы о нулевом скачке
test$pValue
Итого – нулевая гипотеза на уровне значимости 0.05 отвергается
Итого – нулевая гипотеза на уровне значимости 0.05 отвергается

Часть 4. Поиск всех возможных точек разрыва

Составим функцию, в которой есть две точки разрыва, и посмотрим, справится ли алгоритм с ней

set.seed(1)
signal1<-abs(-8-seq(from=-10, to=-5, length.out=50))
signal2<-3*exp(seq(from=-5, to=0, length.out=50))
signal3<-sqrt(seq(from=0, to=10, length.out=50))-4
signal <- c(signal1,signal2,signal3)
y <- rnorm(150) + signal
est <- BinSegBstrap(y = y)
est$cps # находим точки разрыва
plot(y, pch = 16, col = "grey30") # plot of observations, true and estimated signal
lines(signal)
lines(est$est, col = "red")
На удивление, все нашлось
На удивление, все нашлось

Вместо заключения

Весьма интересная задумка. Для решения практических задач в текущем состоянии пакет применим мало, к тому же редко приходится данные аппроксимировать функциями с разрывами, но как инструмент вспомогательного анализа может пригодиться. Ну и интересно потестить, до каких пределов алгоритм работает хорошо, а когда начнет пропускать разрывы / находить лишние.

Комментарии (4)


  1. iggr63
    19.02.2022 20:39

    Где взять этот пакет?


    1. acheremuhin Автор
      19.02.2022 21:02

      Он в открытом доступе. Он скачивается и устанавливается в R обычным путем


  1. adeshere
    19.02.2022 22:02
    +5

    Спасибо за публикацию. Не думал, что об этом до сих пор пишут статьи в математические журналы;-)

    При анализе геодеформационных процессов разрывы в рядах возникают сплошь и рядом. Например, для наклономеров типичен дрейф нуля. Периодически ряд выходит на границу динамического диапазона, и экспериментатору приходится руками "подкручивать" ноль, чтобы вернуть сигнал в центр диапазона. На графике получается скачок уровня. Для тех, кто ведет подобные наблюдения, устранение таких скачков - это повседневная бытовая задача ;-)

    Только в отличие от рассмотренной модели, на практике все немного сложнее. Во-первых, разрыв или скачок - это часто не одна точка, а некоторый переходный процесс с заранее неизвестной длительностью (хотя может быть и одна точка). Во-вторых, скачок очень часто сопровождается более или менее длительным перерывом в наблюдениях. В-третьих, после скачка в сигнале часто присутствует переходный процесс, связанный с эффектом экспериментатора (приборы довольно чувствительные и каждое посещение штольни - это стресс для прибора и катастрофа в сигнале).

    Еще надо учитывать, что в период "послескачкового" пропуска наблюдений нормальный ход деформаций идет себе дальше. Поэтому нельзя просто выровнять уровень ряда на правом и левом концах перерыва. Надо как-то убрать скачок, но не исказить при этом нормальный процесс.

    А еще бывают скачки непонятной природы. Он может быть как реальным эффектом в геосреде, так и локальным артефактом в постамента (треснула микропесчинка под опорой прибора). Но их тоже надо убирать чтобы, к примеру, взяться за анализ приливов.

    Я вот тоже недавно получил такой ряд и задачу - подготовить его для последующей обработки. А я эту тему раньше совсем не курил, и литературу не знаю. Поэтому собрал алгоритм для устранения скачков из того, что было по рукой (в нашем пакете). Получилось примерно вот так:

    1) очищаем сигнал (который с разрывами и скачками) от всех неслучайных составляющих которые можно там выделить (прилив, долговременные тренды и др.)
    2) делаем медианное сглаживание в скользящем окне для подавления шума. Окно лучше взять из нечетного числа точек, чтобы сохранить амплитуду скачка, если он вдруг происходит одномоментно;
    3) ряд до и после скачка аппроксимируется линейной функцией; эти функции экстраполируются навстречу друг другу;
    4) вычисляется разность линейных функций на том временном интервале, который включает: а) сам скачок, плюс б) перерыв в наблюдениях после скачка, плюс в) переходный процесс после скачка. Поскольку две экстраполированные линейные функции не вполне параллельны, разность - это тоже линейная функция, у которой есть среднее значение (= амплитуда скачка) и дисперсия/сигма (= погрешность его оценки). Погрешность нужна для того, чтобы оценить искажения долговременных вариаций, которые мы вносим в сигнал, убирая скачки.

    5) Ну и конечно, скачок после этого убирается из исходного ряда (то есть того, который с приливом и трендами), а не из очищенного суррогата, по которому все оценивалось ;-)

    Картинки
    Это идея метода
    Это идея метода
    А это результат
    А это результат
    И он же в крупном масштабе
    И он же в крупном масштабе

    Но поскольку все эти трюки - это сугубо техническая задача, то у нас (в статьях по анализу данных режимных наблюдений) как-то даже не принято об этом писать. Считается, что обсуждать такую тривиальщину незачем. А я вдобавок в данной тематике новичок, поэтому тем более странно с таким велосипедом публиковаться: настоящие спецы засмеют. Хотя алгоритм в общем рабочий, и с задачей справляется. Но ведь люди на этих скачках десятилетиями собачек едят, а я за пару дней на коленке сварганил...

    А тут оказывается в Кембридже вон оно как - про скользящее среднее пишут. Неожиданно, да.

    P.S. Код процедуры не привожу, так как он состоит из целой кучи небольших почти тривиальных функций, раскиданных по разным местам пакета, и ужасающего legacy, необходимого, чтобы юзер мог заставить все эти функции работать вместе в нужном порядке, просто нажимая на кнопочки в интерфейсе (без программирования). Вдобавок сам алгоритм не автоматический: многие настройки (особенно величину всяких оценивающих окон) юзер задает или проверяет интерактивно на графике.

    P.P.S. А впрочем, для любителей ужасов вот ссылка на исходники пакета в целом ;-)


    1. acheremuhin Автор
      20.02.2022 15:16

      Формально, задачи все-таки разные. Вы, как я понял, говорите про временные ряды. Для них задачи определения скачка, точек излома тренда и т.д. решаются по-другому. Тут все-таки рассматривается не временной ряд, плюс у вас своя практическая специфика. Нельзя знать совсем все методы и приемы во всех областях знания. Поэтому - не бейте пианиста, он играет как умеет.