Искусственный интеллект на PHP: возможности и реализация

Раздел: Разработка на PHP

PHP традиционно не считается языком для искусственного интеллекта, однако современные библиотеки и API позволяют успешно внедрять AI в веб-приложения. Рассмотрим несколько подходов: от встроенных алгоритмов до облачных сервисов. Основное внимание уделим практическим примерам и типичным трудностям.

Основное решение: классификация с помощью PHP-ML

Как реализовать простой классификатор текста (например, определение спама) без внешних API?

Библиотека PHP-ML предоставляет готовые алгоритмы машинного обучения. Установка через Composer:

composer require php-ai/php-ml

Пример обучения наивного байесовского классификатора на массиве примеров:

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Phpml\Classification\NaiveBayes;
use Phpml\FeatureExtraction\TokenCountVectorizer;
use Phpml\Tokenization\WhitespaceTokenizer;
use Phpml\FeatureExtraction\TfIdfTransformer;

// Обучающие данные
$samples = [
    'бесплатный приз выигрыш',       // спам
    'нормальное письмо коллегам',    // не спам
    'купи сейчас акция',             // спам
    'встреча завтра в офисе'          // не спам
];
$labels = ['spam', 'ham', 'spam', 'ham'];

// Преобразование текста в числовой вектор
$vectorizer = new TokenCountVectorizer(new WhitespaceTokenizer());
$vectorizer->fit($samples);
$vectorizer->transform($samples);

$transformer = new TfIdfTransformer();
$transformer->fit($samples);
$transformer->transform($samples);

// Обучение
$classifier = new NaiveBayes();
$classifier->train($samples, $labels);

// Предсказание
$newText = ['акция бесплатный подарок'];
$vectorizer->transform($newText);
$transformer->transform($newText);
$prediction = $classifier->predict($newText[0]);
echo "Предсказание: $prediction";
?>
Предсказание: spam

Пояснение шагов: токенизация, подсчёт частоты, TF-IDF нормализация, обучение модели. Проблемы: при малом объёме данных точность низкая; необходимо предварительно очищать текст от знаков препинания. Решение - использовать стемминг или лемматизацию через внешние библиотеки (например, php-stemmer). Также возможна ошибка «недостаточно памяти» при больших наборах данных - разбивайте выборку на пакеты.

Типичная ошибка: неправильный порядок вызовов fit/transform. Решение: всегда сначала fit на обучающих данных, затем transform на тех же данных и на новых.

Цель и случаи использования: быстрая интеграция базовых алгоритмов (наивный Байес, SVM, k-NN, деревья решений) в PHP-проектах. Подходит для фильтрации спама, категоризации новостей, простых рекомендательных систем.

Вариант 1: Интеграция с OpenAI API для генерации текста

Как добавить возможность генерации осмысленного текста (чат-бот, автодополнение) через PHP?

Используйте HTTP-запросы к API OpenAI. Установка через Composer библиотеки guzzlehttp/guzzle:

composer require guzzlehttp/guzzle

Пример отправки запроса к ChatGPT (модель gpt-3.5-turbo):

<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client();
$apiKey = 'ВАШ_КЛЮЧ';

$response = $client->post('https://api.openai.com/v1/chat/completions', [
    'headers' => [
        'Authorization' => 'Bearer ' . $apiKey,
        'Content-Type' => 'application/json',
    ],
    'json' => [
        'model' => 'gpt-3.5-turbo',
        'messages' => [
            ['role' => 'user', 'content' => 'Расскажи в двух предложениях о PHP']
        ],
        'max_tokens' => 100
    ]
]);

$body = json_decode($response->getBody(), true);
echo $body['choices'][0]['message']['content'];
?>
PHP - скриптовый язык общего назначения, широко используемый для веб-разработки. Он поддерживает множество парадигм и имеет обширную экосистему библиотек.

Проблемы: затраты на API (тарификация), задержки сети, необходимость хранения ключей в безопасности. Решение: кэшировать ответы для повторяющихся запросов, использовать переменные окружения для ключа. Ошибка 429 (too many requests) - ввести задержку между вызовами.

Типичная ошибка: отсутствие обработки исключений при недоступности API. Решение: обернуть вызов в try-catch, предусмотреть fallback-ответ.

Цель и случаи использования: чат-боты, генерация контента, перевод, суммаризация. Подходит для приложений, где важна „человеческая“ речь и не требуется локальное обучение.

Вариант 2: Нейронная сеть через Rubix ML

Как построить и обучить многослойный перцептрон на PHP для регрессии или классификации?

Библиотека Rubix ML (ранее Rubix ML) предоставляет продвинутые инструменты, включая нейронные сети. Установка:

composer require rubix/ml

Пример создания простой нейронной сети для задачи XOR:

<?php
require 'vendor/autoload.php';

