The purpose of this script is to test out different “disagreements” measure.
### Data Generating Process ###
dgp <- function(N, periods_type, s_epsilon, s_alpha, s_beta, p_num, rho_1, rho_2, y_initial, seed){
x = seed
## Generate the graph ##
p_num_value <- if(p_num == "low"){
N * .2
} else if(p_num == "high"){
N * .8
}
p = p_num_value/N
set.seed(6*x + 7)
G <- erdos.renyi.game(N, p, type=c("gnp"), directed = FALSE, loops = F) %>%
as_adjacency_matrix(sparse = F)
## Specify the number of time periods ##
periods <- if(periods_type == "squared"){
N^2 + N + 1
} else if(periods_type == "plus2"){
N + 2
}
d_max = max(rowSums(G))
set.seed(x)
rho_1_values <- if(grepl("unif", rho_1)){
range <- str_extract_all(pattern = "-?\\.?[0-9]", rho_1)
runif(N, as.numeric(range[[1]][1]), as.numeric(range[[1]][2]))
} else if(rho_1 == "seq(1/N, 1, 1/N)"){
seq(1/N, 1, 1/N)
} else if (is.numeric(rho_1)){
rep(rho_1, N)
}
set.seed(x + 7)
rho_2_values <- if(rho_2 == "standard normal"){
rnorm(N, 0, 1)
} else if(rho_2 == "unif(-1, 1)"){
runif(N, -1, 1)
} else if(rho_2 == "norm(0.1, 1)"){
rnorm(N, 0.1, 1)
} else if(rho_2 == "seq(1/N, 1, 1/N)"){
seq(1/N, 1, 1/N)
} else if(rho_2 == "zero"){
rep(0, N)
} else if(rho_2 == "depends on rho_1"){
(1-rho_1)/d_max - 0.01
}else if (is.numeric(rho_2)){
rho_2
}
## determine alpha, beta, and epsilon ##
set.seed(3*x + 7)
alpha = rnorm(N, mean = 0, sd = s_alpha)
set.seed(4*x + 7)
beta = rnorm(N, mean = 0, sd = s_beta)
set.seed(5*x + 7)
epsilon = rnorm(N, mean = 0, sd = s_epsilon)
## Generate Y ##
set.seed(2*x + 7)
y_initial_values <- if(y_initial == "standard normal"){
rnorm(N, 0, 1)
} else if(y_initial == "zero"){
rep(0, N)
}
Y <- matrix(nrow = N, ncol = periods + 1)
colnames(Y) <- 0:periods
Y[, "0"] <- y_initial_values
for(t1 in 1:periods){
t = t1 - 1
y_t <- Y[, paste(t)]
y_t1 <- alpha + beta + rho_1_values * y_t + (rho_2_values * G %*% y_t )+ epsilon
Y[, paste(t1)] <- y_t1
}
comparison_matrix = (diag(N) + G)
comparison_matrix2 = (rho_1_values * diag(N) + rho_2_values * G)
return(list(Y = Y, N = N, periods = periods, periods_type = periods_type, rankY = rankMatrix(Y)[1],
s_epsilon = s_epsilon,
s_alpha = s_alpha,
s_beta = s_beta,
p_num = p_num,
rho_1 = rho_1,
rho_2 = rho_2_values,
d_max = d_max,
y_initial = y_initial, seed = seed,
comparison_matrix = comparison_matrix,
comparison_matrix2 = comparison_matrix2,
G=G))
}
# g of theta
g_theta <- function(matrix, theta){
ifelse(abs(matrix) > theta, 1, 0)
}
# difference
disagreements <- function(original,estimate, N, theta){
return(sum(abs(original - g_theta(estimate, theta)) == 1)/N^2)
}
disagreements2 <- function(original, estimate, N){
return(sum(abs(original - estimate))/N^2)
}
### Ridge ###
ridge <- function(output, lambda, theta){
Y<- output$Y
N <- output$N
periods <- output$periods
F_Y <- c()
Y_v <- c()
for(i in 1:periods){
t <- Y[, paste(i - 1)]
f_t <- matrix(NA, ncol = N*N, nrow = N)
for(j in 1:N){
f_t[j, ]<- c(rep(rep(0, N), j-1), t(t), rep(rep(0, N), N-j))
}
F_Y <- rbind(F_Y, f_t)
Y_v <- rbind(Y_v, t(t(Y[, paste(i)])))
}
A = try(solve(t(F_Y) %*% F_Y + lambda * diag(N^2)) %*% t(F_Y) %*% Y_v, silent = T)
A <- t(matrix(A, N, N))
error <- ifelse(sum(ifelse(class(A) == "try-error", 1, 0)) >0, "error", "no error")
error_message <- ifelse(error == "error", paste(attributes(A)$condition), "")
dis <- disagreements(original = output$comparison_matrix, estimate = A, N = output$N, theta = theta)
dis2 <- disagreements2(output$comparison_matrix2, A, output$N)
diagnostics <- rbind(N= output$N, periods = output$periods_type, rankY = output$rankY,
s_alpha = output$s_alpha,s_epsilon = output$s_epsilon,
s_beta = output$s_beta, p_num = output$p_num, rho_1 = output$rho_1,
rho_2 = output$rho_2, y_initial = output$y_initial, error = error,
error_message = error_message, seed = output$seed, lambda = lambda, theta = theta,
disagreements = round(dis, 3),
disagreements2 = round(dis2, 3))
return(list(A = A, diagnostics = diagnostics, comparison_matrix = output$comparison_matrix, comparison_matrix2= output$comparison_matrix2))
}
We show the output for \(N = 15\). We set \(\lambda = 0.00001\) (because we previously found that \(\lambda = 0.00001\) vs \(\lambda = 0.1\) doesn’t make a difference).
We vary the following
| variable | options |
|---|---|
| periods_type | squared, plus 2 |
| \(s_\alpha\) | 0, 0.2 |
| \(s_\beta\) | 0, 0.2 |
| \(s_\epsilon\) | 0, 0.2 |
| \(\rho_1\) | 0.2, 0.6 |
| \(y_0\) | zero, standard normal |
| \(p_{numerator}\) | low (0.2), high (0.8) |
| \(\theta\) | 0.1, 0.01, 0.0001, 0.0001 |
We base \(\rho_2\) off the following:
\(\rho_1 + d_{max}\rho_2 < 1 \implies \rho_2 < \frac{1 - \rho_1}{d_{max}}\), so we pick
\(\rho_2 = \frac{1 - \rho_1}{d_{max}} - 0.01\)
N = 15
periods_type =c("squared", "plus2")
s_alpha = c(0, 0.2)
s_beta = c(0, 0.2)
s_epsilon = c(0, 0.2)
rho_1 = c(0.2, 0.6)
y_initial = c("standard normal", "zero")
p_num = c("low", "high")
theta = c(0.1, 0.001)
lambda = 0.00001
tests <- expand.grid(N = N,
periods_type = periods_type,
s_alpha = s_alpha,
s_beta = s_beta,
s_epsilon = s_epsilon,
rho_1 = rho_1,
y_initial = y_initial,
p_num = p_num,
lambda = lambda,
theta= theta,
stringsAsFactors = F)
cl <- parallel::makeCluster(3)
doParallel::registerDoParallel(cl)
tbl <- foreach(i = 1:nrow(tests), .combine = rbind, .packages=c('tidyverse', 'igraph', 'Matrix')) %dopar% {
output <- dgp(N = tests[i, "N"],
periods_type = tests[i, "periods_type"],
p_num = tests[i, "p_num"],
s_epsilon = tests[i, "s_epsilon"],
s_alpha = tests[i, "s_alpha"],
s_beta = tests[i, "s_beta"],
rho_1 = tests[i, "rho_1"],
rho_2 = "depends on rho_1",
y_initial = tests[i, "y_initial"],
seed = 1
)
out <- ridge(output = output, lambda = tests[i, "lambda"], theta = tests[i, "theta"])
final <- t(out$diagnostics)
return(final)
}
parallel::stopCluster(cl)
tbl <- as.data.frame(tbl) %>%
mutate(across(c(N, rankY, s_alpha, s_epsilon, s_beta, rho_1, rho_2, lambda, theta, disagreements, disagreements2), as.numeric),
across(c(rho_2), function(x) round(x, 3)))
options(DT.options = list(pageLength = 25))
tbl %>%
datatable()
plot(tbl$disagreements, tbl$disagreements2)
Is 0.1 or 0.001 more successful at minimizing disagreements?
There are 60 cases where 0.001 has lower disagreement values and 60 cases where 0.1 has lower disagreement rates.
Note that this follows high (0.8) and low (0.2) \(p_{numerator}\). In all cases where \(p_{numerator}\) is low, 0.1 does better (or equal). In all cases where \(p_{numerator}\) is high, 0.001 has lower disagreement values ( or equal).
tbl_summ <- tbl %>%
select(N, periods, rankY, s_alpha, s_epsilon, s_beta, p_num, rho_1, rho_2, y_initial, lambda, theta, disagreements) %>%
pivot_wider(names_from = theta, values_from = disagreements, names_prefix = "dis1_") %>%
mutate(best_theta = case_when(dis1_0.1 > dis1_0.001 ~ "0.001",
dis1_0.1 < dis1_0.001 ~ "0.1",
TRUE ~ "equal"),
min = as.numeric(case_when(dis1_0.1 > dis1_0.001 ~ dis1_0.001,
dis1_0.1 < dis1_0.001 ~ dis1_0.1,
TRUE ~ dis1_0.001)))
tbl_summ %>%
group_by(best_theta, p_num) %>%
count()
## # A tibble: 4 × 3
## # Groups: best_theta, p_num [4]
## best_theta p_num n
## <chr> <chr> <int>
## 1 0.001 high 60
## 2 0.1 low 60
## 3 equal high 4
## 4 equal low 4
Let’s say that we choose \(\theta\) such that disagreements are minimized. What does the distribution look like?
plot(density(tbl_summ$min), main = "Distribution of Minimum Disagreement Values")
Now, let’s add \(\theta \in \{0.0001, 1\}\).
N = 15
periods_type =c("squared", "plus2")
s_alpha = c(0, 0.2)
s_beta = c(0, 0.2)
s_epsilon = c(0, 0.2)
rho_1 = c(0.2, 0.6)
y_initial = c("standard normal", "zero")
p_num = c("low", "high")
theta = c(1, 0.0001)
lambda = 0.00001
tests2 <- expand.grid(N = N,
periods_type = periods_type,
s_alpha = s_alpha,
s_beta = s_beta,
s_epsilon = s_epsilon,
rho_1 = rho_1,
y_initial = y_initial,
p_num = p_num,
lambda = lambda,
theta= theta,
stringsAsFactors = F)
cl <- parallel::makeCluster(3)
doParallel::registerDoParallel(cl)
tbl2 <- foreach(i = 1:nrow(tests2), .combine = rbind, .packages=c('tidyverse', 'igraph', 'Matrix')) %dopar% {
output <- dgp(N = tests2[i, "N"],
periods_type = tests2[i, "periods_type"],
p_num = tests2[i, "p_num"],
s_epsilon = tests2[i, "s_epsilon"],
s_alpha = tests2[i, "s_alpha"],
s_beta = tests2[i, "s_beta"],
rho_1 = tests2[i, "rho_1"],
rho_2 = "depends on rho_1",
y_initial = tests2[i, "y_initial"],
seed = 1
)
out <- ridge(output = output, lambda = tests2[i, "lambda"], theta = tests2[i, "theta"])
final <- t(out$diagnostics)
return(final)
}
parallel::stopCluster(cl)
tbl2 <- as.data.frame(tbl2)%>%
mutate(across(c(N, rankY, s_alpha, s_epsilon, s_beta, rho_1, rho_2, lambda, theta, disagreements, disagreements2), as.numeric),
across(c(rho_2), function(x) round(x, 3)))
final_df <- rbind(tbl, tbl2)
final_df %>%
datatable()
Is there a relationship between original and new disagreements measures?
plot(final_df$disagreements, final_df$disagreements2)
Which values of \(\theta\) minimize disagreements?
final_summ <- final_df %>%
select(N, periods, rankY, s_alpha, s_epsilon, s_beta, p_num, rho_1, rho_2, y_initial, lambda, theta, disagreements) %>%
arrange(theta) %>%
pivot_wider(names_from = theta, values_from = disagreements, names_prefix = "dis1_")
best <- apply(X = final_summ[, c("dis1_0.0001", "dis1_0.001", "dis1_0.1","dis1_1")], MARGIN = 1, FUN =function(x){ which(x == min(x))}) %>%
lapply(., names)
final_summ$`min_0.0001` <- sapply(best, function(x)is.element("dis1_0.0001", x), simplify = T) %>% as.numeric
final_summ$`min_0.001` <- sapply(best, function(x)is.element("dis1_0.001", x), simplify = T) %>% as.numeric
final_summ$`min_0.1` <- sapply(best, function(x)is.element("dis1_0.1", x), simplify = T) %>% as.numeric
final_summ$`min_1` <- sapply(best, function(x)is.element("dis1_1", x), simplify = T) %>% as.numeric
final_summ$best_theta <- lapply(best, function(x){ifelse(length(x) >1, paste(x, collapse = ", "), x)}) %>% as.character
final_summ <- final_summ %>%
mutate(min = case_when(min_1 == 1 ~ dis1_1,
min_0.1 == 1 ~ dis1_0.1,
min_0.001 == 1 ~ dis1_0.001,
min_0.0001 == 1 ~ dis1_0.0001,
TRUE ~ min_1))
final_summ %>%
group_by(min_1, min_0.1, min_0.001, min_0.0001, p_num) %>%
count() %>%
arrange(p_num)
## # A tibble: 8 × 6
## # Groups: min_1, min_0.1, min_0.001, min_0.0001, p_num [8]
## min_1 min_0.1 min_0.001 min_0.0001 p_num n
## <dbl> <dbl> <dbl> <dbl> <chr> <int>
## 1 0 0 0 1 high 25
## 2 0 0 1 0 high 6
## 3 0 0 1 1 high 29
## 4 1 1 1 1 high 4
## 5 0 1 0 0 low 7
## 6 1 0 0 0 low 50
## 7 1 1 0 0 low 3
## 8 1 1 1 1 low 4
Let’s say that we choose \(\theta\) such that disagreements are minimized. What does the distribution look like?
plot(density(final_summ$min), main = "Distribution of Minimum Disagreement Values")