Извлечь данные из скользящей средней?

15

Можно ли извлечь точки данных из данных скользящего среднего?

Другими словами, если набор данных имеет только простые скользящие средние из предыдущих 30 точек, возможно ли извлечь исходные точки данных?

Если так, то как?


источник
1
Ответ квалифицированный да, но точная процедура зависит от того, как обрабатывается начальный сегмент данных. Если его просто отбросить, то вы фактически потеряли 15 фрагментов данных, оставив вас с неопределенной системой линейных уравнений. В результате существует много правильных ответов в целом, но вы все равно можете добиться определенного прогресса, если либо (а) более короткие окна (или некоторая такая процедура) использовать для начальных 15 скользящих средних, либо (б) вы можете указать дополнительные ограничения для решение (около 15 измерений ценностей ограничений ...). В какой ты ситуации?
whuber
@whuber Большое спасибо за поиск! У меня 2000 очков. Первая точка MA, скорее всего, является средней из первых 30 исходных точек. Точность уступает в общем правильному результату, особенно точным догадкам в самых «последних» точках. Можете ли вы порекомендовать относительно простой метод? Заранее спасибо!
1
(если вам потребуется больше пяти минут, чтобы написать комментарий ...). Я хотел написать, что усреднение можно представить как умножение матриц. Строки в середине будут иметь 1/30 * [1 1 1 ...] перед диагональю. Вопрос в том, как вы справляетесь с точками на границах вашего вектора, чтобы сделать матрицу обратимой. Вы можете сделать это, предполагая, что они являются результатом усреднения по меньшему количеству элементов или вы думаете о других ограничениях. Обратите внимание, что хотя обращение с матрицей является простым способом ее понять, оно не является наиболее эффективным. Вы, вероятно, хотите использовать БПФ для этого.
Fabee

Ответы:

4

+1 к ответу Фаби, который завершен. Просто примечание, чтобы перевести его на R, основываясь на пакетах, которые я нашел для выполнения операций под рукой. В моем случае у меня были данные, которые представляют собой прогнозы температуры NOAA на трехмесячной основе: январь-февраль-март, февраль-март-апрель, март-апрель-май и т. Д., И я хотел разбить их на (приблизительные) месячные значения, предполагая, что температура каждого трехмесячного периода по существу является средней.

library (Matrix)
library (matrixcalc)

# Feb-Mar-Apr through Nov-Dec-Jan temperature forecasts:

qtemps <- c(46.0, 56.4, 65.8, 73.4, 77.4, 76.2, 69.5, 60.1, 49.5, 41.2)

# Thus I need a 10x12 matrix, which is a band matrix but with the first
# and last rows removed so that each row contains 3 1's, for three months.
# Yeah, the as.matrix and all is a bit obfuscated, but the results of
# band are not what svd.inverse wants.

a <- as.matrix (band (matrix (1, nrow=12, ncol=12), -1, 1)[-c(1, 12),])
ai <- svd.inverse (a)

mtemps <- t(qtemps) %*% t(ai) * 3

Который прекрасно работает для меня. Спасибо @fabee.

РЕДАКТИРОВАТЬ: ОК, обратно переводя мой R на Python, я получаю:

from numpy import *
from numpy.linalg import *

qtemps = transpose ([[46.0, 56.4, 65.8, 73.4, 77.4, 76.2, 69.5, 60.1, 49.5, 41.2]])

a = tril (ones ((12, 12)), 2) - tril (ones ((12, 12)), -1)
a = a[0:10,:]

ai = pinv (a)

mtemps = dot (ai, qtemps) * 3

(Для отладки которого потребовалось намного больше времени, чем для версии R. Во-первых, я не так хорошо знаком с Python, как с R, но также потому, что R гораздо удобнее использовать в интерактивном режиме.)

Wayne
источник
@Gracchus: Извините, не парень C ++, но вы можете найти то, что вам нужно, в библиотеке линейной алгебры C ++ Armadillo ( arma.sourceforge.net ), которая также доступна в R через пакет RcppArmadillo.
Уэйн
Хорошо, посмотрим, работает ли это для вас. Если это так, вы можете выбрать мой ответ ;-)
Уэйн
К сведению, лучшие практики в Python - это абсолютный импорт: python.org/dev/peps/pep-0008/#imports, который значительно упрощает чтение кода других людей, потому что вы на самом деле знаете, откуда берутся функции, вместо необходимости найдите каждого, кого вы не знаете. Хотелось бы, чтобы в R было то же самое. Необходимость поиска каждой маленькой функции в чужом коде действительно размалывает мои механизмы ...
WordsHorwise
Кроме того, ноутбуки Jupyter для интерактивности Python или IPython.
обратном порядке
17

