Створення набору даних «Моніторинг військових кораблів» за допомогою GenAI-підходу

💡 Усі статті, обговорення, новини про AI — в одному місці. Приєднуйтесь до AI спільноти!

Мене звати Петро, я — дослідник даних (Data Scientist) у Data Science Group компанії SoftServe. Трохи більше двох років тому я опублікував статтю «Чотири набори даних про війну». Згадані там набори оновлюються та залишаються актуальними досі. Їх використовують як ентузіасти із цікавості до теми, даних чи України, так і аналітики для досліджень війни із публікацією результатів в блогах, статтях тощо. Ці набори даних було створено або вручну, або за допомогою скрапінгу певних вебресурсів.

За останні два роки у світі з’явились технології, які надали нові можливості для розв’язання багатьох задач, в тому числі й для роботи з наборами даних. Вже за кілька місяців після виходу Великої Мовної Моделі (ВММ) ChatGPT-3.5 в листопаді 2022 року почався бум Generative AI (GenAI), який триває досі. З’явились нові BММ (Gemini, Llama, Anthropic, Mistral), моделі для генерування зображень, відео та коду, і, нарешті, мультимодальні ВММ. Сотні нових компаній та стартапів пропонують найрізноманітніші продукти та інструменти на основі GenAI. Багато GenAI-проєктів та інструментів зібрано в цій добірці.

Вступ

В цій статті я б хотів поділитися методом створення набору даних, використовуючи один із можливих GenAI-підходів. Нижче описано всі етапи створення набору даних, починаючи від ідеї, процесу розроблення, тестування, візуалізації та до публікації на платформі Kaggle.

Працюючи над попередніми наборами даних, я помітив, що Військово-Морські Сили Збройних Сил України (ВМС ЗСУ) публікують інформаційні повідомлення про стан ворожих кораблів в акваторії Азовського, Чорного та Середземного морів у своїх соціальних мережах. Ця інформація дуже часто поширюється в інші публічні мілітарні та не тільки групи, канали тощо. Особливо часто ці пости починають поширювати, коли відносно довго не було масованих ракетних атак, а в море виходять носії крилатих ракет «Калібр» із великим загальним залпом.

Інформаційне повідомлення публікується кожного дня і складається із картинки та тексту (рис.1), які повторюють одну й ту ж інформацію в різній репрезентації. Воно несе певний інформаційний зміст в конкретний день, але цього замало, щоб зробити хоча б якийсь аналіз руху чи періодів перебування кораблів в морі, прослідкувати тенденцію чи, можливо, прив’язати ці дані до іншого набору.


Рис. 1. Приклад інформаційного повідомлення ВМС ЗСУ про стан ворожих кораблів у морських акваторіях від 17 січня 2025 року

Ідея полягає в тому, щоб зробити структурований набір даних у вигляді окремого файлу про моніторинг ворожих військових кораблів у морських акваторіях на основі всіх опублікованих постів. Тобто я очікую на виході файл, де кожен рядок буде репрезентувати одне повідомлення (швидше за все інформацію в певний час доби одного дня) та містити інформацію (таблиця 1) згідно з зображенням та текстом з рисунку 1.

День

Ворожі кораблі у Чорному морі

Носії

Калібру у Чорному морі

Загальний залп у Чорному морі

Ворожі кораблі у Азовському морі

Носії

Калібру у Азовському морі

Загальний залп у Азовському морі

Ворожі кораблі у Середземному морі

Носії

Калібру у Середземному морі

Загальний залп у Середземному морі

2025-01-17

0

0

0

0

0

0

7

2

22

Щоб втілити цей задум, я виділив три окремі завдання, послідовне розв’язання кожного з яких повинно забезпечити успіх проєкту загалом. Виконання завдань можна здійснювати різними шляхами, про вибір підходів до реалізації кожного із них я розповім у наступних розділах. На загальній архітектурі проєкту (рисунок 2) ці три завдання зображені у вигляді окремих структурних блоків:

  • підготовка даних;
  • відбір зображень;
  • витягування інформації із зображень.

Рис. 2. Архітектура проєкту

Підготовка даних

Знайти необхідні для створення набору даних інформаційні повідомлення можна у Telegram-каналі чи на Facebook-сторінці ВМС ЗСУ.

Через відкритий доступ до API та попередній досвід роботи основним джерелом даних було обрано Telegram. Розроблений модуль дозволяє отримати всі інформаційні повідомлення та зображення з досліджуваного Telegram-каналу від початку його створення (за потреби функціональність можна розширити для завантаження відео чи файлів).

