从不同角度看EDA

图片

我们不会谈论食物,而是探索性数据分析(EDA ),这是任何苛刻ML的前奏。

老实说,这个过程很无聊,为了至少对我们的数据有一些有意义的见解,您需要花费足够的时间积极地使用自己喜欢的可视化库。

现在想象一下我们很懒惰(但很好奇),并且在本文中将遵循这一假设。

基于此,我们向自己提出以下问题:本质上是否存在这样一个棘手的工具,该工具仅允许在您喜欢的IDE中按CTRL + ENTER,并在单个屏幕上显示完整的图片(无需向下滚动和无数个微观方面),其中包含有关我们数据集的有用信息?

同时,我们谨记一个不同的想法-如果存在这样的工具,它将不会取代经典的EDA,但是在那些您不必花大量时间进行可视化以快速强调数据中主要模式的情况下,它将为我们提供巨大帮助。

本文的结构:

  1. 小型预处理
  2. 预测器可视化
  3. 变量离散化
  4. 相关漏斗
  5. 排名互相关
  6. 易冲积

我们以导论结尾,并以一个实际的例子为基础。

示例方法
最初,我想获取一些晦涩难懂的数据数组,但最后我意识到,举个例子,这并不是很好-所发现的模式可能看起来并不明显,因此存在争议,但是我们的目标是使用没有先验信息的算法来准备数组,并向我们展示什么我们已经知道,从而证实了我们的生存能力。


在我看来,《泰坦尼克号》似乎是最方便的例子,它的大小不像鸢尾花那么小,它的信息量不大,经过了充分的研究并有明确的预测指标,而且重要的是有历史依据。

此外,我在哈布雷(Habré)上找到了一篇文章,作者对该数据集进行了相当精细的EDA,并根据图片展示了研究结果。 这将是我们的基准。

以“ Baseline_EDA”的大名链接到该文章:
泰坦尼克号on Kaggle:您不会阅读这篇文章的结尾

为了不打扰从网络上下载/读取csv,我们立即从CRAN中捕获原始数据集

install.packages("titanic") data("titanic_train",package="titanic") 

简短的预处理


