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

矩阵目标函数优化遇NaN问题:求配置方案或替代算法

问题描述

我有资产A和B的权重矩阵与收益矩阵:

weights = np.array([[.6, .4], [.5, .5], [.4, .6]]) # 所有元素满足 0 < w < 1
returns = np.array([[1.25, 2.5], [0.64, 0.5], [1.5, 1.6]]).T

希望找到新的权重矩阵,优化如下目标函数:计算weights与returns乘积矩阵的对角线元素乘积并减1,定义如下:

def objective_function(weights, returns):
    mat = np.product(np.diag(weights @ returns)) - 1
    return mat
# 示例输出:0.5561

尝试将权重矩阵扁平化后用Scipy的minimize方法优化,但得到全NaN的权重矩阵:

import numpy as np
from scipy.optimize import minimize

# 重塑为接受3x2矩阵的函数
def funct(weights_flat):
    weights = weights_flat.reshape((3, 2))
    mat = -(np.product(np.diag(weights @ returns)) - 1)
    return mat

# 约束条件:每列元素和为1
constraints = ({'type': 'eq', 'fun': lambda w: np.sum(w, axis=0) - 1})

# 初始猜测(一维数组)
initial_guess_flat = np.ones(6)

# 执行优化
result = minimize(funct, initial_guess_flat, method='SLSQP', constraints=constraints)

# 获取优化后的权重
optimized_weights = result.x.reshape((3, 2))

print("Optimized Weights:")
print(optimized_weights)

运行结果:

>>> Optimized Weights:
[[nan nan]
 [nan nan]
 [nan nan]]

需解决如何重新配置优化函数实现预期效果,或推荐适用的优化包/算法。


解决方案

问题根源

  • 初始猜测不合理:初始值用np.ones(6),重塑后每列和为3,远偏离约束要求的1,易引发数值不稳定。
  • 缺少边界约束:原问题要求权重0 < w < 1,但未添加该约束,优化中可能出现负数或超过1的值,导致计算异常。
  • 约束定义错误:一维输入数组直接用np.sum(w, axis=0)会报错,需先重塑为矩阵再计算列和。

修正后的代码

import numpy as np
from scipy.optimize import minimize

# 固定收益矩阵
returns = np.array([[1.25, 2.5], [0.64, 0.5], [1.5, 1.6]]).T

# 目标函数(最大化原目标,返回负值供minimize最小化)
def funct(weights_flat):
    weights = weights_flat.reshape((3, 2))
    diag_elements = np.diag(weights @ returns)
    obj_value = np.product(diag_elements) - 1
    return -obj_value

# 约束:每列元素和为1
def column_sum_constraint(w):
    weights = w.reshape((3, 2))
    return np.sum(weights, axis=0) - np.ones(2)

# 变量边界:每个权重在(0,1)之间,用微小偏移避免0/1导致梯度问题
bounds = [(1e-6, 1-1e-6)] * 6

# 合理初始猜测:每列均匀分布,满足列和为1的近似条件
initial_guess = np.tile(np.array([1/3, 1/3, 1/3]), 2)

# 执行优化
constraints = {'type': 'eq', 'fun': column_sum_constraint}
result = minimize(funct, initial_guess, method='SLSQP', constraints=constraints, bounds=bounds)

# 输出结果
if result.success:
    optimized_weights = result.x.reshape((3, 2))
    print("优化后的权重矩阵:")
    print(optimized_weights)
    final_obj = -result.fun
    print(f"最终目标函数值:{final_obj:.4f}")
else:
    print("优化失败,原因:", result.message)

关键修正说明

  • 初始猜测:改为每列元素均匀分布,让优化器从接近约束的状态开始迭代,提升收敛性。
  • 边界约束:添加bounds限制权重范围,避免非法值导致计算NaN。
  • 约束函数修复:先重塑数组为矩阵,再计算列和,确保约束逻辑正确。
  • 数值稳定性:用1e-6替代0和1,防止梯度计算出现奇异值。

替代方案推荐

  • trust-constr方法:Scipy中更适合约束优化的方法,对非线性约束和边界的支持更稳健。
  • Pyomo/CVXPY:专业优化建模语言,适合构建复杂优化模型,代码可读性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:28:15