Telegram-канал було створено в середині вересня 2020 року, але регулярно контент почав з’являтися після початку війни в липні 2022 року. Зараз, на основі даних за останній місяць, в каналі публікують в середньому 6-7 постів кожного дня. Всього було завантажено понад 9 тисяч зображень (понад 2 Гб) та 10 тисяч текстових рядків, сформованих в csv-файл (рисунок 3). Ці дані містять україномовні тексти та можуть бути цікаві у дослідженні публікацій ВМС ЗСУ чи бути включені після фільтрації в більший мовний корпус. Кожному рядку файла відповідає окремий пост чи зображення, який містить наступну метаінформацію:

  • `id` - id посту;
  • `text` - текстове повідомлення;
  • `date` - час створення посту;
  • `views` - кількість переглядів на день отримання даних;
  • `img_path` - назва завантаженого зображення;
  • `reactions` - кількість реакцій на час отримання даних;
  • `date_create` - дата отримання даних.

В процесі роботи з API хотілось би виділити дві особливості. Перша — зображення з одного посту мають різні id та можуть бути збережені як окремий рядок в таблиці без тексту. До назви зображення додається суфікс у вигляді порядкового номера. Тобто окремим постом для цього Telegram-каналу можна вважати тільки той, який містить текстове повідомлення, а у назві зображення не має порядкового суфікса.

Друга особливість — функцональність API дозволяє продовжувати завантаження контенту, починаючи з останнього вказаного посту. Тобто для подальшого доповнення даних достатньо вибрати потрібне іd. В нашому конкретному випадку це буде id=10767 (рисунок 3).


Рис. 3. Таблиця всіх постів Telegram-каналу ВМС ЗСУ

Відбір зображень

Так само як і тексти Telegram-каналу, зображення, які їх супроводжують, дуже різноманітні. Вони стосуються втрат противника, рекрутингу, здобутків на полі бою, моніторингу кораблів тощо. Для цього проєкту потрібно вибрати тільки зображення, які відповідають патерну із рисунка 1. Інформаційні пости із подібними зображеннями почали з’являтися в каналі на постійній основі, починаючи з серпня 2022. За дуже приблизними оцінками й припущенням, що було зроблено один інформаційни пост в день, потрібно відібрати близько 900 зображень, що становить 10% від загальної кількості.

В мене було кілька припущень, як можна зробити автоматизований вибір необхідних зображень, кожне з яких мало різний рівень складності. Було обрано найпростіший підхід з точки зору виконання — знайти повторюваний патерн в текстах до постів, відфільтрувати текстовий набір даних згідно з патерном, скопіювати відповідні зображення в окрему папку та візуально оцінити результат.

Розглянувши пару десятків текстів, що публікувались в різні проміжки часу (рисунок 1), я зупинився на дуже простому, але постійно повторюваному патерні «станом на». Як не дивно, але він спрацював на 100%. У нову папку проєкту було скопійовано майже 650 зображень із 900 очікуваних, а це понад 70%. Під час тестування відібраних зображень стало відразу візуально помітно, що це саме ті зображення, на які я очікував. Серед них теж дуже чітко вирізнялись аутлеєри — зображення, які скопійовані через вибраний патерн, але не мають стосунку до моніторингу кораблів. Оскільки їх було всього близько 20, то я просто вручну видалив їх із папки.

Залишилось з’ясувати, чому серед скопійованих зображень відсутні 30% очікуваних. У початково завантажених 9 тисяч зображеннях їх не було виявлено. Дослідження періодів часу відсутності зображень дало чіткі дати, коли вони мали бути опубліковані. Таких періодів було кілька, деякі із них були більш як 10 днів, деякі — в один чи кілька днів. Швидкий перегляд Telegram-каналу в ці дати дав зрозуміти, що їх не публікували із невідомих мені причин. Проте проглянувши відповідні дати на фейсбук-сторінці, я виявив, що там їх публікували. Було прийнято рішення витратити зайву годину часу та вручну завантажити зображення для періодів відсутності понад 10 днів. Таким чином вдалося доповнити набір ще на 170 зображень.

Отож, загалом вийшло майже 800 зображень, і це близько 90% від максимально очікуваної кількості. Візуально проаналізувавши відібрані зображення, я помітив, що використовувались як мінімум 4 різні типи дизайну (рисунок 4) для їх створення. Це може бути потенційною проблемою для наступного кроку витягнення структурованої інформації із зображень.

Водночас ці чотири типи зображень для одного й того ж типу повідомлень дозволяють побачити еволюцію дизайну Військово-Морських Сил ЗСУ.






