Перейти к основному контенту

Data Science в продажах: анализ настроений клиентов

Узнайте, как с помощью data science анализировать эмоции клиентов и получать ценные инсайты для оптимизации продаж.
Обновлено 31 авг. 2026 г.  · 9 мин читать

Изучить с помощью AI

ChatGPTClaudePerplexity

Иллюстрация концепции искусственного интеллекта

Кейсы применения data science могут относиться практически к любой отрасли, где накапливается или может накапливаться большой объём данных.  Именно в магазинах и на сайтах электронной коммерции происходит реальный клиентский опыт людей, привлечённых маркетинговыми кампаниями, и собираются ценные данные о покупках конкретного бренда или компании. Здесь люди принимают окончательное решение, действительно ли они хотят купить тот или иной товар, заинтересуются ли они чем-то, чего изначально не планировали, сколько готовы заплатить, вернутся ли в этот магазин и какой отзыв оставят о своём опыте.

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

Кейс применения data science в продажах: анализ настроений клиентов 

Анализ настроений клиентов — это автоматизированный процесс определения эмоций клиентов при использовании ими услуг или продуктов определённой компании. Обычно это неструктурированные текстовые данные, собранные из онлайн-опросов, социальных сетей, тикетов в поддержку, форм обратной связи, отзывов о продуктах, форумов, телефонных звонков, писем и чат-ботов. В машинном обучении анализ настроений проводится методами обработки естественного языка (NLP), которые применяют статистические и лингвистические подходы для извлечения положительных, отрицательных и нейтральных оценок прямо из текстовых данных. По сути, на выходе получаем два параметра:

  • Полярность: указывает, положительное или отрицательное настроение.
  • Магнитуда: указывает силу этого настроения.

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

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

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

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

Посмотрим, как анализ настроений работает на практике, на наборе данных с отзывами о фильмах с IMDB:

import pandas as pd

movies = pd.read_csv('movies.csv', index_col=0).reset_index(drop=True)
print(f'Number of reviews: {movies.shape[0]:,}\n')
print(movies.head())
Number of reviews: 7,501

                                              review  label
0  This short spoof can be found on Elite's Mille...      0
1  A singularly unfunny musical comedy that artif...      0
2  An excellent series, masterfully acted and dir...      1
3  The master of movie spectacle Cecil B. De Mill...      1
4  I was gifted with this movie as it had such a ...      0

У нас есть два столбца: один с текстом каждого отзыва и второй — с оценкой общего настроя: положительный (1) или отрицательный (0).

Посчитаем долю положительных и отрицательных отзывов:

round(movies['label'].value_counts()*100/len(movies['label'])).convert_dtypes()
0    50
1    50
Name: label, dtype: Int64

Итак, пропорции положительных и отрицательных отзывов почти равны.

Применение метода BOW 

Далее необходимо преобразовать текстовые данные в числовой вид, поскольку модель машинного обучения работает только с числовыми признаками. В частности, мы создадим признаки, считающие, сколько раз каждое слово встречается в соответствующем отзыве. Самый базовый и прямолинейный подход для этого — мешок слов (bag-of-words, BOW), который строит словарь всех слов, встречающихся в документе, и считает частоту каждого слова в каждом отзыве. В результате мы получим новые признаки — по одному на каждое слово — с соответствующими частотами.

Применим метод BOW к нашему набору данных:

from sklearn.feature_extraction.text import CountVectorizer

# Creating new features
vect = CountVectorizer(max_features=200)
vect.fit(movies.review)
X_review = vect.transform(movies.review)
X_df = pd.DataFrame(X_review.toarray(), columns=vect.get_feature_names())

# Combining the new features with the label
movies_bow = pd.concat([movies['label'], X_df], axis=1)
print(movies_bow.head())
  label  10  about  acting  action  actors  actually  after  again  all  ...  \
0      0   0      0       0       0       0         0      0      0    0  ...  
1      0   1      0       1       0       1         0      0      0    3  ...  
2      1   0      0       0       0       0         0      1      0    0  ...  
3      1   0      0       0       1       0         0      0      0    0  ...  
4      0   1      0       0       1       0         0      0      0    3  ...  

  will  with  without  work  world  would  years  you  young  your 
0     0     1        0     0      0      1      0    0      0     0 
1     2     7        1     0      0      2      0    3      0     2 
2     0     2        0     0      0      0      0    0      1     0 
3     0     0        0     0      0      0      0    1      1     0 
4     0     2        0     1      0      0      0    0      0     0 

[5 rows x 201 columns]

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

Использование модели контролируемого обучения для предсказания настроений

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

Accuracy score: 0.754

Confusion matrix:
[[37.62772101 13.23856064]
[11.32829853 37.80541981]]

