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

В основном искусственные нейронные сети разрабатывают на таких языках программирования высокого уровня, как C или C++, но вы можете создать нейронную сеть и на PHP, что, скорее всего, будет наиболее удобным решением для реализации системы искусственного интеллекта в веб-приложении. В этой статье я помогу вам создать свою первую нейронную сеть на PHP с использованием класса для работы нейронной сетью на примере одной из самых распространенных топологий нейронных сетей – многослойного перцептрона (multi-layer perception).

Подобно человеческому мыслительному процессу, нейронная сеть:

  1. получает некоторый ввод (ваши данные)

  2. анализирует и обрабатывает его

  3. предоставляет на выходе какое-либо значение (т.е. результат вычисления)

Именно поэтому топология в этом примере (многослойного перцептрона) будет состоять из трех слоев:

  • Входной слой (Input layer)

  • Скрытый слой (hidden layer)

  • Выходной слой (output layer)

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

Подготовка входных данных для нейронной сети на PHP

Поскольку нейронные сети являются сложными математическими моделями, вы не можете скармливать входному слою нейронов любой тип данных. Данные должны быть нормализованы, прежде чем сеть сможет использовать их. В нашем случае это означает, что данные должны быть приведены к диапазону от -1 до 1. К сожалению, в PHP нет функции для нормализации данных, поэтому вам придется сделать это самостоятельно, но я поделюсь с вами формулой для нормализации:

I = Imin + (Imax-Imin)*(D-Dmin)/(Dmax-Dmin)

Где Imin и Imax представляют диапазон нейронной сети (от -1 до 1), а Dmin и Dmax - минимальное и максимальное значение данных.

После нормализации данных вы должны определиться с количеством нейронов во входном слое. Например, если ваши данные представляют цвета в формате RGB, и вы хотите определить, является ли красный или синий доминирующим цветом, вам понадобится четыре входных нейрона (три нейрона для хранения значений красного, зеленого и синего, а четвертый – это смещение, обычно равное 1). Ниже приведен PHP-код для этого вычисления:

<?php
require_once("class_neuralnetwork.php");
$n = new NeuralNetwork(4, 4, 1);  // количество нейронов в каждом слое сети -- 4 во входном, 4 в скрытом и 1 в выходном
 $n->setVerbose(false); // Не отображать сообщения об ошибках
// тестовые данные
// Первый массив — это входные данные, а второй — ожидаемое выходное значение (1 означает синий, 0 — красный)
 $n->addTestData( array (0, 0, 255, 1), array (1));
  $n->addTestData( array (0, 0, 192, 1), array (1));
  $n->addTestData( array (208, 0, 49, 1), array (0));
  $n->addTestData( array ( 228,  105, 116, 1), array (0));

  $n->addTestData( array (128, 80, 255, 1), array (1));
  $n->addTestData( array ( 248,  80, 68, 1), array (0));
?>

Здесь всего один нейрон в выходном слое, потому что у нас может быть только два возможных результата. Для более сложных задач выходной слой может задействовать более одного нейрона, что позволит нам получить в качестве возможных выходных значений множество комбинаций нулей и единиц.

Обучение нейронной сети в PHP

Прежде чем нейронная сеть сможет решить задачу, она для начала должна научиться ее решать. Здесь мы можем провести параллель с уравнением. Вы предоставляете тестовые данные и ожидаемый результат, а сеть должна решить уравнение, найдя связь между входными и выходными данными. Этот процесс называется обучением (training). В нейронных сетях эти связи представлены весами нейронов. Для обучения сети можно использовать несколько алгоритмов, но самый популярный из них – алгоритм обратного распространения ошибки (backpropagation).

Изначально мы инициализируем сеть случайными весами. Затем нам нужно повторить следующие шаги:

  1. Запустить сеть на тестовых данных.

  2. Получить фактический вывод.

  3. Вычислить ошибку (желаемый результат - текущий результат сети)

  4. Вычислить поправки весов.

  5. Обновить веса.

Процесс будет продолжаться до тех пор, пока все тестовые данные не будут правильно классифицированы или алгоритм не достигнет критерия остановки. Обычно программист пытается обучить сеть максимум три раза, а максимальное количество раундов обучения (эпох) составляет 1000. Кроме того, каждому алгоритму обучения нужна функция активации (характеристическая функция). Для обратного распространения функция активации - это гиперболический тангенс (tanh).

