Fork me on GitHub

三. 逻辑回归

逻辑回归

Logistic Regression 是一个非常经典的二分类算法 ,也可以用于多分类(只需做个转换即可)

1. 逻辑回归中的条件概率

谈到分类,也许没有比逻辑回归更简单的方法了,受到工业界的极大的欢迎。逻辑回归的基本概念,以及如何一步步来构建逻辑回归中起到最核心作用的条件概率。

逻辑回归是二分类问题的“神器”,非常简单和实用,是在线系统中使用率最高的模型。

二分类问题

  • 预测贷款违约情况(会/不会)
  • 预测广告点击率(会/不会)
  • 商品推荐(会购买/ 不会购买)
  • 情感分析(正面/负面)
  • 预测疾病(阳性/阴性)
  • ...还有其他很多分类问题... 

基准(Baseline)

逻辑回归是很靠谱的基准(baseline),搭建任何分类模型时首先可以考虑逻辑回归,之后在逐步尝试更复杂的模型。

基准(baseline)在建模过程中非常重要。简单来讲,在设计模型的阶段, 首先试图通过简单的方法来快速把系统搭起来, 之后逐步把模块细化, 从而不断得到更好的解决方案。对于分类任务, 逻辑回归模型可以

称得上是最好的基准, 也是比较靠谱的基准。 在实际工作中, 切忌一上来就使用复杂的模型, 这是不可取的,复杂的模型是很难调参的。从基本模型开始训练,有参考值可以较好的定位问题;

    逻辑回归作为基准,逻辑回归的效果可以达到0.69的准确率,支持向量积svn的效果0.72,神经网络的效果0.71,多层的神经网络准确率0.712;我们可以看到它的上线;

       可以得到我们是否需要使用更复杂的模型,得到投入产出比;可行性分析;每个场景都有它的门槛,比如无人驾驶没有达到0.999是不能上路的;

                   

分类问题、二分类问题

分类问题

年龄 工资 学历 逾期 y
20 4000 本科 yes 1
25 5000 专科 no  0
21 6000 本科 no  0
25 5000 专科 yes 1
28 8000 本科 no  0
27 7000 专科 ?y6

学习输入到输出的映射 f: X --> y ,X输入, y输出 ; 

  X = {年龄, 工资, 学历} , y为逾期; 

P(y6=0| x6)= ?

P(y6=1| x6)= ?

二分类问题

  假如我们有办法表示条件概率:P( Y=0| X )    P ( Y = 1| X ) ...... 

可设计分类规则:

if P( Y=0| X )  >  P ( Y = 1| X ) 
    Y = 0
else 
    Y = 1

 核心问题是:  如何通过条件概率 p(y|x) 来描述x 和 y 之间的关系。 

逻辑回归实际上是基于线性回归模型构建起来的, 所以这里也希望通过线性回归方程一步步来构造上述的条件概率p(y∣x)。

但不能把条件概率p(y∣x)表示成 p(y|x) = wT x + b,因为右边的式子不满足条件概率的性质。

那么是否可以改造线性回归 wT x + b使得它的值域映射到(0, 1)区间了? 如何把正无穷到负无穷区间的值映射到(0,1)区间?   答案就是使用逻辑函数。

有效的概率需要具备的性质

  假如我们有办法表示条件概率:P( Y=0| X )   和 P ( Y = 1| X ) ...... 

  上述概率需要具备的性质有:

   ①   0 <= P( Y=0| X ) <= 1         ② P( Y=0| X ) + P ( Y = 1| X )  = 1 

    0 <= P( Y=1| X ) <= 1 

逻辑函数

逻辑函数的应用非常广泛, 特别是在神经网络中处处可见, 很大程度上是源于它不可或缺的性质:

可以把任意区间的值映射到(0, 1)区间。这样的值既可以作为概率, 也可以作为一种权重。另外, 由于大多数模型在训练时涉及到导数 (derivative)的计算, 同时逻辑函数的导数具有极其简单的形态, 这也使得