这个示例在网络中通过上下预处理而变得非常混乱,以至于我不会特别涉猎这个话题,我正在做一些基本的事情:提取gonoratora(标题)的名称作为重要的预测变量,并使用它来填补年龄差距。

 library(tidyverse) titanic_train %>% str d <- titanic_train %>% as_tibble %>% mutate(title=str_extract(Name,"\\w+\\.") %>% str_replace(fixed("."),"")) %>% mutate(title=case_when(title %in% c('Mlle','Ms')~'Miss', #   title=='Mme'~ 'Mrs', title %in% c('Capt','Don','Major','Sir','Jonkheer', 'Col')~'Sir', title %in% c('Dona', 'Lady', 'Countess')~'Lady', TRUE~title)) %>% mutate(title=as_factor(title), Survived=factor(Survived,levels = c(0,1),labels=c("no","yes")), Sex=as_factor(Sex), Pclass=factor(Pclass,ordered = T)) %>% group_by(title) %>% #  -      mutate(Age=replace_na(Age,replace = median(Age,na.rm = T))) %>% ungroup #             table(d$title,d$Sex) 

头衔女的
先生5170
太太0126
小姐0185
师父400
先生80
转速60
博士61个
淑女02

并非所有的酸奶都同样健康...


通常,在分析开始时,我将不提供信息的变量放在一边(我保留而不是永久删除,因为当我从模型中获得最大收益时,对一些待处理变量进行工程设计会获得模型质量增益的一定百分比)。

评估变量“效用”的度量标准是freqRatio(最流行值的频率相对于第二个频率值的比率)和percentUnique(幂或基数-唯一数量的值在总数量中的比例)
从插入符号包中可以看到详细的帮助
?caret::nearZeroVar

 (feat.scan <- caret::nearZeroVar(x = d,saveMetrics = T) %>% rownames_to_column("featName") %>% as_tibble) 

图片

对我而言,最方便的是在二维平面中监视变量(通过记录两个轴,以使点不会由于离群点而过度绘制成一小堆)。
我从不怀疑这是否是EDA,但是在撰写本文时,我想:我们现在正在对预测变量的某些有用性,其视觉评估进行探索性分析,那么为什么不是EDA?

 # install.packages("ggrepel") library(ggrepel) ggplot(feat.scan,aes(x=percentUnique,y=freqRatio,label=featName,col=featName))+ geom_point(size=2)+ geom_text_repel(data = feat.scan,size=5)+scale_x_log10()+scale_y_log10()+theme_bw() 

图片

我们认为离群预测变量在功率(X轴)或频率比(Y轴)方面都是无用的,因此,请搁置:
旅客编号 名称; 车票 客舱

 useless.feature <- c("PassengerId","Name","Ticket","Cabin") d <- d %>% select_at(vars(-useless.feature)) 

这个宇宙是离散的


为了理解下面列出的库如何准备数据-在本节中,我们以小示例显示在数据准备阶段这些库中发生了什么。

第一步,有必要将所有数据归为一类-一组中的数据通常可以是分类的和数字的,而且,数字可以具有离群值,而分类的数据可以是罕见的类别。

要将连续变量转换为分类变量,我们可以将数字分解为具有一定采样周期的箱。

分解为5个bin的最简单示例:

 iris %>% as_tibble %>% mutate_if(is.numeric,.funs = ggplot2::cut_number,n=5) 

图片

为了获得预测变量之间各个元素之间关系的强度和方向性,使用了第二个技巧- 一种热编码

 library(recipes) iris %>% as_tibble %>% mutate_if(is.numeric,cut_number,n=5) %>% recipe(x = .) %>% step_dummy(all_nominal(),one_hot = T) %>% prep %>% juice %>% glimpse 

现在,我们有23个预测器,而不是5个预测器,但是二进制预测器:

图片

通常,转换技巧到此为止,但是我们“非经典” EDA的3个库中有2个的工作就是从这些阶段开始的。

接下来,我介绍3个可视化库的功能:

  1. Correlationfunnel-显示各个预测变量值对目标的影响(即您可以将其称为EDA超越学习)
  2. 成绩 -显示单个预测变量值对其他预测变量的其他单个变量值的影响(即,您可以将其称为EDA非超前学习)
  3. easyalluvial-显示每个目标的前“ X”个预测变量的分组值的累积关系(即,您可以将其称为EDA超越学习)

显然,它们的功能是不同的,因此,在演示这些库时,我将根据该软件包的上述功能引用作者在“ Baseline_EDA” 文章中的结论。 (例如,如果作者显示了年龄对生存的依赖性,那么我将在Correlationfunnel中插入这样的引号,如果年龄在班级上,然后在Lares中等等)

第一个图书馆上台了。

相关漏斗


relatedfunnel旨在加快探索性数据分析(EDA)
图片

该方法在库小插图中有很好的描述;我将给出一个用二进制值计算相关性的片段

图片

该库假定我们的数据中存在目标(因变量),并且在一张图片上立即显示了关系的强度和方向,并且还按此力的降序排列形成了一个视觉漏斗(实际上,这就是名称)。

库中内置的二值化函数使您可以将小类别简化为“其他”。

由于该库不适用于整数变量,因此我们会将其转换为数字并返回到Titanic。

 #install.packages("correlationfunnel") library(correlationfunnel) d <- d %>% mutate_if(is.integer,as.numeric) d %>% binarize(n_bins = 5,thresh_infreq = .02,one_hot = T) %>% #    correlate(target = Survived__yes) %>% plot_correlation_funnel() # "interactive = T" - plotly! 

图片

在X轴上,我们具有关联的强度和方向,在Y轴上,我们的预测变量按降序排列。 第一个总是将目标反映为 他与自己的关联性最强(-1; 1)。

让我们检查一下该图上的结论与“ Baseline_EDA”作者的结论如何重叠。
下图证实了以下理论:客舱等级越高,生存机会越大。 (“在上方”是指相反的顺序,因为第一类高于第二类,尤其是第三类。)
漏斗显示,就相关强度而言,该类别是第三个预测因子,而实际上,在第3类中,第1类的逆相关性是强的正相关性。
比较男性和女性的生存机会。 数据证实了先前表达的理论。

(一般来说,我们已经可以说模型的主要因素将是乘客的性别)

漏斗显示,根据相关程度,乘客的性别为第二,女性与生存率相关,男性与死亡相关。
您还可以检验年轻一代得以幸存的假设,因为 他们动作更快,游泳更好等

如您所见,这里没有显式的依存关系。

漏斗确实说明了此预测变量的重要性不高(我记得,优先级/标题包含年龄,这就是为什么年龄不那么重要)的原因,但是即使在此处,漏斗也显示在“减去无限大-20岁”类别(即儿童)中存在更多的生存机会。 )和30-38岁(有钱人,可能是1类)。
让我们介绍诸如生存率之类的指标,并看看其对上一阶段结果所显示的群体的依赖性

(作者所在的组即标题)。

漏斗充分证实了作者的发现
现在,让我们看一下可以从船上亲戚人数获得的信息。

缺少亲戚以及大量亲戚很可能对生存产生负面影响。

漏斗中的SibSP清楚地表明了同样的意思。

当然,除了作者的结论外,在这里您还可以看到其他模式,我将沉思的乐趣留给读者

劳斯


通过互相关排名查找见解

图片

该库的作者走得更远-他不仅展示了对目标的依赖,还展示了对一切的依赖。

等级互相关不仅以易于使用和理解的表格格式解释了特定目标特征与其余特征的关系,而且还解释了数据所有值的关系

它会使用一种热门编码(1和0)以及其他智能分组(例如“其他”标签)自动将类别列转换为数值,以实现不太频繁的值和新功能过时的功能。


使用上面的链接,您可以看到一个示例,作者在该示例中将《星球大战》数据集馈入了他的程序包,并演示了找到的依赖项,这很不错。

让我们尝试我们的例子。

 # ,     : # devtools::install_github("laresbernardo/lares") library(lares) corr_cross(df = d,top = 30) 

图片

除了与基于引号的结论相交之外,在Correlationfunnell中,我们还提供了一些引文,无论目标是什么,我们都可以在此处看到:
也可以找到其他模式。 年龄和阶级之间存在负相关关系,这很可能是由于年纪较大的乘客可能更负担得起更昂贵的机舱。

在上面的引用中,作者对总共2个字段的相关性分析得出了这样的结论,但是鉴于“一键编码”,从Age + P_Class_1之间的强正相关性可以明显看出这一点。
另外,机票价格和等级是紧密相关的(高相关系数),这是可以预料的。

上方第三行:票价+ P_Class_1

除了与作者的结论相交之外,这里可以强调更多有趣的事情,我也将沉思的乐趣留给读者。

除了可以选择的X个最有力的见解之外,您还可以反映整个图片以及这些重要点在总质量中的位置

 corr_cross(df = d,type=2) 

图片

易冲积


利用冲积图进行数据探索

图片

在这里,与前两个软件包一样,作者在开始时对数值变量进行二值化处理,但随后他与这些库的路径有所不同:该库而不是{One-HotEncoding + related},而是列出了最有趣的预测变量的前X个(用户决定要转移哪些预测变量) )通过值,形成颜色取决于目标的流,以及流的宽度取决于该流中的观察数。

