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

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

В этой статье, хотелось бы рассмотреть создание системы для классификации по семи базовым эмоциям и заключение эмоционального состояния человека с видеоматериала. Для реализации такой системы было решено создать сверточную нейронную сеть с помощью библиотеке pytorch для задачи классификации и использования данной модели для анализа видео, и составление эмоционального состояния используя библиотеку OpenCV и чат-бота с генеративным искусственным интеллектом, разработанный компанией OpenAI – ChatGPT 4.

Сверточные нейронные сети (СНС, или CNN от английского Convolutional Neural Networks) — это класс глубоких нейронных сетей, наиболее эффективно применяемых в задачах анализа изображений. Основное отличие сверточных нейронных сетей от других видов нейронных сетей заключается в использовании операции свертки вместо обычных матричных умножений в одном или нескольких их слоях. Суть свертки — в применении фильтра (или ядра) к исходному изображению для выявления определенных характеристик, таких как края, углы или другие текстуры. Это позволяет СНС эффективно обрабатывать визуальную информацию. На вход принимаются значения для каждого пикселя изображения в диапазоне цветовой палитры (как продемонстрировано на рисунке 1), далее данные проходят слои свертки и пулинга, и после подаются в функцию активации и нейронную сеть.

Рисунок-1. последовательность CNN
Рисунок-1. последовательность CNN

