前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于 mlr 包的逻辑回归算法介绍与实践(上)

基于 mlr 包的逻辑回归算法介绍与实践(上)

作者头像
庄闪闪
发布2022-04-08 14:41:11
2.3K0
发布2022-04-08 14:41:11
举报
文章被收录于专栏:庄闪闪的R语言手册

前言

本期介绍的是 《Machine Learning with R, tidyverse, and mlr》 一书的第四章——逻辑回归(logistic regression)。逻辑回归是基于概率分类的有监督学习算法,它依赖于直线方程,产生的模型非常容易解释和交流。在其最简单的形式中,逻辑回归被用来预测二分类问题,但算法的变体也可以处理多个类。

1. 逻辑回归简介

逻辑回归算法通常应用于二分类问题,称为二项逻辑回归 (binomial logistic regression),当处理三分类或更多分类问题时,称为多项逻辑回归 (multinomial logistic regression)。该算法的应用过程如 Fig 1 所示,其中虚线表示中间还有其他过程,稍后会有介绍。

Fig 1. 逻辑回归过程

逻辑回归学习的模型输出新数据属于每个类的概率,再将新数据分配到它们最有可能属于的类。

1.1 二分类问题

假设你是一家 15 世纪艺术博物馆的馆长,当一些据称出自著名画家之手的艺术品来到博物馆时,你的工作就是判断它们是真品 (original)还是赝品 (forgery) (一个二分类问题)。我们可以对每幅画进行化学分析,并知道这一时期的许多赝品使用的颜料铜含量低于真品。通过使用逻辑回归来学习一个模型,它可以根据一幅画的铜含量来告诉你一幅画是真品的概率。

Fig 2 是一些已知画作的铜含量,并用一条直线来模拟画作的类别和铜含量的关系。平均而言,赝品的铜含量低于真品。

Fig 2. 画作类别与铜含量直线关系图

x 轴表示铜含量,y 轴显示分类类别,就像是一个连续变量一样,赝品和真品分别取 0 和 1 的值。y = 0.5 处的红色虚线表示分类阈值。蓝色实线表示在铜含量和类别之间建立的线性关系。由图可以看出,该直线关系有许多错误分类,分类效果较差。

Fig 3. 画作类别和铜含量 logistic 关系图

Fig 3 是使用 logistic 函数来模拟画作类别和铜含量的关系,使用和 Fig 2 相同的数据。由图中可以看出,和直线关系相比,分类效果较好。更重要的是,由于 logistic 函数将铜含量映射为 0 和 1 之间的值,所以 x 轴可以将其输出解释为含有特定铜含量的画作是真品的概率。另外,随着铜含量的增加,是真品的概率趋近于 1,相反,随着铜含量的减少,是真品的概率趋近于 0。

上文所介绍的内容中,只有一个预测变量——铜含量,但是如果我们有多个预测变量应该如何进行呢?可以借助接下来要介绍的 log odds

1.1.1 log odds

一幅画是真品的 odds 是:

odds = \frac{p}{1-p}

其中,p 是一幅画是真品的概率,范围为 0-1。odds 是表示某事发生可能性的一种方便的方式,其值大于 0,它可以告诉我们一件事发生的可能性比它不发生的可能性大多少。

Fig 4. 根据铜含量计算的真品的 odds

Fig 4 所示,这幅画的铜含量与这幅画是否是真品的 odds 之间并不是线性关系。接下来,对 odds 取对数,即为 log odds:

log~odds=ln(\frac{p}{1-p})

这个函数又称为 logit 函数。

Fig 5. 根据铜含量计算的真品的 log odds

Fig 5 可以看出,此时铜含量和这幅画是否是真品的 log odds 之间呈线性关系,且 log odds 的值是无界的。正值意味着某事更有可能发生而不是不发生,负值则相反。此外,线性关系意味着当我们有多个预测变量时,我们可以将它们的贡献加到 log odds 中,根据所有预测变量的信息,得到一幅画是真品的总的 log odds

