Как найти похожие события сигнала в python - PullRequest
2 голосов
/ 24 января 2020

У меня есть один сигнал, и теперь я хочу найти, что подобные события происходили несколько раз в этом сигнале. Например, на картинке ниже мы видим три события.

enter image description here

Я создал это, используя следующие значения:

import matplotlib.pyplot as plt


y = [
    0, 1, 2,
    .3, .4, .4, .6, .5, .4, .3, .4, .5, .6, .7, .6, .5, .4, .3, .5, .7, .8, .6, .3, .4, .5, .6, .5, .4, .3, #1
    .3, .3, .3, .3, .3, 5, 4,
    0, 1, 3, 4, 8, 9, 13, 10, 7, 4, 6, 3, 4, 3, #2
    .3, 4, 4.4, 4.3, 3, 3.4, 3.2, 4, 3.8, 4, 6, 6, 5, 4, 1,
    .3, .4, .5, .6, .5, .4, .3, .4, .5, .6, .7, .6, .3, .4, .3, .5, .7, .8, .6, .3, .4, .6, .6, .5, .4, .3,  # 1
    0, 1, 3, 4, 6, 9, 13.5, 9.5, 7, 4, 6, 3, 4, 3, #2
    .3, .4, .5, .4, .5, .4, .3, .4, .5, .6, .7, .6, .5, .4, .3, .5, .7, .8, .6, .3, .4, .5, .6, .5, .4, .3,  # 1
    0, 1, 3, 4, 8, 9, 14, 10, 7, 4, 6, 3, 4, 3, #2
    .3, 2, 1, 1,
    2, 3, 4, 4.5, 4, 3, 2, 3, 4, 4, 4, 3, 2, #3
    1,2,2,1,1,
    2, 3, 4, 4, 4, 3, 2, 3, 4, 5, 4, 3, 2, #3
    1,2,3, .2, .1, 0
]

plt.plot(y)
plt.show()

Первое событие: enter image description here

Второе событие: enter image description here

Третье событие: enter image description here

Первое событие произошло 3 раза, второе событие 3 раза и третье событие 2 раза. Они почти похожи. В реальной ситуации сходство будет немного меньше, чем показано на рисунке выше.

Теперь я хочу найти: 1. события подобного типа 2. насколько они похожи 3. где это произошло.

Например, первое событие произошло снова в:

timestamp | сходство

04 - 22 | 100%

60 - 90 | 95%

110 - 130 | 96%

Я хочу сделать это в python. Как я могу это сделать? Есть ли библиотеки для обработки сигналов для такого рода задач?

1 Ответ

0 голосов
/ 24 января 2020

Используя numpy, вы можете дифференцировать, используя numpy.diff, который может дать вам подсказку на основе определенного порога, в котором происходят ваши события. После того, как вы получите эти события, вы можете использовать numpy.correlate между вашими событиями и входным сигналом, чтобы найти наиболее вероятные места, где происходят события.

корреляция

дифференциация


Последующее наблюдение

Если вы хотите полностью автоматизировать его для любого произвольного сигнала, должно быть какое-то машинное обучение где-то там Я не буду давать вам машинное обучение всем go сразу. Я, однако, дам вам указания относительно того, какие параметры могут рассматриваться как факторы в вашем al go.

Взгляните на следующее

import matplotlib.pyplot as plt
import numpy as np

y = [0, 1, 2,
     .3, .4, .4, .6, .5, .4, .3, .4, .5, .6, .7, .6, .5, .4, .3, .5, .7, .8, .6, .3, .4, .5, .6, .5, .4, .3,
     .3, .3, .3, .3, .3, 5, 4,
     0, 1, 3, 4, 8, 9, 13, 10, 7, 4, 6, 3, 4, 3,
     .3, 4, 4.4, 4.3, 3, 3.4, 3.2, 4, 3.8, 4, 6, 6, 5, 4, 1,
     .3, .4, .5, .6, .5, .4, .3, .4, .5, .6, .7, .6, .3, .4, .3, .5, .7, .8, .6, .3, .4, .6, .6, .5, .4, .3,
     0, 1, 3, 4, 6, 9, 13.5, 9.5, 7, 4, 6, 3, 4, 3,
     .3, .4, .5, .4, .5, .4, .3, .4, .5, .6, .7, .6, .5, .4, .3, .5, .7, .8, .6, .3, .4, .5, .6, .5, .4, .3,
     0, 1, 3, 4, 8, 9, 14, 10, 7, 4, 6, 3, 4, 3,
     .3, 2, 1, 1,
     2, 3, 4, 4.5, 4, 3, 2, 3, 4, 4, 4, 3, 2,
     1, 2, 2, 1, 1,
     2, 3, 4, 4, 4, 3, 2, 3, 4, 5, 4, 3, 2,
     1, 2, 3, .2, .1, 0
     ]

x = 5                                               #Mean Convolution Window Width
v = np.full(x,1/x)                                  #Convolution vector
y=np.convolve(y,v)                                  #Apply X-Width Convolution on signal to get average between X samples
diff_y = np.abs(np.diff(y))
plt.figure()
plt.plot(diff_y)
plt.show()

diff_y_filtered=diff_y
diff_y_filtered[diff_y < 0.20*np.nanmax(diff_y)] = 0 #Differientiate the signal to look for large variations
plt.figure()
plt.plot(y)
plt.plot(diff_y_filtered)
plt.show()

diff_y_peaks = np.diff(diff_y_filtered)                                         #Second derivative
diff_y_peaks = np.convolve(diff_y_peaks,[-1/8,-1/4,-1/2,1.75,-1/2,-1/4,-1/8])   #You may wanna tweak the filter
plt.figure()
plt.plot(diff_y_peaks)
plt.show()

diff_y_peaks[diff_y_peaks < 0.5] = 0;               #This is a parameter that would be tweaked
diff_y_peaks[diff_y_peaks > 0]=np.nanmax(y)         #Make things pretty
plt.figure()
plt.stem(diff_y_peaks)
plt.plot(y)
plt.show()

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

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

Затем я фильтрую второй раз и снова сворачиваюсь. Вы можете настроить этот фильтр, чтобы получить лучшие результаты. Некоторые фильтры находят больше возможных точек отсечки, а некоторые - меньше. Это не имеет большого значения, если вы получаете много точек отсечки рядом друг с другом, потому что вы можете обучить свою модель, чтобы найти слишком малые длины событий, или вы можете напрямую указать, что, скажем, 2 точки отсечки на расстоянии 5 выборок не составляют событие.

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

...