逻辑函数受到了很大的欢迎。

逻辑函数的输出可以当做概率,线性回归的值域是负无穷到正无穷,把线性回归和逻辑回归整合到一起;

上述例子可以写成以下形式:

 

样本的条件概率

  当把线性回归的式子和逻辑函数拼在一起的时候, 就可以得到合理的条件概率的表达式。新的条件概率如下图:

逻辑回归中我们针对的是 二分类问题 , 所以一个样本必须要属于其中的某一个分类。这就意味着, 条件概率 p(y=1|x) 和 p(y=0|x) 之和一定会等于1。

对于特征向量 x 和二分类标签y ,我们可以定义如下的条件概率:

 对于逻辑回归, 它的参数是 w, b, 前者是向量, 后者是标量。

在这里, 两个条件概率的表达式是可以替换顺序的。只要能保证两个条件概率之和等于1就可以了。

 

逻辑回归是线性分类器(判断标准:看模型的决策边界)

落在决策边界上有个性质:它的概率是等于0的,它既属于左边的又属于右边的,它俩的概率是等同的,通过这个条件即可去求决策边界,如果所示;

 模型的实例化 == 定义明确的目标函数  ----  优化算法 

 

2. 逻辑回归的目标函数

如何构造逻辑回归模型的目标函数,它是从条件概率获得。先理解最大似然估计,之后在最大似然的框架下试着推导出逻辑回归的目标函数。

最大似然估计

最大似然估计(Maximum Likelihood Estimation)在机器学习建模中有着举足轻重的作用。它可以指引我们去构造模型的目标函数, 以及求出使目标函数最大或者最小的参数值。

如何理解最大似然估计呢?

       一个比较抽象的解释是: 假如有个未知的模型(看作是黑盒子), 并且它产生了很多能观测到的样本。这时候, 我们便可以通过最大化这些样本的概率反过来求出模型的最优参数,

这个过程称之为最大似然估计。

问题:投掷硬币

假设有一枚不均匀的硬币出现正面或者反面的概率是不同的,我们设定出现正面的概率为θ,我们用H来表示正面,T表示反面。当我们投掷了6次之后得到了如下的结果,而且我们假定每次投掷事件都

是互相独立的,则 θ为多少?

  D = {H, T, T, H, H, H},  θ = ?     2/3

通过最大似然估计的角度去求解参数:

假设未知参数为 θ,已知的样本为D, 最大似然估计通过最大化 P( D| θ ) 来求解未知参数。  D = {H, T, T, H, H, H},  P(H) = θ, θ = ?

逻辑回归的似然函数

每一个样本的似然概率

  假设我们拥有数据集 D = {(xi,yi)}ni=1    , xi ∈ Rd , yi ∈ {0, 1}

对于其中的任意样本(xi,yi),我们可以定义它的似然概率:

逻辑回归的似然函数

  对于单个样本的 条件概率 已经定义过了, 这个概率也可以看作是似然概率。下一步得把所有的样本全部考虑进来, 这时候我们得到的就是所有样本的似然概率

假设我们拥有数据集 D = {(xi,yi)}ni=1    , xi ∈ Rd , yi ∈ {0, 1}

    {xi}5i=1 = {x1,x2,x3,x4,x5}

对于其中的任意样本(xi,yi),我们可以定义似然概率

 

对于所有样本的似然概率,我们可以定义为:

有了所有样本的 似然概率 之后, 我们的目标就是要求出让这个似然概率最大化的模型的参数( 对于逻辑回归模型就是w, b),这个过程称之为 最大似然估计(maximum likelihood estimation)。

逻辑回归的最大似然估计

把乘积转换成累加之和,并改成最小化问题:

需要最大化目标函数:

    每个样本的条件概率相乘 

 

得到了逻辑回归的目标函数之后, 首先来做一层简化,  就是把乘积的形式改造成加法形式。这对于后续的运算有很大的帮助。 把乘积转换成累加之和,并改成最小化问题;