1.1.2 如何预测分类

那么,我们如何从铜含量和 log odds 的直线关系中得出结论呢? 设我们有以下线性关系:

log~odds=intercept + slope \times copper

当通过新数据的铜含量计算出 log odds 后,再将其转换为画作为真品的概率 p:

p=\frac{1}{1+e^{-log~odds}}

若 p>0.5,则为真品。这种 log oddsoddsprobability 的转换如 Fig 6 所示。

Fig 6. log odds 到 odds 到 probability 的转换

当我们有多个预测变量时,对应的线性方程形式可以写为:

log~odds=ln(\frac{p}{1-p})=\beta_0+\beta_1x_1+\beta_2x_2+...+\beta_kx_k

新画作整个分类过程如 Fig 7 所示 (以两个预测变量(copper & lead)为例)。

Fig 7. 新画作整个分类过程

通过使用算法学习得到的线性模型,将新数据的铜含量(copper)和铅含量(lead)转换为它们的 log odds (或 logits)。接下来,使用 logistic 函数将 log odds 转换为概率 p。若 P 大于 0.5,则为真品。

1.2 多分类问题

上面的例子介绍的是二项逻辑回归问题。但我们也可以使用逻辑回归的变体预测多分类问题,即多项逻辑回归。在多项逻辑回归中,该模型为每个实例的每个输出类估计了一个 logit,而不是仅对每个实例估计一个 logit。将这些输出类的 logit 输入到 softmax function 中转换为概率 p,其和为 1。然后,选择概率最大的类作为输出类。该过程如 Fig 8 所示。

Fig 8. 多项逻辑回归过程

2. 建立逻辑回归模型

在此,我们建立一个二项逻辑回归模型来预测一名乘客是否能在泰坦尼克号灾难中幸存下来。加载包:

代码语言:javascript
复制
library(mlr)
library(tidyverse)

