Введение
Нейронные сети неуклонно приобретают все большее значение в жизни человека. Они ускоряют работу специалистов в десятки раз, избавляя человечество от рутинной части работы, связанной с большими объемами данных.
Нейронные сети - будущая сверхдержава человечества. Я думаю, что у этой области огромный потенциал для развития. В настоящее время нейронные сети могут справляться с такими задачами, как создание текстов, написание и перевод кода на различные языки программирования, быстрый анализ данных, поиск и исправление ошибок в коде и многое другое. Нейронные сети нового поколения могут решать различные творческие задачи. Они используются в различных областях, таких как транспорт, сельское хозяйство, медицинское обслуживание, безопасность, дизайн, социальные исследования и развлечения. Широкое использование нейронных сетей вызывает некоторые опасения у определенных групп людей, которые боятся потерять работу, а также у людей, испытывающих опасения, связанные с возможностью кражи и неправомерного использования персональных данных. Безусловно, в будущем нам следует рассмотреть меры безопасности и нормы ограничений при использовании нейронных сетей.
Цели и задачи работы
Несмотря на то, что нейронные сети распространены повсеместно, пока не каждый может создать для себя удобную нейронную сеть, которая помогала бы ему в решении повседневных задач и учебе. Я решил попробовать написать код для своей первой экспериментальной нейронной сети, способной различать изображения собак и кошек.
В процессе работы над созданием конечного продукта меня мотивировал тот факт, что, очевидно, в ближайшем будущем люди, умеющие работать с нейронными сетями, будут иметь преимущество при приеме на работу.
Цели:
Создать нейросеть для распознавания изображений кошек и собак.
Задачи:
изучить язык программирования Python для написания нейронных сетей,
овладеть умением определять задачи для нейронных сетей и разрабатывать алгоритмы для них.
Я думаю, что это довольно сложная цель для меня, потому что мне пришлось с нуля изучать раздел Python, посвященный созданию нейронных сетей.
Моим конечным продуктом станет - сверточная нейронная сеть для различения изображений кошек и собак. Я написал и обучил свою нейронную сеть в октябре-ноябре 2023 года.
Задачи классификации, которые легко решает двухлетний ребенок, все еще непросты для программ. Распознавать объекты в окружающем мире гораздо сложнее, чем играть в шахматы.
Основная часть
История развития нейросетей
Нейросеть – математическая модель, работающая по принципу нервной системы живых организмов. Основными компонентами нейросети являются нейроны, которые функционируют аналогично нейронам в человеческом мозге. Нейроны объединяются в слои, и каждый нейрон принимает входные сигналы, обрабатывает их и передает результат следующему слою нейронов. Главной особенностью нейросетей является способность к обучению. Они могут обучаться как под управлением человека, так и самостоятельно, применяю раннее полученный опыт.
История существования нейросетей не такая длительная, как история человечества, поэтому позвольте обозначить её основные вехи.
Развитие искусственных нейросетей началось с появления первых электронно-вычислительных машин (ЭВМ) в конце 1940-х годов. Канадский физиолог и нейропсихолог Дональд Хебб внес вклад в создание алгоритма нейронной сети и сформулировал основные принципы ее работы.
В 1954 году на практике впервые применили нейросеть на компьютерах.
1958 год: Американский ученый по нейрофизиологии Фрэнк Розенблатт разработал перцептрон, алгоритм распознавания образов, и представил его общественности. Это событие считается одной из важных вех в развитии нейросетей.
1960-е годы: В это десятилетие интерес к нейросетям временно угас из-за ограниченных вычислительных мощностей компьютеров, которые не позволяли выполнять сложные задачи, возложенные на нейросети.
1980 год: Интерес к нейросетям вернулся благодаря увеличению вычислительных мощностей компьютеров. В этот период появилась система с механизмом обратной связи, и начались исследования в области алгоритмов самообучения.
1990-е годы: В следующие два десятилетия вычислительные мощности значительно выросли, и ученые смогли применять нейросети во многих областях. Появились программы распознавания речи, имитация зрения и восприятия информации.
21 век: Нейросети стали частью искусственного интеллекта (ИИ).
Нейросети могут решать следующие задачи:
Нейросети используются для анализа и генерации текста, перевода с одного языка на другой, создания чат-ботов и автоматической обработки текстовых данных.
Задачи распознавания объектов, сегментации изображений, распознавания лиц и даже автономного вождения требуют нейронных сетей для анализа и понимания изображений и видео.
Нейросети используются для персонализированной рекомендации контента, такого как фильмы, музыка, товары, и т. д.
В области здравоохранения нейросети используются для анализа медицинских изображений, диагностики болезней и прогнозирования течения заболеваний.
Машинное обучение и нейронные сети помогают в анализе больших объемов данных и прогнозировании будущих событий.
Исследование языков программирование для создания нейросетей
Для написания нейросетей используются следующие языки программирования:
Pythonимеет следующие преимущества:
1) Простота и удобство в использовании.
2) Обширное сообщество и богатая экосистема с библиотеками для машинного обучения.
Однако есть некоторые минусы:
1) Медленнее выполнение в сравнении с C++ и Java.
2) Иногда требует использования библиотек на C/C++ для оптимизации.
С++ имеет следующие плюсы:
1) Высокая производительность и возможность оптимизации.
2) Широкие возможности для параллельных вычислений.
Однако есть некоторые недостатки:
1) Более низкий уровень абстракции, что может затруднить разработку и отладку.
2) Сложнее в обучении и использовании для новичков.
Язык Java хорош своей:
1) Портабельностью и надежностью.
2) Удобными инструментами для многопоточных приложений.
Но
1) Производительность часто ниже, чем у C++ и Python.
2) Есть ограничения из-за сборки мусора и управления памятью
Исходя из проведенного исследования, я решил создать свою сеть на языке Python (версия 3.11.6). Python - самый популярный язык для машинного обучения и анализа данных. Вот почему я выбрал этот язык для написания своей нейронной сети.
Основные принципы работы нейросети
Как работает нейросеть. Классический алгоритм
Принцип работы нейросетей следующий:
Нейроны: Нейронные сети состоят из нейронов, которые аналогичны нейронам в мозге. Каждый нейрон принимает входные сигналы, выполняет вычисления и передает выходные сигналы другим нейронам.
Входные данные: на вход нейросети поступают данные. Эти данные могут представлять собой изображения, текст, звук или любую другую форму информации, зависящую от задачи, которую решает нейросеть.
Веса и смещения: каждый входной сигнал умножается на вес и добавляется смещение.
Функция активации: после применения весов и смещений к входным данным, результат проходит через функцию активации. Функция активации определяет, должен ли нейрон активироваться и передавать сигнал дальше.
Слой за слоем: нейроны организованы в слои, и данные проходят через нейроны последовательно от входного слоя к выходному слою. Промежуточные слои называются скрытыми слоями и помогают извлекать признаки из данных.
Обучение: нейронные сети «дрессируются» на основе обучающих данных. В процессе обучения нейросеть настраивает веса и смещения, чтобы минимизировать ошибку между прогнозами и фактическими данными.
Прогнозирование: после обучения нейросеть может использоваться для прогнозирования или классификации новых данных. Входные данные передаются через обученную сеть, и она выдает прогноз или классификацию на основе своих знаний.
Критерии создания нейронной сети
Для того, чтобы лучше понимать какой должная быть будущая нейросеть я разработал критерии для ее оценки.
Критерий |
5 баллов |
4 points |
3 points |
2 points |
Точность Моя программа должна корректно распознавать большинство изображений из общего числа |
100 - 95% |
94-90% |
89-80% |
79-70% |
Матрица ошибок Нейронная сеть, которую я написал, должна правильно различать изображения для каждого класса животных (кошек и собак). |
Нет ошибок |
1 - 2 ошибки |
3 - 5 ошибки |
6 - 10 ошибок |
Устойчивость к шуму Моя нейронная сеть должна быть способна распознавать изображения с различными дефектами, такими как: шум, артефакты и другие искажения |
Высокая |
Средняя |
Низкая |
Очень низкая |
Надежность работы Моя нейронная сеть должна быть проста в использовании, обновление не должно вызывать сложностей даже у начинающего программиста |
Высокая |
Средняя |
Низкая |
Очень низкая |
Создание нейросети для распознавания кошек и собак
В процессе обучения сеть много раз просматривал обучающую выборку в определенном порядке. Один полный проход по выборке называется эпохой обучения. Моя нейронная сеть прошла 30 циклов обучения. При обучении исходный набор данных был разделен на 2 части - обучающую выборку и тестовые данные. Выборка в моем случае состояла из 25 000 изображений собак и кошек. 20 000 из них были использованы для обучения, 5000 - для тестирования. Все изображения находятся в папке Petimages2. Используемый набор данных - Кошка против собаки Классификация изображений Google. Набор данных для обучения должен был соответствовать следующему критерию - согласованности, поскольку противоречивые данные в обучающей выборке могли привести к низкому качеству обучения сети.
Были импортированы необходимые библиотеки, такие как os, random, numpy, tensorflow, PIL и т.д.
Имя файла, в котором была сохранена модель, было - "cat_dog_classifier.keras".
В строке был указан текущий каталог, в котором находился исполняемый скрипт. Это было использовано для создания полных путей к каталогам с данными и изображениями.
Были сформированы пути к различным каталогам. “PetImages2” - корневой каталог данных, “Train” и “Test” - подкаталоги для обучающих и тестовых данных соответственно, “images” - каталог с изображениями для классификации.
img_width, img_height = 200, 200: эти две переменные определили размеры изображений, которые будут использоваться при обучении модели. В данном случае изображения были масштабированы до размера 200x200 пикселей.
batch_size = 32: определено количество изображений в одном пакете данных, которые были переданы модели за одну итерацию обучения.
epochs = 30: это количество эпох, то есть количество полных циклов прохождения обучающего набора данных через модель.
rescale=1.0 / 255.0: масштабировал значения пикселей от диапазона [0, 255] до [0, 1]. Проще говоря, это преобразование цвета в диапазон от 0% до 100%.
rotation_range=15: установите диапазон углов поворота для произвольного поворота изображений в градусах.
width_shift_range=0.2, height_shift_range=0.2: определите диапазоны случайного горизонтального и вертикального смещения изображений.
shear_range=0.2: установил диапазон для случайного изменения угла наклона изображений.
zoom_range=0.2: определен диапазон случайного масштабирования изображений.
horizontal_flip=True: включено случайное горизонтальное отражение изображений.
fill_mode=“nearest”: определил стратегию заполнения для случайного смещения и/или поворота изображений. В данном случае использовалась заливка ближайшими пикселями.
test_datagen: преобразованные данные для тестирования модели.
os.path.exists(model_name): в этой строке использовалась функция os.path.exists(), чтобы проверить, существует ли файл модели с именем model_name. Если файл существовал, это означало, что модель уже была обучена и сохранена. Условие проверялось, если os.path.exists(model_name) было верно, и программа приступит к загрузке этой существующей модели.
Если файл модели не существовал, то были созданы генераторы для обучающих и тестовых данных с использованием ранее определенных параметров (таких как масштабирование, поворот и т.д.). Эти генераторы использовались для подготовки данных для обучения модели.
Был создан последовательный объект, который представлял собой линейную стековую модель. В данном случае модель создавалась шаг за шагом, добавляя слои один за другим.
Слой Conv2D представляет собой сверточный слой. 32 — это количество фильтров здесь, (3, 3) - размер ядра свертки, “relu” - функция активации, а input_shape указывает размер входных изображений.
Уровень Batch Normalization выполнил пакетную нормализацию, что помогло ускорить обучение, уменьшив внутреннюю ковариацию. Другими словами, это предотвратило слишком большое отклонение значений от нормы / друг от друга.
MaxPooling2D слой выполнил операцию субдискретизации, уменьшив размерность изображения путем выбора максимального значения из каждой области. Другими словами, он удалил потенциально ненужные части из изображения, сохранив общий смысл.
Уровень отсева применял случайную деактивацию нейронов с вероятностью 0,2, что помогло предотвратить переобучение.
Аналогичные блоки были добавлены для создания глубокой структуры. Это помогло извлечь из изображений более сложные объекты.
Слои Flatten и Dense преобразовали данные в плоский вектор и добавили полностью связанный слой.
Выходной слой с sigmoid activation использовался для бинарной классификации. Он возвращал вероятность принадлежности к классу 1 (или 0).
ReduceLROnPlateau - контролер, который контролировал точность (accuracy) данных проверки. Если точность не улучшалась в течение 2 эпох (терпение=2), это снижало скорость обучения (learning rate) в полтора раза (коэффициент=0,5). Это помогло устранить возможные проблемы со сходимостью модели.
EarlyStopping - если значение функции потерь (loss) по данным проверки не улучшалось в течение 3 эпох (терпение=3), то обучение прерывалось, и модель восстанавливала наилучшие веса. Это предотвращало переобучение и экономило время.
Скорость обучения была параметром, определявшим размер шага, который делала модель при корректировке весов в процессе обучения. Слишком высокая скорость обучения может привести к тому, что модель “перепрыгнет” через минимум, а слишком низкая скорость обучения может замедлить обучение или застрять на локальном минимуме.
Функция потерь была показателем, который измерял, насколько хорошо модель выполняет задачу. В задачах двоичной классификации (two-class) в качестве функции потерь часто используется двоичная перекрестная энтропия. Чем ниже значение функции потерь, тем лучше модель выполняет свою задачу.
model.compile (optimizer = «adam», loss=«binary_crossentropy», metrics = [“accuracy»]): после определения архитектуры модели ее нужно было “скомпилировать”, т.е. задать параметры обучения. В этом случае я использовал оптимизатор Adam, функцию потери энтропии binary_cross для бинарной классификации (кошка/собака) и метрику для оценки производительности - точности.
optimizer = «adam»: оптимизатор определил метод, который модель использовала для обновления весов и минимизации функции потерь в процессе обучения. «Adam» - популярный оптимизатор, который эффективно адаптируется к изменениям скорости обучения для каждого параметра.
loss = «binary_crossentropy»: это функция потерь, которую модель стремилась минимизировать в процессе обучения. В данном случае, поскольку у нас задача бинарной классификации (кошки или собаки), была использована «binary_crossentropy». Эта функция измеряла, насколько прогнозы модели отличались от фактических значений.
metrics=[“accuracy”]: это показатель, который отслеживался в процессе обучения для оценки производительности модели. Здесь использовалась “accuracy” (точность), которая измеряла долю правильных предсказаний модели.
model.fit: этот метод запустил процесс обучения. Модель была обучена на данных, предоставленных train_generator, с использованием таких параметров, как количество эпох (epochs), размер пакета (batch_size) и данные для проверки (test_generator). Также были включены обратные вызовы early_stopping и learning_rate_reduction, которые контролировали процесс обучения.
model.save (model_name): после завершения обучения модель была сохранена в файле с именем, указанным в model_name. Это позволило мне использовать обученную модель в будущем без необходимости переподготовки.
history.history: это объект, который сохранил метрики и функции потерь в процессе обучения. history.history [“accuracy”][-1] вернул последнее значение точности для обучающих данных, и history.history[“val_accuracy”][-1] - о данных проверки.
model.save: модель была сохранена в файле с именем, указанным в поле model_name, чтобы ее можно было повторно использовать без переподготовки.
После завершения обучения последние значения точности обучающих и тестовых данных были извлечены из history.история. Эти значения отображались в консоли, что позволило мне оценить производительность модели.
Функция classify_random_images случайным образом выбрала несколько изображений из image_dir. Затем размер каждого изображения был изменен, нормализован и передан модели для классификации (кошка или собака). Результаты были отображены в консоли.
В бесконечном цикле вызывалась функция классификации случайных изображений, и программа ожидала ввода пользователем перед каждым новым набором изображений.
Я проверил нейронную сеть на корректность и убедился, что она может распознавать изображения собак и кошек.
Оценка по выбранным критериям, следующая:
Точность - 100 - 95%
Матрица ошибок - 6 - 10 ошибок
Устойчивость к шуму - Очень низкая
Надежность работы – Средняя
Заключение
В настоящее время организуется большое количество приютов для домашних животных. Кормление животных в таких приютах может производиться автоматически. На клетках можно разместить изображения животных, которые будут считываться нейронной сетью, распознающей картинку. Исходя из этого, будет выбран корм для кошек или собак. В будущем можно будет поработать над улучшением этой сети, чтобы распознавание было более дифференцированным. Например, программа могла различать разные породы собак и кошек. Кроме того, распознавание будет основываться не на картинках, а на живых объектах. Вы можете создать модификацию для разделения животных на одной и той же картинке. Если вы сможете улучшить сеть так, чтобы она могла не только отличать собаку от кошки на фотографии, но и идентифицировать лица конкретных, реальных домашних животных, то в долгосрочной перспективе такую нейронную сеть можно будет использовать для создания паспортов животных и поиска потерянных питомцев.
Мне пришлось изучать совершенно новые вещи в ускоренном темпе и сразу же применять их на практике, что заставило меня выйти из своей зоны комфорта. Поскольку это был мой первый опыт написания кода для нейронной сети и ее дальнейшего обучения, мне было сложно. Но когда я увидел, что первоначальная версия нейронной сети имела точность классификации изображений животных 75%, а позже увеличилась до 96%, это придало мне уверенности в том, что мне удалось создать то, что я задумал. Эта работа была мне интересна, поэтому мне было легче преодолевать возникшие трудности.
В процессе работы над проектом мне пришлось просмотреть большое количество информации по интересующей меня теме. При сборе информации для разработки и обучения нейронной сети мне пришлось фильтровать, оценивать и выбирать надежные источники. Эти навыки помогли мне, как разработчику, не только найти необходимую информацию, но и критически проанализировать ее, выделив ключевые аспекты.
Список использованных источников и литературы
https://www.ibm.com/topics/neural-networks
https://www.analyticsvidhya.com/blog/2020/07/neural-networks-from-scratch-in-python-and-r/
https://en.wikipedia.org/wiki/Donald_O._Hebb
https://en.wikipedia.org/wiki/Frank_Rosenblatt
https://en.wikipedia.org/wiki/Artificial_neural_network#History
https://en.wikipedia.org/wiki/Deep_learning
https://www.guru99.com/java-vs-python.html
https://ru.wikipedia.org/wiki/C%2B%2B
https://ru.wikipedia.org/wiki/Java
https://en.wikipedia.org/wiki/Natural_language_processing
https://en.wikipedia.org/wiki/Computer_vision
https://en.wikipedia.org/wiki/Recommender_system
https://en.wikipedia.org/wiki/Medical_imaging
https://en.wikipedia.org/wiki/Data_analysis
https://cs231n.github.io/neural-networks-1/
https://en.wikipedia.org/wiki/Medical_diagnosis\
https://en.wikipedia.org/wiki/Financial_forecast
https://en.wikipedia.org/wiki/Artificial_intelligence_in_video_games
https://www.w3schools.com/python/python_ml_getting_started.asp
https://www.tensorflow.org/resources/models-datasets?hl=ru
https://realpython.com/tutorials/machine-learning/