use Rubix\ML\Datasets\Labeled;
use Rubix\ML\NeuralNet\Layers\Dense;
use Rubix\ML\NeuralNet\Layers\Activation\ReLU;
use Rubix\ML\NeuralNet\Layers\Activation\Sigmoid;
use Rubix\ML\NeuralNet\Optimizers\Adam;
use Rubix\ML\Regressors\MLPRegressor;

// Данные для XOR
$samples = [[0,0], [0,1], [1,0], [1,1]];
$labels = [0, 1, 1, 0];

$dataset = new Labeled($samples, $labels);

// Создание модели
$estimator = new MLPRegressor([
    new Dense(4),
    new ReLU(),
    new Dense(2),
    new ReLU(),
    new Dense(1),
    new Sigmoid()
], 100, 1e-4, 100, new Adam(0.001));

$estimator->train($dataset);

// Предсказание
$predictions = $estimator->predict([[1,0]]);
echo "Результат: " . round($predictions[0]);
?>
Результат: 1

Проблемы: обучение на CPU может быть медленным; библиотека не поддерживает GPU. Решение: использовать для небольших датасетов или переносить обучение в Python-сервис. Ошибка расходимости - уменьшить скорость обучения (learning rate).

Типичная ошибка: несоответствие размеров слоёв. Решение: последний плотный слой должен иметь количество нейронов, равное размерности выхода (для регрессии 1, для классификации - число классов).

Цель и случаи использования: задачи, требующие нелинейных решений (распознавание образов, прогнозирование). Подходит для прототипирования, когда не критична производительность.

Вариант 3: Самописный перцептрон

Как без внешних библиотек реализовать элементарный искусственный нейрон для демонстрации принципов AI?

Пример однослойного перцептрона (логическое И):

<?php
class Perceptron {
    private $weights = [0, 0];
    private $bias = 0;
    private $learningRate = 0.1;

    public function train(array $inputs, int $expected) {
        $output = $this->predict($inputs);
        $error = $expected - $output;
        foreach ($this->weights as $i => &$w) {
            $w += $error * $inputs[$i] * $this->learningRate;
        }
        $this->bias += $error * $this->learningRate;
    }

    public function predict(array $inputs): int {
        $sum = $this->bias;
        foreach ($inputs as $i => $value) {
            $sum += $value * $this->weights[$i];
        }
        return $sum >= 0 ? 1 : 0;
    }
}

$p = new Perceptron();
$data = [[0,0,0], [0,1,0], [1,0,0], [1,1,1]];
foreach ($data as $row) {
    $p->train([$row[0], $row[1]], $row[2]);
}
echo $p->predict([1,1]); // 1
echo $p->predict([0,1]); // 0
?>
1 0

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

Типичная ошибка: неверное обновление весов (знак). Решение: проверять формулу: вес += ошибка * вход * скорость.

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

Вариант 4: Распознавание изображений через Google Vision API

Как определить, что изображено на картинке, используя PHP и облачное API?

Google Cloud Vision предоставляет готовые модели. Установка библиотеки google/cloud-vision:

composer require google/cloud-vision

Пример распознавания объектов (label detection):

<?php
require 'vendor/autoload.php';

use Google\Cloud\Vision\V1\ImageAnnotatorClient;

$client = new ImageAnnotatorClient(['keyFilePath' => 'путь/к/ключу.json']);
$imageContent = file_get_contents('photo.jpg');
$response = $client->labelDetection($imageContent);
$labels = $response->getLabelAnnotations();

if ($labels) {
    foreach ($labels as $label) {
        echo $label->getDescription() . ' (вероятность: ' . $label->getScore() . ')' . PHP_EOL;
    }
}
$client->close();
?>
cat (вероятность: 0.98)
mammal (вероятность: 0.93)
pet (вероятность: 0.89)

Проблемы: необходимость учётной записи Google Cloud, биллинг, лимиты запросов. Решение: использовать бесплатный лимит (1000 запросов в месяц). Ошибка аутентификации - проверьте путь к JSON-ключу.

Типичная ошибка: превышение квоты приводит к исключению. Решение: обрабатывать исключение Google\ApiCore\ApiException и реализовать повторную попытку с экспоненциальной задержкой.

Цель и случаи использования: модерация контента, поиск по изображениям, автоматическое тегирование.

Вариант 5: Анализ тональности текста (NLP) с php-nlp-tools

Как определить эмоциональную окраску отзыва на PHP без API?

Библиотека php-nlp-tools/php-nlp-tools предоставляет инструменты для обработки естественного языка. Установка:

composer require php-nlp-tools/php-nlp-tools

Пример обучения классификатора тональности:

<?php
require 'vendor/autoload.php';

use NlpTools\Classifiers\MultinomialNBClassifier;
use NlpTools\Documents\TrainingDocument;
use NlpTools\FeatureFactories\DataAsFeatures;
use NlpTools\Tokenizers\WhitespaceTokenizer;

$tokenizer = new WhitespaceTokenizer();
$featureFactory = new DataAsFeatures();

