Scipy中差分进化(DE)替代暴力寻优报错问题求助
brute Works but differential_evolution Throws an Error? Let's break down the issue and fix it step by step:
Root Cause
Your objective function fun returns a pandas Series instead of a scalar value, which differential_evolution can't handle.
Look at the line where you calculate p_hat:
p_hat = df_Res.sum() / len(df_Res.index)
df_Res.sum() returns a Series (since df_Res is a single-column DataFrame), so dividing by the length still leaves you with a Series. scipy.optimize.brute is lenient enough to implicitly use the underlying scalar value of the Series, but differential_evolution strictly requires a single numerical value to compute fitness for its iterative optimization process. This mismatch is why you get the ambiguous truth value error— the optimizer tries to evaluate the Series as a boolean, which pandas doesn't allow.
Fix 1: Return a Scalar Instead of a Series
Modify the return line in your fun function to extract the scalar value from the Series. Use .item() (the cleanest way for single-value Series) or .iloc[0]:
def fun(z, *params): A,B,C = z df_1, df_2 = params # Explicitly unpack params for clarity # Calculate score without modifying original df_2 (see Fix 2 below) df_2_copy = df_2.copy() df_2_copy['S'] = df_2_copy['X']*A + df_2_copy['Y']*B + df_2_copy['Z']*C # Top score logic df_Sort = df_2_copy.sort_values(['S', 'X', 'M'], ascending=[False, True, True]) df_O = df_Sort.set_index('O') M_Top = df_O[~df_O.index.duplicated(keep='first')].M M_Top = M_Top.sort_index() # Compare to df_1 df_1_R = df_1_M.reindex(M_Top.index) T_N_T = M_Top == df_1_R # Calculate p_hat and return scalar df_Res = pd.DataFrame({'it_is':T_N_T}) p_hat = df_Res.sum() / len(df_Res.index) return -p_hat.item() # Convert Series to scalar here
Fix 2: Avoid Modifying the Original df_2
Your original function modifies the input df_2 by adding an 'S' column. This can cause unexpected side effects in iterative optimizers like differential_evolution, which call the function hundreds of times. The fix above creates a copy of df_2 first to isolate calculations from the original data.
Test the Fixed Code
Now run differential_evolution again—it should work correctly:
from scipy.optimize import differential_evolution import pandas as pd # Re-initialize data and setup df_1_M df_1 = pd.DataFrame({'O' : [1,2,3], 'M' : [2,8,3]}) df_2 = pd.DataFrame({'O' : [1,1,1, 2,2,2, 3,3,3], 'M' : [9,2,4, 6,7,8, 5,3,4], 'X' : [2,4,6, 4,8,7, 3,1,9], 'Y' : [3,6,1, 4,6,5, 1,0,7], 'Z' : [2,4,8, 3,5,4, 7,5,1]}) df_1 = df_1.set_index('O') df_1_M = df_1.M.sort_index() # Bounds min_ = -2 max_ = 2 bounds = [(min_, max_)] * 3 params = (df_1, df_2) # Run differential evolution DE = differential_evolution(fun, bounds, args=params) print('Global maximum ', DE.x) print('Function value at global maximum ',-DE.fun)
You'll get results similar to the brute method, but with drastically faster execution for higher dimensions or finer resolutions.
内容的提问来源于stack exchange,提问作者R. Cox

