You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用数值优化器求解最优消费、闲暇与劳动供给?

数值优化入门问题指引

问题背景

我是数值优化领域的新手,针对以下逻辑清晰的优化问题寻求入门解法:

优化问题

目标是最大化效用函数:
$$
U = \alpha \log(c - \gamma_c) + (1-\alpha)\log(\ell - \gamma_\ell)
$$
约束条件:

  1. 消费约束:$c = (1-\tau)wh + I$
  2. 时间约束:$\ell = T - h$
  3. 非负约束:$c > \gamma_c$,$\ell > \gamma_\ell$,$h \geq 0$

其中参数 $\gamma_c$、$\gamma_\ell$、$\tau$、$\bar{\alpha}$ 均已知,$\alpha = \bar{\alpha} + e$($e$ 为随机项),$T$ 为总时间(原符号 $T_i$ 应为 $T$)。

我已通过拉格朗日乘数法手动得到闭形式解:

  • 最优劳动供给:$h = \alpha(T - \gamma_\ell) - \frac{(1-\alpha)(I - \gamma_c)}{(1-\tau)w}$
  • 最优闲暇:$\ell = T - h$
  • 最优消费:$c = (1-\tau)wh + I$

已用R实现闭形式解计算,代码如下:

library(tidyverse)

w_par = c(4, 0.4)
i_par = c(3, 0.04)
e_par = c(0, 0.01^2)
gamma_l = 8; gamma_c = 50; tau = 0.08; Time = 24; alpha_bar = 0.7;N = 10000
gamma_h = Time - gamma_l
theta_true = c(gamma_h, gamma_c, alpha_bar, sqrt(e_par[2]))

set.seed(1)
df <- data.frame(w = exp(rnorm(n = N, mean = w_par[1], sd = sqrt(w_par[2]))),
                 I = exp(rnorm(n = N, mean = i_par[2], sd = sqrt(i_par[2]))),
                 e = rnorm(n = N, mean = e_par[1], sd = sqrt(e_par[2]))) %>% 
  mutate(a = alpha_bar + e,
         h = a*gamma_h - (((1-a)*(I-gamma_c))/((1-tau)*w)),
         L = Time - h,
         C = (1-tau)*w*h+I,
         U = a*log(C-gamma_c) + (1-a)*log(L-gamma_l))

现仅保留数据框中 w、I、e、a 四列及已知参数,请问:

  1. 能否用优化器求解最优 $h$、$\ell$、$c$?
  2. 求解步骤是什么?
  3. 优化器结果与闭形式解是否一致?

注:仅需入门指引,此模型用于学习方法,以便应用于工作中无闭形式解的模型;支持R或Python实现,只要能得到 $U$、$\ell$、$c$ 即可。


解答

1. 能否用优化器求解?

完全可以。即使存在闭形式解,用优化器求解也是学习数值优化方法的绝佳练习,尤其能为后续处理无闭形式解的模型打基础。

2. 求解步骤

核心思路

将问题转化为最大化效用函数(或等价的最小化负效用函数,因为多数优化器默认求最小值),同时通过逻辑判断约束条件,让优化器避开无效解。

R实现步骤

  • 步骤1:定义目标函数
    编写负效用函数(适配优化器的最小值求解逻辑),加入约束检查,违反约束时返回极大值让优化器自动避开:

    neg_utility <- function(h, w, I, a, gamma_c, gamma_l, tau, Time) {
      c <- (1 - tau) * w * h + I
      l <- Time - h
      # 约束检查:违反则返回极大值
      if (c <= gamma_c || l <= gamma_l || h < 0) {
        return(1e10)
      }
      - (a * log(c - gamma_c) + (1 - a) * log(l - gamma_l))
    }
    
  • 步骤2:批量求解每条观测
    用rowwise()遍历数据,调用R内置的optim()函数,以闭形式解的结果作为初始值加快收敛:

    df_optim <- df %>%
      rowwise() %>%
      mutate(
        # 生成初始值,避免负数
        h_init = max(a*(Time - gamma_l) - ((1-a)*(I - gamma_c))/((1-tau)*w), 0.1),
        # 调用优化器求解
        optim_res = list(optim(par = h_init,
                               fn = neg_utility,
                               w = w, I = I, a = a,
                               gamma_c = gamma_c, gamma_l = gamma_l,
                               tau = tau, Time = Time)),
        # 提取最优结果并计算衍生变量
        h_optim = optim_res[[1]]$par,
        L_optim = Time - h_optim,
        C_optim = (1 - tau)*w*h_optim + I,
        U_optim = a*log(C_optim - gamma_c) + (1 - a)*log(L_optim - gamma_l)
      ) %>%
      ungroup() %>%
      select(-optim_res, -h_init)  # 清理中间变量
    

Python实现步骤(入门版)

用scipy.optimize.minimize()函数,逻辑与R一致:

import numpy as np
import pandas as pd
from scipy.optimize import minimize

# 定义负效用函数
def neg_utility(h, w, I, a, gamma_c, gamma_l, tau, Time):
    c = (1 - tau) * w * h + I
    l = Time - h
    if c <= gamma_c or l <= gamma_l or h < 0:
        return 1e10
    return - (a * np.log(c - gamma_c) + (1 - a) * np.log(l - gamma_l))

# 对单条观测求解
def solve_single_row(row):
    # 生成初始值
    h_init = row['a']*(24 - 8) - ((1-row['a'])*(row['I'] - 50))/((1-0.08)*row['w'])
    h_init = max(h_init, 0.1)
    # 调用优化器
    res = minimize(neg_utility, x0=h_init,
                   args=(row['w'], row['I'], row['a'], 50, 8, 0.08, 24))
    # 计算结果
    h_optim = res.x[0]
    L_optim = 24 - h_optim
    C_optim = (1-0.08)*row['w']*h_optim + row['I']
    U_optim = row['a']*np.log(C_optim -50) + (1-row['a'])*np.log(L_optim -8)
    return pd.Series([h_optim, L_optim, C_optim, U_optim],
                     index=['h_optim', 'L_optim', 'C_optim', 'U_optim'])

# 批量求解
df_optim = df.join(df.apply(solve_single_row, axis=1))

3. 优化器结果与闭形式解是否一致?

理想情况下完全一致,实际计算中会存在极小的浮点误差(通常在$1e-8$量级),可忽略不计。

你可以通过R代码验证差值:

df_compare <- df_optim %>%
  mutate(h_diff = abs(h - h_optim),
         L_diff = abs(L - L_optim),
         C_diff = abs(C - C_optim))

# 查看差值统计
summary(df_compare[, c('h_diff', 'L_diff', 'C_diff')])

输出的最大差值通常远小于1,说明结果高度吻合。


内容的提问来源于stack exchange,提问作者Jorge Paredes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 20:42:07