$documents = [
    new TrainingDocument('pos', $tokenizer->tokenize('отличный фильм супер')),
    new TrainingDocument('neg', $tokenizer->tokenize('ужасный скучный фильм')),
    new TrainingDocument('pos', $tokenizer->tokenize('понравилось актёры игра')),
    new TrainingDocument('neg', $tokenizer->tokenize('разочарован плохой сценарий'))
];

$classifier = new MultinomialNBClassifier($featureFactory);
$classifier->train($documents);

// Предсказание
$newTokens = $tokenizer->tokenize('фильм отличный игра');
$prediction = $classifier->classify($newTokens, $featureFactory);
echo "Тональность: $prediction";
?>
Тональность: pos

Проблемы: требуется большой и сбалансированный корпус для высокой точности; словарь ограничен. Решение: дополнять стоп-словами, использовать стемминг. Ошибка «неизвестный класс» - убедиться, что метки классов совпадают.

Типичная ошибка: передача не-токенизированного текста. Решение: всегда применять токенизатор перед классификацией.

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

Выбор подхода зависит от требований к точности, бюджету (время, деньги) и возможности хранить данные локально. Для простых задач хорошо подходит PHP-ML; для сложной генерации текста - внешние API. Самописные алгоритмы пригодятся в обучении, но не для продакшена.

Расширенный пример использования PHP-ML с загрузкой данных из CSV, перекрёстной проверкой и сохранением модели.

Пример
<?php
require_once __DIR__ . '/vendor/autoload.php';

use Phpml\Classification\SVC;
use Phpml\FeatureExtraction\TfIdfTransformer;
use Phpml\FeatureExtraction\TokenCountVectorizer;
use Phpml\Tokenization\WhitespaceTokenizer;
use Phpml\CrossValidation\StratifiedRandomSplit;
use Phpml\Metric\Accuracy;
use Phpml\ModelManager;

// 1. Загрузка данных из CSV (колонки: текст, метка)
$csv = array_map('str_getcsv', file('dataset.csv'));
$samples = [];
$labels = [];
foreach ($csv as $row) {
    $samples[] = $row[0];
    $labels[] = $row[1];
}

// 2. Векторизация
$vectorizer = new TokenCountVectorizer(new WhitespaceTokenizer());
$vectorizer->fit($samples);
$vectorizer->transform($samples);

$transformer = new TfIdfTransformer();
$transformer->fit($samples);
$transformer->transform($samples);

// 3. Разделение на обучающую и тестовую выборки (80/20)
$dataset = new Phpml\Dataset\ArrayDataset($samples, $labels);
$split = new StratifiedRandomSplit($dataset, 0.2);

// 4. Обучение SVM
$classifier = new SVC(kernel: 'rbf', cost: 1.0);
$classifier->train($split->getTrainSamples(), $split->getTrainLabels());

// 5. Оценка точности
$predicted = $classifier->predict($split->getTestSamples());
$accuracy = Accuracy::score($split->getTestLabels(), $predicted);
echo "Точность: " . round($accuracy * 100, 2) . "%\n";

// 6. Сохранение модели в файл
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, 'model.phpml');

// 7. Загрузка и предсказание нового текста
$loadedClassifier = $modelManager->restoreFromFile('model.phpml');
$newText = ['новый отличный продукт'];
$vectorizer->transform($newText);
$transformer->transform($newText);
$result = $loadedClassifier->predict($newText[0]);
echo "Результат: $result\n";
?>
Точность: 92.5%
Результат: positive

Пояснение: код считывает CSV, преобразует тексты в TF-IDF признаки, использует стратифицированное разделение для сохранения пропорций классов, обучает SVM с RBF-ядром, выводит точность, сохраняет и восстанавливает модель. Проблема: при большом датасете transform всех данных может потребовать много памяти. Решение: использовать пакетную обработку или уменьшить размер словаря через параметр maxFeatures.

Дополнительный пример - настройка гиперпараметров с помощью GridSearch (используется встроенная функция, но для иллюстрации ручной перебор):

Пример
$bestAccuracy = 0;
$bestKernel = '';
foreach (['linear', 'rbf', 'poly'] as $kernel) {
    $classifier = new SVC(kernel: $kernel, cost: 10);
    $classifier->train($split->getTrainSamples(), $split->getTrainLabels());
    $pred = $classifier->predict($split->getTestSamples());
    $acc = Accuracy::score($split->getTestLabels(), $pred);
    if ($acc > $bestAccuracy) {
        $bestAccuracy = $acc;
        $bestKernel = $kernel;
    }
}
echo "Лучшее ядро: $bestKernel с точностью $bestAccuracy";
Лучшее ядро: rbf с точностью 0.925

Ручной поиск параметров - простой способ оптимизировать модель без внешних зависимостей.

Искусственный интеллект на PHP - comments

En
Php ai (php)