pamsbel 0.0.2
A module for the multiple signals predictive analysis
Requires Python: >=3.7

Модуль pamsbel (Predictive Analysis of the Multiple Signals from Belgorod - Предиктивный анализ множественных сигналов из Белгорода) предназначен для прогнозирования будущего значения векторного временного ряда (то есть, нескольких согласованных во времени временных рядов) на основе имеющейся истории их значений и заданной временной дискретности. 
Для использования модуля в настоящее время требуются данные в csv-файлах - отдельно по каждому сигналу, а также отдельно обучающие и пробные данные. Далее следует теоретическое описание работы анализатора, а также инструкция по использованию

Теоретическое описание

Предположения:
Существует некоторый базовый уровень сигнала - это периодическая функция, имеющая конечное число гармоник. Отклонения значений сигнала от базового уровня подчиняются нормальному распределению.
Сигналы со значениями выше и ниже базового уровня на порядок (в 10 раз), считаются выбросами и не анализируются.
Имеется достаточное количество сигналов, не являющихся выбросами, в обучающих данных.
Модель прогноза – авторегрессия. Длина окна авторегрессии является параметром обучения.
Модель использует разбиение сигналов на пакеты. Пакет ограничивается временным промежутком, внутри которого приходящие сигналы усредняются. 
Прогноз выдается в виде предсказанных средних сигналов в следующем после пробных данных t-м периоде (по умолчанию t=1).

Алгоритм обучения

Вход: csv-файлы с заголовками «Время, Значение» и набором значений для каждого сигнала (один сигнал - один csv-файл); длина временного промежутка, соответствующего пакету данных (bucket_size); максимальная длина окна регрессии (число пакетов - limit_window); минимально допустимая длина обучающих данных для регрессии (min_butches), по умолчанию 5.
Выход: коэффициент детерминации (R2); ширина окна регрессии (window); коэффициенты регрессии (rcoeffs); смещение регрессии (rintercept); словари для преобразования сигналов в одно число (xdict); список zkt_list, содержащий для каждого сигнала его минимальное натуральное значение (zmin), порядок перехода к натуральному числу (k), временной сдвиг начала отсчета (timeshift). 
Процедура:
Фильтрация плохих данных для каждого сигнала по п. 3 Предположений.
Разбиение данных на пакеты по времени. Период пакета далее называется просто периодом. Внутри периода показания усредняются. Если хотя бы один сигнал отсутствует - сигнал в периоде равен 0. Получаем данные по периодам – векторный временной ряд.
Делаем векторы целочисленными, используя принцип последнего наибольшего изменения энтропии. Запоминаем порядок перехода к натуральным значениям (k), натуральный сдвиг (zmin) и временной сдвиг (timeshift) для каждого сигнала.
Объединяем сигналы в один сигнал с помощью модуля genser с сохранением словарей объединения xdict. Получаем числовой временной ряд.
Устанавливаем R2=0.
Запускаем цикл от 1 до limit_window с переменной цикла window. 
Разбиваем временной ряд на корректные последовательности периодов для построения регрессий: выбираем все такие последовательности  из  непустых периодов из ряда, что -й период после последнего члена последовательности не пуст и имеет значение .
Строим коэффициенты авторегрессии coeffs на всех парах  для всех имеющихся . 
Вычисляем R2 для построенной авторегрессии. Если он оказался больше текущего R2, обновляем R2 и записываем текущие window, R2, coeffs, intercept, соответственно, в результирующие значения rwindow, rR2, rcoeffs и rintercept. 
Петля цикла, начатого на шаге 6.
Выдаем ответ в виде R2, rwindow, rcoeffs, rintersept, xdict, [zmin, k, timeshift] (последний список - свой для каждого сигнала).

Алгоритм детектирования аномалии

Вход: csv-файлы с заголовками «Время, Значение» и набором значений для каждого сигнала (пробные сигналы); значения из алгоритма обучения (bucket_size, rwindow, rcoeffs, rintersept, xdict, [zmin, k, timeshift]).
Выход: предсказанные значения сигнала на период t после окончания пробного вектора данных. 
Процедура:
Фильтрация плохих данных для каждого пробного сигнала.
Разбиение данных на пакеты по времени. Период пакета далее называется просто периодом. Внутри периода показания усредняются. Если хотя бы один сигнал отсутствует - сигнал в периоде равен 0. Получаем данные по периодам – векторный временной ряд.
Делаем векторы целочисленными, используя уже имеющиеся параметры k, zmin и timeshift для каждого сигнала. 
Объединяем сигналы в один сигнал с помощью функции transform_with, использующей возможности модуля genser. Получаем временной ряд из целых чисел. 
Строим прогноз с помощью имеющихся параметров регрессии rcoeffs, rintersept. Получаем одно число.
С помощью transform_out_up и словарей xdict, получаем целые числа для каждого сигнала. 
С помощью k, zmin и timeshift, вычисляем значения сигналов в их единицах для периода t и выдаем их. 

Инструкция по использованию функций модуля

Функция find_regression
find_regression(signals, bucket_size, tpred, min_butches = 5, limit_window = 200)
Имеет атрибуты:
	signals: это список имен csv-файлов с обучающими данными (один файл - один сигнал);
	bucket_size: длина периода пакета (вещественное число, в единицах времени, принятых в колонках Время csv-файлов);
	tpred: номер предсказываемого периода (обычно 1);
	min_butches: минимально допустимая длина обучающих данных для регрессии (в периодах), по умолчанию - 5;
	limit_window: максимальная длина окна регрессии, по умолчанию - 200.
