Пошаговое руководство по созданию модели классификации типов личности Bi-LSTM с использованием PyTorch

«Я-образ» является ключом к человеческой личности и человеческому поведению. Измените представление о себе, и вы измените личность и поведение», — Максвелл Мальц.

Можем ли мы классифицировать и предсказывать тип личности человека, исключительно используя его сообщения в Интернете? В этой статье основное внимание будет уделено разработке модели классификации Bi-LSTM типа личности с использованием Word2Vec. Перед этим мы узнаем, как мы можем классифицировать типы личности с помощью индикатора типов Майерс-Бриггс.

Что такое МБТИ?

Индикатор типа Майерс-Бриггс (MBTI) классифицирует типы личности по 16 различным категориям по 4 параметрам:

  • Интроверсия (I) — Экстраверсия (E)
  • Интуиция (N) — Ощущение (S)
  • Мышление (Т) — Чувство (Ж)
  • Оценка (J) — Восприятие (P)

Когда у человека есть 1 атрибут из 4 вышеперечисленных измерений. Например, тот, кто предпочитает интроверсию (I), интуицию (N), мышление (T) и суждение (J), будет классифицирован как тип личности INTJ.

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

Если вам интересно, какой у вас тип личности по MBTI, вы можете пройти бесплатный тест на странице 16personalities.

Обзор данных

Данные, которые мы будем использовать для обучения наших моделей, взяты из (MBTI) Myers-Briggs Personality Type Dataset на Kaggle. Набор данных содержит 8675 записей с помеченными типами личности и текстовой историей сообщений пользователей. Данные были собраны через форум PersonalityCafe, потому что он предоставляет большой выбор людей и связанных с ними типов личности MBTI, а также образцы их письма.

Весь код, использованный в этом проекте, доступен в записной книжке Google Colaboratory, ссылка на которую приведена в конце статьи. Мы можем загрузить данные прямо из Kaggle в нашу записную книжку Google Colaboratory. Теперь, когда у нас есть готовые данные, мы можем просмотреть их структуру, а также разделить их на обучающий и тестовый наборы.

------------------------------------ 
Size of training dataset: 7807 
Size of testing dataset: 868 
------------------------------------
------------------------------------ 
Sample Data 
LABEL: INTP
SENTENCE: 'Piano has joined my list too.|||When you are asked to add smileys into your text messages|||Can you say same things for yourself? An absolute yes.  How you deal with it? tried doing what they wanted me to do for sometime. It was too draining. Now, I do not even bother...'
------------------------------------

Поскольку у нас есть только 8675 записей, разделение обучения и тестирования на 90%-10% (7807–868) подходит, чтобы убедиться, что у модели достаточно данных для обучения. Глядя на вывод выше, каждая запись имеет метку, представляющую тип личности, и строку, содержащую серию сообщений от одного и того же пользователя, где каждое сообщение разделено тремя вертикальными чертами «|||».

Распределение классов

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

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

В таблице показаны редкие типы личности, а также некоторые более распространенные типы. Мы знаем, что дисбаланс классов реален, но есть ли у нас классы в правильном порядке частотности по сравнению с распределением в реальном мире?

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

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

Ключевые типы личности

Учитывая, что распределение классов сильно отличается от распределения в реальном мире, мы можем изучить ключи типа личности, которые составляют буквы в типе MBTI.

Мы можем видеть, как ключи личности представлены в данных на графиках ниже.

Согласно приведенным выше графикам, Чувствующие-Мыслители имеют наиболее точное представление о распределении в реальном мире. Поэтому мы будем представлять все метки либо как T, либо как F, в зависимости от того, какую из них они содержат. Например, «INTJ» станет «T», а «INFJ» станет «F». Поэтому вместо того, чтобы предсказывать тип личности в целом, мы можем попытаться обучить нашу модель предсказанию мыслителей и чувствующих.

Подготовка данных

Для начала нам нужно предварительно обработать текстовые данные. Предварительная обработка включает удаление ссылок на веб-сайты, номеров, хэштегов и ненужных знаков препинания (мы можем оставить смайлики, такие как «:)», потому что это может помочь в нашем анализе настроений). Мы также удаляем стоп-слова, которые являются общеупотребительными информационными словами низкого уровня, такими как «и, из, но». Наконец, мы размечаем слова, что представляет собой процесс, который разделяет слова в предложении. Например, преобразование «Это предложение» в [это, есть, предложение].

Входное представление

Встраивание слов — это изученное представление текста, в котором слова, имеющие одинаковое значение, имеют одинаковое числовое представление. Другими словами, вложения слов основаны на родстве каждого слова в корпусе. Поскольку они представляют собой числовое представление, такое как [0.2,0.4,0.3], их можно вычесть или добавить к другим вложениям слов. Например, King-Man = Queen. Модель встраивания слов пытается найти слово, которое будет как можно ближе к королю и как можно дальше от человека. Ответ может быть королевой.

Если вы незнакомы или хотите узнать больше о встраиваниях слов, я рекомендую эту статью:



Во-первых, мы создадим собственные вложения слов, используя модель FastText с размером встраивания 100 и размером окна 5. Мы также загрузите предварительно обученную модель встраивания слов под названием "glove-twitter-100", которая даст нам дополнительные встраивания слов.

Теперь, когда у нас есть доступные модели встраивания, нам нужно соединить их, чтобы убедиться, что у нас есть вложение для каждого токена/слова в каждом предложении наших данных.

