Прогнозна модель ухвалювала рішення на основі рядів приблизно від 10 000 зовнішніх джерел у різних форматах (XML, Excel, CSV), де дані надходили з пропусками, викидами і без контексту походження, а лік записів ішов на мільярди.
Побудували конвеєр із незалежних мікросервісів-розбирачів на Python, які паралельно приводять різнорідні формати до спільного вигляду, без дублів завантажують їх у сховище часових рядів разом із паспортом об'єкта і з очищених рядів збирають датасети для моделі.
Розбір перестав бути послідовним вузьким місцем - джерела обробляються паралельно, а прогноз повертається в систему готовою машиночитаною заявкою, звітами й графіками замість ручного зведення файлів.
Рішення на завтра починається далеко від моделі
Щодня організація вирішує, купити чи продати актив на найближчу добу-дві. Помилка в прогнозі швидко перетворюється на реальні гроші, тому результат моделі має спиратися на дані, яким можна довіряти.
До моделі ці дані проходять довгий шлях. Вони надходять приблизно від 10 000 зовнішніх джерел, і лік записів від самого початку йде на мільярди. Один об'єкт віддає XML, інший - Excel чи CSV. Частота вимірювань різниться, у рядах трапляються пропуски та викиди, а саме число без контексту не пояснює, де і що виміряли.
Наша частина проєкту була саме тут: між сирим вивантаженням та готовим датасетом. Потрібно було зібрати десятки гігабайтів різнорідної історії, привести її до спільного вигляду й не втратити зміст по дорозі.
Візьмемо одне вимірювання та проведемо через увесь конвеєр
На вхід надходить черговий файл або порція даних від зовнішнього об'єкта. Спершу спеціалізований розбирач розпізнає формат, видобуває часовий ряд і пов'язує його з джерелом. Потім дані проходять чистку, потрапляють у сховище часових рядів і перетворюються на вектори, над якими можна рахувати формули. З готових векторів фахівець збирає датасет для моделі.
Після розрахунку шлях триває: прогноз повертається в систему, з'являється у звітах і графіках, а потім перетворюється на структурований файл заявки для зовнішньої системи-приймача. Цінність виникає лише тоді, коли число доходить до конкретної дії.
Десять тисяч джерел не можна розбирати послідовно
Послідовна обробка такого обсягу забирала б години, тому розбір поділено на незалежні мікросервіси на Python і розподілено по різних серверах. Джерела обробляються паралельно, а збій одного розбирача не потребує зупиняти весь потік.
Кожен формат ізольований від решти системи. Якщо один постачальник змінює структуру файлу, коригується його розбирач; сховище, чистка, векторний шар і моделі й далі працюють із попереднім внутрішнім представленням.
Завантаження ідемпотентне. Повторно надісланий файл або повторний запуск не створюють другої копії тих самих записів. Перед завантаженням система звіряє, що вже оброблено, і не тягне розібрані дані в базу заново. Це дає змогу безпечно перезапускати задачі після збою, не очищаючи результат вручну.
Число отримує паспорт об'єкта
Часовий ряд зберігає послідовність значень, але зміст перебуває поряд. Для кожного об'єкта є паспорт: назва, координати та атрибути, які пояснюють походження вимірювання і його місце в загальній структурі.
Без такого паспорта два однакові числа можуть стосуватися різних об'єктів і описувати різні процеси. Тому сховище з'єднує історію вимірювань із довідковими таблицями, а не складає все в одну широку таблицю без контексту.
Спеціалізована база часових рядів тримає роки історії з подобовими чанками та компресією. Агрегати для графіків будуються на запит, тому заради кожного нового періоду не потрібно заздалегідь створювати ще одну копію даних.
| Шар | Що він зберігає | Навіщо це наступному етапу |
|---|---|---|
| Паспорт об'єкта | Назва, координати та атрибути | Ряд не втрачає походження та зміст |
| Часовий ряд | Значення за часом | Можна аналізувати історію та будувати агрегати |
| Чистий вектор | Зіставний ряд без технічного сміття | Формули та моделі отримують єдине представлення |
| Датасет | Обрані вихідні та похідні ознаки | Модель навчається на наборі під конкретне завдання |
Чистка має відрізнити помилку від важливого сплеску
У вимірюваннях неминучі пропуски та значення, що вибиваються із загального ряду. Перед розрахунками конвеєр заповнює прогалини та прибирає викиди, щоб випадковий провал або технічний стрибок не спотворив навчання.
Але агресивна чистка небезпечна не менше за брудні дані. Реальний сплеск може бути якраз тією подією, що впливає на прогноз. Тому підготовка ряду має прибрати технічне сміття й водночас зберегти значущі зміни вихідного процесу.
Чистий ряд не означає ідеально гладкий. Якщо вирівняти всі різкі зміни, разом із помилками зникнуть події, заради яких будується прогноз.
Ця робота відбувається до того, як дані побачить модель. У результаті фахівець порівнює зіставні ряди, а не пояснює алгоритму, чому в одному джерелі пропущено годину, а в іншому випадково з'явилася неможлива величина.
Формула збирає новий ряд без ручного вивантаження
Очищені ряди приводяться до єдиного векторного представлення. Над векторами можна виконувати арифметику: додавати, віднімати, множити й ділити один ряд на інший. Так із вихідних вимірювань з'являються похідні ознаки.
Калькулятор зберігає формулу й виконує її над рядами прямо в контурі даних. Аналітику не доводиться вивантажувати десятки файлів, зводити стовпці вручну й повторювати ту саму роботу для наступного періоду. Він обирає потрібні вихідні та похідні вектори й збирає датасет під конкретну модель.
Шар машинного навчання вів окремий фахівець. Конвеєр передавав йому підготовлені датасети та приймав прогноз назад. Такий поділ важливий: якість підготовки можна розвивати незалежно від конкретної моделі, а модель не має щоразу заново виконувати завдання збору й очищення.
Прогноз повертається як готова заявка
Результат розрахунку використовується у звітах і графіках, але на цьому процес не закінчується. Система формує машиночитну заявку - структурований файл, який приймає зовнішня система. Прогноз не залишається клітинкою, яку людина має вручну перенести й заново витлумачити.
Ручний ланцюжок "зібрати файли, розібрати, почистити, звести, порахувати" перетворюється на повторюваний конвеєр. Фахівець працює з бібліотекою рядів і формул, модель отримує підготовлений датасет, а підсумок доходить до контуру ухвалення рішень.
Далі доби-двох невизначеність зростає
Робочий горизонт прогнозу - найближча доба-дві. Система може розрахувати й дальший період, але точність закономірно знижується разом із горизонтом. Це властивість вихідної задачі, а не дефект сховища чи конвеєра.
Сам конвеєр також не робить погане джерело добрим автоматично. Його результат залежить від повноти даних, коректності паспортів і правил чистки. Він показує та готує доступну історію, але не може відновити зміст, якого джерело від початку не передало.
Архітектура при цьому допускає зростання без заміни основи: підключення нових джерел і форматів, розширення бібліотеки формул, нові датасети та щільніший зв'язок із моделями й зовнішніми системами. Кожен новий формат отримує власний розбирач, а вже очищені ряди й далі проходять спільний шлях.
Це реальний проєкт, поданий знеособлено. Впізнавані деталі - галузь, конкретику, усе, за чим можна визначити замовника, - ми навмисно змінюємо; ім'я та комерційні таємниці замовника не розкриваємо. Незмінною лишається суть: яке завдання розв'язували і яким інженерним підходом. Кейс написано, щоб показати проблему та її вирішення - що і як ми робимо.