我们需要最大的目标函数,上述公式推导为:

  对于严格递增的函数,添加log项,对结果没有影响; 

 

 目标函数的进一步简化

经过一系列的简化操作之后,发现不能继续再简化了。剩下的工作就是要寻找让目标函数最小化的参数w, b。那如何求出最优解呢? 一个经典的优化算法是梯度下降法!

3. 梯度下降法

优化领域的核心内容 - 梯度下降法。几乎所有的机器学习模型我们均可以通过梯度下降法来学出最优的参数。另外,我们试着通过梯度下降法来求解逻辑回归的最优参数。

函数优化中常见的两种主流方法:

  • 把导数设置为0;
  • 循环迭代式方法比如梯度下降法;

求函数的最大值/ 最小值

对于求解函数的最优参数, 通常有两种简单的方法:

  • 把导数设置为0
  • 基于迭代式的算法来求解, 如梯度下降法


第一种方法我们也称之为解析解(Analytic Solution)。但这里需要注意的一点是并不是所有的目标函数都可以通过把导数设置为0的方式来求解的。一个经典的例子就是逻辑回归的目标函数。 对于这类的

问题我们不得不采用另外一种更通用的方法-迭代式的优化算法。其中最经典的无非就是梯度下降法

梯度下降法

梯度下降法非常实用, 几乎所有的模型都可以使用梯度下降法来训练。这也说明此方法是具有通用性的, 不管问题有多复杂。特别是对于深度学习, 它的作用无可替代, 我们常说的反向传播算法 (back-

propagation)其实本质上就是梯度下降法。需要注意的一点是:  梯度下降法依赖于求导,  这也是为什么对函数的求导能力如此重要!

 假设有函数f(x),求是的f(x)值最小的参数x,可根据如下梯度下降法来求解最优解x

  • 初始化x1
  • for  t = 1, 2, ...:
  • xt + 1 = xt - η∇f(xt

案例1:求解函数f(x) = 4x2 + 5x + 1的最小值  

普通解法就是: x = - b / 2a = - 5 / 8 = - 0.625 

 梯度下降法: f ' (x) = 8x + 5    η = 0.1;

  

     x会收敛,不断的趋近于 -0.625  

案例2:求解函数 f(x) = x12 + x22  的最小值?   x = (x1, x2

 梯度下降解法:

  • 初始化x1
  • for  t = 1, 2, ...:
  • xt + 1 = xt - η∇f(xt

  x1w = 1,x2 = 1, η = 0.1:

  fx1 ' (x)  = 2x1  , f'x2 (x) = 2x

 

对于梯度下降法来说, 有一个重要的参数叫作学习率(learning rate),  我们可以把它看作是可调节的参数(也称之为超参数)。学习率对于收敛以及对最终的结果起到很重要的作用。

学习率(learning rate)的影响

对于逻辑函数的求导

梯度下降法的核心是对函数的求导。 逻辑回归的目标函数本身具有一定的复杂度, 其中就涉及到对逻辑函数的求导过程。对逻辑函数的求导:

 

逻辑回归的目标函数:

逻辑回归的梯度下降法

对于逻辑回归, 我们有两组参数分别为w, b, 所以求导的关键也就围绕这两组参数。这个过程中会涉及到一些 复合函数的求导法则 。

逻辑回归的梯度下降法 - 求解 w 

 

 

逻辑回归的梯度下降法 - 求解 b 

 有了对w, b的结果之后, 最终可以写出整个逻辑回归的梯度下降法的过程:

梯度下降法过程中, 如何判断迭代过程是否已经收敛 ?

  • 如果在相邻两个时间段损失函数没有任何变化 或者变化很小, 即可以认为优化过程已收敛
  • 如果在相邻两个时间段参数的值没有变化 或者变化很小, 即可以认为优化过程已收敛

当我们使用梯度下降法来求解逻辑回归的最优解时, 不管怎么初始化, 结果是一样的。主要的原因是逻辑回归的目标函数为凸函数。

如果一个函数为 凸函数 ,它只有全局最优解 , 所以不管怎么初始化, 最后收敛到的结果是同一个点。

全局最优解 VS 局部最优解

 

4. 随机梯度下降法

随机梯度下降法以及小批量梯度下降法。这两者均是梯度下降法的变种,适合用在数据量比较大的场景。实际上,工业界中用得最广泛的是小批量梯度下降法。

梯度下降法的缺点

  当样本很多的时候, 每一次迭代所花费的时间成本是很高的。举个例子, 当数据集里有一百万个样本的时候, 每一次的参数更新就需要循环所有的样本并把它们的梯度做累加。

随机梯度下降法SGD

随机梯度下降法(SGD) 可以看作是梯度下降法的极端的情况。在梯度下降法里, 每次的参数更新依赖于所有的样本。然而, 在随机梯度下降法里,  每一次的迭代不再依赖于所有样本的梯度之和,  而是仅仅依

赖于其中一个样本的梯度 。所以这种方法的优势很明显, 通过很“便宜”的方式获得梯度, 并频繁的对参数做迭代更新,  这有助于在更短的时间内得到收敛结果。

虽然SGD用很低的成本可以更新到模型的参数, 但也有自身的缺点。

  由于梯度的计算仅依赖于一个样本,计算出的结果包含较大的噪声;实际上, SGD的收敛效率通常是更高的, 而且有些时候SGD的最后找出来的解更优质。

由于在随机梯度下降法中, 我们用一个样本的梯度来代替所有样本的梯度之和, 计算出来的结果包含大量噪声,并且不太稳定。为了部分解决这个问题, 我们通常会把学习率设置为较小的值, 这样可以有效削

弱梯度计算中带来的不稳定性。

相比梯度下降法, 当我们使用随机梯度下降法的时候可以看到每一次迭代之后的目标函数或者损失函数会有一些波动性。有时候的更新会带来目标值的提升, 其他时候的更新可能反而让目标值变得更差。

但只要实现细节合理, 大的趋势是沿着好的方向而发展的。

小批量梯度下降法

  梯度下降法和随机梯度下降法其实可以看作是两个极端,  前者在计算梯度时考虑所有的样本,  后者则仅仅考虑其中的一个样本。既然这两个极端各有各自的优缺点, 那是否可以使用一个折中的方案

呢? 答案是肯定的, 这个方法叫作 小批量梯度下降法 (mini-batch gradient descent)。 它每次从样本中选择一部分子集,并基于这些选出来的样本计算梯度, 并做参数的更新。

 

从零实现小批量梯度下降法

下面的代码用来实现基于梯度下降法的逻辑回归。如何把循环的代码写成矩阵、向量的形式。

# 导入相应的库 
import numpy as np 
import matplotlib.pyplot as plt 
%matplotlib inline 
# 随机生成样本数据。 二分类问题,每一个类别生成5000个样本数据 
np.random.seed(12) 
num_observations = 5000 
x1 = np.random.multivariate_normal([0, 0], [[1, .75],[.75, 1]], num_observations) 
x2 = np.random.multivariate_normal([1, 4], [[1, .75],[.75, 1]], num_observations) 
X = np.vstack((x1, x2)).astype(np.float32) 
y = np.hstack((np.zeros(num_observations), 
               np.ones(num_observations))) 
print (X.shape, y.shape) 
# 数据的可视化 
plt.figure(figsize=(12,8)) 
plt.scatter(X[:, 0], X[:, 1], 
      c = y, alpha = .4) 
# 实现sigmoid函数 
def sigmoid(x): 
  return 1 / (1 + np.exp(-x)) 
# 计算log likelihood 
def log_likelihood(X, y, w, b): 
  """ 
  针对于所有的样本数据,计算(负的)log likelihood,也叫做cross-entropy loss 
  这个值越小越好 
  X: 训练数据(特征向量), 大小为N * D 
  y: 训练数据(标签),一维的向量,长度为D 
  w: 模型的参数, 一维的向量,长度为D 
  b: 模型的偏移量,标量 
  """ 
  
  # 首先按照标签来提取正样本和负样本的下标 
  pos, neg = np.where(y==1), np.where(y==0) 
  
  # 对于正样本计算 loss, 这里我们使用了matrix operation。 如果把每一个样本都循环一遍效率会很低。 
  pos_sum = np.sum(np.log(sigmoid(np.dot(X[pos], w)+b))) 
  
  # 对于负样本计算 loss 
  neg_sum = np.sum(np.log(1-sigmoid(np.dot(X[neg], w)+b))) 
  
  # 返回cross entropy loss 
  return -(pos_sum + neg_sum) 
# 实现逻辑回归模型 
def logistic_regression_minibatch(X, y, num_steps, learning_rate): 
  """ 
  基于梯度下降法实现逻辑回归模型 
  X: 训练数据(特征向量), 大小为N * D 
  y: 训练数据(标签),一维的向量,长度为D 
  num_steps: 梯度下降法的迭代次数 
  learning_rate: 步长 
  
  如果对于这块不是很熟悉,建议再看一下梯度下降法的推导视频 ^^ 
  """ 
  w, b = np.zeros(X.shape[1]), 0 
  for step in range(num_steps): 
    
    # TODO 随机采样一个batch, batch大小为100 
       
    # TODO 计算预测值与实际值之间的误差 
    
    # TODO 对于w, b的梯度计算 
    grad_w = 
    grad_b = 
    
    # 对于w, b的梯度更新 
    w = w - learning_rate * grad_w 
    b = b - learning_rate * grad_b 
    
    # 每隔一段时间,计算一下log likelihood,看看有没有变化 
    # 正常情况下, 它会慢慢变小,最后收敛 
    if step % 10000 == 0: 
      print (log_likelihood(X, y, w, b)) 
  
  return w,b 

w, b = logistic_regression_minibatch(X, y, num_steps = 500000, learning_rate = 5e-4) 
print ("(自己写的)逻辑回归的参数w, b分别为: ", w, b) 
# 这里我们直接调用sklearn的模块来训练,看看跟自己手写的有没有区别。如果结果一样就说明是正确的! 
from sklearn.linear_model import LogisticRegression 
# C设置一个很大的值,意味着不想加入正则项 (后续会看到正则作用,这里就理解成为了公平的比较) 
clf = LogisticRegression(fit_intercept=True, C = 1e15) 
clf.fit(X, y) 
print ("(sklearn)逻辑回归的参数w, b分别为: ", clf.coef_, clf.intercept_, ) 

 

比较不同的算法

对于各类梯度下降法做一个总结:

  • 在工业界中,最常用的方法为小批量梯度下降法
  • 小批量梯度下降法也有助于更好地利用GPU的计算能力
  • 小批量梯度下降法折中了梯度下降法和随机梯度下降法各自的优缺点,更好地解决梯度噪声的问题,更新更加稳定。
  • 随机梯度下降法或者小批量梯度下降法有助于解决鞍点(saddle point)的问题。

三者的比较

 

 

 

 

5. 预测银行客户是否开设账户

用逻辑回归模型来解决一个分类问题 - 预测银行客户是否开设账户。在这个过程中,会涉及到数据可视化、独热编码、F1-SCORE等技术。

基于用户的相关信息(如年龄,教育程度、婚姻状况等)来预测是否用户未来会有开设定期存款账户的需求。这种问题在银行业务上很常见,对于银行来讲,他们希望挖掘出一些潜在的客户,并精准地提供一些相

关的服务。 这个问题是很经典的二分类问题(预测结果为会开设或者不会开设),很适合用逻辑回归来解决。

这一次的案例会涉及到如下几个方面的内容:

    • 数据的理解和分析,具体分析哪一个特征对结果影响比较大
    • 独热编码 的表示,对于类别特征我们首先需要把它转换成独热编码的形式
    • 逻辑回归的使用
    • 精确率 、 召回率 、 F1-Score 的使用

理解数据

理解数据是解决问题的第一步,在这里我们从多方位来理解一下数据本身的一些特点比如哪些特征具有更好地预测能力,下面给出了部分数据的快照以及字段的说明。

 

 

 对于二分类问题来讲, 一个很重要信息是标签数据如每个标签的占比有多少。当一类标签的占比明显高于另外一类的时候, 我们其实要采取一些措施的,这里包括对样本的处理,也包括评估结果上的处理。

对于每一个特征,我们也可以做一些分析,如观察哪些特征对最后的预测产生更重要的影响。对于这些特征的分析我们可以通过一些可视化的分析即可以得到。

特征选择

对特征本身的重要性有大概的认知之后,我们可以选择把那些关联度不高的特征可以从数据中剔除掉。对于特征个数很多的数据来讲,这种操作还是非常有效的。但由于目前案例的数据特征并没有特别多,在这里先保留所有的特征。关于 特征选择 ,其实有很多不同的方法如根据 相关性 来选择、根据 贪心算法 来选择、根据树模型来选择等等,在后续的课程里会做详细的讲解。

类别变量和独热编码

对于类别型变量如本科、硕士、博士,在放到模型之前我们需要做特殊的处理,因为我们都知道模型的输入一定是数量化的信息,那如何把“本科,硕士,博士“这些字段转换成数量化的信号呢?

如果一个特征的值为类别型变量,”本科“, ”硕士“,”博士“,每一个值如何转换成数字呢?

硕士大于本科, 博士大于硕士, 类似于男大于女, 或者女大于男。 从这个角度考虑,我们就不能把类别型变量直接设置为某一个具体的值, 因为这些值本身是有大小关系的。

正确的做法是把变量值转化为独热编码的形态。

 

独热编码

对于类别型变量,正确做法是使用独热编码(one-hot encoding), 这也是最常用的编码方式。 然后直接把独热编码输入到模型就可以了。 一般来讲,独热编码的转换会让特征维度上升,比如对于一个类别型变

量 - “城市”, 可能的取值为1000多个,那当我们把这个变量转换成独热编码之后就变成了1000多维的向量。

模型训练

模型的评估

对于这个案例,标签类型的占比是很不平衡的,这种数据我们也称之为不平衡数据(imbalanced data)。 对于不平衡数据,评估标准上也需要格外地注意,因为选错了评估标准可能导致建模本身失去了意义。

假如我们有1000个样本,其中990个为负样本,10个为正样本,最后我们以准确率来评估模型的效果。

 

 

由于负样本很多,假如把所有的样本分类成负样本, 准确率已经高达99%, 看似训练得很好。

在数据不平衡的场景下,准确率会失去意义。我们可以不训练任何的模型,直接把所有的样本分类成样本, 准确率仍然高达99%,所以这个说明不了任何问题。 在这种情况下,我们倾向于使用另外一种评估标

准叫作F1-SCORE。

 

 

 编程的实现

 基于逻辑回归来实现银行客户的分类,很多的模块已经做了详细的解释,对于标记为TODO的部分请填写一下代码,并最后运行查看结果

# 导入一些必要的库 
import pandas as pd 
import numpy as np 
from sklearn import preprocessing 
import matplotlib.pyplot as plt 
%matplotlib inline 
plt.rc("font", size=14) 
from sklearn.linear_model import LogisticRegression # 逻辑回归模型 
from sklearn.model_selection import train_test_split # 用来拆分训练和测试数据 
import seaborn as sns 
sns.set(style="white") 
sns.set(style="whitegrid", color_codes=True) 
# 读取数据 
data = pd.read_csv('/home/anaconda/data/Z_NLP/banking.csv', header=0) 
data = data.dropna() 
# 打印数据大小 
print(data.shape) 
# 打印数据的列名 
print(list(data.columns)) 
# 计算正样本和负样本的比例 
count_no_sub = len(data[data['y']==0]) # 计算负样本个数 
count_sub = len(data[data['y']==1])  # 计算正样本个数 
pct_of_no_sub = count_no_sub/(count_no_sub+count_sub) # 计算百分比 
print('未开户的百分比: %.2f%%' % (pct_of_no_sub*100)) 
pct_of_sub = count_sub/(count_no_sub+count_sub) 
print('开户的百分比: %.2f%%' % (pct_of_sub*100)) 

# 把"education“字段里的三个值 "basic.9y", "basic.6y", "basic.4y"合并成同一个值"Basic" 
print (data['education'].unique()) 
data['education']=np.where(data['education'] =='basic.9y', 'Basic', data['education']) 
data['education']=np.where(data['education'] =='basic.6y', 'Basic', data['education']) 
data['education']=np.where(data['education'] =='basic.4y', 'Basic', data['education']) 
# 数据可视化分析:Job字段和预测变量之间关系 
%matplotlib inline 
table=pd.crosstab(data.job,data.y) 
table.div(table.sum(1).astype(float), axis=0).plot(kind='bar', stacked=True) 
plt.title('Stacked Bar Chart of Job title vs Purchase') 
plt.xlabel('Job') 
plt.ylabel('Proportion of Purchase') 
plt.savefig('purchase_vs_job') 
# 数据可视化分析:Marital Status字段和预测变量之间关系 
table=pd.crosstab(data.marital,data.y) 
table.div(table.sum(1).astype(float), axis=0).plot(kind='bar', stacked=True) 
plt.title('Stacked Bar Chart of Marital Status vs Purchase') 
plt.xlabel('Marital Status') 
plt.ylabel('Proportion of Customers') 
plt.savefig('mariral_vs_pur_stack') 

# 数据可视化分析:Education字段和预测变量之间关系 
table=pd.crosstab(data.education,data.y) 
table.div(table.sum(1).astype(float), axis=0).plot(kind='bar', stacked=True) 
plt.title('Stacked Bar Chart of Education vs Purchase') 
plt.xlabel('Education') 
plt.ylabel('Proportion of Customers') 
plt.savefig('edu_vs_pur_stack') 

# 数据可视化分析:Day of week字段和预测变量之间关系 
# 我们可以发现,这个字段跟预测变量之间关系相对较弱 
table=pd.crosstab(data.day_of_week,data.y)#.plot(kind='bar') 
table.div(table.sum(1).astype(float), axis=0).plot(kind='bar', stacked=True) 
plt.title('Stacked Bar Chart of Day of Week vs Purchase') 
plt.xlabel('Day of Week') 
plt.ylabel('Proportion of Purchase') 
plt.savefig('dow_vs_purchase') 

# 类别型变量需要转换成独热编码形式,列出所有类别型变量 
cat_vars=['job','marital','education','default','housing','loan','contact','month','day_of_week','poutcome'] 
for var in cat_vars: 
# TODO 每个变量转换成类别型变量, 参考函数 pd.get_dummies 
cat_list = 
data= 

# 剔除掉原来类别型变量,只保留独热编码 
data_final=data.drop(cat_vars, axis=1) 
data_final.columns.values 

# TODO 构造训练数据,X为特征,y为标签 
# TODO 把数据分为训练和测试数据 # 训练逻辑回归模型 from sklearn.linear_model import LogisticRegression from sklearn import metrics # TODO 初始化逻辑回归模型并在训练数据上训练 # TODO 计算F1-SCORE, 使用classification_report函数 from sklearn.metrics import classification_report print(classification_report(y_test, y_pred))

 

 
 
 
 
 
posted @ 2021-08-28 09:44  kris12  阅读(2607)  评论(0)    收藏  举报
levels of contents