Я пытаюсь выразить сказанное в ответе. Допустим, у вас есть большой вектор с n = 2000 записей. Если вы вычисляете скользящее среднее с окном длины = 30 , вы можете записать это как умножение векторной матрицы y = A x вектора x с матрицейxn=2000=30y=Axx

A=130(1...10...001...10...0...1...100...01...1)

которая имеет из них , которые сдвинуты по мере продвижения по рядам , пока 30 из них не попал в конец матрицы. Здесь усредненный вектор у имеет размеры 1970 года. Матрица имеет 1970 строк и 2000 столбцов. Следовательно, оно не обратимо.3030y19702000

Если вы не знакомы с матрицами, думать об этом как системы линейных уравнений: вы ищете для переменных таким образом, что в среднем в течение первых тридцати выходов у 1 , среднего по второй урожайности тридцать у 2 и так далее.x1,...,x2000y1y2

Проблема с системой уравнений (и матрицей) состоит в том, что в ней больше неизвестных, чем уравнений. Таким образом, вы не можете однозначно определить ваши неизвестных . Интуитивно понятная причина в том, что вы теряете измерения при усреднении, потому что первые тридцать измерений x не получают соответствующий элемент по y, поскольку вы не можете сместить окно усреднения за пределы x .x1,...,xnxyx

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

Другой, может быть проще, способ заключается в использовании Псевдообратного от A . Это порождает вектор z = A y, который имеет ту же размерность, что и x, и обладает свойством минимизации квадратичного расстояния между y и A z (см. Википедию ).AAz=AyxyAz

Кажется, это работает довольно хорошо. Вот пример, где я нарисовал примеров из гауссовского распределения, добавил пять, усреднил их и восстановил x по псевдообратному.2000x

восстановление исходного сигнала по скользящей средней с использованием псевдообратного

Многие числовые программы предлагают псевдообращения (например, Matlab, Numpy в Python и т. Д.).

Вот код Python для генерации сигналов из моего примера:

from numpy import *
from numpy.linalg import *
from matplotlib.pyplot import *
# get A and its inverse     
A = (tril(ones((2000,2000)),-1) - tril(ones((2000,2000)),-31))/30.
A = A[30:,:]
pA = pinv(A) #pseudo inverse

# get x
x = random.randn(2000) + 5
y = dot(A,x)

# reconstruct
x2 = dot(pA,y)

plot(x,label='original x')
plot(y,label='averaged x')
plot(x2,label='reconstructed x')
legend()
show()

Надеюсь, это поможет.

fabee
источник
Это отличный ответ, но я думаю, что вы ошибаетесь, когда говорите, что «он минимизирует квадратичное расстояние между y и Az». На самом деле y и Az - это одно и то же. Что минимизируется, так это норма z, которая хорошо работает с реальными сигналами, которые я пробовал, но не так хороша, если ваш исходный сигнал имеет много выбросов.
gdelfino
Я не уверен, что я следую. y и Ax это одно и то же, но не y и Az. Это правда, что это также минимизирует норму z. Я также не понимаю, почему это не работает для моих примеров. Синяя и красная линии очень хорошо совпадают. Я что-то упустил в вашем комментарии?
Fabee
y - скользящее среднее, вычисленное из исходного сигнала x путем умножения на A. Эта процедура дает нам сигнал z, который имеет то же самое скользящее среднее y. Следовательно, y = Az. Таким образом, только норма z сводится к минимуму. Если исходный сигнал имеет большое значение нормы, то процедура не даст хороших результатов. Ниже приведен пример сигнала с большим значением нормы:
gdelfino
{42,8, -33,7, 13,2, -45,6, 10,2, 35,8, -41,4, 20,253, 43,3429, -33,2735, 13,6135, -45,1067, 10,6346, 36,1352, -40,9703, 20,6616, 43,6796, -32,8966, 14,0406, -44,7001, 10,9988 , 36.4675, -40.7277, 20.8823, 43.7878, -32.7415, 13.9951, -44.7947, 11.044, 36.3873, -40.7117, 20.7505, 43.8204, -32.9399, 13.9129, -44.9549, 10.8703, 36.1559, -402.833. , 13.5468, -45.2374, 10.3787, 35.8235, -41.5161, 19.9717, 43.0658, -33.7125, 13.0321}
gdelfino
Пожалуйста, используйте размер окна 8 для сигнала выше. Таким образом, отфильтрованный сигнал очень отличается по форме от исходного сигнала.
Гдельфино