将数值变量分解为HH(高高),MH(中高),M(中),ML(中低),LL(低中)类别

首先,让我们根据相关漏斗图获取最重要的预测变量:

 cor.feat <- c("title","Sex","Pclass","Fare") 

接下来,我们制定时间表

 # install.packages("easyalluvial") library(easyalluvial) al <- d %>% select(Survived,cor.feat) %>% alluvial_wide(fill_by = "first_variable") add_marginal_histograms(p = al,data_input = d,keep_labels = F) 

图片

对于作者的报价,我们使用适当的预测变量重新绘制图表

 cor.feat <- c("Sex","Pclass","Age") al <- d %>% select(Survived,cor.feat) %>% alluvial_wide(fill_by = "first_variable") add_marginal_histograms(p = al,data_input = d,keep_labels = F) 

图片

例如,下图清楚地表明,幸存者的主要群体是所有年龄段的一年级和二年级的女性。

该图还显示,幸存的3年级女性也不是一个小群体

在男子中,除三等兵和一小部分年龄较大的男子(大部分来自一等兵)外,所有15岁以下的男孩都幸存下来。

以上已得到证实,但我们仍然可以看到年龄在LL,ML的3级男性幸存者的流动。

上面的所有内容都与“ easyalluvial”程序包有关,但是作者编写了第二个程序包“ parcats”,该程序包使上面的图具有交互性(如本节标题所示)。
这样不仅可以看到工具提示的上下文,还可以重新定向流程以更好地视觉感知。 (不幸的是,尽管该库不是很优化,并且放慢了泰坦尼克号的速度)

 # install.packages("parcats") library(parcats) cor.feat <- c("title","Sex","Pclass","Fare") a <- d %>% select(Survived,cor.feat) %>% alluvial_wide(fill_by = "first_variable") parcats(p = a,marginal_histograms = T,data_input = d) 

图片

红利


除探索性数据分析外,简易冲积库还可以用作黑匣子模型的解释器(黑匣子模型的分析模型无法解释其参数-模型基于某些预测变量以何种逻辑给出答案)。

链接到作者的文章: 用冲积图可视化模型响应
而且,我所看到的所有库都有其独特之处,一张图上的最大值解释了黑匣子在不超过二维坐标系(每个预测变量一个)中的响应,颜色解释了响应。

easyalluvial库可让您同时对两个以上的预测变量执行此操作(当然,最好不要忘了它)。

例如,让我们在数据数组上训练随机森林,并使用3个预测变量来反映对随机森林的解释。

 library(ranger) m <- ranger(formula = Survived~.,data = d,mtry = 6,min.node.size = 5, num.trees = 600, importance = "permutation") library(easyalluvial) (imp <- importance(m) %>% as.data.frame %>% easyalluvial::tidy_imp(imp = .,df=d)) #      #  N-     (   .  !)   dspace <- get_data_space(df = d,imp,degree = 3) #     pred = predict(m, data = dspace) alluvial_model_response(pred$predictions, dspace, imp, degree = 3) 

另外,作者还有一个CARET模型的连接器(我不知道这在考虑整洁模型时有多重要)

 library(caret) trc <- trainControl(method = "none") m <- train(Survived~.,data = d,method="rf",trControl=trc,importance=T) alluvial_model_response_caret(train = m,degree = 4,bins=5,stratum_label_size = 2.8) 

图片

结论


我再一次重申,我不要求更换经典的EDA,但是同意,当有一种可以节省大量时间的替代方法时,这是很好的选择,特别是考虑到人们天生懒惰,这就是进步的动力:)

Source: https://habr.com/ru/post/zh-CN480532/


All Articles