.

Сделать репост в соц сети!

Показаны сообщения с ярлыком word2vec. Показать все сообщения
Показаны сообщения с ярлыком word2vec. Показать все сообщения

четверг, 26 июля 2018 г.

Анализ тональности текста с использованием word2vec и реализацией в pipeline Python



Анализ тональности текста или сентимент анализ - это метод классификации текста. Самый популярный пример из курсов по машинному обучению - прогноз оценки, которую поставит посетитель ресторана заведению на основе его отзыва. Или, по другому, можем ли мы спрогнозировать на основе отзыва посетителя, будет ли он рекомендовать этот ресторан или нет.
В HR сама собой напрашивается аналогичная задача: можем ли мы спрогнозировать на основе отзыва увольняющегося работника в exit интервью спрогнозировать, будет ли он рекомендовать нашу компанию коллегам / будет ли он отзываться о компании позитивно или негативно. Хотя, безусловно, класс решаемых задач значительно шире. Я бы отослал здесь к статье Raja Sengupta Как NLP может в корне изменить HR. NLP - это Natural language processing или проще - анализ текстов. Моя задача проще - я хочу показать код для решения одной задачи в Python.

word2vec vs "bag of words"

Одним из самых популярных методов анализа текстов (а точнее, этот метод просто хронологически более ранний - и, может быть, более интуитивно понятный) является метод "мешок слов "bag of words". Мы просто получаем столько переменных, сколько у нас слов в тексте (исключая "мусорные" или редкие слова). Т.е. если в отзывах у нас используется 1 485 слов, то у нас будет 1485 новых переменных / колонок. И если в отзыве содержится слово - оно же название переменной - то переменная принимает значение "1", в противном случае "0". Т.е. если респондент написал отзыв "хорошая компания", то из 1485 ячеек напротив данного респондента будет только две "1" - в колонках "хорошая" и "компания".
Этот подход интуитивно понятен, но он имеет ряд недостатков (что делать с "не"? и т.п...), но главное: в этом подходе не отражается смысл слов, фраз.
word2vec
Преодолением такого подхода является метод word2vec (буквально 'word' to 'vector'), который превращает весь текст в N-мерное пространство, и каждое слово это вектор со своими координатами, т.е. буквально можно записать так:

'опрос': array([ 0.05069825, -0.01941545,  0.00567565, -0.0276236 ,  0.01180002,
      .......  0.00385726])
Не показываю весь вектор, потому что он имеет 100 значений. И эти 100 значений - это переменные в нашем уравнении.
"Плюс" этого метода в том, что близкие по значению слова имеют близкие координаты векторов. Например, когда я делал модель для функционала HR, то для слова "компенсации" самые близкие координаты вектора имело слово "c&b". И это замечательно, потому что в подходе "bag of words" слова "c&b" и "компенсации" это разные слова, а в подходе word2vec эти слова хоть и не идентичны, но очень близки.

Данные

У меня свой датасет, которым я с вами не поделюсь, но вы можете опробовать этот код на своих данных. Структура данных достаточно проста:
  1. переменная "текст";
  2. бинарная переменная 1/ 0, +1 / -1 и т.п..

Я свои данные взял из нашего исследования факторов текучести персонала (участвуем в исследовании) . Помимо всего прочего, в нашем опросе есть две переменные:
"Отзыв о компании";
"Готовы ли Вы рекомендовать эту компанию в качестве работодателя своим знакомым, коллегам?"


Реализация в Python


Итак, начинаем  с загрузки данных
import pandas as pd
import numpy as np
df = pd.read_csv('data.csv', sep=',', encoding = 'cp1251')
df.info()
Data columns (total 2 columns):
y 792 non-null int64
Отзыв о компании 792 non-null object
dtypes: int64(1), object(1)
df['y'].value_counts()
1    404
0    388
Name: y, dtype: int64


Да, у нас очень небольшой датасет, лучше иметь несколько тысяч, даже несколько десятков тысяч строк данных. Но моя задача скромнее - показать алгоритм. Выборка у нас достаточно сбалансированная - соотношение тех, кто готов рекомендовать компанию, и тех, кто не готов - почти 50/50.
Первая задача, которую нам надо решить - создать словарь слов. Т.е. присвоить каждому слову координаты вектора. Для этого нам необходимо взять весь текст и обучить его. Но прежде нам необходимо преобразовать наши отзывы из формата pandas в формат, годный для преобразований word2vec.
Преобразуем таким образом

import nltk
import nltk.data
tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
from nltk.tokenize import sent_tokenize, word_tokenize
import re 
 def preproc(sentence):
    sent_text = re.sub(r'[^\w\s]','', sentence)
    words = sent_text.lower().split()
    return(words)
 def senttxt(sent, tokenizer, remove_stopwords=False ):
        raw_sentences = tokenizer.tokenize(oped.strip())
        sentences = []
        for raw_sentence in raw_sentences:
            
            sentences.append(preproc(raw_sentence))
        
        len(sentences)
        return sentences
txt_snt = df['Отзыв о компании'].tolist()
sentences = []
for i in range(0,len(nyt_opeds)):
    sent = txt_snt[i].replace("/.", '')
    sentences += senttxt(sent, tokenizer)
В итоге мы получаем объект вот такого формата
sentences[0]
['классическая',
 'российская',
 'компания',
 'с',
 'назначениями',
 'не',
 'по',
 'знаниям',
 'а',
 'по',
 'личной',
 'приверженности',
 'не',
 'соблюдающая',
 'свои',
 'же',
 'правила',
 'делающая',
 'глупость',
 'за',
 'глупостью',
 'и',
 'оправдывающая',
 'их',
 'еще',
 'большими',
 'глупостями']
Этот формат уже можно использовать для создания словаря. Что мы и делаем.