Рис. 4. Еволюція дизайну інформаційних повідомлень ВМС ЗСУ

Витягування інформації

Тепер можна перейти до основного, хоча й не останнього розділу статті. Хоча він і є завершальним етапом проєкту зображеного на рисунку 2, але насправді першим, що я зробив після виникнення ідеї, був маленький POC (proof of concept). Я перевірив за допомогою UI кількох мультимодальних LLMs можливість витягування необхідної інформації із зображень в структурованому вигляді. Тільки після того, як я переконався в цьому, було зроблено описані вище кроки.

Оскільки інформаційні повідомлення містять як текст, так і зображення, то можна розглянути як мінімум два різні підходи до формування структурованих даних. Перший — використати за основу NLP (Natural Language Processing) та працювати із текстами. Другий — використати CV (Computer Vision) підходи до зображень. В цей момент часу можна ще більше спростити собі життя, використати ВММ до тексту чи мультимодальну ВММ до зображень та GenAI-підходи. Зокрема, для виконання цього завдання без класичних NLP та CV-методів.

POC. В цій фазі проєкту я використав безкоштовні версії Gemini-1.5-Flash із Gemini Chat (Google), ChatGPT-4o-mini із Chat GPT (OpenAI) та Gemini-2.0-Flash-Experimental із AI Studio (Google). Оскільки отримані результати мене задовольняли, я не пробував експериментувати із платними версіями чи іншими моделями.

Серед вищезгаданих трьох кандидатів ВММ я зупинився на Gemini-2.0-Flash-Experimental із наступних причин:

  • бажаний структурований результат досягався простішим пропмтом;
  • хотілось попрацювати із зображеннями;
  • хотілось протестувати можливості нової моделі (вона досі експериментальна);
  • хотілось спробувати новий продукт AI Studio від Google (тепер можна користуватися не тільки Vertex AI).

Промпт. Основою багатьох сучасних проєтів на основі GenAI є промпт. Інколи розробка промпта потребує багато часу, додаткових даних та нестандартного підхіду. Проте для цього завдання все було більш-менш швидко, як по часу, так і по зусиллях. Можливо, це пов’язано із вибором моделі.

Дуже простий промпт «Промпт_1» до моделі на тестових зображеннях дозволяв завжди отримувати правильні числа на виході, але сам вихідний JSON-формат не завжди був однаковий. Інколи частково змінювались назви ключів чи структура самого JSON-об’єкта. Серед згенерованих варіантів JSON-схем було обрано як стандарт ту, яка найкраще описувала структуру вихідних даних. Розширення схемою промпту «Промпт_2» дозволило отримувати стабільні результати на виході без змін у структурі JSON-об’єкта.

Варто відзначити, що вихідна інформація завжди автоматично перекладається на англійську, хоча сам текст на зображенні українською. Для збереження мови оригіналу треба додавати спеціальну інструкцію до промпту.

Промпт_1.

Extract information from an image. The output must be provided in JSON format. Write the JSON output and nothing more.

Промпт_2.

Extract information from an image. The output must be provided in JSON format.
Example output:
{
  "date": <%Y-%m-%d> or <%Y-%m-%d %m:%s>,
  "black_sea": {
    "enemy_ships": <number>,
    "kalibr_carriers": <number>,
    "total_salvo": <number>
  },
  "azov_sea": {
    "enemy_ships": <number>,
    "kalibr_carriers": <number>,
    "total_salvo": <number>
  },
  "mediterranean_sea": {
    "enemy_ships": <number>,
    "kalibr_carriers": <number>,
    "total_salvo": <number>
  },
  "kerch_strait_passage": {
    "black_sea": {
      "total": <number>,
      "moved_towards_bosporus": <number>
    },
    "azov_sea": {
      "total": <number>,
      "moved_from_strait_bosporus": <number>
    }
  }
}
Write the JSON output and nothing more.

Тестування підходу. Для тестування витягування інформації було створено тестовий набір зображень, який містить по 10 випадкових зображень кожного із чотирьох наявних типів (рисунок 4). Таким чином тестовий набір склав 5% від загальної кількості зображень.

Отриманий результат для кожного зображення із тестового набору даних було перевірено вручну. У світі ML є загальне неписане правило — якщо точність моделі на тестовому наборі даних понад 90%, то ваша модель хороша та її можна використовувати в продукті. Тут я теж виходив із цих самих міркувань. Якщо результат на тестовому наборі буде близький до 90%, можна запускати код на всьому наборі зображень. Якщо ні, треба повертатися на один крок назад, і думати над покращенням промпту чи використовувати зовсім інший підхід.