Видно, что модель пометила 11% всех положительных отзывов как отрицательные, а 13% — как положительные, хотя они были отрицательными. В качестве возможных путей повышения точности модели можно рассмотреть исключение стоп-слов (то есть малоинформативных слов, которые встречаются слишком часто, таких как "about", "will", "you" и т. п.) и увеличение размера словаря.

При применении метода BOW мы можем получить сотни или даже тысячи новых признаков в датафрейме. Это способно привести к излишне сложной модели: переобученной, с чрезмерным количеством ненужных признаков и параметров. Один из способов исправить это — использовать регуляризацию, которая ограничивает функцию модели. Настраиваемый параметр здесь — C, отражающий силу регуляризации. Протестируем 2 значения этого параметра: 100 и 0.1, и посмотрим, какое даст лучшую работу модели на тестовых данных:

lr_1 = LogisticRegression(C=100)
lr_1.fit(X_train, y_train)
predictions_1 = lr_1.predict(X_test)

lr_2 = LogisticRegression(C=0.1)
lr_2.fit(X_train, y_train)
predictions_2 = lr_2.predict(X_test)

print(f'Accuracy score, lr_1 model: {round(accuracy_score(y_test, predictions_1), 3)}\n'
      f'Accuracy score, lr_2 model: {round(accuracy_score(y_test, predictions_2), 3)}\n\n'
      f'Confusion matrix for lr_1 model, %:\n{confusion_matrix(y_test, predictions_1)/len(y_test)*100}\n\n'
      f'Confusion matrix for lr_2 model, %:\n{confusion_matrix(y_test, predictions_2)/len(y_test)*100}')
Accuracy score, lr_1 model: 0.753
Accuracy score, lr_2 model: 0.756

Confusion matrix for lr_1 model, %:
[[37.53887161 13.32741004]
[11.32829853 37.80541981]]

Confusion matrix for lr_2 model, %:
[[37.67214571 13.19413594]
[11.19502443 37.93869391]]

Разница в точности модели при выбранных значениях параметра C несущественна. Вероятно, можно было бы найти значение, которое улучшит качество сильнее, поэкспериментировав с большим числом вариантов. Однако здесь у нас всего 200 новых признаков, так что модель не слишком сложная, и шаг с регуляризацией в нашем случае не обязателен.

Вместо предсказания меток 0 или 1 с помощью функции predict можно предсказывать вероятность настроения с помощью predict_proba. Здесь важно помнить, что напрямую применять accuracy score или матрицу ошибок к предсказанным вероятностям нельзя, так как эти метрики работают только с классами. Следовательно, нужно дополнительно преобразовать вероятности в классы. По умолчанию вероятность больше либо равная 0.5 переводится в класс 1, иначе — в класс 0.

lr = LogisticRegression()
lr.fit(X_train, y_train)

# Predicting the probability of the 0 class
predictions_prob_0 = lr.predict_proba(X_test)[:, 0]

# Predicting the probability of the 1 class
predictions_prob_1 = lr.predict_proba(X_test)[:, 1]

print(f'First 10 predicted probabilities of class 0: {predictions_prob_0[:10].round(3)}\n'
      f'First 10 predicted probabilities of class 1: {predictions_prob_1[:10].round(3)}')
First 10 predicted probabilities of class 0: [0.246 0.143 0.123 0.708 0.001 0.828 0.204 0.531 0.121 0.515]
First 10 predicted probabilities of class 1: [0.754 0.857 0.877 0.292 0.999 0.172 0.796 0.469 0.879 0.485]

Выводы 

Существуют и другие полезные подходы, которые можно применить к нашему набору данных для более детального анализа настроений:

  • использовать n-граммы (сочетания слов) вместо отдельных слов, чтобы сохранять контекст,
  • исключать стоп-слова,
  • ограничивать размер словаря по верхним или нижним порогам частоты,
  • создавать числовые дополнительные признаки, описывающие длину каждого отзыва или количество знаков препинания (последнее иногда коррелирует с величиной настроения),
  • исключать числа, некоторые символы, слова определённой длины или учитывать более сложные шаблоны слов,
  • применять стемминг и лемматизацию, то есть приводить слова к их основам,
  • использовать более продвинутые подходы вместо BOW для построения словаря, например TfIdf (term frequency–inverse document frequency), который учитывает, как часто слово встречается в отзыве относительно остальных отзывов.
  • использовать специализированные библиотеки для анализа настроений, такие как TextBlob, SentiWordNet, VADER (Valence Aware Dictionary and Sentiment Reasoner).

Если вы хотите разобраться в этих и других полезных техниках для проведения содержательного анализа настроений, посмотрите курс Sentiment Analysis in Python.

Темы
Data Science
Машинное обучение