Комп'ютерний зір (Computer Vision)


16.05.2024

Комп'ютерний зір вже не є чимось фантастичним і будь-хто може використовувати його як інструмент для своїх задач. У системах безпеки, верстатах з Числовим Програмним Керуванням, у роботах, дронах - все це вже використовується і доступно у вигляді бібліотек та готових рішень, які не потребують спеціальних знань математики та особливих навичок програмування.

Про що ця стаття

Опис того, як працює комп'ютерний зір, приклади на Python детекції, трекінгу, сегментації об'єктів за допомогою простих алгоритмів та нейронних мереж. Розпізнавання текстів з зображень. Приклад навчання і використання власної Нейронної мережі. Створення власної маленької примітивної нейронної мережі на Python для загального розуміння роботи нейронних мереж.

Перелік прикладів

Всі приклади, які використані у статті можна знайти у репозиторії: https://git.avislab.com/andre/cv

Зауважте, що відеофайли, і файли нейронних мереж yolov8 у репозиторії відсутні.

geometry
Детекція геометричних фігур
sot
Трекінг одного об'єкта (Single Object Tracking). Захоплення об'єкта
predict
Розпізнавання об'єктів на відео
obb
Oriented Bounding Box (OBB)

face_detect
Виявлення облич людей

face_blur
Розмиття облич на відео

pose
Пози людей
seg
Сегментація об'єктів
own_nn
Навчання нейронної мережі для сегментації об'єктів. Виявлення "5 пальців"
plate_detection
Приклад розпізнавання номерних знаків автомобілів
track
Відстеження (Tracking) об'єктів

read_text
Конвертація зображень в текст

nn - приклад власної примітивної нейронної мережі

Що таке Комп'ютерний зір? Що таке Машинний зір?

Комп'ютерним зором називають системи, які аналізують зображення, відео, намагаються інтерпретувати корисну інформацію отриману з відео, фото, аудіо ряду. Тобто це загальне поняття.

Машинним зором називають реалізацію комп'ютерного зору у конкретному застосуванні яке окрім аналізу даних, виконує відповідні дії. Наприклад, робот бачить деталь, орієнтує її потрібним чином. Тобто, у випадку з Машинним зором застосовується фізичний вплив на ситуацію.

Де використовується Комп'ютерний / Машинний зір

Комп'ютерний / Машинний зір використовується для автоматизації процесів на виробництві, у процесі керування трафіком на автошляхах, в автопілотах сучасних автівок, для слідкування урядом за громадянами, у воєнній галузі для виявлення цілій і автоматичного наведення. Машинний зір використовують системи доступу, автоматичні шлагбауми, та системи безпеки. Ви можете зустріти реалізацію машинного зору сумісно з нейронними мережами у цілком цивільних додатках до мобільних телефонів. Наприклад, ви фотографуєте пляшку вина, а додаток лише за фотографією виявляє що це за вино та у яких найближчих магазинах його можна купити. Також Машинний зір використовується для аналізу відео, зображень та аудіо з метою класифікації, виявлення заборонених предметів, емблем, слів тощо. І це також буде у прикладах. Одним з прикладів такої обробки є розмиття облич, номерних знаків на відео і фото.

Що потрібно щоб почати роботу з Комп'ютерним зором?

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

Класифікація задач Комп'ютерного зору

Комп'ютерного зір має розв'язувати певні задачі які можна умовно класифікувати на такі основні категорії:

(SOT) Single Object Tracking - відстеження одного об'єкта. Наприклад, Ваш робот встановлює деталь і він має виявити її положення, перемістити її, виконати якісь дії, і у полі зору буде лише цей один об'єкт, який він має не тільки детектувати, а і трекати, тобто розуміти що це той самий об'єкт, що і був на попередньому кадрі. Інший приклад - захоплення і ведення цілі. У прикладі sot.py використовується прості алгоритми, коли комп'ютер не розрізняє обїект, а лише розуміє що фрагмент зображення переміщується і намагається відстежувати його. Також є варіант з використанням нейромережі. Хочу зауважити, що при моїх тестах коректніше працювали прості алгоритми, але в інших умовах результат може бути іншим.

Приклад: sot.py

