
лр1
.pdfМИНОБРНАУКИ РОССИИ САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА) Кафедра биотехнических систем
ОТЧЕТ по лабораторной работе №1
по дисциплине «Моделирование биологических процессов и систем»
ТЕМА: ВРЕМЕННЫЕ РЯДЫ. РАСЧЕТ СКОЛЬЗЯЩИХ СТАТИСТИК
Вариант 1
Студентка гр. 0501 |
________________ |
Слободина Ю.А |
Преподаватель |
|
Тероева Ю. А. |
|
|
|
Санкт-Петербург
2023

ЛАБОРАТОРНАЯ РАБОТА № 1
ВРЕМЕННЫЕ РЯДЫ. РАСЧЕТ СКОЛЬЗЯЩИХ СТАТИСТИК
ЦЕЛЬ РАБОТЫ: изучение влияния размера окна фильтра скользящего среднего на результаты фильтрации (на примере 10-ти
секундного тренда ЧСС).
Задачи: написать код, построить графики.
Основные теоретические положения
Временной ряд (Time Series) – это последовательность значений,
описывающих протекающий во времени процесс и измеренных в последовательные моменты времени (чаще - через равные промежутки).
В этой лабораторной работе на примере анализа 10-тисекундного тренда ЧСС рассмотрим такой метод анализа временных рядов как скользящее среднее (moving average). Он может быть полезен при анализе данных, собранных в результате длительного мониторинга (например, за неделю) или же для визуальной демонстрации наблюдаемых в данных зависимостей.
Скользящее среднее сглаживает колебания, наблюдаемые в данных, и
позволяет получить представление о тенденции или закономерности в данных. Полученный паттерн затем может быть использован в том числя для оценки будущих значений ряда (предсказание).
1.Простое скользящее среднее (SMA - Simple Moving Average)
2.Взвешенное скользящее среднее (WMA - Weighted Moving Average)
Формула для WMA использует разные веса для точек данных. Как правило, вес уменьшается с каждой точкой. Это позволит уменьшить факт
«отставания от реальности».