Як не дивно, точність на тестовому наборі становила 100%, я не знайшов помилок. Такий результат дає підстави вважати, що і для всього обсягу даних буде схожий результат, оскільки всі типи зображень мають схожу структуру та повністю представлені в текстовому наборі даних.

Код. Частину коду, яка відповідає за витягування інформації з зображення, можна знайти в цьому гісті. Код написаний на основі відкритої документації AI Studio для розробників. Його легко адаптувати до інших моделей чи завдань. Необхідною умовою для запуску коду є генерація API_KEY в AI Studio.

Попри те, що промпт до ВММ містить зображення, загальна кількість токенів дорівнює 800, а приблизний час оброблення одного запиту становить всього три секунди. Повний час оброблення всіх зображень повинен складати близько 40 хвилин. Проте як я вже згадував раніше, використовувалась безкоштовна версія моделі, яка має обмеження 10 запитів на хвилину та 1500 запитів на день. Через те, що швидкість виконання коду 20 запитів на хвилину, довелось додати часову затримку 90 секунд після кожних 9 запитів. Це збільшило загальний час оброблення всього набору зображень із 40 хвилин до 2 годин, що насправді не вплинуло на кінцеве завдання — отримати структуровану таблицю про рух ворожих кораблів в морських акваторіях.

Результат. На основі витягнутих даних із кожного зображення було сформовано структурований csv-файл data_monitoring.csv, який складається із 15 колонок, що відповідає очікуваній таблиці 1 (навіть більше, 4 останні колонки не були початково задумані) та повністю покриває згадувані на зображеннях дані:

  • date — час спостереження (може бути тільки дата);
  • img_name — назва файлу, з якого було витягнуто інформацію;
  • black_sea.enemy_ships — кількість ворожих кораблів у Чорному морі;
  • black_sea.kalibr_carriers — кількість носіїв крилатих ракет «Калібр» у Чорному морі;
  • black_sea.total_salvo — загальний ракетний залп у Чорному морі;
  • azov_sea.enemy_ships — кількість ворожих кораблів у Азовському морі;
  • azov_sea.kalibr_carriers — кількість носіїв крилатих ракет «Калібр» в Азовському морі;
  • azov_sea.total_salvo — загальний ракетний залп в Азовському морі;
  • mediterranean_sea.enemy_ships — кількість ворожих кораблів у Середземному морі;
  • mediterranean_sea.kalibr_carriers — кількість носіїв крилатих ракет «Калібр» у Середземному морі;
  • mediterranean_sea.total_salvo — загальний ракетний залп у Середземному морі;
  • kerch_strait_passage.black_sea.total — кількість кораблів, які пройшли Керченську протоку з Азовського в Чорне море;
  • kerch_strait_passage.black_sea.moved_towards_bosporus — кількість кораблів, які пройшли Керченську протоку з Азовського в Чорне море та продовжили рух в напрямку Босфору;
  • kerch_strait_passage.azov_sea.total — кількість кораблів, які пройшли Керченську протоку із Чорного в Азовське море;
  • kerch_strait_passage.azov_sea.moved_from_strait_bosporus — кількість кораблів, які пройшли Керченську протоку із Чорного в Азовське море з напрямку Босфору.

Тестування даних. Для тестування фінальних результатів було обрано кілька логічних припущень, порушення яких вказувало б на помилки. Їх можна швидко перевірити та за необхідності виправити:

  1. Перевірка колонок таблиці на NaN-значення. Така перевірка може потенційно показати проблемні зображення. Всього є 5 зображень, для яких замість чисел було згенеровано NaN-значення. Два з п’яти зображень не мають частини з інформацією про проходження кораблів через Керченську протоку. Одне замість конкретної цифри містить напис «дані уточнюються». Для цих трьох випадків NaN-значення були замінені на 0. Для двох інших випадків я не знайшов пояснень, тому просто замінив NaN-значення на необхідні числа.
  2. Перевірка колонок таблиці на максимальні та мінімальні значення. Ніяких аномалій не було виявлено.
  3. Перевірка на правило: кількість ворожих кораблів завжди має бути більшою або дорівнювати кількості носіїв крилатих ракет. Було виявлено та виправлено два значення.

