代码之家  ›  专栏  ›  技术社区  ›  kittygirl

如何估算R脚本的运行时间?

r
  •  0
  • kittygirl  · 技术社区  · 5 年前

    我有一个 数据帧 如下所示:

    > str(df)
    'data.frame':    8219 obs. of  60 variables:
     $ q01: int  3 3 3 1 4 3 1 5 2 5 ...
     $ q02: int  3 3 3 2 4 5 4 4 3 5 ...
     $ q03: int  4 2 1 2 4 4 2 3 2 2 ...
     $ q04: int  3 4 2 3 2 2 2 4 4 5 ...
     .
     .
     .
     $q60: int   3 3 5 2 1 2 4 2 1 2 ...
    

    每个项目都是 int 从1到5。
    当我奔跑时 corr.test(df,method = "kendall") ,即使两个小时过去了,我也无法得到任何输出。

    作为时间管理,如果我能估计出过程时间,如果是10分钟,我可以喝一杯咖啡。如果需要两个小时,我可以先编写另一个项目。

    是否有估算R脚本运行时间的方法?

    另外,我的笔记本电脑是双核2.4GHz,8GB内存。

    1 回复  |  直到 2 年前
        1
  •  6
  •   Peter Mortensen icecrime    2 年前

    这是一种基于数据行数估计时间的方法。我模拟了一个60列的数据帧,然后使用 lapply() system.time() 以计算定时。

    library(psych)
    # create 9000 rows of data w/ 60 columns
    system.time(data <- as.data.frame(matrix(round(runif(9000*60,min = 1, max = 5)),
                                             nrow = 9000)))
    id <- 1:9000
    data <- cbind(id,data)
    observations <- c(100,200,500,1000,2000)
    theTimings <- lapply(observations,function(x){
         system.time(r <- corr.test(data[id <= x,2:61],method = "kendall"))
    })
    theNames <- paste0("timings_",observations,"_obs")
    names(theTimings) <- theNames
    theTimings
    

    …以及输出:

    > theTimings
    $timings_100_obs
       user  system elapsed
      0.435   0.023   0.457
    
    $timings_200_obs
       user  system elapsed
      1.154   0.019   1.174
    
    $timings_500_obs
       user  system elapsed
      5.969   0.026   5.996
    
    $timings_1000_obs
       user  system elapsed
     24.260   0.045  24.454
    
    $timings_2000_obs
       user  system elapsed
    106.465   0.109 106.603
    

    生成预测

    我们可以从迄今为止的分析中获取数据,拟合模型,并预测更大数据集的时间。首先,我们用时序信息创建一个数据帧,然后拟合一个线性模型。我们将打印模型摘要以检查R^2的拟合度。

    time <- c(0.457,1.174,5.996,24.454,106.603)
    timeData <- data.frame(observations,time)
    fit <- lm(time ~ observations, data = timeData)
    summary(fit)
    

    总结表明,线性模型似乎与数据很好地吻合,认识到我们使用了少量的观测值作为模型的输入。

    > summary(fit)
    
    Call:
    lm(formula = time ~ observations, data = timeData)
    
    Residuals:
          1       2       3       4       5
      9.808   4.906  -7.130 -16.769   9.186
    
    Coefficients:
                   Estimate Std. Error t value Pr(>|t|)
    (Intercept)  -14.970240   8.866838  -1.688  0.18993
    observations   0.056193   0.008612   6.525  0.00731 **
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    Residual standard error: 13.38 on 3 degrees of freedom
    Multiple R-squared:  0.9342,    Adjusted R-squared:  0.9122
    F-statistic: 42.57 on 1 and 3 DF,  p-value: 0.007315
    

    接下来,我们将使用额外数量的观测值构建另一个数据帧,并使用它来生成预测的时间。

    predictions <- data.frame(observations = c(3000,4000,5000,6000,7000,8000,9000))
    data.frame(observations = predictions,predicted = predict(fit,predictions))
    

    根据我们的模型,9000个观测数据帧在我的笔记本电脑上大约需要8.2分钟。

    > data.frame(observations = predictions,predicted = predict(fit,predictions))
      observations predicted
    1         3000  153.6102
    2         4000  209.8037
    3         5000  265.9971
    4         6000  322.1906
    5         7000  378.3841
    6         8000  434.5776
    7         9000  490.7710
    
    > 490 / 60
    [1] 8.166667
    

    我们需要在更多的观测值上运行模型,以确定是否有2000到9000之间的观测值会使算法降级到线性可扩展性以下。

    此外,请注意,时序会因CPU速度、内核数量和机器上的可用RAM而异。这些测试是在2015年的MacBook Pro 15上进行的,配置如下。

    Enter image description here

    改进模型

    考虑到原始帖子和我的回答之间的来回评论,我们可以假设,在2000次观察之后,非线性效应变得突出。我们可以通过在模型中添加二次项并生成新的预测来测试这一点。

    首先,我们将收集3000、4000和5000次观测的数据,以增加模型中的自由度,并提供更多数据,从中我们可以检测到二次效应。

    > theTimings
    $timings_3000_obs
       user  system elapsed
    259.444   0.329 260.149
    
    $timings_4000_obs
       user  system elapsed
    458.993   0.412 460.085
    
    $timings_5000_obs
       user  system elapsed
    730.178   0.839 731.915
    

    接下来,我们将运行有和没有二次效应的线性模型,生成预测,并比较结果。首先,我们将运行模型并打印二次模型的摘要。

    observations <- c(100,200,500,1000,2000,3000,4000,5000)
    obs_squared <- observations^2
    time <- c(0.457,1.174,5.996,24.454,106.603,260.149,460.085,731.951)
    timeData <- data.frame(observations,obs_squared,time)
    fitLinear <- lm(time ~ observations, data = timeData)
    fitQuadratic <- lm(time ~ observations + obs_squared, data = timeData)
    summary(fitQuadratic)
    
    > summary(fitQuadratic)
    
    Call:
    lm(formula = time ~ observations + obs_squared, data = timeData)
    
    Residuals:
          1       2       3       4       5       6       7       8
    -0.2651  0.2384  0.7455 -0.2363 -2.8974  4.5976 -2.7581  0.5753
    
    Coefficients:
                   Estimate Std. Error t value Pr(>|t|)
    (Intercept)   1.121e+00  1.871e+00   0.599   0.5752
    observations -7.051e-03  2.199e-03  -3.207   0.0238 *
    obs_squared   3.062e-05  4.418e-07  69.307 1.18e-08 ***
    ---
    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
    
    Residual standard error: 2.764 on 5 degrees of freedom
    Multiple R-squared:  0.9999,    Adjusted R-squared:  0.9999
    F-statistic: 3.341e+04 on 2 and 5 DF,  p-value: 4.841e-11
    

    不仅使用二次模型将R^2提高到0.9999,而且在α=0.05时,线性项和二次项都与0有显著差异。有趣的是,模型中有一个二次项,线性效应是负的。

    最后,我们将为这两个模型生成预测,将它们组合成一个数据帧并打印结果。

    predLinear = predict(fitLinear,predictions)
    predQuadratic <- predict(fitQuadratic,predictions)
    data.frame(observations = predictions$observations,
               obs_squared = predictions$obs_squared,
               predLinear,
               predQuadratic)
    

    …以及结果:

      observations obs_squared predLinear predQuadratic
    1         3000     9.0e+06   342.6230      255.5514
    2         4000     1.6e+07   482.8809      462.8431
    3         5000     2.5e+07   623.1388      731.3757
    4         6000     3.6e+07   763.3967     1061.1490
    5         7000     4.9e+07   903.6546     1452.1632
    6         8000     6.4e+07  1043.9125     1904.4181
    7         9000     8.1e+07  1184.1704     2417.9139
    

    结论

    首先,随着我们添加数据,9000次观测的处理时间的线性预测从491秒增加到1184秒。正如预期的那样,向模型中添加数据有助于提高其准确性。

    其次,二次模型的时间预测是线性模型的2倍多,2417.9秒的预测在实际运行时间的13.74秒内,误差小于0.6%。

    附录

    问题:处理所有观察结果到底需要多长时间?

    当我运行9000个观测数据帧进行测试时,需要40分钟才能完成。这比最初的线性预测长了近5倍,最多可进行2000次观测,比最多可进行4000次观测的线性预测略长2倍。

    > # validate model
    > system.time(r <- corr.test(data[,2:61],method = "kendall"))
        user   system  elapsed
    2398.572    2.990 2404.175
    > 2404.175 / 60
    [1] 40.06958
    >
    

    结论: 而线性版本的模型比 IHME COVID-19 predicted fatalities model 最初预测美国有100万至200万人死亡,但它仍然太不准确,无法作为预测一个人的机器在60个变量中完成9000次观测分析所需时间的预测工具 corr.test() .

    然而,二次模型非常准确,这说明了在使用任何一个模型进行预测之前,开发多个假设的重要性。

    问:核心的数量不是无关紧要吗?

    对我的回答的一些评论断言,由于R corr.test() 函数使用单个线程来处理数据,CPU上的内核数量与运行时性能无关。

    我对这个答案的测试以及我对支持多线程的R函数所做的性能分析(例如。, Improving Performance of caret::train() with Random Forest ),表明在实践中,速度相似但内核较少的CPU比内核较多的CPU慢。

    在这种特定情况下,我们分析了 corr.test() ,我在一台 HP Spectre x360 与英特尔 Core i7-6500U 同样以2.5GHz运行的CPU,但它只有两个内核。它的处理时间比英特尔更快地缩短 Core i7-4870HQ CPU(同样为2.5GHz),如下表所示。

    Enter image description here

    从表中可以看出,在100次观测时,i7-U6500比Core i7-4870HQ慢22.5%,并且随着包括定时模拟在内的观测次数增加到4000次,这一差距也在增加。