R 中警告信息:自 2019 年 7 月以来,mlr 处于“仅维护”模式。未来的开发将只在 mlr3 中进行(https://mlr3.mlr-org.com)。由于对 mlr3 的关注,在 mlr 中可能会有未捕获的 bug,请考虑切换。

2.1 加载泰坦尼克号数据集

该数据集在 titanic 包中,有 891 个实例和 12 个变量。

代码语言:javascript
复制
install.packages("titanic")#安装包
data(titanic_train, package = "titanic")#加载数据
titanicTib <- as_tibble(titanic_train)#转换为 tibble 格式
titanicTib #查看数据
# A tibble: 891 x 12
#   PassengerId Survived Pclass Name         Sex     Age SibSp Parch Ticket   Fare Cabin
#         <int>    <int>  <int> <chr>        <chr> <dbl> <int> <int> <chr>   <dbl> <chr>
# 1           1        0      3 Braund, Mr.~ male     22     1     0 A/5 21~  7.25 ""   
# 2           2        1      1 Cumings, Mr~ fema~    38     1     0 PC 175~ 71.3  "C85"
# 3           3        1      3 Heikkinen, ~ fema~    26     0     0 STON/O~  7.92 ""   
# 4           4        1      1 Futrelle, M~ fema~    35     1     0 113803  53.1  "C12~
# 5           5        0      3 Allen, Mr. ~ male     35     0     0 373450   8.05 ""   
# 6           6        0      3 Moran, Mr. ~ male     NA     0     0 330877   8.46 ""   
# 7           7        0      1 McCarthy, M~ male     54     0     0 17463   51.9  "E46"
# 8           8        0      3 Palsson, Ma~ male      2     3     1 349909  21.1  ""   
# 9           9        1      3 Johnson, Mr~ fema~    27     0     2 347742  11.1  ""   
#10          10        1      2 Nasser, Mrs~ fema~    14     1     0 237736  30.1  ""   
# ... with 881 more rows, and 1 more variable: Embarked <chr>

tibble 包含以下变量:

  • PassengerId: 每个乘客都有一个独特的任意数字。
  • Survived: 表示是否存活的整数(1=存活,0=死亡)。
  • Pclass: 乘客是住在一等舱,二等舱还是三等舱。
  • Name: 乘客姓名的字符向量。
  • Sex: 包含“男性”和“女性”的字符向量。
  • Age: 乘客的年龄。
  • SibSp: 乘客船上兄弟姐妹和配偶的总数。
  • Parch: 乘客船上父母和孩子的总数。
  • Ticket: 乘客票号的字符向量。
  • Fare: 乘客买票的金额。
  • Cabin: 乘客座舱号的字符向量。
  • Embarked: 乘客出发港口的字符向量。

2.2 充分利用数据:特征工程和特征选择

通常我们不会使用整个数据集来进行建模。在正式建模之前,首先要对数据进行清理,包括将数据转换为正确类型、纠正错误和删除不相关数据等步骤。对于泰坦尼克号数据集,主要有以下三个处理步骤:

  1. Survived, Sex, Pclass 三个变量转换为因子(factor)。(converting to factors)
  2. 添加新的变量 FamSizeSibSpParch 两个变量之和。(feature engineering)
  3. 选择认为对模型有预测价值的变量。(feature selection)
2.2.1 转换为因子 (converting to factors)

每个变量都应该被视为一个因子,因为它们代表了在整个数据集中重复出现的不同情况之间的离散差异。

2.2.2 特征工程(feature engineering)

这是一项极其重要的机器学习任务,它是对数据集中的变量进行修改,以提高它们的预测值。特征工程有两种方式:

  • Feature extraction.
  • Feature creation.

Feature extraction 是将预测信息保存在变量中,但以一种无用的格式保存。例如,假设有一个变量,它包含事件发生的年、月、日和时间。一天中的时间有重要的预测价值,而年、月、日则没有。为了让这个变量在模型中有用,只需要提取一天中的时间信息作为一个新变量。

Feature creation 是将现有的变量组合起来创建新变量。例如,添加新的变量 FamSizeSibSpParch 两个变量之和。

2.2.3 特征选择(feature selection)

这是另一个非常重要的机器学习任务:保留增加预测价值的变量,删除没有增加预测价值的变量。

泰坦尼克号数据清理代码如下:

代码语言:javascript
复制
fctrs <- c("Survived", "Sex", "Pclass")#定义将要转换为因子的变量的向量
titanicClean <- titanicTib %>%
  mutate_at(.vars = fctrs, .funs = factor) %>% #将变量转换为因子
  mutate(FamSize = SibSp + Parch) %>% #定义新的变量
  select(Survived, Pclass, Sex, Age, Fare, FamSize)#选择可以增加预测价值的变量
titanicClean#查看处理后的数据集
# A tibble: 891 x 6
#   Survived Pclass Sex      Age  Fare FamSize
#   <fct>    <fct>  <fct>  <dbl> <dbl>   <int>
# 1 0        3      male      22  7.25       1
# 2 1        1      female    38 71.3        1
# 3 1        3      female    26  7.92       0
# 4 1        1      female    35 53.1        1
# 5 0        3      male      35  8.05       0
# 6 0        3      male      NA  8.46       0
# 7 0        1      male      54 51.9        0
# 8 0        3      male       2 21.1        4
# 9 1        3      female    27 11.1        2
#10 1        2      female    14 30.1        1
# ... with 881 more rows

2.3 绘制数据

首先,使用 gather() 函数将数据转化为 untidy 形式:每个预测变量名保存在一列中,它们的值保存在另一列中。这样就可以使用 ggplot2 作分面图把不同的变量画在一起。

代码语言:javascript
复制
titanicUntidy <- gather(titanicClean, key = "Variable", value = "Value",
                        -Survived)
titanicUntidy
# A tibble: 4,455 x 3
#   Survived Variable Value
#   <fct>    <chr>    <chr>
# 1 0        Pclass   3    
# 2 1        Pclass   1    
# 3 1        Pclass   3    
# 4 1        Pclass   1    
# 5 0        Pclass   3    
# 6 0        Pclass   3    
# 7 0        Pclass   1    
# 8 0        Pclass   3    
# 9 1        Pclass   3    
#10 1        Pclass   2    
# ... with 4,445 more rows
代码语言:javascript
复制
titanicUntidy %>%
  filter(Variable != "Pclass" & Variable != "Sex") %>% #过滤掉Pclass和Sex两个变量
  ggplot(aes(Survived, as.numeric(Value))) +
  facet_wrap(~ Variable, scales = "free_y") + #绘制不同变量分面图
  geom_violin(draw_quantiles = c(0.25, 0.5, 0.75)) + #小提琴形状并画出分位数线
  theme_bw()

Fig 9. 三个变量分面图

小提琴图显示沿 y 轴的数据密度。每把小提琴上的线代表第 1 个四分位数、中位数和第 3 个四分位数(从最低到最高)。

接下来绘制关于 PclassSex 两个变量的图,分别查看不同舱位和性别所占幸存人数的比例。

Fig 10. 两个变量比例图

2.4 训练模型

现在我们已经清理了数据,接下来用 mlr 包创建任务、learner 和模型(使用 "classif.logreg" 来作为逻辑回归的 learner)。

代码语言:javascript
复制
titanicTask <- makeClassifTask(data = titanicClean, target = "Survived")#创建任务
logReg <- makeLearner("classif.logreg")#指定learner
logRegModel <- train(logReg, titanicTask)#训练模型
#Error in checkLearnerBeforeTrain(task, learner, weights) : 
#  Task 'titanicClean' has missing values in 'Age', but learner 'classif.logreg' does not support that!

此时报错,查看年龄数据可知存在缺失值,而逻辑回归无法处理这样的数据。

2.5 处理缺失值

处理缺失数据有两种方法:

  • 简单地从分析中排除缺少数据的情况。
  • 应用一种机制来填补空白。

当缺失值的情况与完整情况的比例非常小时,第一种选择可能是有效的。在这种情况下,省略带有缺失值的实例不太可能对模型的性能产生很大的影响。

第二种选择是使用一些算法来估计那些缺失值,用这些估计值替换 NA,并使用这个新数据集来训练模型。估计缺失值的方法有很多种,例如均值插补,也就是取缺失数据变量的均值,用它来替换缺失值。

在本例中,由于年龄缺失值较多,故使用第二种处理缺失值的方法。

代码语言:javascript
复制
imp <- impute(titanicClean, cols = list(Age = imputeMean()))#均值插补
sum(is.na(titanicClean$Age))#原数据集年龄变量缺失值个数
#[1] 177
sum(is.na(imp$data$Age))#新数据集年龄变量缺失值个数
#[1] 0

2.6 重新训练模型

代码语言:javascript
复制
titanicTask <- makeClassifTask(data = imp$data, target = "Survived")#定义任务
logRegModel <- train(logReg, titanicTask)#训练模型

使用经过处理缺失值的新数据来训练模型。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 庄闪闪的R语言手册 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1. 逻辑回归简介
    • 1.1 二分类问题
      • 1.1.1 log odds
      • 1.1.2 如何预测分类
    • 1.2 多分类问题
    • 2. 建立逻辑回归模型
      • 2.1 加载泰坦尼克号数据集
        • 2.2 充分利用数据:特征工程和特征选择
          • 2.2.1 转换为因子 (converting to factors)
          • 2.2.2 特征工程(feature engineering)
          • 2.2.3 特征选择(feature selection)
        • 2.3 绘制数据
          • 2.4 训练模型
            • 2.5 处理缺失值
              • 2.6 重新训练模型
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档