Отож, на етапі тестування даних було внесено зміни тільки в 7 рядків таблиці, що становить менш як 1%. На момент редагування статті фінальна таблиця містить 804 рядки та покриває 90% теоретично можливих даних. Повторне дослідження періодів відсутності показує, що ще залишається 55 випадків, коли пропущений 1 день, 16 випадків — 2 дні, 3 випадки — 3 дні та 1 випадок — 4 дні. Також для чотирьох днів є два зображення. Причиною цьому є уточнення даних, наприклад, о 6 годині було зафіксовано 3 ворожих кораблі, а трохи пізніше 5, тому публікували в той же день ще одне додаткове інформаційне повідомлення.

Візуалізація. Звісно, однієї часової відмітки спостереження в день може бути замало для просунутої аналітики. Було б ідеально мати дані хоча б раз на годину. Проте навіть із такою агрегацією можна дізнатися дуже багато прихованих за даними контекстів, побудувати історію навколо моніторингу ворожих кораблів, знайти часові тренди та пов’язати ці дані з іншими наборами даних. Така робота потребує окремих зусиль, але зараз вона принаймні можлива.

Для наочного спостереження даних я хочу опублікувати в цій статті тільки одну візуалізацію, яка показує кількість носіїв крилатих ракет «Калібр» в акваторіях Чорного, Азовського та Середземного морів від початку публікації інформаційних повідомлень в Telegram-каналі ВМС ЗСУ. Із зображень чітко простежується певна поведінка, та для її пояснення потрібно більше досліджень, що не є метою цієї статті. Особливо цікавою є візуалізація в Азовському морі — перебування ракетоносіїв спостерігається тільки в червні 2024 року.





Рис. 5. Носії крилатої ракети «Калібр» в акваторіях Чорного, Азовського та Середземного морів від серпня 2022 року

Набір даних

Повний набір даних Warships Monitoring розміщено на платформі Kaggle. Він містить в собі, крім вже описаних двох файлів, ще дві таблиці з метаданими та дві папки із зображеннями:

  • data_monitoring.csv — моніторинг руху ворожих кораблів в морських акваторіях (описано вище);
  • data_posts.csv — всі інформаційні повідомлення Telegram-каналу ВМС ЗСУ (описано у розділі «Підготовка даних»);
  • metadata_images.csv — деяка додаткова інформація про зображення;
  • metadata_images_test.csv — деяка додаткова інформація про зображення для тестування;
  • images — папка з усіма зображеннями;
  • images_test — папка, що містить 40 зображень для тестування (може бути використана для тестування, якби хтось спробував витягнути дані іншим способом).

Інші набори даних про війну

Як я вже згадував на самому початку, опис інших моїх мілітарних наборів даних можна знайти в статті «Чотири набори даних про війну». Проте там не згадано про два інші пізніше створені та не менш важливі набори даних:

  • Massive Missile Attacks on Ukraine — тут можна знайти дані про ворожі масовані атаки на Україну поза межами фронту. Дані містять атаки БПЛА та крилатих ракет, починаючи з вересня 2022 року. Саме цей набір даних містить інформацію про запущені крилаті ракети «Калібр». Його поєднання з описаним у статті набором даних може розкрити взаємозв’язок між кількістю ракетоносіїв в акваторіях морів та реальними атаками, які вже відбулись.
  • The Army of Drones — тут дані про втрати окупанта тільки від дронів, які постачались в ЗСУ на основі проєкту Army of Drones. Проте результати втрат перестали публікуватися, тому там остання дата — середина літа 2024 року.

Водночас існують інші мілітарні набори даних, які активно використовуються в повсякденному житті та інших проєктах. В моїй добірці вже є кілька з них. Якщо вам доводилось працювати з такими, то діліться в коментарях, було б добре скласти повний список таких даних.

Наприкінці

Оскільки ви дочитали до цього місця, то хочу сказати вам дякую. Якщо виникли питання щодо згаданого в статті матеріалу, буду радий відповісти. Описаний в статті набір даних (інші набори даних) можна підтримати кнопкою upvote на платформі Kaggle.

Сам набір даних планую оновлювати з періодичністю не більше ніж раз в місяць. Також було б добре вручну дозавантажити зображення для відсутніх дат та оновити ними набір даних. Можливо, хтось хотів би зайнятися цим завданням. Оскільки основна таблиця набору даних створена повністю автоматизовано, то у випадку виявлення помилок прошу повідомити мене про них особисто.

P.S. Жодне слово в цій статті не було написане AI. AI було використано тільки для генерування картинки в наборі даних.

👍ПодобаєтьсяСподобалось20
До обраногоВ обраному2
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Дякую за детальний підхід і його опис! Класний набір!

P.S. Жодне слово в цій статті не було написане AI.

❤️ Дякую!

Підписатись на коментарі