Рис.1 Флагман мирового кинематографа
Рис.1 Флагман мирового кинематографа

В продолжении поста о создании алгоритма распознавания картин художников, хочу поделиться одной мыслью. Искусственный Интеллект как я его всегда представлял, являлся неким разумом, рациональной машиной по разрешению заданных вопросов и задач, заданных человеком. Будь то скрипт с исходными данными, или же голосовой помощник, он готов дешифровать и анализировать входящую информацию и выдавать ответ, даже если он в принципе неверный. Просто статистически данный ответ являлся наиболее верным за определённый отрезок времени (массив данных). Т.е. в большинстве алгоритмов главенствует системный подход к обработке данных (по аналогии, по логике, по большинству совпадений и т.д.). Как бы я обрадовался если увидел где-нибудь "нелогичный" нерациональный ИИ-помощник, который выдавал странный, но главное правильный вариант из множества возможных, так сказать, попадал бы в "яблочко". К примеру, хотел бы я посмотреть вечером фильм,но, и чтобы этот фильм мне точно понравился бы. Задаю вопрос онлайн-помощнику, и что он выдаёт? Он выдаёт то, что смотрели и лайкали множество людей до этого, или он выдаёт высокорейтинговое кино определённого жанра, который я задал, но не имеющего ничего общего с тем, что мне действительно по душе. Я, конечно, знаю, какие фильмы мне пришлись "по душе". Лезу в поисковик, и набираю фильм наподобие... или фильмы похожие на... после чего вижу три-четыре портала с бесконечными списками фильмов. Вхожу и обнаруживаю, что эти фильмы, во первых далеки друг от друга по своей сути, и во вторых они может мне и понравились бы мне, но с совсем другой стороны, как будто я увидел их случайно щёлкая пультом ТВ и решил остановиться на них.

По большинству критериев отбора в данном случае ими являются отнюдь банальные вещи: актёры, которые снимались в моём фильме, который я обозначил как "то, что надо", жанр, и даже эпоха создания такого кино (70е, 80е или же совсем современное кино). Иногда дело обстоит лучше, подборка искомых вариантов предполагает круто заверченный сюжет или арт-хаус атмосферу подбираемых фильмов, локацию с эпохой не создания, а освещения событий в таком кино (викторианская Англия или же ближайшее будущее как пример). Здесь дело обстоит уже лучше, и такие варианты мне как правило "заходят", но опять же, не так глубоко, как тот фильм, что я обозначил как эталон. А в жизни, именно то кино, которое попадает в душу, выходит на меня как правило случайно, незапланированно, давая волю случаю и воображению. Нейронные сети мозга оптимально подбирают контент для просмотра (или прослушивания) исходя из огромного пласта уже имеющейся информации, желаний, потребностей личности. Они сами отыскивают нужное в безбрежном море текстового, видео и аудио контента и заостряют наше внимание в неожиданный день и час, чтобы мы прислушались к оному. Я не футурист, но я вижу ближайшее будущее с более продвинутым уровнем обучаемого искусственного интеллекта, который бы решал подобные задачи с высокой вероятности, загрузив в исходные данные к примеру, все фильмы и дату их создания, которые вы можете вспомнить, не менее 100. Потом он сам бы разложил их на присущие критерии и оценки, и закачав инфу из онлайн-баз по фильмам, выбрал наиболее оптимальные на сегодняшний момент варианты.

Но я отвлёкся, в продолжении прошлого поста о создании программы, по интерпретации картин художников и фоторетуши и присваивания рейтинга на основании 1000 критериев, продолжу его описание. Напомню, что у меня родилась идея создать платформу по цифровизации входящих изображений, полного распознавания контента и присваивания уникального рейтинга, основываясь на растущем массиве данных, прошедших через данный алгоритм.

Рис.2 Блоксхема с классами и критериями отбора изображений.
Рис.2 Блоксхема с классами и критериями отбора изображений.
# установить устройство для вычислений / set computation device
device = ('cuda:0' if torch.cuda.is_available() else 'cpu')
print(f"Computation device: {device}")

# создание модели для обучения / create model
m = effnetv2_s(num_classes = 1)
for param in m.parameters(): 
    param.requires_grad = True

# загрузка последних весов сети / load the last weights of model
if os.path.exists(opt.best_weights):
    try:
        m.load_state_dict(torch.load(opt.best_weights,map_location = device))
        print("The pre-trained network has been loaded!")
    except Exception:
        print("The pre-trained network has not been loaded!")
m.to(device)
m.eval()

Фрагмент скрипта алгоритма распознавания.

Суть данной модели в том, что все вычисления проходят последовательно, эту последователность нужно будет менять, чтобы достигнуть максимально идеального распознавания входящих картинок. При всём изобилии стандартных параметров картинок (кол-во пикселов, цветонасыщенность, контраст, чёткость), наиболее интересными критериями в моём случае являются критерии изобразительного искусства. И оно не ограничивается лишь стилями произведения (натюрморт, пейзаж, портрет, скетч, абстракция..) но и массой других. Чем рисовали или фотографировали (инструмент), какие материалы исползовали (краски, уголь, мозайка, фотошоп, фотоаппарат наконец), какую технику использовали, масса сравнительных доп. критериев (aka рембрандт, aka вангог, aka микельанджело) может быть также применено. Отдельные критерии можно добавлять как в начале цикла, так и в любом другом месте, вставляя его в последовательную цепь вычислений. Для начала я ограничился лишь 3мя: это наличие цвета, признак фотографии, признак наличия живых объектов на изображении. Они выстроены в порядке сложности вычислений от простого к сложному и максимально упрощены тем что существует альтернативный класс в каждом из вычислений (неопределено). И каждый критерий в зависимости от определённой отработанной иерарахии будет добавлять определённое кол-во баллов для итогового вычисления рейтинга (по 100 или 10 бальной шкале).

