逻辑回归案例

827 阅读3分钟

1、背景

在进行每一笔股票交易时,交易者(股民)都要给其账户所在的证券公司支付一些手续费,虽然单笔交易的手续费不高,但是股票市场每日都有巨额的成交量,每一笔交易的手续费汇总起来,数量便相当可观。这部分收入对于一些证券公司来说很重要,甚至可以占到营业总收入的50%以上,因此,证券公司对于客户(即交易者)的忠诚度和活跃度是很看重的。如果一个客户不再通过某个证券公司交易,即该客户流失了,那么该证券公司便损失了一个收入来源,因此,证券公司会搭建一套客户流失预警模型来预测客户是否会流失,并对流失概率较大的客户采取相应的挽回措施,因为通常情况下,获得新客户的成本比保留现有客户的成本要高得多。

2、读取数据

股票客户流失.xlsx

    import pandas as pd
    df = pd.read_excel("股票客户流失.xlsx")

    df.head()

image.png

3、划分特征变量和目标变量

x = df.drop(columns="是否流失")
y = df["是否流失"]

第1行代码用drop()函数删除“是否流失”列,将剩下的数据作为特征变量赋给变量X。第2行代码通过DataFrame提取列的方式提取“是否流失”列作为目标变量,并赋给变量y。

4、划分训练集和测试集

进行模型搭建和使用前都会将数据分成训练集数据(简称训练集)和测试集数据(简称测试集)。顾名思义,训练集用于训练数据和搭建模型,测试集则用于检验训练后所搭建模型的效果。划分训练集和测试集的目的一是为了对模型进行评估,二是可以通过测试集对模型进行调优。

from sklearn.model_selection import train_test_split

x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2)

x_train.head()

数据的划分是随机的,可以利用head()函数查看划分后的训练集和测试集的前5行数据,结果如下图所示。

image.png

每次运行程序时,train_test_split()函数都会随机划分数据,如果想要让每次划分数据的结果保持一致,可以设置random_state参数,代码如下。

x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,random_state=1)

其中为random_state参数赋值为1,该数字没有特殊含义,可以换成其他数字,它相当于一个种子参数,使得每次划分数据的结果一致。

5、模型搭建

from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(x_train,y_train)

6、预测数据结果

y_pred = model.predict(x_test)
y_pred[0:100]

image.png

接着将模型的预测值y_pred和测试集的实际值y_test进行汇总。其中y_pred是一个numpy.ndarray类型的一维数组结构,y_test为Series类型的一维序列结构,用list()函数将它们都转换为列表,再根据2.2.1小节所讲的知识点将它们集成到一个DataFrame中,代码如下。

a = pd.DataFrame()
a["预测值"] = list(y_pred)
a["实际值"] = list(y_test)
a.head()

image.png

如果想查看所有测试集数据的预测准确度,可以使用如下代码。

model.score(x_test,y_test)
0.7977288857345636

7、预测概率

逻辑回归模型的本质是预测概率,而不是直接预测具体类别。通过如下代码就可以获取概率值。

y_pred_proba = model.predict_proba(x_test)
a = pd.DataFrame(y_pred_proba,columns=["不流失概率","流失概率"])
a.head()

image.png

8 、获取逻辑回归系数

逻辑回归模型在本质上是将线性回归模型通过Sigmoid函数进行非线性转换。本案例共有5个特征变量,所以预测y=1(流失)的概率P的公式如下。

image.png

通过如下代码可以获取上述公式中的系数和截距项,其中model为之前训练的模型名称,通过coef_属性可以获取特征变量前的系数ki,通过intercept_属性可以获取截距项k0。

model.coef_

array([[ 2.41952469e-05,  8.16881491e-03,  1.04320950e-02,
        -2.54894468e-03, -1.10120609e-04]])
model.intercept_
array([-1.43393291e-06])