将文本特征应用于客户流失数据集

2021-09-03 16:38:13 浏览数 (1)

磐创AI分享

作者 | Jinhang Jiang

编译 | VK 来源 | Towards Data Science

目录

  • 动机
  • 业务问题和数据
  • 特征工程与建模
  • 评价与特征分析
  • 摘要

动机

在我的上一篇博客“什么是嵌入,你能用它做什么”中,我谈到了嵌入可以把高维、非结构化的数据转换成低维的数值表示,可以用在各种机器学习模型中。

在今天的博客中,我将向你介绍如何使用额外的客户服务说明,在一个小型的客户流失数据集上提高4%的准确率。

我在“将文本特征纳入分类项目”这个项目的基础上建立了博客(https://towardsdatascience.com/integrate-text-content-into-classification-project-eddd8e18a7e9)。这篇文章中,我通过应用情感分析和SBERT语句嵌入扩展了旧项目。然后用XGBoost和Random Forests(流行的研究算法)对数据进行拟合。

业务问题和数据

一家电话公司从2070个客户那里收集了原始数据集,并标记了服务状态(保留/取消)。这家电话公司希望利用这些数据来了解客户流失问题,从而采取战略举措留住未来可能取消这项服务的客户。这种分析也有助于公司识别导致客户取消服务的因素。

数据集包含17个特征,包括客户ID、一般人口统计信息和服务使用信息。该公司还提供了客户服务人员留下的评论,指出了客户的问题以及他们是如何帮助客户的。标签以3:2的比例分发。

特征工程与建模

我将在我们的数据上演示四种不同的特征工程方法:首先,我对所有离散变量使用one-hot编码。其次,运用情感分析、句子嵌入、TF-IDF等方法对客服笔记进行分析。

one-hot编码
代码语言:javascript复制
# 加载程序包
from sklearn.preprocessing import LabelEncoder
import pandas as pd

# 读取数据
customer = pd.read_csv("Customers.csv")
comment = pd.read_csv("Comments.csv")

# 提取离散变量
le = LabelEncoder()
col = customer.select_dtypes(include=object)
col_names = col.columns

# 变换变量
for x in col_names:
    customer[x]=le.fit(customer[x]).transform(customer[x])

LabelEncoder将帮助我们把所有的离散变量变成数字。例如,它将把性别变量(M/F)变成[1或2]。由于这个项目的主要重点是演示如何将文本特征合并到我们的分析中,所以我没有对数据进行任何额外的特征工程。

情绪分析
代码语言:javascript复制
# 加载textblob
from textblob import TextBlob

# 定义函数以提取极性和主观性
def find_pol(review):
    return TextBlob(review).sentiment.polarity
def find_sub(review):
    return TextBlob(review).sentiment.subjectivity

# 进行情绪分析
customer['sentiment'] = comment['Comments'].apply(find_pol)
customer['subjectivity'] = comment['Comments'].apply(find_sub)

# 将平均分数分配给同一条消息
for i in range(0,115):
    value = customer[customer.Comments==i].sentiment
    mean = customer[customer.Comments==i].sentiment.mean()
    std = customer[customer.Comments==i].sentiment.std()
    outliers = (value-mean).abs() > std
    customer["sentiment"][outliers.index]= mean

在这个项目中,我使用了一种流行的情绪分析技术TextBlob来提取极性和主观性。然而,它对同一条信息给出了不同的分数。所以我做了一个转换来平均同一条消息的分数。你可以在这里找到更多关于textblob的信息:https://textblob.readthedocs.io/en/dev/quickstart.html#sentiment-analysis。

SBERT语句嵌入
代码语言:javascript复制
# 从sentence_transformer加载SBERT
from sentence_transformers import SentenceTransformer
sbert_model = SentenceTransformer('stsb-mpnet-base-v2',
                                   device='cuda')

sentence_embeddings = sbert_model.encode(comment.Comments) 

# 嵌入的形状是(2070, 768),将其转换为1
sent_emb = pd.DataFrame(sentence_embeddings).mean(axis=1)
customer["sent_emb"] = sent_emb

Sentence BERT(SBERT)是自然语言处理中最先进的模型之一。它基于BERT的思想,由德国达姆施塔特技术大学的UKP实验室开发。他们有许多预训练好的模型,可用于各种用途。你可以在这里查完整的清单:https://docs.google.com/spreadsheets/d/14QplCdTCDwEmTqrn1LH4yrbKvdogK4oQvYO1K1aPR5M/edit#gid=0。

句子嵌入有768个特征,这对于我们的模型来说太多了。我尝试了Tensorflow的自编码器,但是没有明显的改进。因此,我将这些值平均化。

基于TF-IDF的词汇抽取
代码语言:javascript复制
# 加载程序包
from sklearn.feature_extraction.text import TfidfVectorizer
import math

# 计算语料库中的词
feature = []
for i in df["patterns"]:
    feature.append(i.split())
    flat_list = [item for items in feature for item in items]
    feature=len(set(flat_list))

# 只取最常用词的前10%
# 将“最大文档频率”设置为0.2以保持唯一性

max_feature = math.ceil(feature*0.1)
tfidfvectoriser=TfidfVectorizer(strip_accents="ascii",
                                max_features=max_feature,
                                max_df = 0.2)
tfidfvectoriser.fit(df["patterns"])
tfidf_vectors=tfidfvectoriser.transform(df["patterns"])
tfidf_vectors=pd.DataFrame(tfidf_vectors.toarray())
tfidf_vectors.columns = tfidfvectoriser.get_feature_names()

# 将单词合并到原来的表中
customer = pd.merge(customer,
                    tfidf_vectors,
                    left_index=True,
                    right_index=True)

到目前为止,我们已经对文本数据进行了情感分析、句子嵌入和TF-IDF。这三种不同的技术帮助我们从文档级、句子级和词汇级提取信息。现在,让我们看看这些特征工程可以对模型产生什么影响,并探讨影响客户保留或退出服务决策的特征。

评价与特征分析

由于我只有一个相当小的数据集(2070个观测值),很可能发生过拟合。因此,我使用交叉验证技术,而不是简单地将其拆分为训练和测试数据集。我将fold数设置为10,并将平均准确度和平均roc_auc_score分数作为最终输出。

XGBoost

我从基本的xgboostclassifier模型开始,逐步将情感特征、句子嵌入和TF-IDF添加到模型中。如你所见,通过添加这三个新特征,准确度得分比基础模型提高了2.7%,roc-auc分比基础模型提高了1.3%。

BayesianOptimization,最终的准确度评分比基础模型提高了4.6%,roc-auc评分也提高了1.9%。

上面的混淆矩阵表明,误报和漏报的数量非常接近,因此没有出现过拟合。如果企业想找出模型无法识别这些客户的原因,我认为他们应该手动查看数据,研究这些客户内部的相似性以及这些客户与其他客户之间的差异。

随机森林

正如你可能已经注意到的,在许多学术研究论文中,作者通常更喜欢随机森林而不是GBM(Gradient Boosting Machines )。我发现Quora解释了两个原因:第一,RF比GBM更容易调整;其次,RF比GBM更难过拟合。因此,我还检查了随机森林如何处理这些特征。

如图所示,最终的准确度得分和roc_auc得分分别上升了3.8%和1%。对于超参数调整,我发现本文可能很有用:https://towardsdatascience.com/hyperparameter-tuning-the-random-forest-in-python-using-scikit-learn-28d2aa77dd74。

特征重要性

为了研究模型中最重要的特征,我使用了xgboost内置函数:“plot_importance”

代码语言:javascript复制
from xgboost import plot_importance

plot_importance(model_final)
plt.subplots_adjust(left=0.5, bottom=1.6, right=2.4, top=6)
plt.show()

结果表明,最重要的特征是:年龄、费率计划、长途、估计收入、客服信息、主观性、情感极性等。

摘要

在这个博客中,我演示了如何通过从文档级、句子级和词汇级提取信息来将文本数据合并到分类问题中。

这个项目展示了小数据集如何为小企业实现理想的性能。它还说明了如何使用自然语言处理技术,以促进监督机器学习问题,如分类。分析表明,我创建的特征是模型中最重要的特征之一,它们有助于建立对不同客户群的描述。

0 人点赞