Для обучения модели были выбраны несколько датасетов, доступных на платформе Kaggle(https://www.kaggle.com/datasets/msambare/fer2013), которые включают изображения лиц, классифицированные по семи эмоциональным категориям: 'Злость', 'Отвращение', 'Страх', 'Счастье', 'Нейтральность', 'Грусть', и 'Удивленность'. Эти датасеты содержат разнообразные лицевые выражения, что обеспечивает комплексный набор данных для тренировки и проверки точности CNN. Суммарное количество всех материалов составило 34059 изображений.

Рисунок 2 - классы согласно датасету
Рисунок 2 - классы согласно датасету

Архитектура нейронной сети была построена для изображений размером 48 на 48 пикселей в градации серого. Она построена с использованием PyTorch, популярной библиотеки глубокого обучения. Сеть начинается с двух сверточных слоев (self.conv1 и self.conv2), каждый из которых следует за функцией активации ReLU и слоем пулинга (self.pool).

class EmotionCNN(nn.Module):
    def __init__(self):
        super(EmotionCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
        self.fc1 = nn.Linear(64 * 12 * 12, 1024)
        self.dropout = nn.Dropout(0.5)
        self.fc2 = nn.Linear(1024, num_classes)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.pool(self.relu(self.conv1(x)))
        x = self.pool(self.relu(self.conv2(x)))
        x = x.view(-1, 64 * 12 * 12)
        x = self.relu(self.fc1(x))
        x = self.dropout(x)
        x = self.fc2(x)
        return x

Функция EmotionCNN() представляет собой архитектуру сверточной нейронной сети (СНС) в PyTorch для классификации эмоций на изображениях. Она начинается с двух сверточных слоев, которые используются для извлечения визуальных признаков из входных изображений; каждый сверточный слой следует за функцией активации ReLU и слоем максимального пулинга для уменьшения размерности пространственных данных. Далее, вытянутые признаки подаются на полносвязный слой, который преобразует их в вектор из 1024 элементов, после чего применяется слой dropout для снижения риска переобучения. Завершается архитектура вторым полносвязным слоем, который отображает 1024 элемента в число выходов, соответствующее количеству классов эмоций (num_classes). Эта сеть способна выучивать сложные визуальные признаки благодаря своей глубине и использованию нелинейностей, а слой dropout и методы пулинга помогают контролировать переобучение, делая ее мощным инструментом для классификации эмоций.

for epoch in range(num_epochs):
    model.train()
    running_loss = 0.0
    for images, labels in train_loader:
        images, labels = images.to(device), labels.to(device)
        outputs = model(images)
        loss = criterion(outputs, labels)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        running_loss += loss.item()

    train_loss = running_loss / len(train_loader)
    train_losses.append(train_loss)

    model.eval()
    running_loss = 0.0
    with torch.no_grad():
        for images, labels in test_loader:
            images, labels = images.to(device), labels.to(device)
            outputs = model(images)
            loss = criterion(outputs, labels)
            running_loss += loss.item()

    test_loss = running_loss / len(test_loader)
    test_losses.append(test_loss)

    print(f'Epoch {epoch + 1}, Train Loss: {train_loss:.4f}, Test Loss: {test_loss:.4f}')

Данный алгоритм описывает процесс обучения и тестирования сверточной нейронной сети (СНС), для задачи классификации эмоций с использованием PyTorch на заданном устройстве. Модель переносится на определённое устройство (CPU или GPU) для эффективного выполнения вычислений. В качестве функции потерь используется кросс-энтропийная потеря, оптимизатор — Adam с 0.001 коэффициентом скорости обучения. В процессе обучения для каждой эпохи итерируется по загрузчику обучающих данных (train_loader), вычисляется потеря на обучающем наборе, обновляются веса модели. Затем, в режиме оценки (eval), модель тестируется на независимом наборе данных без вычисления градиентов (torch.no_grad()), для определения потерь на тестовом наборе данных. Записываются потери обучения и тестирования для последующего анализа. Вывод информации о потерях после каждой эпохи позволяет наблюдать за процессом обучения и корректировать параметры модели при необходимости, чтобы минимизировать разницу между потерями на обучающем и тестовом наборах данных, тем самым улучшая её способность к обобщению на новых данных.

model.eval()
dummy_input = torch.randn(1, 1, 48, 48, device=device)  
onnx_path = "new_model_emotion_recognition_112.onnx"
torch.onnx.export(model,               
                  dummy_input,        
                  onnx_path,           
                  export_params=True,  
                  opset_version=10,    
                  do_constant_folding=True,  
                  input_names=['input'],  
                  output_names=['output'],  
                  dynamic_axes={'input': {0: 'batch_size'},    
                                'output': {0: 'batch_size'}})
print(f"Модель успешно экспортирована в {onnx_path}")

Данный код демонстрирует процесс экспорта предобученной модели нейронной сети, созданной с использованием PyTorch, в формат ONNX (Open Neural Network Exchange). ONNX — это открытый формат, предназначенный для представления моделей машинного обучения, который позволяет моделям быть переносимыми и используемыми в различных фреймворках, инструментах, платформах и оптимизаторах.

Также, для вывода заключения по эмоциональному состоянию человека было решение использовать чат-бота Chat GPT 4. Для реализации данной была написана следующая функция с помощью библиотеке g4f(https://github.com/xtekky/gpt4free):

    def get_emotional_state_report(self, emotion_count):
        total_emotions = sum(emotion_count.values())
        emotion_percentages = {emotion: (count / total_emotions) * 100 for emotion, count in emotion_count.items()}
        
        emotions_summary = "\n".join(
            [f"{emotion}: {percentage:.2f}%" for emotion, percentage in emotion_percentages.items()])
        prompt = f"Ты - психолог, специалист по психическому и эмоциональному состоянию с многолетним стажем. Ты должен написать большое заключение и отчет об общем конкретном эмоциональном состоянии человека и его основное состояние" \
                 f" по видео которое тебе показали, без перечисление всех обнаруженных эмоций с довольно большим выводом без перечисления источников на основе следующего распределения эмоций:\n{emotions_summary}\n\nЭмоциональное состояние таково:"
        print(prompt)  # Только для отладки

        self.client = Client()

        response = self.client.chat.completions.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}],
        )

        
        return response.choices[0].message.content

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

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

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


  1. Dr1mlax
    19.04.2024 01:58

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


  1. VladPavlushin
    19.04.2024 01:58

    Пожалуй пора начинать изучать труды Станиславского