Выбор весов зависит от характера динамики исследуемого ряда.
Например, веса могут возрастать линейно или экспоненциально. В случае линейно взвешенной скользящей средней = .
Построению и простой, и взвешенной скользящих средних присущи два недостатка. Первый из них проявляется в том, что при расчете их значений учитываются только те значения ряда, которые охвачены окном.
Второй недостаток заключен в самом принципе расчета средних значений – при продвижении окна на один интервал времени значение скользящей средней реагирует на изменение дважды: первый раз значение скользящей средней изменится при включении в нее нового отсчета, второй раз – при выбытии этого значения из порядка скользящей средней.
Полный код программы
1. data = CSV.read("hr10.csv", DataFrame)
2.
3. test = collect(Int64, 10:10:100)
4.
5.fs = 0.1 #1 отчет на 10 секунд
6.# вариант 1, то есть наш фрагмент берем через 0.1 ч от начала записи
7.# то есть через 6 минут = 360 секунд
8.begin_ = Int(fs*360)
9.data = data[!,1]
10.data = data[Int(begin_):length(data)] #для графика всего массива
11.#data = data[begin_:66] #для визуализации работы фильтров в увеличенном
масштабе
12.
13.# входной сигнал inp - вектор точек
14.inp = data
15.#inp = test # для проверки на тестовых данных
16.out = fill(0.0, size(inp)) # выход - массив такой же длины
18.#slide_flt_mean_3 = SlideMeanFilter{eltype(inp)}(3)
19.#after_mean_3 = exe(slide_flt_mean_3, inp, out)
21.#out = fill(0.0, size(inp))
23.#slide_flt_mean_6 = SlideMeanFilter{eltype(inp)}(6)
24.#after_mean_6 = exe(slide_flt_mean_6, inp, out)
26.#out = fill(0.0, size(inp))
28.#slide_flt_mean_9 = SlideMeanFilter{eltype(inp)}(9)
29.#after_mean_9 = exe(slide_flt_mean_9, inp, out)
31.#out = fill(0.0, size(inp))
33.#slide_flt_linear_3 = SlideMeanFilter_Linear{eltype(inp)}(3)
34.#after_linear_3 = exe(slide_flt_linear_3, inp, out)
36.#out = fill(0.0, size(inp))
38.#slide_flt_linear_6 = SlideMeanFilter_Linear{eltype(inp)}(6)
39.#after_linear_6 = exe(slide_flt_linear_6, inp, out)
41.#out = fill(0.0, size(inp))
43.#slide_flt_linear_9 = SlideMeanFilter_Linear{eltype(inp)}(9)
44.#after_linear_9 = exe(slide_flt_linear_9, inp, out)
46.plot(inp, label = "inp") # график массива
47.
48.# получение графиков по заданию
49.#plot!(after_mean_3, label = "SMA_3", marker = :circle)
50.#plot!(after_mean_6, label = "SMA_6", marker = :circle)
51.#plot!(after_mean_9, label = "SMA_9", marker = :circle)
53.#plot!(after_linear_3, label = "LWMA_3", marker = :square)
54.#plot!(after_linear_6, label = "LWMA_6", marker = :square)
55.#plot!(after_linear_9, label = "LWMA_9", marker = :square)
Файл "lab-1_p_6.jl"
using CSV using Plots
using DataFrames
mutable struct SlideMeanFilter{T} buf::Vector{T} # кольцевой буфер k::Int # состояние фильтра
need_restart::Bool #маркер инициализации фильтра
# конструктор объектов типа SlideMeanFilterтребуется задать только
размер окна
function SlideMeanFilter{T}(window) where T new(fill(T(0), window - 1), 1, true)
end
end
#функция вызова фильтра (от execute)
#принимает аргумент типа SlideMeanFilter и одну точку сигнала
function exe(obj::SlideMeanFilter{T}, x::T) where T buf, k = obj.buf, obj.k
if obj.need_restart # инициализация на первой точке
#заполняем буфер первой точкой fill!(buf, x)
#отмечаем, что инициализация уже не требуется obj.need_restart = false
end
sum_x = x
#сумма всех элементов в буфере + 1 новая точка for xi in buf
sum_x +=xi
end
#собственно, сам расчет среднего
window = length(buf) + 1 y = sum_x / window
#в буфер записываем новую точку buf[k] = x
k += 1
#@show(buf)
#проверка, не кончился ли буфер
if k > length(buf)
# возвращаемся в его начало k = 1
end
# фиксируем состояние фильтра obj.k = k
return y
end
function exe(obj::SlideMeanFilter{T}, inp::AbstractVector{T}, out::AbstractVector) where T
for i in eachindex(inp) x = inp[i]
y = exe(obj, x) out[i] = y
end
return out
end
Файл «lab-1_p_8.jl»
using CSV using Plots
using DataFrames
mutable struct SlideMeanFilter_Linear{T} buf::Vector{T} # кольцевой буфер need_restart::Bool #маркер инициализации фильтра
# конструктор объектов типа SlideMeanFilterтребуется задать только
размер окна
window::Int
deminator::Int
function SlideMeanFilter_Linear{T}(window) where T deminator = sum(collect(Int64, 1:1:window)) new(fill(T(0), window - 1), true, window, deminator)
end
end
#функция вызова фильтра (от execute)
#принимает аргумент типа SlideMeanFilter и одну точку сигнала
function exe(obj::SlideMeanFilter_Linear{T}, x::T) where T buf = obj.buf
if obj.need_restart # инициализация на первой точке
#заполняем буфер первой точкой fill!(buf, x)
#отмечаем, что инициализация уже не требуется obj.need_restart = false
end
sum_x = x*obj.window #последний элмент умножаем на значение окна, это первое слагаемое
# сумма всех элементов в буфере + 1 новая точка for i in eachindex(buf)
sum_x += i*buf[i]
end
#вычисление среднего
y = sum_x /obj.deminator
temp = buf[2:length(buf)] # делаем срез от буфера со второго значения
и до конца
append!(temp, x) #добавляем х, получили новый буфер, "движение" окна по значениям
obj.buf = temp #обновляем буфер return y
end
function exe(obj::SlideMeanFilter_Linear{T}, inp::AbstractVector{T}, out::AbstractVector) where T
for i in eachindex(inp) x = inp[i]
y = exe(obj, x) out[i] = y
end return out
end
Файл «linear_v2.jl»
using CSV using Plots
using DataFrames
mutable struct SlideMeanFilter_lin_2{T} buf::Vector{T} # кольцевой буфер k::Int # состояние фильтра
need_restart::Bool #маркер инициализации фильтра window::Int
deminator::Int
# конструктор объектов типа SlideMeanFilterтребуется задать только
размер окна
function SlideMeanFilter_lin_2{T}(window) where T deminator = sum(collect(Int64, 1:1:window))
new(fill(T(0), window - 1), 1, true, window, deminator)
end
end
#функция вызова фильтра (от execute)
#принимает аргумент типа SlideMeanFilter и одну точку сигнала
function exe(obj::SlideMeanFilter_lin_2{T}, x::T) where T buf, k = obj.buf, obj.k
if obj.need_restart # инициализация на первой точке
#заполняем буфер первой точкой fill!(buf, x)
#отмечаем, что инициализация уже не требуется obj.need_restart = false
end
sum_x = x*obj.window
coeff = length(buf) - k + 1 #поправочный коэффициент для расчета линейного веса
# сумма всех элементов в буфере + 1 новая точка for i in eachindex(buf)
w = i + coeff # вычисление веса
if w > length(buf)
w = w - length(buf) # поправка с учетом кругового буфера
end
sum_x +=w * buf[i]
end
# собственно, сам расчет среднего
y = sum_x / obj.deminator
#в буфер записываем новую точку buf[k] = x
k += 1
#@show(buf)
#проверка, не кончился ли буфер if k > length(buf)
# возвращаемся в его начало k = 1
end
# фиксируем состояние фильтра obj.k = k
return y
end
function exe(obj::SlideMeanFilter_lin_2{T}, inp::AbstractVector{T}, out::AbstractVector) where T
for i in eachindex(inp) x = inp[i]
y = exe(obj, x) out[i] = y
end
return out end

Полученные графики
На рисунках 1-6 представлен входной сигнал и сигнал после разных видов скользящего среднего.
Рисунок 1 – График всего сигнала и после SMA с окном 9
Рисунок 2 – График сигнала и после SMA с окнами 3, 6, 9

Рисунок 3 – График сигнала и после LWMA с окнами 3, 6, 9
Рисунок 4 – График сигнала и после SMA и LWMA с окном 3