【问题标题】:glmnet crossvalidation with grouped dataglmnet 与分组数据的交叉验证
【发布时间】:2017-07-15 10:19:27
【问题描述】:

我正在使用 glmnet 获取网络数据。通常,数据是分类的(因子的高基数)并且具有数百万个样本。我正在处理“大数据”并希望内存效率。

因为它是分类的,所以可以通过分组和传递每组的成功和失败次数来更有效地表示数据:例​​如 'male','30-35' :30 次成功,50 次失败

我面临的问题是交叉验证...通过分组我不能只对我的数据集进行分区(称为 X 原始分组数据集)。我想要的是能够传入原始分组数据自变量,然后将“折叠的结果”分区:例如,30 个成功 50 个失败将被分成 10 个#success,#failure 对(复制什么会如果我对原始未分组的数据进行交叉验证,就会发生这种情况。有没有以这种方式运行 cv.glmnet?复制所有数据 k 次(具有不同的成功失败值)的替代方案显然内存效率较低。

假设我有 2 个组和 2 个折叠:

male','30-35' : 30 成功,50 失败

female','30-35' : 50 次成功,30 次失败

那么我想要的是

X = 

    [[male','30-35'] 

    [female','30-35']]

y = 

[[20,30], [10,20],

[[25,30], [25, 0] ]

所以 X 变量包含 n 个组。 y 因变量然后有 n 行,并且有 2 列(每列包含一个成功失败的元组) - 每列代表一个折叠。现在我并不是说我追求这个特定的数据结构,只是对于分组数据,我不想创建一个 kN 行 X_fold 矩阵和相应的具有 kN 行的 y_fold 矩阵。

即X_fold =

[['male','30-35',...] 

['female','30-35',...]

['male','30-35',...] 

['female','30-35',...]
]

和 y_fold =

[[20,30], ,
[25,30], 
[10,20]
[25, 0] ]

关键是X有很多行和列,当独立数据相同时我不想复制它,只有成功和失败的数量会发生变化(允许折叠为0成功和0失败的某些行)

我假设如果不修改源代码就无法做到这一点,但我想再次检查没有其他人遇到过这个问题。

【问题讨论】:

  • 您能否举例说明您想要的褶皱是什么样子的?
  • 我已经澄清了。我想我建议对于分组数据,在折叠之间划分行的标准方法没有意义。相反,应该对结果计数进行分区(因此 y 数据变为 n 行(num_outcomes * num_folds),其中 num_outcomes 将是 2 用于逻辑回归。我假设这必须在代码中完成,但也许已经有一个分支代码?
  • X 和 Y 折叠是什么意思?
  • 我认为如果您问自己假设数据已分组(因此结果变量是成功和失败的计数)并且它有数百万行,您将如何对数据集执行交叉验证会更容易和 10 的因素。

标签: r group-by glmnet


【解决方案1】:

您提到了交叉验证,但这并不是真正的问题。您想要的是,当您的所有变量都是分类变量时,将您的数据集总结为一个因子列联表,并使模型适合响应和不响应的计数。这是逻辑回归中相当知名的技术。它既适用于拟合基础模型,也适用于交叉验证。

要看看它是如何工作的,让我们生成一个示例数据集(100 万行):

set.seed(12345)
df <- data.frame(
    x1 = factor(sample(10, 1e6, TRUE)),
    x2 = factor(sample(20, 1e6, TRUE)),
    x3 = factor(sample(5, 1e6, TRUE)),
    x4 = factor(sample(15, 1e6, TRUE)),
    y = rbinom(1e6, 1, 0.1))

现在将其折叠为列联表(15000 个单元格/行):

library(dplyr)
dfsmry <- df %>%
    group_by(x1, x2, x3, x4) %>%
    summarise(y = sum(y), ny = n() - y)

现在拟合弹性网络模型。当对汇总数据进行逻辑回归拟合时,响应是一个 2 列矩阵,其中包含每个单元格中的总失败次数和成功次数。

# to make life easier: see https://github.com/hong-revo/glmnetUtils
library(glmnetUtils)

# base model
mod <- glmnet(cbind(ny, y) ~ x1 + x2 + x3 + x4, data = dfsmry, family = "binomial")

# do crossvalidation
cvmod <- cv.glmnet(cbind(ny, y) ~ x1 + x2 + x3 + x4, data = dfsmry, family = "binomial")

【讨论】:

  • 感谢您生成示例代码 _ 我应该这样做!我将尝试生成自己的版本(不需要 glmnetUtils - 与我的 R 不兼容)
  • 问题在于采样方案 cv.glmnet 对分组数据做了什么(即在交叉验证期间)。我声称当前 cv.glmnet 对 rows (即组)进行统一采样(测试是在 cv.glmnet 中添加 keep=T 参数 - 在此示例中无法运行它),而什么需要对未分组的数据进行统一采样。
  • 如果你真的有几百万行和几十列,那么你使用什么采样方案并不重要。如果你有几十行几百万列,那就另当别论了。
  • 另外,glmnetUtils 只需要 glmnet 本身所需的东西,所以如果你可以使用一个,你可以同时使用。
猜你喜欢
  • 2018-03-20
  • 2017-03-15
  • 2017-12-03
  • 1970-01-01
  • 2021-08-05
  • 2023-03-03
  • 2019-01-28
  • 1970-01-01
  • 2018-06-22
相关资源
最近更新 更多