Object Detection - проста детекція (розпізнавання об'єктів) на кожному кадрі відео. Тобто, не стоїть задача розуміти на поточному кадрі відео це новий об'єкт, чи це той самий, що і на попередньому. Детекція об'єктів можлива з використанням простих алгоритмів, коли попередньо обробляється зображення, виокремлюються контури та по цих контурах намагаються впізнати об'єкт. Такий варіант можна використовувати у промисловості, де приблизно однакове освітлення, розміри об'єктів і результат роботи системи можна протестувати та налагодити. У прикладах це детекція ліній, кола, прямокутників.

Приклад: line1.py, line2.py, circle.py, rectangle.py

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

Приклад: predict.py

Object Tracking - досить часто треба не тільки впізнавати об'єкти, але і відстежувати їх переміщення при цьому розрізняти обпекти з розумінням що це ті самі обпекти що і на попередніх кадрах. Тому під час трекінгу кожному об'єкту присвоюється свій ідентифікатор (ID). Якщо машинний зір налаштовано не дуже якісно, або відео потік не достатньо чіткий можуть відбуватися перескакування ID. Тобто буде вважатися, що це новий об'єкт. Це є однією з проблем налаштування трекінгу.

Приклад: track0.py, track1.py, track2.py

Instance Segmentation - сегментація - це визначення контурів об'єкта. Фактично - обмальовування об'єкта.

Приклад: seg.py

Image Classification - Класифікація зображення. Наприклад, перелік того, що містить зображення. Або класифікація на "пейзаж", "портрет", "скрін з екрана", "текст" і таке інше.

Приклад: відсутній

Pose Estimation - Детекція поз людини. Досить цікаво виглядає у роботі. Можна зробити щось, що буде реагувати на Ваші жести. Приклад з використанням нейронної мережі демонструє як це працює.

Приклад: pose.py

Емоції, Жести - також достатньо цікаве завдання, на жаль прикладу не можу навести. Можливо надалі зроблю і доповню цю статтю.

Приклад: відсутній

Oriented Bounding Boxes Object Detection - один зі способів розмічати знайдені об'єкти, але з поворотом прямокутника.

Приклад: obb.py

Розпізнавання тексту - розпізнавання тексту на зображеннях - це досить стара задача, існує багато реалізацій і деякі з них використано у прикладах. Саме розпізнавання текстів нас цікавить у комбінації з розпізнанням об'єктів. Наприклад, нам треба виявляти та читати номерні знаки на автівках, та не реагувати на написи на інших об'єктах.

Приклад: read_text.py1, read_text2.py

Комбінація вище згаданих задач - у реальному житті доводиться вирішувати складні, комбіновані задачі та доводиться поетапно розбивати складну задачу на прості. Наприклад: трекінг автівок + Detection номерних знаків + Розпізнавання тексту номерних знаків, верифікація розпізнаних знаків, пошук по базі даних і так далі.

Програмне забезпечення

Яке програмне забезпечення будемо використовувати?

Python3

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

OpenCV

Відома потужна бібліотека для аналізу, обробки та роботи з зображеннями, відео.

YOLOv8

YOLOv8 - це потужна реалізація нейронні мережі для аналізу зображень (відео). Не знаю чи можна YOLOv8 назвати фреймворком у повному розумінні цього терміну, тому я буду називати його просто YOLOv8. https://github.com/ultralytics/ultralytics

CVAT

CVAT - cистема для розмітки зображень. Можна використовувати онлайн сервіс, а можна використовуючи Docker підняти свій сервер для локальної роботи. Найбільш цінним для навчання нейронних мереж є Dataset! Це купа зображень з розмітками об'єктів (класів) на цих зображеннях. Можна використовувати готові доступні датасети, та коли знадобиться зробити власний Dataset для подальшого навчання власної нейронної мережі, Вам допоможе CVAT. Ця платформа дозволяє організувати колективну роботу над датасетом.

COCO_to_YOLOv8

COCO_to_YOLOv8 - cкрипт для конвертації датасету з формату COCO (який видає CVAT) у формат YOLOv8. Сподіваюсь, наступні версії CVAT зможуть формувати вихідні дані у форматі потрібному YOLOv8. Та поки що доведеться використовувати скрипт-конвертор.

Також треба розуміти навіщо потрібні наступні модулі:

NumPy

Фундаментальний пакет для Python, який спрощує роботу багатомірними масивами, матрицями, операціями між ними, їх перетвореннями та таке інше.

PyTorch

Фреймворк (розробка Facebook) для машинного навчання для мови програмування Python з відкритим кодом. Використовується у тому числу для задач комп'ютерного зору. Тензорні обчислення по аналогії з NumPy. Має можливість виконання обчислювань на GPU, що значно прискорює обробку даних. Якщо Ви будите робити свою нейромережу - PyTorch це той інструмент який варто розглянути. У примітивному прикладі власної нейромережі, я буду використовувати лише NumPy. Та якщо плануєте щось трохи складніше "Hello World!" - PyTorch. До речі YOLOv8 "написаний" на PyTorch.

TensorFlow

Ще одна розробка аналогічна PyTorch тільки від Google. Я не використовую TensorFlow, тому наразі нічого сказати не можу.

Встановлення програмного забезпечення

З часом процедура встановлення програмного забезпечення може змінятися. Тому рекомендую дивитися у документацію до відповідного ПЗ щодо встановлення останніх версій і підтримки вашого "заліза" та ОС. Наведу приклад на час написання статті для Ubuntu.

Бібліотека OpenCV

sudo apt update
sudo apt install libopencv-dev
dpkg -l libopencv-dev

Пакет OpenCV для Python

Пакет opencv для Python:

pip install opencv-python

або прокачана версія "opencv-python":

pip install opencv-contrib-python

PyTorch

Команда встановлення PyTorch залежить від того яка у Вас ОС, платформа і таке інше. Тому йдемо за посиланням:

https://pytorch.org/get-started/locally/

обераємо потрібне і отримаємо команду для встановлення PyTorch.

YOLOv8

pip install ultralytics

Документація: https://docs.ultralytics.com/quickstart/

CVAT

Документація: https://docs.cvat.ai/docs/administration/basics/installation/

NumPy

Для роботи з масивами, матрицями, тензорами

pip install numpy

pytesseract

Розпізнає текст на картинках

pip pip install pytesseract

EasyOCR

Розпізнає текст на картинках

pip install easyocr

Алгоритми які працюють без нейронних мереж

Розпізнавання простих геометрій

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

Розпізнавання руху та SOT

Одним з прикладів простої обробки зображень є виявлення руху. Зміни на зображенні не потребують знання який саме об'єкт там знаходиться і рухається. Інший, цікавіший приклад - трекінг певної ділянки зображення SOT (Single object trecking). Тобто можна вказати зону на зображенні, який треба "супроводжувати". Це використовується для наведення на ціль. При чому комп'ютер не розуміє що саме зображено, він просто розуміє, що це "щось" і воно можливо переміщується. У прикладі для захвату і веденні об'єкта я використовую маркер у центрі екрана. При натисканні на клавіатурі кнопки "пробіл" виконується захоплення і подальший супровід об'єкта. У коді прикладу можна попробувати декілька алгоритмів у тому числі з використанням готової нейронної мережі.

Дивись рядки:

def createTreker():
    return cv2.TrackerMIL_create()  # метод Multiple Instance Learning
    #return cv2.legacy.TrackerMOSSE_create()  # Minimum Output Sum of Squared Error
    #return cv2.TrackerGOTURN_create() # Neural network

Хоча не можу сказати, що при моїх тестах нейронка працювала краще.

Ці методи принципово відрізняються від того, про що піде мова далі, а саме про використання нейронних мереж. Різниці полягає у тому, що НМ намагаються розпізнати та кваліфікувати об'єкти на зображенні. Наприклад, розрізняти людину, автівку, інші об'єкти.

Нейромережі для роботи з зображеннями

На поточний момент можна знайти багато реалізацій нейронних мереж, які спеціалізуються на обробці зображень та відео (відео - це фактично послідовність зображень). З часом будуть з'являтися нові рішення. На поточний момент я обрав YOLOv8.

Чому YOLOv8?

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

Використання готових нейронних мереж

Працюючи з YOLOv8 Ви можете використовувати вже навчені нейронні мережі. Приклад такого використання:

from ultralytics import YOLO

# Load model
model = YOLO('yolov8m-face.pt')

# Perform tracking with the model
results = model.track(source=0, show=True)

У цьому прикладі використовується вже готова нейромережа для виявлення облич. Приклад кастомної обробки результатів і свого маркування виявлених об'єктів можете побачити в інших прикладах, наприклад: seg/seg.py

Детально про готові моделі, які можна завантажити читайте тут: https://docs.ultralytics.com/ru/models/yolov8/#supported-tasks-and-modes

Зверніть увагу на початок назви файлів yolov8n, yolov8s, yolov8m, yolov8l, yolov8x. Літери n, s, m, l, x означають "розмір" моделі. Чим більший розмір - більше параметрів, модель краще працює, та потребує більше ресурсів і часу. Ви можете знайти свій баланс між якістю і швидкістю підібравши потрібний розмір моделі.

Навчаємо свою нейронну мережу

Першим кроком навчання власної нейронної мережі для детекції або сегментації зображення є створення датасету. Треба зібрати як змога більшу кількість зображень того, чому ви збираєтесь навчити нейромережу і розмітити зображення. Тобто вказати де саме і що саме зображено на кожному з зображень. Важливо також щоб були зображення і без об'єктів, які ми хочемо знаходити. Можна знайти в інтернеті готові датасети, зроблені іншими людьми. Та я покажу як можна зробити самому. Я покажу це на прикладі п'яти пальців, тобто навчу нейромережу впізнавати 5 пальців. Ви можете спробувати більш амбітне завдання - навчити нейромережу розрізняти жести, типу "OK", "палець в гору" тощо. Та для прикладу я буду використовувати лише один клас, тобто у прикладі буде розпізнаватися лише один об'єкт - 5 пальців. І це буде сегментація об'єкта. Тобто не тільки детекція того, що об'єкт присутній на зображення, а і "обкреслюванні" його на зображенні.

Для цього нам спочатку треба підготовити фото. Можна зробити окремі фото, або зняти відео і "розрізати" відео на окремі фото за допомогою програми ffmpeg.

Приклад команди ffmpeg для розрізання відео на окремі фото:

ffmpeg -i train.mp4 -vf fps=1.5 images_train/img%03d.png

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

CVAT

В інтернеті можна знайти приклади роботи з CVAT. Детально на цьому не буду зупинятися. Після завершення розмітки вивантажуємо дані з зображеннями у форматі COCO.

Отримаємо архів який треба розпакувати, наприклад у паку "COCO_dataset". Там мають бути теки:

annotations
images

Для YOLOv8 потрібен свій формат тому за допомогою скрипта COCO_to_YOLOv8 конвертуємо датасет у формат YOLOv8.

Хочу зазначити що датасет слід розділити на дві частини - одну приблизно відсотків 70 для навчання, решта 30% для перевірки навчання. Це можна зробити вручну ще на етапі розмітки у CVAT, або за допомогою скрипта COCO_to_YOLOv8. Читай документацію: https://github.com/Koldim2001/COCO_to_YOLOv8

Приклад команди:

python3 coco_to_yolo.py --coco_dataset="COCO_dataset" --autosplit=True --percent_val=30

У результаті роботи цього скрипта отримаємо теку YOLO_dataset наступної структури:

YOLO_dataset
    train
    validation
data.yaml

Тепер можна переходити до навчання нашої нейронної мережі. Це робиться дуже просто:

train.py:

from ultralytics import YOLO

# Load an official or custom model
model = YOLO('yolov8s-seg.pt')  # Load an official Detect model

results = model.train(data='data.yaml', epochs=100, imgsz=640, batch=16)

Якщо процес навчання не почався і випав з помилкою, уважно читаємо у якому конфігураційному файлі треба поправити шлях до теки датасету.
У мене це ~/.config/Ultralytics/settings.yaml

Процес навчання не швидкий. По закінченню навчання отримаємо теку runs наступної структури:

runs
    detect
        train
            weights
                best.pt
        train2
        train3

Якщо ми будемо запускати навчання декілька раз, отримаємо теки train2, train3 і так далі.

У цих теках нас цікавить файл best.pt Це кращі weights для навченої нейронної мережі.

Приклад використання власної нейронної мережі

Приклад використання навченої нейронної мережі:

from ultralytics import YOLO

# Load custom model
model = YOLO('best.pt')
results = model.predict(source=0, iou=0.65, conf=0.95, show=True)

fivefingers-seg.py:

from ultralytics import YOLO

# Load custom model
model = YOLO('fivefingers-seg.pt')
results = model.predict(source=0, iou=0.65, conf=0.98, show=True, verbose=False)

У цьому прикладі файл fivefingers-seg.pt це перейменований best.pt отриманий після навчання нейронної мережі.

Деякі моменти щодо навчання нейронної мережі

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

"Недонавчена" нейронна мережа

Якщо набір зображень для навчання був замалий, або розмічений з помилками, нейромережа може бути не достатньо навченою ("недонавченою"), що спричинить не стабільну детекцію об'єктів, або не коректну детекцію, коли зовсім сторонні об'єкти будуть сприйматися як ті що треба знайти. Загальні поради - збільшити кількість даних для навчання, збільшити кількість епох навчання.

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

"Перенавчена" нейронна мережа

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

Некоректно навчена нейронна мережа

Одним з прикладів невірного підходу до навчання нейронної мережі є приклад з розпізнанням рукописних цифр. Нейрону мережу навчають розпізнавати рукописні цифри, але у датасеті є лише зображення з рукописними цифрами. Тобто варіантів того, що це може бути взагалі не цифра, а скажімо буква чи символ, не повідомляється нейромережі. У результаті у "уяві" нейромережі існують лише 10 варіантів того, що вона бачить. Тобто, у її уяві їй можуть показати лише 0,1,2,3,4,5,6,7,8,9. Відповідно, коли показати будь-що - вона все одно побачить одну з цифр. При навчанні нейронної мережі треба враховувати подібні ситуації.

Некоректне застосування нейронної мережі

Те саме, що і з людьми - вчили на одне, а застосовують для розв'язання інших задач, а начальству пофіг - воно не розбирається і бажання не має. Результат... ну ви зрозуміли - як завжди.

Приклад Розпізнавання номерних знаків авто як приклад комбінованої задачі

У теці plate_detection знаходиться приклад читання номерних знаків авто. У прикладі використовується готова, вже навчена нейронна мережа, яка вміє розрізняти автомобільні номери на авто. Саме розрізняти, а не читати. Тобто за її допомоги можна визначити зони на зображенні де детектовано номерний знак. Другим етапом - "вирізається" ділянка з номерним знаком авто і за допомогою бібліотеки easyocr намагаємось розпізнати знак. Тобто перетворити зображення у текст. Далі перевіряємо чи не знаходиться цей номерний знак у масиві "bad_boys" і якщо так, тоді помічаємо його відповідним написом.

Дивись: plate_detection.py

Це простий приклад поєднання декількох механізмів роботи комп'ютерного зору.

Структура нейронної мережі

Що таке Нейронна мережа і як вона працює під капотом?

Нейронна мережа це насправді - математична модель, яка структурою нагадує поєднання нейронів у нашому мозку, тому її назвали "нейронною мережею".

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

В Інтернеті частенько наводять приклад з розпізнаванням рукописних цифр розмір зображень 28x28 - це 784 пікселів. Тобто на вході 784 нейрони, а на виході 10 - кожен відповідає окрему цифру. І той вихідний нейрон, який буде мати більший результат і буде сигналізувати про розпізнану відповідну цифру.

Розглянемо найпростішу структуру нейронної мережі:

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

Кожен зв'язок двох нейронів має два параметри "вагу" і "зміщення". Як можна помітити на окремий нейрон впливають зв'язки з усіма нейронами попереднього шару.

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

-Як відбувається навчання? Для навчання власної мережі спочатку готуємо датасет. Це навчальні дані, які містять різні комбінації вхідних даних і те який має бути результат на виході. Чим більше таких навчальних даних, тим краще. Далі ми якось рандомно виставляємо початкові weights для нашої нейронної мережі, або завантажуємо якісь підготовлені, наприклад з попереднього навчання. Подаємо на вхід нейронної мережі навчальні комбінації даних по черзі, дивимось що на виході. Зрозуміло, що вихідні результати будуть відрізнятися від бажаних. Тому доводиться підкручувати "weights". Для цього ідемо з кінця до початку. Тобто, дивимось які зв'язки впливають на вихідний нейрон, і відповідно "підкручуємо" weights цих зв'язків. Потім переходимо до попереднього шару нейронів і так далі до вхідного шару. Цей процес називають "Зворотне розповсюдження".

Для оцінки куди та на скільки крутити weights використовують поняття "Градієнтний спуск". Про ці речі ви можете почитати в Інтернеті. Ця ж стаття має ознайомчий характер і має на меті знайомство з нейронними мережами на практичних прикладах. Отже, за один цикл навчання підібрати всі параметри не вийде, бо нейрони пов'язані між собою і впливають один на одного. І як тільки ви "підкрутите" в одному місці, в іншому щось "вилізе" не туди. Тому цю процедуру повторюють багато разів і це називають епохами навчання.

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

Чи можна назвати Нейронну мережу Штучним Інтелектом?

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

Створення своєї власної простої Нейронної Мережі на Python

Посилання на приклад нейронної мережі на Python: https://git.avislab.com/andre/cv/src/master/nn

Я створив простенький приклад двошарової нейронної мережі дивись теку nn. Придумав для неї наступну задачу: Маємо 7-сегментний індикатор, по сегментах, які загоряються треба визначати відповідну цифру. Звісно, це примітивна задача, яку можна вирішити багатьма більш раціональними методами. Та нас цікавить виключно "експериментарщина".

Отже, на вході у нас 7 параметрів, кожен відповідає за відповідний сегмент 7-сегментного індикатора. Я пронумерував сегменти наступним чином:

7-сегментний індикатор

Створив масив dataset у якому числа близькі до 1.0 означають що відповідний сегмент "світиться", а числа близькі до 0.0 - "не світиться".

dataset = [
    [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0], #1
    [1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0], #2
    [1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0], #3
    [0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0], #4
    [1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0], #5
    [1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0], #6
    [1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0], #7
    [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], #8
    [1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0], #9
]

7-сегментний індикатор

І масив результатів, тобто який вихід має "загорітися" при відповідній комбінації на вході.

results = [
    [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
    [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
    [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
    [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
    [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
    [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
]

Уважний читач помітить що dataset не містить "0", та "пустоту". Це зроблено навмисно, подивимось що вийде.

Навчання:

python3 ./train.py

Після навчання буде згенеровано файл test.npz, це фактично "weights" нашої мережі. Вони будуть використовуватися для роботи нашої мініатюрної нейронної мережі.

Перевіряємо роботу:

python3 ./test.py

Цікаві результати

Результат роботи такий - ті цифри, які були у навчальному датасеті розпізнаються з досить непоганою впевненістю (Confidence) 80%-90%.

А от "0", якого не було у навчальному датасеті розпізнався як "8". Воно і не дивно, 0 та 8 досить схожі, у нуля не вистачає лише "перемички" посередині.

Повна пустота, якої теж не було в навчальному датасеті розпізнана, як "1" правда з дуже низьким Confidence (впевненість нижче 20%). І тут є пояснення - "1" найближча до "пустоти", бо має найменшу кількість "засвічених" сегментів з усіх шифер.

І це реально дивує як така математична модель дає відповідь максимально схожу на ту, яку б, напевно, дала б людина.

Приклад не коректного навчання і використання нейронної мережі

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

Аналогічна показова ситуація трапилася у прикладі розпізнання 5 пальців. Я навчав нейронну мережу на фото, зроблених на світлому фоні тільки моїми "білими" руками і я був одягнений у темну одежу. Відповідно нейронна мережа нормально працювала у тій локації. А от в офісі, де фон інший, я одягнений в іншу одежу, їй було важко розпізнавати мої 5 пальців. Це через те, що її не навчали у цих умовах. Чим більше різних комбінацій буде при навчанні, тим краще буде працювати нейронна мережа. ЇЇ можна довчити, і вона буде чіткіше розрізняти мої 5 пальців. Доки... я не одягну рукавички. Ну Ви зрозуміли, при навчанні нейронної мережі треба їй надати максимально можливо кількість варіантів.

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

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

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

Висновки

Нейронні мережі дуже цікава річ, з якою потрібно ознайомитись у будь-якому випадку всім, хто займається програмуванням. І після цього Ви зможете визначитись чи потрібні Вам взагалі нейронні мережі, та як і для розв'язання яких задач їх застосовувати. Сучасні програмні рішення дозволяють використовувати нейронні мережі як інструмент, не заглиблюючись у те, як вони працюють "під капотом". Це дає можливість використовувати їх ширшому колу людей, які не надто розбираються у тонкощах математики, і тонкощах навчання нейронних мереж. Окрім позитивного це може мати негативний ефект, оскільки бездумне використання інструмента який потребує тонкого налаштування, може мати негативні наслідки. Також існують моменти, які дозволяють при певних умовах використовувати нейронні мережі для шахрайства при чому не можна довести, що це було зроблено за допомогою нейронної мережі. Ви не можете проаналізувати weights нейронні мережі та з'ясувати чому її вчили. Якщо для зламу системи використовується шкідливий програмний код (троян), або код використовує вразливість системи, це можна проаналізувати. Принаймні існує шанс проаналізувавши код програми з'ясувати що вона робить. Проаналізувати характеристики нейронної мережі та зробити висновки що робить нейронна мережа майже неможливо.

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

Якщо що - пишіть у коментарі.

Бажаю успіхів!

Корисно знати
Коментарі:
Додати коментар
Code
* - обов'язкові поля

Архіви