3 Estimation
- Now we estimate the choice model, using data we generate
- Again, the choice model in the paper is as follows:
\[ \begin{align} u_{idt}(C, s) &= u_{\gamma}(w_{it} + h_{idt}(C, s)) \\ h_{idt}(C, s) &= -p_{idt} - \mathbf{1}_{d, t-1} \cdot \psi_{idt} - e(C, y_{d}) - p_{idt} \cdot R_{idt}(C, s) \\ \text{where } \psi_{idt} &= \mathbf{1}_{d, t-1} \cdot \eta_{0} + \mathbf{1}_{f_{d}, t-1} \cdot \eta_{it} + \mathbf{1}_{m_{d}} \cdot \mathbf{1}_{t=0} \cdot \xi_{it} \end{align} \]
- At each period \(t\), consumer \(i\) chooses \(d\) so as to maximize her expected utility:
\[ \begin{align} d_{it} &= \mathop{\rm argmax}\limits_{d \in D_{it}} \left\{ v_{idt} + \varepsilon_{idt} \right\} \\ \text{where } v_{idt} &= \mathbb{E}_{C, s}[u_{idt}(C, s)] = \mathbb{E}[h_{idt}] -\frac{\gamma}{2}\mathbb{E}[h_{idt}^{2}] \end{align} \]
We estimate the model by simulated maximum likelihood method. In doing so, we adopt a two-step estimation procedure since the cost model is easier to estimate but requires a large amount of data, while the demand model is making use of rich variations in choice but computationally demanding.
Therefore, we estimate risk and monitoring score parameters \((\theta_{\lambda}, \sigma_{\lambda}, \theta_{s}, \sigma_{s})\) first.
Then, we feed the estimates into the demand models as truth.
The overall log likelihood function is expressed as follows:
\[ \begin{align} \mathscr{L}_{i} = \sum_{t \leq T_{i}} \int_{\lambda} \underbrace{\mathscr{L}(R_{it}, s_{i}, C_{it}, d_{it} \mid \lambda, \psi, x_{it}, p_{it}, D_{it}, d_{i, t-1} ; \Theta)}_{(A): \text{obs. stoc outcome}} \cdot \underbrace{g_{\lambda}(\lambda \mid x_{it} ; \theta_{\lambda}, \sigma_{\lambda})}_{(B): \text{latent var.}} d\lambda \end{align} \]
- We can decompose the likelihood component A as follows:
\[ \begin{align} (A) = & \ln \Pr(d_{it} \mid \lambda, x_{it}, p_{it}, D_{it}, d_{i, t-1}; a, \psi_{0}, \psi_{1}, \theta_{\eta}, \theta_{\xi}, \alpha, \theta_{\beta}) \notag \\ & + \ln \Pr(C_{it} \mid \lambda, x_{it}) + \ln g(l_{it} \mid d_{it}, x_{it}; \alpha, \theta_{\beta}) \notag \\ & + \ln g_{s}(s_{i} \mid \lambda, x_{it}; \theta_{s}, \sigma_{s}) + \ln g_{R}(R_{idt} \mid C_{it}, s_{i}, \lambda, x_{it}; \theta_{R}, \theta_{R, m}, \sigma_{R}) \end{align} \]
3.1 Fuctions
- To estimate the choice model, we write the following functions:
gen_lambda
is a function that draws unobserved consumer risk \(\lambda\). In this function, we draw \(\lambda\) for \(R\) timesLL_choice
is a function that calculates choice probability that a consumer chooses each plan for each draw of \(\lambda\)LL_renewal_price
is a function that calculates choice probability that a consumer chooses each plan for each draw of \(\lambda\)SLL
is a function that calculates the simulated log-likelihood of consumer’s choice. We maximize this fucntion to get the estimates of choice model parameters
- Note that when optimizing an objective function, it is important to keep the realizations of the shocks the same across the evaluations of the objective function. If the realization of the shocks differ across the objective function evaluations, the optimization algorithm will not converge because it cannot distinguish the change in the value of the objective function due to the difference in the parameters and the difference in the realized shocks
- To avoid this problem, we generate \(\lambda\) outside the optimization algorithm
## Generate Lambda
<- function(df, cost_par, R){
gen_lambda # Parameters
<- cost_par[1:6]
theta_lambda <- cost_par[7]
sigma_lambda
# Generate mu_lambda
<- df %>%
output ::mutate(mu_lambda = theta_lambda[1]
dplyr+ theta_lambda[2]*x_1 + theta_lambda[3]*x_2
+ theta_lambda[4]*x_3 + theta_lambda[5]*x_4
+ theta_lambda[6]*ifelse(m == 1 & t == 0, 1, 0))
# Generate epsilon_lambda (draw R times)
<- matrix(rnorm(N * R, 0, sigma_lambda), nrow = N)
epsilon_lambda colnames(epsilon_lambda) <- c(paste("lambda", 1:R, sep = "_"))
<- data.frame(expand_grid(i = 1:N), epsilon_lambda) %>%
epsilon_lambda ::as_tibble()
tibble
## lambda
<- output %>%
output ::left_join(epsilon_lambda, by = c("i")) %>%
dplyr::mutate_at(.vars = vars(starts_with("lambda")),
dplyr.funs = ~ exp(mu_lambda + .)) %>%
::select(-mu_lambda)
dplyr
return(output)
}
# Calculate Choice Probability
<- function(df, theta, cost_par, R, lambda){
cal_v # Parameters
<- theta[1:4]
eta_f <- theta[5:6]
xi <- theta[7:9]
alpha_m0 <- theta[10:13]
alpha_m1 <- theta[14]
beta <- theta[15]
risk_aversion
# Cost Parameters
<- cost_par[8:11]
theta_score <- cost_par[12]
sigma_score <- cost_par[13]
l0 <- cost_par[14]
a_l
# Price
<- df$price * matrix(rep(1, dim(df)[1] * R), nrow = dim(df)[1])
price colnames(price) <- c(paste("price", 1:R, sep = "_"))
<- data.frame(price) %>%
price ::as_tibble()
tibble
# Generate Demand Friction
<- lambda %>%
demand_friction ::mutate_at(vars(starts_with("lambda")),
dplyrfuns(ifelse(f == prior_firm,
0,
1] + eta_f[2]*x_1 + eta_f[3]*x_2 + eta_f[4]*x_3)
eta_f[+ ifelse(d == 1 & t == 0,
1] + xi[2]*log(.),
xi[0))) %>%
::rename_with(\(x) str_replace(x, "lambda", "demand_friction"),
dplyrstarts_with("lambda")) %>%
::select(matches("demand_friction"))
dplyr
# Generate E_score
<- lambda %>%
E_score ::mutate_at(vars(starts_with("lambda")),
dplyrfuns(ifelse(t == 0 & m == 1,
exp(theta_score[1] + theta_score[2]*log(.)
+ theta_score[3]*x_1 + theta_score[4]*x_2
+ sigma_score^2 / 2),
0))) %>%
::rename_with(\(x) str_replace(x, "lambda", "E_score"),
dplyrstarts_with("lambda"))
# Generate E_oop
<- lambda %>%
E_oop ::mutate_at(vars(starts_with("lambda")),
dplyrfuns(.*exp(-.)*(l0^(a_l)/(a_l - 1))*policy_limit^(-a_l + 1))) %>%
::rename_with(\(x) str_replace(x, "lambda", "E_oop"),
dplyrstarts_with("lambda")) %>%
::select(matches("E_oop"))
dplyr
# Generate E_oop_sq
<- lambda %>%
E_oop_sq ::mutate_at(vars(starts_with("lambda")),
dplyrfuns(.*exp(-.)*((2 * l0^(a_l)) / ((a_l - 1) * (a_l - 1))) * policy_limit^(-a_l + 2))) %>%
::rename_with(\(x) str_replace(x, "lambda", "E_oop_sq"),
dplyrstarts_with("lambda")) %>%
::select(matches("E_oop_sq"))
dplyr
# Generate E_R_s
<- E_score %>%
E_R_s ::mutate_at(vars(starts_with("E_score")),
dplyrfuns(ifelse(t == 0 & m == 1,
1] + alpha_m1[2]*x_1 + alpha_m1[3]*x_2 + alpha_m1[4]*.) / beta,
(alpha_m1[1] + alpha_m0[2]*x_1 + alpha_m0[3]*x_2) / beta))) %>%
(alpha_m0[::rename_with(\(x) str_replace(x, "E_score", "E_R_s"),
dplyrstarts_with("E_score")) %>%
::select(matches("E_R_s"))
dplyr
# Generate E_R_s_sq
<- E_score %>%
E_R_s_sq ::mutate_at(vars(starts_with("E_score")),
dplyrfuns(ifelse(t == 0 & m == 1,
1] + alpha_m1[2]*x_1 + alpha_m1[3]*x_2 + alpha_m1[4]*.) / beta^2,
(alpha_m1[1] + alpha_m0[2]*x_1 + alpha_m0[3]*x_2) / beta^2))) %>%
(alpha_m0[::rename_with(\(x) str_replace(x, "E_score", "E_R_s_sq"),
dplyrstarts_with("E_score")) %>%
::select(matches("E_R_s_sq"))
dplyr
# Generate E_R_C
<- lambda %>%
E_R_C ::mutate_at(vars(starts_with("lambda")),
dplyrfuns(0.98 * exp(-.) + 1.2 * (1 - exp(-.)))) %>%
::rename_with(\(x) str_replace(x, "lambda", "E_R_C"),
dplyrstarts_with("lambda")) %>%
::select(matches("E_R_C"))
dplyr
# Generate E_R_C_sq
<- lambda %>%
E_R_C_sq ::mutate_at(vars(starts_with("lambda")),
dplyrfuns(0.98^2 * exp(-.) + 1.2^2 * (1 - exp(-.)))) %>%
::rename_with(\(x) str_replace(x, "lambda", "E_R_C_sq"),
dplyrstarts_with("lambda")) %>%
::select(matches("E_R_C_sq"))
dplyr
# Calculate E_h
<- - price - demand_friction - E_oop - E_R_s * E_R_C * price
E_h <- E_h %>%
E_h ::rename_with(\(x) str_replace(x, "price", "E_h"),
dplyrstarts_with("price"))
# Calculate E_h_sq
<- price^2 + demand_friction^2 + E_oop_sq + E_R_s_sq*E_R_C_sq*price^2
E_h_sq + 2*price*demand_friction + 2*price*E_oop + 2*price*(E_R_s*E_R_C*price)
+ 2*demand_friction*E_oop + 2*demand_friction*(E_R_s*E_R_C*price)
+ 2*E_oop*(E_R_s*E_R_C*price)
<- E_h_sq %>%
E_h_sq ::rename_with(\(x) str_replace(x, "price", "E_h_sq"),
dplyrstarts_with("price"))
# Calculate v
<- (E_h - (risk_aversion / 2) * E_h_sq) %>%
v ::rename_with(\(x) str_replace(x, "E_h", "v"),
dplyrstarts_with("E_h"))
<- df %>%
output ::bind_cols(v)
dplyr
return(output)
}
<- function(df, theta, cost_par, R, lambda){
cal_choice_probability ## Calculate v
<- cal_v(df, theta, cost_par, R, lambda)
v
## Calculate Choice Probability
<- v %>%
output ::group_by(i, t) %>%
dplyr::mutate_at(vars(starts_with("v")),
dplyrfuns(exp(.) / sum(exp(.)))) %>%
::ungroup() %>%
dplyr::rename_with(\(x) str_replace(x, "v", "choice_probability"),
dplyrstarts_with("v"))
}
# Log-likelihood for Choice Probability
<- function(df, theta, cost_par, R, lambda){
LL_choice ## Calculate Choice Probability
<- cal_choice_probability(df, theta, cost_par, R, lambda)
choice_probability
## Calculate Log-likelihood
<- choice_probability %>%
LL_choice ::mutate_at(vars(starts_with("choice_probability")),
dplyrfuns(choice * log(.))) %>%
::summarise_at(vars(starts_with("choice_probability")),
dplyrfuns(sum(.)))
<- as.matrix(LL_choice) %>%
LL_choice apply(1, mean)
# Output
<- LL_choice
output
return(output)
}
# Log-likelihood for Renewal Price
<- function(df, theta, cost_par, lambda){
LL_renewal_price # Parameters
<- theta[7:9]
alpha_m0 <- theta[10:13]
alpha_m1 <- theta[14]
beta
# Generate log-likelihood of R_s
## In the paper, we assume away uncertainty in s
<- df %>%
R_s ::filter(t == 1) %>%
dplyr::mutate(gamma_alpha = ifelse(score == 1,
dplyr1] + alpha_m0[2]*x_1 + alpha_m0[3]*x_2,
alpha_m0[1] + alpha_m1[2]*x_1 + alpha_m1[3]*x_2 + alpha_m1[4]*score),
alpha_m1[LL_gamma = log(((beta^gamma_alpha)/gamma(gamma_alpha)) * R_s^(gamma_alpha - 1) * exp(-beta * R_s)))
<- sum(R_s$LL_gamma)
LL_R_s
## 作ったが、Choice Modelの推定においては不要
# Generate log-likelihood of R_C
## We first match lambda in t = 0, since claim surcharge is resulted from lambda in t = 0
# lambda_t0 <- lambda %>%
# dplyr::filter(t == 0, f == 1) %>%
# dplyr::select(i, m, matches("lambda"))
#
# R_C <- df %>%
# dplyr::filter(t == 1) %>%
# dplyr::mutate(m = ifelse(score == 1, 0, 1)) %>%
# dplyr::left_join(lambda_t0, by = c("i", "m")) %>%
# dplyr::mutate_at(vars(starts_with("lambda")),
# funs((exp(-.)^(R_C == 0.98)) * (1 - exp(-.)^(R_C == 1.2)))) %>%
# dplyr::rename_with(\(x) str_replace(x, "lambda", "LL_surcharge"),
# starts_with("lambda")) %>%
# dplyr::summarise_at(vars(starts_with("LL_surcharge")),
# funs(sum(.)))
#
# LL_R_C <- as.matrix(R_C) %>%
# apply(1, mean)
<- LL_R_s
output
return(output)
}
## Simulated Log-likelihood
<- function(df, theta, cost_par, R, lambda){
SLL ## Choice Probability
<- LL_choice(df, theta, cost_par, R, lambda)
LL_choice
## Renewal Price
<- LL_renewal_price(df, theta, cost_par, lambda)
LL_renewal_price
## Output
<- (-1) * (LL_choice + LL_renewal_price)
output print(output)
return(output)
}
3.2 Optimization
# Cost Parameters
<- 0
cost_par 1:6] <- theta_lambda
cost_par[7] <- sigma_lambda
cost_par[8:11] <- theta_score
cost_par[12] <- sigma_score
cost_par[13] <- l0
cost_par[14] <- a_l
cost_par[
# Choice Parameters
<- 0
theta 1:4] <- eta_f
theta[5:6] <- xi
theta[7:9] <- alpha_m0
theta[10:13] <- alpha_m1
theta[14] <- beta
theta[15] <- risk_aversion
theta[
# Generate lambda
<- 50
R <- gen_lambda(df, cost_par, R)
lambda
## Initial Value
# x0 <- rep(1, length(theta))
# x0[7] <- 20
# x0[10] <- 20
# x0[14] <- 20
# x0[15] <- 0
<- numeric(length(theta))
x0 7] <- 1
x0[10] <- 1
x0[14] <- 1
x0[
<- theta
x0
## Optimization
<- optim(par = x0,
res fn = SLL,
control = list(maxit = 10^6),
method = "Nelder-Mead",
df = df,
cost_par = cost_par,
R = R,
lambda = lambda)
<- res$par theta_est