С готовым скриптом всё только начиналось, и по нескольким тестам я понял что на это потребуются годы. Тестирование началось с первой части модуля, который должен был определить, исходный файл фотография или же что-то иное. Началась долгая и последовательная череда тестирования модели, которая покажет наилучшую последовательность распознований и параметров для данного набора критериев. Выбрал алгоритм от простого к сложному по предположению, в моём случае цвет-нецвет, фото-нефото и есть ли живое на картинке или нет. Результаты я (слава Богу) документировал, не обессудьте за безсистемность записей.

Первый тест> прогнал 44 файлов, один файл был забракован по непонятной причине, в папке фото оказались 8 нефотографий, причём большинство из них это сканированные полотна реальных картин. И в папке nfoto вышло 2.5 ошибки (0,5 это ошибка, но в то же время спорная - там чашка кофе сфотографированная, но отретушированная в фотошопе). Пару картинок скрипт вообще не обрабатывал, причина этого так и осталось загадкой, потому как после многих обновлений эти файлы так и были приняты.

Второй тест> прогнал 301 изображение, в папке foto 44 ошибочных результата (большинство это фантасмагория с качественной анимацией и сканы известных полотен художников. В папке nfoto только 2 ошибочных результата. Один и тот же снимок мужчины (фотография из журнала) и фото автомобиля не низкого разрешения. Итог этого теста - налицо перекос ошибочных интерпретаций в сторону нефото.

Третий тест> 3940 фото, 3461 нефото

ЦВЕТ. выдало 29 ошибок из 1929>1.5%

Ч.Б выдало 0 ошибок

НЕОПРЕДЕЛЕНО выдало 98 файлов из 2415>4,05% (абсолютные Ч.Б изображения)

ЖИВОЕ выдало 16 ошибок из 1313>1.2% (ракушки и морские растения, пляж)

Я решил продолжить тест и поиграться с одним чудным параметром, называется confidence level, по умолчанию выставлен 0,85. Этот параметр отвечает за степень "уверенности"модели в принятии решении о классификации. Чем ближе этот параметр к 1 (max значение), тем более уверенно скрипт будет раскидывать файлы по папкам, менее взвешено так сказать. Посмотрим как это будет отображено на практике.

print("Start with parameters:")  
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    # папка с исходными данными / input folder with data
    parser.add_argument('--input_folder', type=str, default='input')
    # папка с выходными данными / output folder with data
    parser.add_argument('--output_folder', type=str, default='output')
    # файл для весов лучшей модели / best weights file
    parser.add_argument('--best_weights', type=str, default='./best_weights.pth')
    # размер изображения / image size
    parser.add_argument('--image_size', type=int, default=528)
    # доверительная вероятность / confidence level
    parser.add_argument('--conf_level', type=float, default=0.85)
    # парсинг параметров / parsing of parameters
    opt = parser.parse_args()
print(opt)

Фрагмент кода разпознавающего скрипта eval.py с выделением параметра conf_level

Четвёртый тест> С увеличенным паметром conf_level до значения 0,9 (вместо 0,85 по-умолчанию):

ЖИВОЕ (ОШИБКИ)> 12 ИЗ 1293 (0,92%)

НЕЖИВОЕ (ОШИБКИ)> 36 ИЗ 470 (7,6%)

НЕОПРЕДЕЛЕНО> 397 из 2175 (18.25%)

Пятый тест> С увеличенным паметром conf_level до значения 0,95:

ЖИВОЕ (ОШИБКИ)> 5 ИЗ 1253 (0,39%)

НЕЖИВОЕ (ОШИБКИ)> 25 ИЗ 398 (6,28%)

НЕОПРЕДЕЛЕНО> 509 из 2175 (23,4%)

Шестой тест> С увеличенным паметром conf_level до значения 1:

ЖИВОЕ > 0 файлов

НЕЖИВОЕ> 0 файлов

НЕОПРЕДЕЛЕНО> 2160 из 2175 файлов, все что были прочитаны

Тенденция ясна, чем выше ставить данный параметр от заданной точки, тем больше файлов отправляется в "корзину". Но вместе с этим, количество ошибочных распознаваний значительно уменьшается, доходя до 0 ошибок ("нечем ошибаться, всё отбраковано"). Оставлил conf_level пока по умолчанию, но в будущем, когда будет масса критериев и соответственно ошибок, я возможно подниму его до 0,9.

P.S. Я продолжаю работать над тестированием этого модуля, и приглашаю всех, кто неравнодушен, писать в комментариях свои пожелания по распознаванию и по платформе в целом, фидбэки и предложения. Думаю, найдутся и единомышленники, которые поправят мои ошибки, внесут свои идеи.  Продолжение следует..

Комментарии (0)