Выдает: 
	коэффициент детерминации (число от 0 до 1), 
	ширину окна регрессии (натуральное число), 
	массив коэффициентов регрессии (одномерный массив numpy), 
	смещение регрессии (вещественное число), 
	словари объединения сигналов (xdict, описано выше), 
	список списков значений zmin, k, timeshift для каждого сигнала (расшифровано выше).

Функция mpredict
mpredict(testdatas, bucket_size, window, coeffs, intersept, zkt_list, xdict, tpred)
Имеет атрибуты:
	testdatas: это список массивов тестовых данных (один двумерный массив numpy - один сигнал);
	bucket_size: длина периода пакета (обязательно такая же, как при обучении);
	window: ширина окна регрессии, взятая из обучения.
	coeffs: массив коэффициентов регрессии (одномерный массив numpy), полученный при обучении; 
	intersept: смещение регрессии (вещественное число), полученное при обучении; 
	zkt_list: список списков значений zmin, k, timeshift для каждого сигнала, полученные при обучении;
	tpred: номер предсказываемого периода, тот же, что использовался при обучении.

Пример использования:

bucket_size = 3.55
tpred = 1
signals = ['data_signal_1.csv','data_signal_2.csv','data_signal_3.csv']
R2, window, rcoeffs, rintersept, xdict, zkt_list = find_regression(signals, bucket_size, tpred)
print(R2, window, rcoeffs, rintersept, xdict, zkt_list)

(0.8594218863432357,
 201,
 array([ 0.12990423,  0.07990346, -0.17805474, -0.0080245 ,  0.11820415,
         0.10865325,  0.06294693,  0.00173738,  0.00984271, -0.06253231,
        -0.02017544,  0.0537714 ,  0.25662127, -0.00155052,  0.00733356,
         0.16420553,  0.13150763,  0.07468324, -0.04135923,  0.06313589,
         0.01695072,  0.05983484, -0.04219053,  0.03892356, -0.08088054,
         0.13710962, -0.04676385, -0.16324633,  0.00902921, -0.01515911,
         0.054173  , -0.03246742,  0.08942269, -0.04380646, -0.00170435,
         0.01234265,  0.06826053,  0.05829495,  0.04432922, -0.0709024 ,
        -0.03105618, -0.05997907, -0.05744114, -0.15358585, -0.06736983,
         0.04515696, -0.01735742, -0.00477754, -0.01677818, -0.17889376,
         0.02830902,  0.0661404 ,  0.00255517, -0.07447113, -0.18399365,
        -0.00583392, -0.01132818, -0.07397917, -0.12788764, -0.10439693,
         0.02106017, -0.06519662,  0.01724907, -0.145595  , -0.06093818,
        -0.13488975,  0.09538773,  0.02381783, -0.05334055,  0.04224518,
        -0.06488874, -0.059401  ,  0.0045413 , -0.01051061, -0.03483464,
        -0.01949424, -0.02517046, -0.04038027,  0.03053969, -0.0504194 ,
        -0.10746171,  0.0068395 ,  0.10245972, -0.02944012, -0.00044645,
         0.01098932,  0.00242725, -0.02600154,  0.11259209, -0.05399829,
         0.07909833, -0.00302023,  0.04604326, -0.09397503, -0.0085805 ,
         0.01982022, -0.00154714, -0.0246451 ,  0.11752231, -0.01533724,
        -0.00758767,  0.02908908, -0.03994337,  0.00555571,  0.05408896,
         0.03629997,  0.06401169,  0.05889061, -0.04640827,  0.02393655,
        -0.00792111,  0.09433468, -0.15593704,  0.07660249,  0.02977611,
        -0.08176336, -0.08181442, -0.02828463,  0.04717065, -0.09169298,
         0.0810152 ,  0.12372397,  0.04228278, -0.00978288,  0.10683852,
        -0.17383107,  0.05090237, -0.05361853, -0.01668086, -0.01995553,
         0.05417718, -0.0697921 , -0.09706373,  0.01244864,  0.09458851,
        -0.07438107, -0.05463491, -0.07461752,  0.02698491,  0.08094443,
         0.05227155, -0.05949204, -0.06271673,  0.16010253, -0.03977753,
        -0.00142912,  0.07223468,  0.11962645, -0.11633341,  0.0606028 ,
         0.08651576, -0.03371849,  0.0675592 ,  0.00569065,  0.03602324,
         0.04041169,  0.12574673,  0.01700858,  0.02722169,  0.05284299,
         0.04935053,  0.05136423,  0.09106281, -0.01807883, -0.05470435,
         0.049454  ,  0.03777484,  0.07440139,  0.17051863,  0.0193165 ,
        -0.0118531 ,  0.04529961,  0.06557775, -0.00150094,  0.04434032,
        -0.03500737,  0.05947388, -0.09727509,  0.08738783, -0.04152743,
        -0.09853266, -0.12521105, -0.0510732 ,  0.03633801, -0.01984226,
        -0.04327667, -0.10741304, -0.0196117 ,  0.10361669,  0.03995349,
        -0.13559598, -0.03676163, -0.02387323, -0.05416748,  0.0466902 ,
        -0.06452942, -0.061337  , -0.07678691, -0.03125047,  0.08163181,
        -0.03220542]),
 122559005665.17397,
 [([337022333175], {0: 16355, 1: 20606685}),
  ([16355, 20606685], {1: 11715, 2: 1759})],
 [[8224, 4, 1.8154075205739213],
  [14951, 4, 0.2922640916926331],
  [2165, 3, 0.479827145278759]])

testdatas = [np.genfromtxt(signal,  delimiter=',',  dtype = None,  skip_header = 1)[-1000:] for signal in signals]
pred_signals = mpredict(testdatas, bucket_size, window, rcoeffs, rintersept, zkt_list, xdict, tpred)
print(pred_signals)

[1.9656, 2.396, 3.817]