R {targets}:如何为数据科学和机器学习创建可重复的管道
作者:互联网
R {targets} 包是 R 中用于统计、数据科学和机器学习的管道工具。该包允许您在仅在必要时运行的管道中编写和维护可重现的 R 工作流程(例如,数据或代码已更改) 。最好的部分是 - 今天您将学习如何使用它。
在本文结束时,您将拥有用于在著名的泰坦尼克数据集上加载、准备、分割、训练和评估逻辑回归模型的完整管道。您将看到它是多么容易使用targets
,以及为什么在您的下一个数据科学项目中使用该包可能是一个好主意。
但什么是逻辑回归?阅读我们针对机器学习初学者的完整指南。
什么是 R {targets} 以及为什么需要它?
数据科学和机器学习归结为实验。每个实验可能需要几秒钟到几天的时间才能完成,到最后,结果可能无效(如果您更新代码或数据)。
这正是本题targets
要解决的问题。它使您能够维护可重复的工作流程,了解管道如何组合在一起,跳过已经是最新的任务,并仅运行必要的计算。这样,您可以节省时间和计算能力。
该软件包允许您完全在 R 中进行研究和实验,即使在 2022 年末,这种情况也很少见。大多数管道工具要么与语言无关,要么特定于 Python,因此看到具有本机 R 支持的东西总是受欢迎的。
您将使用的项目targets
将具有以下结构:
├── _targets.R ├── data.csv ├── R/ │ ├── 函数.R
第一个文件 -_targets.R
由包创建,稍后会详细介绍。它data.csv
用作数据源的虚拟示例。您不需要它,因为您可以从数据库或网络加载数据。您真正需要的唯一文件是R/functions.R
,因为它将包含构成管道的所有 R 函数。
如果尚未创建文件夹和文件,请创建它,然后让我们开始编写几个用于训练机器学习模型的函数。
让我们编写机器学习管道
正如简介部分中提到的,我们将编写一个机器学习管道,用于在泰坦尼克号数据集上训练和评估逻辑回归模型。
该管道将分布在R/functions.R
文件中的五个 R 函数中。以下是每个函数的作用的描述:
get_data()
- 返回泰坦尼克号数据集的训练子集。我们将在整篇文章中仅使用这个子集。prepare_data()
- 一个冗长的函数,用于清理数据集、提取有意义的特征、删除未使用的特征以及估算缺失值。train_test_split()
- 将我们的数据集分为训练和测试子集 (80:20)。fit_model()
- 将逻辑回归模型拟合到训练集。evaluate_model()
- 返回测试集的混淆矩阵。
这是一个相当长的文件,因此请随意从下面的代码片段中复制/粘贴它(如果需要,不要忘记安装软件包):
library(titanic)(泰坦尼克号) 库( dplyr ) 库( modeest ) 库( mice ) 库( caTools ) 库( caret ) get_data < -function ( ) { return ( titanic_train ) } prepare_data < -function ( data ) { #将空字符串转换为NaN 数据$客舱[数据$客舱== "" ] <- NA data $ Embarked [ data $ Embarked == "" ] <- NA # 标题提取 数据$ Title <- gsub ( "(.*, )|(\\..*)" , " " , data $ Name ) rare_titles <- c ( "Dona" , "Lady" , "the Countess" , "Capt" , "Col" , "Don" , “博士” 、 “少校”, “牧师” , “先生” , "Jonkheer" ) data $ Title [ data $ Title == "Mlle" ] <- "Miss" data $ Title [ data $ Title == "Ms" ] <- "Miss" data $ Title [ data $ Title == " Mme" ] <- "Mrs" data $ Title [ data $ Title %in% rare_titles] <- "Rare" # Deck 提取 数据$ Deck <- Factor ( sapply ( data $ Cabin , function ( x ) strsplit ( x , NULL ) [[ 1 ] ] [ 1 ] ) ) # 删除未使用的列 data <- data %>% select ( -c (乘客ID ,姓名,舱位,Ticket ) ) # 缺失数据插补 data $ Embarked [ is.na ( data $ Embarked ) ] <- mlv ( data $ Embarked , method = "mfv" ) Factor_vars <- c ( "Pclass" , "Sex" , "SibSp" , “帕奇” , “上船” , “标题” ) 数据[ factor_vars ] <- lapply (数据[ Factor_vars ] , function ( x ) as.factor ( x ) ) impute_mice <- mouse ( data [ , ! names ( data ) %in% c ( "Survived" ) ] , method = "rf" ) result_mice <- Complete ( impute_mice ) # 赋值给原始数据集 data $ Age <- result_mice $年龄 数据$ Deck <- result_mice $ Deck 数据$ Deck <- as.factor ( data $ Deck ) return ( data ) } train_test_split <- function ( data ) { set.seed ( 42 ) Sample_split <- Sample.split ( Y =数据$幸存, SplitRatio = 0.8 ) train_set <-子集( x =数据, sample_split == TRUE ) test_set <-子集( x =数据, sample_split == FALSE ) 返回(列表(“train_set” = train_set , “test_set” = test_set )) } fit_model <- 函数(数据) { 模型<- glm (幸存~ ., data = data , family = "binomial" ) return ( model ) } valuate_model <- function ( model , data ) { 概率<-预测( model , newdata = data , type = "response" ) pred <- ifelse (概率> 0.5 , 1 , 0 ) 厘米<-混淆矩阵(因子( pred ) ,因子(数据$幸存) ,正值= as.character ( 1 ) ) 返回( cm ) }
接下来,我们将在将每个函数添加到管道之前验证其是否按广告所示工作。
你有不完整的数据吗?如果您更喜欢使用 R 而不是 Python Pandas,这里有三个用于数据插补的 R 包。
手动评估我们的机器学习流程
让我们首先加载数据并显示数据集的头部:
数据 <- get_data()<- get_data ( ) 头(数据)
默认情况下,数据集非常混乱并且充满缺失值。该prepare_data()
函数是为了解决这个问题:
data_prepared <- 准备数据(数据)<-准备数据(数据) 头(数据准备)
接下来,我们将数据集分为训练和测试子集。完成后,将打印两者的尺寸:
data_splitted <- train_test_split(data_prepared)<- train_test_split ( data_prepared ) 暗淡( data_splitted $ train_set ) 暗淡( data_splitted $ test_set )
让我们将逻辑回归模型拟合到测试集并打印模型摘要:
data_model <- fit_model(data_splitted$train_set)<- fit_model ( data_splitted $ train_set ) 摘要( data_model )
总结还有很多内容,但重要的是我们没有收到任何错误。最后一步是打印混淆矩阵:
data_cm <-评估模型(data_model,data_splitted$test_set)<-评估模型(数据模型,数据分割$测试集) 数据厘米
就是这样——一切正常,所以让我们把它带到targets
下一步。
R {targets} 中的机器学习管道 — 简单英语解释
到目前为止,您应该R/functions.R
创建一个文件并填充五个函数,用于训练和评估逻辑回归模型。
问题仍然是——如何将这些函数添加到targets
管道中?答案很简单,只需从 R 控制台运行以下命令即可:
目标::use_targets()
该包将自动为您创建一个新文件 - _targets.R
. 这是一个普通的 R 脚本:
在其中,您必须修改一些内容:
- 第 12 行— 添加脚本所需的所有外部 R 包。
- 第 28 行— 将虚拟管道替换为实际管道。
管道的每个步骤都必须放置在tar_target()
函数内部。该函数接受步骤名称及其将运行的命令。请记住,该名称没有用引号引起来,这意味着您可以将一个步骤的结果传递给另一步骤。
这是整个修改后的_targets.R
文件:
# 由 use_targets() 创建。 # 按照下面的注释填写这个目标脚本。 # 然后按照手册检查并运行管道: # https://books.ropensci.org/targets/walkthrough.html#inspect-the-pipeline # nolint # 加载定义管道所需的包: library ( targets ) # library(archetypes) # 根据需要加载其他包。# nolint # 设置目标选项: tar_option_set ( packages = c ( "tibble" , "titanic" , "dplyr" , "modeest" , "mice" , "caTools" , ) , # 你的目标需要运行的包 format = "rds" # 默认存储格式 # 根据需要设置其他选项。 ) # tar_make_clustermq() 配置(可以不用管): options ( clustermq.scheduler = "multicore" ) # tar_make_future() 配置(可以不用管): # 安装软件包 {{future}}, {{future.callr} } 和 {{future.batchtools}} 允许 use_targets() 配置 tar_make_future() 选项。 # 使用自定义函数运行 R/ 文件夹中的 R 脚本: tar_source ( ) # source("other_functions.R") # 根据需要获取其他脚本。# 诺林特 # 将下面的目标列表替换为您自己的目标列表: list ( tar_target ( data , get_data ( ) ) , tar_target ( data_prepared , prepare_data ( data ) ) , tar_target ( data_splitted , train_test_split ( data_prepared ) ) , tar_target ( data_model , fit_model ( data_splitted $ train_set ) ) ) , tar_target( data_cm , evaluate_model ( data_model , data_splitted $ test_set )) )
这就是我们需要做的,准备工作。我们现在将检查管道中是否存在任何错误。
检查管道是否有错误
每次编写新管道或对旧管道进行更改时,最好检查一下是否一切正常。这就是tar_manifest()
函数发挥作用的地方。
您可以直接从 R 控制台调用它:
目标::tar_manifest(字段=命令)命令)
如果没有错误,您应该看到以下输出:
该tar_manifest()
函数用于创建描述计算管道中的目标及其依赖关系的清单文件。清单文件作为管道的蓝图,指导目标的执行和管理。
这里一切看起来都很好,但这并不是我们能做的唯一检查。
R {targets} 依赖图
让我们讨论一个额外的、更直观的测试。该tar_visnetwork()
函数呈现依赖关系图,显示管道从左到右的自然进展。
当您第一次调用此函数时,系统可能会提示您安装visnetwork
库(按键盘上的 1):
目标::tar_visnetwork()tar_visnetwork ()
您可以清楚地看到依赖关系 - 每个管道元素的输出都作为输入传递到下一个元素。左侧显示为三角形的功能与其各自的管道元素连接。
接下来,让我们最终运行管道。
运行目标管道
运行管道也可以归结为调用单个函数 - tar_make()
:
目标::tar_make()tar_make ()
如果您没有看到任何错误(红色文本块),则意味着您的管道已成功执行。您应该看到创建了一个新_targets
文件夹:
这_targets/objects
是一个包含每个管道步骤的输出的文件夹。我们可以加载最后一步的结果(混淆矩阵)并将其显示在 R 控制台中:
目标::tar_read(data_cm):: tar_read ( data_cm )
是的,就是这么简单!但最好的功能之一targets
是,它不会运行代码或数据未更改的管道步骤。我们可以通过重新运行管道来验证这一点:
目标::tar_make():: tar_make ( )
这就是 R 包的力量targets
。接下来让我们做一个简短的回顾。
总结 R {目标}
今天,您通过实践示例了解了 {targets} 包的基础知识。您现在拥有了一个可以根据自己的喜好进行修改的机器学习管道。例如,您可以从文件而不是库加载数据集,您可以绘制混淆矩阵或打印变量重要性。基本上,您可以做的事情没有限制。您必须在文件中进行的修改很少,并且您可以通过参考文档_targets.R
轻松地找出它们。