R

时间:2018-07-19 01:20:53

标签: r optimization calibration demographics

我不熟悉R中的模型优化/校准,但我渴望学习,并且确实需要一些帮助。我的问题与人口统计建模有关。

我已经进行了一些研究,找到了herehere的帮助,但都没有完全回答我的问题。

我有一个标量(倾向)矩阵,其中每一列必须总计为1。这些倾向用于估计给定人口(按年龄划分的人口)将产生的家庭数量。倾向模型倾向于高估历史上的住户数量(我知道其真实住户数量)。

我想通过调整倾向,以使列仍加1,并且初始值为零的倾向必须保持为零,从而对模型进行校正,以最大程度地减少住户数的误差。

简单的示例:

  # Propensities matrix
  mtx <- matrix(c(0.00,  0.00,  0.85,  0.00,  0.15, 0.35,  0.45,  0.00,  
               0.20,  0.00, 0.65,  0.15,  0.00,  0.20,  0.00), ncol = 3)

  # Population by age cohort
  pop <- c(2600, 16200, 13400)

  # True number of households
  target <- c(7000, 4500, 5500)

  # Function to optimise
  hh <- function(mtx, pop, target) {
    # Estimate living arrangements
    x <- mtx %*% pop 
    # Estimate number of households using parent cohorts (1,2 and 4)
    x <- c(x[1,1]/2, x[2,1]/2, x[4,1]) - target
    return(x)
  }

我没有为优化/校准步骤添加任何代码,因为这很尴尬,而且我什么也做不了!

理想情况下,在此过程结束时,我将有一套倾向可以很好地推广到许多不同地区。关于我应该如何实现它的任何建议?有用的链接吗?

更新

下面的代码段执行Enrico建议的本地搜索方法。

library(tidyverse)
library(NMOF)

data <- list(mtx = matrix(c(0.00,  0.00,  0.90,  0.00,  0.10, 0.25,  0.50,  0.00,   
                            0.25,  0.00, 0.60,  0.20,  0.00,  0.20,  0.00), ncol = 3),
             pop = c(2600, 16200, 13400),
             target = c(7190, 4650, 5920))

# True mtx
mtx.true <- matrix(c(0.00,  0.00,  0.75,  0.00,  0.25, 0.35,  0.45,  0.00,
                     0.20,  0.00, 0.65,  0.15,  0.00,  0.20,  0.00), ncol = 3)

# Function to optimise
households <- function(x, data) {

  # Estimate living arrangements
  z <- x %*% data$pop 

  # Estimate number of households using parent cohorts (1,2 and 4)
  z <- c(z[1,1]/2, z[2,1]/2, z[4,1]) - data$target
  sum(abs(z))

}

# Local search function to perturb propensities
neighbour <- function(x, data) {

  # Choose random column from mtx
  i <- sample(1:ncol(x), 1)
  # Select two non-zero propensities from mtx column
  j <- which(x[, i] != 0) %>% sample(2, replace = FALSE)

  # Randomnly select one to perturb positively 
  x[j[1], i] <- 0.1 * (1 - x[j[1], i]) + x[j[1], i]
  # Perturb second propensity to ensure mtx column adds to 1
  x[j[2], i] <- x[j[2], i] + (1 - sum(x[,i]))

  x

}

# Local search algorithm inputs 
localsearch <- list(x0 = data$mtx,             
                    neighbour = neighbour,
                    nS = 50000,                
                    printBar = FALSE)

# Execute 
now <- Sys.time()
solution <- LSopt(OF = households, algo = localsearch, data)
#> 
#> Local Search.
#> Initial solution:  2695 
#> Finished.
#> Best solution overall: 425.25
Sys.time() - now
#> Time difference of 6.33272 secs

# Inspect propensity matrices
print(solution$xbest)
#>           [,1]   [,2] [,3]
#> [1,] 0.0000000 0.3925  0.6
#> [2,] 0.0000000 0.4250  0.2
#> [3,] 0.2937976 0.0000  0.0
#> [4,] 0.0000000 0.1825  0.2
#> [5,] 0.7062024 0.0000  0.0
print(mtx.true)
#>      [,1] [,2] [,3]
#> [1,] 0.00 0.35 0.65
#> [2,] 0.00 0.45 0.15
#> [3,] 0.75 0.00 0.00
#> [4,] 0.00 0.20 0.20
#> [5,] 0.25 0.00 0.00

谢谢!

1 个答案:

答案 0 :(得分:0)

我只能对优化部分发表评论。

您提供的代码就足够了;只有您的目标函数求和为向量。您将需要将此向量转换为要最小化的单个数字,例如平方和或绝对值。

关于方法,我会尝试启发式;实际上,我会尝试使用Local-Search方法。这些方法通过您定义的函数对解决方案进行操作。因此,您可以将解决方案编码为矩阵。更具体地说,您将需要两个函数:目标函数(本质上具有)和邻域函数,该函数将解决方案作为输入并对其进行修改。在您的特定情况下,它可能需要一个矩阵,从一列中选择两个非零元素,然后增加一个而减少另一个。因此,列总和将保持不变。

也许教程http://enricoschumann.net/files/NMOF_Rmetrics2012.pdf令人感兴趣,它带有R代码http://enricoschumann.net/files/NMOF_Rmetrics2012.R