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

如何使用scipy.minimize仅优化自定义函数指定参数最小化返回值

问题解决方法

scipy.optimize.minimize本身就支持固定部分参数、只优化指定参数的场景,不需要修改你原有的优化器函数,核心是做一层参数适配封装,同时处理days为整型的特殊要求。

核心实现逻辑

  • 把所有不需要调整的固定入参提前打包,通过闭包方式绑定,不需要传入minimize
  • 把所有待优化的参数(weights列表的所有元素 + days)拼接成一维数组,作为minimize唯一接收的待优化变量
  • 由于scipy大部分内置优化器针对连续浮点值设计,对整型参数days,要么在目标函数内部做取整处理,要么直接选用支持混合整数优化的全局优化器

可直接复用的代码示例

首先修正你原函数里的明显笔误(形参名和调用名不一致、循环覆盖外层变量、未定义变量),再做优化适配:

import numpy as np
import pandas as pd
from scipy.optimize import minimize
from typing import List, Callable

# 修正笔误后的原目标计算函数
def optimizer(
    df_grouped,
    df: pd.DataFrame,
    weights: List[float],
    my_func: Callable,
    days: int,
    day_str: str, 
    df_all: pd.DataFrame
):
    all_scores = {}
    # 原代码未定义df_day,这里按常规时间切片逻辑补全,可根据你的实际业务调整
    df_day = df[df["date"] <= day_str].tail(days)
    for i, sub_df in enumerate(df_grouped):
        scores = my_func(df_day=df_day, df=sub_df, weights=weights)
        all_scores[i] = scores
   
    avg_vals = np.mean([df_all.loc[key]["val1"] for key in all_scores], axis=0)
    # 原代码未定义day_to_compare,这里按传入的目标日期补全
    truth_vals = df_all.loc[day_str]["val1"]
    score = np.mean(abs(avg_vals - truth_vals), axis=0)
    return score

# 封装适配minimize的目标函数,绑定固定参数
def build_target(fixed_params: dict):
    def calc_loss(x):
        # x为一维待优化数组:前N位对应weights元素,最后1位对应days
        weights = x[:-1]
        days = int(round(x[-1])) # 对连续优化结果做整数转换
        return optimizer(
            df_grouped=fixed_params["df_grouped"],
            df=fixed_params["df"],
            weights=weights,
            my_func=fixed_params["my_func"],
            days=days,
            day_str=fixed_params["day_str"],
            df_all=fixed_params["df_all"]
        )
    return calc_loss

if __name__ == "__main__":
    # 1. 填入所有固定参数的实际值
    fixed_params = {
        "df_grouped": your_actual_df_grouped,
        "df": your_actual_df,
        "my_func": your_actual_my_func,
        "day_str": your_target_day_str,
        "df_all": your_actual_df_all
    }
    # 2. 设置待优化参数初始值:[w1,w2,w3,w4, initial_days]
    x0 = [1, 10, 30, 40, 7]
    # 3. 设置参数边界(根据业务规则调整,示例为权重非负、days在1-30区间)
    bounds = [
        (0, None), (0, None), (0, None), (0, None),
        (1, 30)
    ]
    # 4. 初始化目标函数执行优化
    target_func = build_target(fixed_params)
    res = minimize(
        fun=target_func,
        x0=x0,
        bounds=bounds,
        method="L-BFGS-B"
    )
    # 解析最优结果
    best_weights = res.x[:-1]
    best_days = int(round(res.x[-1]))
    best_score = res.fun
    print(f"最优权重:{best_weights}\n最优天数:{best_days}\n最小score:{best_score}")

关键注意点

  • 参数边界可以根据实际业务调整,比如限制权重和为1、days不超过数据集最长时间跨度,避免优化出无意义的参数值
  • 如果days取值跨度大、对结果影响敏感,不建议用连续优化器加手动取整的方案,可以替换成scipy.optimize.differential_evolution,该方法支持通过integrality参数指定哪些维度是整数变量,不需要手动取整,全局寻优能力也更强
  • 这类评分优化问题大多是非凸的,不要只跑一组初始值,建议多换几组初始权重和初始days尝试,避免陷入局部最优

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 17:43:13