Памятка по книге "Искусственный интеллект и компьютерное зрение", O'Reilly. Примеры на GitHub
Компоненты, необходимые для работы с ИИ:
Задача | Примеры моделей |
---|---|
Классификация изображений | ResNet-152 (2015), MobileNet (2017) |
Классификация текста | BERT (2018), XLNet (2019) |
Сегментация изображений | U-Net (2015), DeepLabv3 (2018) |
Преобразование изображений | Pix2Pix (2017) |
Распознавание объектов | YOLO9000 (2016), Mask R-CNN (2017) |
Генерация речи | WaveNet (2016) |
Примеры из книги можно запускать в браузере на портале Google Colab. Либо необходимо на домашнем компьютере поставить необходимые пакеты.
Сначала необходимо установить интерпретатор языка Python. Краткая инструкция по установке- здесь.
Под разные проекты бывает необходимо использовать разные версии Pytnon. Для этого в систему необходимо установить эти необходимые версии Python. Различные версии устанавливаются в разные директории. На мой взгляд, путь к каждой версиям лучше прописывать в системную переменную окружения PATH. Тогда,
Например, использование различных версий Python для установки пакетного менеджера pip:
A> python -m pip install pip B> py -3.8 -m pip install package НЕ работает> python3.8 -m pip install pip
NOTE: В интернете встречается вызов Python с указанием версии ("python3.8 -m pip install pip"). Но чтобы такой вызов исполнялся системой, в директории Python должен быть exe-файл с названием python3.8.exe. А такого файла в директории установки нет, есть только python.exe, python3.dll, python312.dll. Dll файлы не могут запускаться напрямую как exe, они подгружаются к использующему их приложению. Возможно python312.dll используется при работе утилиты py. Файл python.exe исполняется при вызове "python -m pip install pip". Но тут, чтобы использовался Python нужной версии необходимо указать путь к нужной директории, например "с:/Python38/python -m pip install pip". Иначе, как уже было сказано выше, система запустит python.exe из первой же директории в путях PATH где найдет такой файл.
Каждый проект на Python рекомендуется реализовывать в своем виртуальном окружении, VENV. Для этого:
PS C:\> py -3.11 -V Python 3.11.7
PS E:\Code\AI> py -3.11 -m pip install --upgrade pip ... Successfully installed pip-23.3.2
PS E:\Code\AI> py -3.11 -m venv venv PS E:\Code\AI>
PS E:\Code\AI> ./venv/scripts/activate (venv) PS E:\Code\AI>
(venv) PS E:\Code\AI> python -V Python 3.11.7
(venv) PS E:\Code\AI> pip install tensorflow==2.0 ERROR: Could not find a version that satisfies the requirement tensorflow==2.0 (from versions: 2.12.0rc0, 2.12.0rc1, 2.12.0, 2.12.1, 2.13.0rc0, 2.13.0rc1, 2.13.0rc2, 2.13.0, 2.13.1, 2.14.0rc0, 2.14.0rc1, 2.14.0, 2.14.1, 2.15.0rc0, 2.15.0rc1, 2.15.0) ERROR: No matching distribution found for tensorflow==2.0 [notice] A new release of pip is available: 23.2.1 -> 23.3.2 [notice] To update, run: python.exe -m pip install --upgrade pip (venv) PS E:\Code\AI> python -m pip install --upgrade pip
(venv) PS E:\Code\AI> python -m pip install --upgrade pip ... Successfully installed pip-23.3.2
(venv) PS E:\Code\AI> pip install tensorflow==2.15.0 ... (venv) PS E:\Code\AI>
Устанавливаем вспомогательные пакеты:
(venv) PS E:\Code\AI> pip install matplotlib
Сохраняем используемые пакеты в "requirements.txt" и выходим из виртуального окружения. Для запуска своих скриптов нам надо будет снова войти в окружение!
(venv) PS E:\Code\AI> pip freeze > requirements.txt (venv) PS E:\Code\AI> deactivate PS E:\Code\AI>
Хотя мы вручную поставили лишь несколько пакетов, но они автоматически подтянули за собой все необходимые им дополнительные пакеты. Получился внушительный список, содержимое "requirements.txt":
absl-py==2.0.0 astunparse==1.6.3 cachetools==5.3.2 certifi==2023.11.17 charset-normalizer==3.3.2 contourpy==1.2.0 cycler==0.12.1 flatbuffers==23.5.26 fonttools==4.47.0 gast==0.5.4 google-auth==2.26.1 google-auth-oauthlib==1.2.0 google-pasta==0.2.0 grpcio==1.60.0 h5py==3.10.0 idna==3.6 imageio==2.33.1 keras==2.15.0 kiwisolver==1.4.5 lazy_loader==0.3 libclang==16.0.6 Markdown==3.5.1 MarkupSafe==2.1.3 matplotlib==3.8.2 ml-dtypes==0.2.0 networkx==3.2.1 numpy==1.26.3 oauthlib==3.2.2 opt-einsum==3.3.0 packaging==23.2 pillow==10.2.0 protobuf==4.23.4 pyasn1==0.5.1 pyasn1-modules==0.3.0 pyparsing==3.1.1 python-dateutil==2.8.2 requests==2.31.0 requests-oauthlib==1.3.1 rsa==4.9 scikit-image==0.22.0 scipy==1.11.4 six==1.16.0 tensorboard==2.15.1 tensorboard-data-server==0.7.2 tensorflow==2.15.0 tensorflow-estimator==2.15.0 tensorflow-intel==2.15.0 tensorflow-io-gcs-filesystem==0.31.0 termcolor==2.4.0 tifffile==2023.12.9 typing_extensions==4.9.0 urllib3==2.1.0 Werkzeug==3.0.1 wrapt==1.14.1
Из архива на GitHub скачиваем фото кошки с собаки, директория sample-images. Эту директорию я положил в директорию проекта. Скрипт взят из книги, и немного поправлен:
import tensorflow as tf from tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictions from tensorflow.keras.preprocessing import image import numpy as np import matplotlib.pyplot as plt def classify(img_path): img = image.load_img(img_path, target_size=(224, 224)) model = tf.keras.applications.resnet50.ResNet50() img_array = image.img_to_array(img) img_batch = np.expand_dims(img_array, axis=0) img_preprocessed = preprocess_input(img_batch) prediction = model.predict(img_preprocessed) print(decode_predictions(prediction, top=3)[0]) cat_path = "sample-images/cat.jpg" classify(cat_path) img = image.load_img(cat_path, target_size=(224, 224)) plt.imshow(img) plt.show()
При запуске скрипта скачалась модель ResNet50 (~10MB) и распозналась кошка породы 'tabby' с вероятностью 0.5719771:
(venv) PS E:\Code\AI> python script1.py 2024-01-07 02:11:11.597174: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`. WARNING:tensorflow:From E:\Code\AI\venv\Lib\site-packages\keras\src\losses.py:2976: The name tf.losses.sparse_softmax_cross_entropy is deprecated. Please use tf.compat.v1.losses.sparse_softmax_cross_entropy instead. WARNING:tensorflow:From E:\Code\AI\venv\Lib\site-packages\keras\src\backend.py:1398: The name tf.executing_eagerly_outside_functions is deprecated. Please use tf.compat.v1.executing_eagerly_outside_functions instead. 2024-01-07 02:11:14.462242: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations. To enable the following instructions: SSE SSE2 SSE3 SSE4.1 SSE4.2 AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags. WARNING:tensorflow:From E:\Code\AI\venv\Lib\site-packages\keras\src\layers\normalization\batch_normalization.py:979: The name tf.nn.fused_batch_norm is deprecated. Please use tf.compat.v1.nn.fused_batch_norm instead. Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/resnet/resnet50_weights_tf_dim_ordering_tf_kernels.h5 102967424/102967424 [==============================] - 10s 0us/step 1/1 [==============================] - 1s 764ms/step Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/imagenet_class_index.json 35363/35363 [==============================] - 0s 1us/step [('n02123045', 'tabby', 0.5719771), ('n02124075', 'Egyptian_cat', 0.21763451), ('n02123159', 'tiger_cat', 0.060934357)]
Наблюдается много ворнингов из-за deprecated функций, которые не рекомендуется использовать и которые скоро будут удалены. А так-же рекомендуется перекомпилировать tensorflow для поддержки инструкций CPU для оптимизации. Не обращаем на это внимание.
Попробуем классифицировать еще и фото собаки.
import tensorflow as tf from tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictions from tensorflow.keras.preprocessing import image import numpy as np import matplotlib.pyplot as plt def classify(img_path): img = image.load_img(img_path, target_size=(224, 224)) model = tf.keras.applications.resnet50.ResNet50() img_array = image.img_to_array(img) img_batch = np.expand_dims(img_array, axis=0) img_preprocessed = preprocess_input(img_batch) prediction = model.predict(img_preprocessed) print(decode_predictions(prediction, top=3)[0]) cat_path = "sample-images/cat.jpg" classify(cat_path) dog_path = "sample-images/dog.jpg" classify(dog_path) img = image.load_img(cat_path, target_size=(224, 224)) plt.imshow(img) plt.show() img = image.load_img(dog_path, target_size=(224, 224)) plt.imshow(img) plt.show()
Результат получаем как в книжке - собака породы корги с вероятностью 0,83.
1/1 [==============================] - 1s 751ms/step [('n02123045', 'tabby', 0.5719771), ('n02124075', 'Egyptian_cat', 0.21763451), ('n02123159', 'tiger_cat', 0.060934357)] 1/1 [==============================] - 1s 714ms/step [('n02113186', 'Cardigan', 0.8349694), ('n02113023', 'Pembroke', 0.15543425), ('n02110806', 'basenji', 0.0028011024)]
Таблица доступных моделей представлена здесь - Keras Available models
В книге используются следующие модели, обученные на наборе данных ImageNet:
Модель | Размер | Топ 1 | Топ 5 | Параметров | Кол. слоев |
---|---|---|---|---|---|
ResNet-50 | 98 MB | 74.9% | 92.1% | 25.6M | 107 |
MobileNet | 16 MB | 70.4% | 89.5% | 4.3M | 55 |
Топ 1 - сколько раз ответ с наибольшей оценкой был верен. Топ 5 - был верен один из 5-ти ответов с наибольшими оценками.
"Тепловая карта" показывает какие пиксели дают наибольший вклад в распознавание объекта на картинке. В книге приведен скрипт visualization.py, который подсвечивает более теплыми цветами эти пиксели. Для работы скрипта необходимо установить следующие пакеты:
(venv) PS E:\Code\AI> pip install keras-vis (venv) PS E:\Code\AI> pip install tf-explain (venv) PS E:\Code\AI> pip install opencv-python
Запуск скрипта:
(venv) PS E:\Code\AI> python visualization.py --process image --path sample-images/dog.jpg
При запуске скрипта с GitHub выяснилось, что он использует модель VGG16, которая скачивается автоматически и занимает ~528MB. В предыдущем примере с классификацией кошки и собаки использовалась модель ResNet50, которая тоже скачалась при запуске скрипта и заняла 98MB. Не хотелось бы выкачивать все модели и занимать слишком много места на диске, поэтому я поправил скрипт для использования ResNet50 вместо VGG16.
import numpy as np import tensorflow from tensorflow.keras.preprocessing import image from tensorflow.keras.utils import get_file from tensorflow.keras.applications.vgg16 import preprocess_input from tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictions from tf_explain.core.grad_cam import GradCAM import PIL from PIL import Image, ImageDraw, ImageFont import matplotlib.pyplot as plt import matplotlib.cm as cm import matplotlib.image as mpimg from argparse import ArgumentParser import glob import os USE_VGG16 = False if USE_VGG16: #Select a model to use, in this case VGG16 model = tensorflow.keras.applications.vgg16.VGG16(weights='imagenet', include_top=True, input_tensor=None, input_shape=None, pooling=None, classes=1000) #Check with 'print(model.summary())', in this case it is "block5_conv3" last_conv_layer_name = "block5_conv3" #Must include layers between last convolutional layer and prediction layer #Layer names can be found through 'print(model.summary())' classifier_layer_names = ["block5_pool", "flatten", "fc1", "fc2", "predictions"] else: model = tensorflow.keras.applications.resnet50.ResNet50() last_conv_layer_name = "conv5_block3_3_conv" #classifier_layer_names = ["conv5_block3_3_bn", "conv5_block3_out", "avg_pool", "predictions"] #case 1 classifier_layer_names = ["conv5_block3_3_bn", "avg_pool", "predictions"] #case 2 ....
Согласно переменной USE_VGG16 будет использоваться модель либо VGG16, либо ResNet50.
Судя по описанию в скрипте, для визуализации необходимо выбрать последний сверточный слой, и все следующие слои до слоя "predictions" (Переменные last_conv_layer_name и classifier_layer_names). Посмотреть какие слои есть в модели можно скриптом:
import tensorflow as tf USE_VGG16 = True if USE_VGG16: model = tf.keras.applications.vgg16.VGG16(weights='imagenet', include_top=True, input_tensor=None, input_shape=None, pooling=None, classes=1000) else: model = tf.keras.applications.resnet50.ResNet50() print(model.summary())
Если использовать все слои, согласно рекомендации, то меня смутило обилие зеленого цвета поверх песка слева от морды собаки. Поэтому я попровал исключить слой "conv5_block3_out", стало чуть лучше и более похоже на то, что выдала модель VGG16 в оригинальном скрипте. Но результат все равно выглядит странно, т.к. ожидалось, что сеть окажет большее внимание ушам собаки, как это было на иллюстрации в книге. Не понятно, что я сделал не так :).
"Тепловой цвет" можно сделать более выраженным, если повысить коэффициент модифицированного слоя при наложении на оригинальное изображение. Например использовать 0.7, вместо 0.4 в исходном скрипте.
... # Superimpose the heatmap on original image #superimposed_img = jet_heatmap * 0.4 + img - ORIGINAL superimposed_img = jet_heatmap * 0.7 + img superimposed_img = tensorflow.keras.preprocessing.image.array_to_img(superimposed_img) ...
Запуск скриптов на кошке показал, что слой "conv5_block3_out" все-таки надо использовать, иначе засвечивается совсем что-то неадекватное. Итоговый результат тепловой карты для разных моделей, (коэффициент подкрашивания 0.7):
Похоже, что сеть VGG16 справляется все-таки лучше, чем ResNet50.
В книге используются команды Linux для скачивания наборов данных, их сортировки и прочего. Искать аналоги этим командам в Windows - лишняя трата времени, потребуется ставить различные утилиты и смотреть как это все работает. Гораздо проще запустить Linux внутри Windows, если используется Windows 10 и выше. Есть много наглядных видео-инструкций как это сделать, например PyLounge: WSL На Windows 10. Краткая напоминалка:
wsl --set-default-version 2
Команды Powershell для управления WSL:
// Посмотреть список запущенных подсистем wsl --list --running // Закрыть конкретную подсистему wsl -t Ubuntu-20.04 // Закрыть все подсистемы wsl --shutdown
Доступ к диску С в окне Ubuntu:
// ChangeDirectory cd /mnt/c // List содержимого ls
Команды Linux:
ls : вывести список (list) grep cat : выбрать в списке имена содержащие шаблон, в данном случае "cat" в имени файла sort : упорядочить имена, sort -R : упорядочить в случайном порядке (Random) head -250 : выбирает 250 имен с начала списка (tail с конца) mv : Move file xargs : конструирует строку параметров и исполняет с ней команду xargs -I : ReplaceString xargs -I {} mv {} train/cat/ : перемещает каждый файл из входного списка в директорию // В текущей директории выбираем все файлы содержащие в имени "cat", // случайно сортируем и 250 первых файлов перемещаем в директорию train/cat/ ls | grep cat | sort -R | head -250 | xargs -I {} mv {} train/cat/