Давайте посмотрим, как можно обучить нейронную сеть в PHP:

<?php
$max = 3;
 // обучаем сеть максимум за 1000 эпох с максимальной квадратичной ошибкой 0,01
 while (!($success=$n->train(1000, 0.01)) && $max-->0) {
// обучение не удалось -- инициализируем веса сети повторно
$n->initWeights();
 }

// получаем необходимое для обучения количество эпох
if ($success) {
$epochs = $n->getEpoch(); // get the number of epochs needed for training
}
?>

Среднеквадратическая ошибка модели (mean squared error – mse), также известная как стандартное отклонение (standard deviation), представляет собой среднее значение квадратов ошибок. Значение среднеквадратической ошибки по умолчанию обычно равно 0.01, что означает, что обучение прошло успешно, если среднеквадратическая ошибка меньше 0.01.

Перед началом работы с реальными примерами на PHP рекомендуется сохранить вашу нейронную сеть в файл или базу данных SQL. Если вы не сохраните ее, вам придется проводить обучение каждый раз, когда кто-то запускает ваше приложение. Простым задачам нейронные сети обучаются быстро, но обучение более сложным задачам занимает гораздо больше времени, а свести к минимуму любое ожидание для ваших пользователей – в ваших же интересах. К счастью, в PHP-классе, который мы используем в этом примере, есть функции save и load:

<?php
$n->save('my_network.ini');
?>

Обратите внимание, что расширение файла должно быть .ini.

PHP-код нашей нейронной сети

Ниже приведен PHP-код готового приложения, которое получает значения красного, зеленого и синего и вычисляет, какой цвет в них превалирует: синий или красный:

<?php
require_once("class_neuralnetwork.php");
$r = $_POST['red'];
$g = $_POST['green'];
$b = $_POST['blue'];

$n = new NeuralNetwork(4, 4, 1); // инициализируем нейронную сеть
$n->setVerbose(false);
$n->load('my_network.ini'); // загружаем сохраненные веса в инициализированную нейронную сеть. Таким образом, вам не нужно будет обучать сеть каждый раз, когда вы запускаете приложение.

$input = array(normalize($r),normalize($g),normalize($b));  // обратите внимание, что вам придется написать функцию нормализации, подходящую для вашей конкретной задачи

$result = $n->calculate($input);
If($result>0.5) {
// превалирующий цвет синий
}
else {
// превалирующий цвет красный
}
?>

Ограничения нейронных сетей

Основное ограничение нейронных сетей заключается в том, что они могут решать только линейно разделимые (линейно сепарабельные) задачи, а многие задачи не являются линейно разделимыми. Т.е., не линейно разделимые задачи требуют другого подхода искусственного интеллекта. Однако нейронные сети все-таки решают достаточное количество задач, требующих помощи компьютерного интеллекта, чтобы занимать важное место среди алгоритмов искусственного интеллекта.


Материал подготовлен в рамках курса "PHP Developer. Professional".

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


  1. Hardcoin
    17.04.2023 16:58

    они могут решать только линейно разделимые (линейно сепарабельные) задачи

    Как мы все теперь знаем, написание кода и рисование фотореалистичных картин - линейно разделимые задачи.


  1. PigData
    17.04.2023 16:58

    У кого-нибудь это работает? Там $result = $n->calculate как минимум выдает массив и такой if не работает. Но даже если брать $result[0] доминирующий цвет определяется не правильно (тут вопрос еще почему в коде нет нормализации данных на входе). Автор перевода может дать свой вариант полностью рабочего кода? Или это просто перевод древней статьи без теста кода и проверки актуальности класса?


    1. CoderDoder
      17.04.2023 16:58

      Последний комит в 2017 году. Скорее всего нужно пробовать запускать на старых версиях php


  1. riky
    17.04.2023 16:58
    +1

    Было бы интересно попробовать через ffi подключить какую нибудь библиотеку для нс. А ещё в пхп есть fann


    1. SerafimArts
      17.04.2023 16:58

      Так уже же есть, ей тысяча лет в обед https://github.com/dstogov/php-tensorflow


  1. Expany
    17.04.2023 16:58
    +1

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