Подготовка ввода

Сначала мы хотим создать таблицу поиска. Для начала мы превратим список слов в указатель, чтобы мы могли легко ссылаться на вложения слов. Например, у нас есть словарь: [кошка, играть, он, с]. Мы можем представить предложение этих слов как «Он играет с кошкой» в [2,1,3,0] на основе индекса в списке словаря. Затем мы можем вызвать слова из нашей матрицы внедрения, где матрица внедрения может выглядеть примерно так:

  • [[0.1, 0.3, 0.4], [0.2, 0.5,0.1], [0.3, 0.7, 1.3], [0, 0.1, 0.3]]

Где у нас есть:

  • [0.1, 0.3, 0.4] представляет «кошку»
  • [0.2, 0.5,0.1] представляет «играть»
  • [0.3, 0.7, 1.3] представляет «он»
  • [0, 0,1, 0,3] представляет «с»

Мы можем использовать индекс слова [2,1,3,0] для поиска соответствующих значений вложения в матрице вложения, поскольку они будут иметь один и тот же индекс.

Затем мы добавляем токен для пост-заполнения «[PAD]», чтобы создать одинаковую длину последовательности для каждого поста во всем нашем наборе данных. В дополнение к этому мы добавляем токены «[НЕИЗВЕСТНО]» для неизвестных слов.

Затем мы объединяем вложения слов из каждой модели, чтобы каждое слово имело размерность вложения 200. Мы добавляем каждое объединенное вложение слова в таблицу поиска встраивания. После этого мы применяем пост-заполнение и кодирование, где мы кодируем каждое слово в предложениях для обучения и тестирования в соответствующий индекс слова. Наконец, мы кодируем метки классов.

Создание модели Bi-LSTM

Рекуррентная нейронная сеть (RNN) — это тип искусственной нейронной сети, которая использует последовательные или временные данные. Архитектура RNN содержит блоки памяти (скрытые состояния), которые позволяют сети запоминать последовательность данных и использовать шаблоны для прогнозирования. Если вы не знакомы с RNN, я рекомендую прочитать эту статью:



Мы будем использовать модифицированную RNN, называемую двунаправленной долговременной кратковременной памятью (Bi-LSTM). Основным преимуществом LSTMпо сравнению с ванильной RNN является добавление гейтов забывания, которые позволяют модели сохранять важную информацию с течением времени и избегать взрыва. /Исчезающие проблемы с градиентом. Используя Bi-LSTM, мы идем в двух направлениях (двунаправленный), где прямой LSTM получает входную последовательность в исходном порядке, а обратный LSTM получает входную последовательность в обратном порядке. Мы объединяем последние последние скрытые состояния прямого LSTM и обратного LSTM для окончательного прогноза. Эта проблема требует, чтобы мы построили модель для задачи от N до 1. Задачи от N до 1 означают, что у нас есть несколько входных данных (слова в постах) и один выход (мыслитель/чувствующий).

Чтобы сократить вычислительные затраты, мы будем использовать nn.Embedding из PyTorch в качестве таблицы поиска, чтобы получить встраивание слов для каждого токена/слова в процессе обучения моделей, а не генерировать их заранее. Подробную информацию о выходных данных nn.LSTM можно найтиздесь. Прямое и обратное последнее скрытое состояние можно извлечь из h_n во втором возвращаемом значении torch.nn.RNN.

Теперь мы можем обучить модель. Здесь мы используем пакеты из-за ограничений времени выполнения Google Colab. Мы устанавливаем гиперпараметры и обучаем модель, печатая результаты для каждой эпохи.

Epoch: 1, loss: 0.69157, train_acc: 0.56 
Epoch: 2, loss: 0.64290, train_acc: 0.62 
Epoch: 3, loss: 0.59776, train_acc: 0.67 
Epoch: 4, loss: 0.66052, train_acc: 0.56 
Epoch: 5, loss: 0.65018, train_acc: 0.65 
Epoch: 6, loss: 0.66304, train_acc: 0.62 
Epoch: 7, loss: 0.56721, train_acc: 0.71 
Epoch: 8, loss: 0.53994, train_acc: 0.73 
Epoch: 9, loss: 0.55724, train_acc: 0.75 
Epoch: 10, loss: 0.56955, train_acc: 0.76 
Epoch: 11, loss: 0.49989, train_acc: 0.79 
Epoch: 12, loss: 0.43205, train_acc: 0.84 
Epoch: 13, loss: 0.44620, train_acc: 0.80 
Epoch: 14, loss: 0.41894, train_acc: 0.82 
Epoch: 15, loss: 0.35122, train_acc: 0.86 
Finished Training

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

Предсказание новых сообщений

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

text = "I am an INFJ because I feel everything deeply."
predict_personality(text)
OUTPUT: Predicted Personality Type: F

Заключение

Из этой статьи мы узнали об индикаторе типов Майерс-Бриггс (MBTI) и о том, как его можно использовать для классификации типов личности и ключей типов личности. Мы также глубоко погрузились в создание с нуля модели Bi-LSTM, которая способна прогнозировать сообщения и пытаться классифицировать автора как мыслителя или чувствующего. В будущем мы сможем использовать/объединять больше данных из разных источников и пробовать различные методы НЛП для классификации типов личности.

Код, использованный в этой статье, можно найти в этом Блокноте