Scipy Optimize возвращает только x0, только одну итерацию - PullRequest
0 голосов
/ 10 октября 2018

Я использую scipy optimize, чтобы получить минимальное значение для следующей функции:

def randomForest_b(a,b,c,d,e):
 return abs(rf_diff.predict([[a,b,c,d,e]]))

В конце концов я хочу иметь возможность получить оптимальные значения (a) и (b) с учетом аргументов (в, г, д).Тем не менее, просто чтобы узнать, как работает функция оптимизации, я пытаюсь получить оптимальное значение (а) с учетом других аргументов.У меня есть следующий код:

res=optimize.minimize(randomForest_b, x0=45,args=(119.908500,65.517527,2.766103,29.509200), bounds=((45,65),))
print(res) 

И я даже пытался:

optimize.fmin_slsqp(randomForest_b, x0=45,args=(119.908500,65.517527,2.766103,29.509200), bounds=((45,65),))

Однако оба они просто возвращают значение x0.

Optimization terminated successfully.    (Exit mode 0)
        Current function value: 1.5458542752157667
        Iterations: 1
        Function evaluations: 3
        Gradient evaluations: 1
array([ 45.])

Текущее значение функции является правильным, однако между всеми числами в пределах, x0 не возвращает минимальное значение функции.У меня установлены границы, потому что переменная a может быть числом от 45 до 65. Я что-то упускаю или делаю что-то не так?И, если возможно, как я могу получить оптимальные значения a и b?

Вот пример полного кода, который я использую: из массива импорта импортировать scipy.optimize как оптимизировать из scipy.optimize минимизировать импорт

a=np.random.uniform(low=4.11, high=6.00, size=(50,))
b=np.random.uniform(low=50.11, high=55.99, size=(50,))
c=np.random.uniform(low=110.11, high=120.99, size=(50,))
d=np.random.uniform(low=50.11, high=60.00, size=(50,))
pv=np.random.uniform(low=50.11, high=60.00, size=(50,))

df=pd.DataFrame(a, columns=['a'])
df['b']=b
df['c']=c
df['d']=d
df['pv']=pv
df['difference']=df['pv']-df['d']

from sklearn.model_selection import train_test_split 
y=df.loc[:, 'difference']
x=df.iloc[:, [0,1,2,3]]
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)

from sklearn.ensemble import RandomForestRegressor
rf_difference = RandomForestRegressor(n_estimators = 1000, oob_score=True, 
random_state = 0)
rf_difference.fit(x_train, y_train) 

def randomForest_b(a,b,c,d):
    return abs(rf_difference.predict([[a,b,c,d]]))

res=optimize.minimize(randomForest_b, 
x0=0,args=(51.714088,110.253656,54.582179), bounds=((0,6),))
print(res)

optimize.fmin_slsqp(randomForest_b, x0=0,args= 
(51.714088,110.253656,54.582179), 
bounds=((0,6),))

1 Ответ

0 голосов
/ 13 октября 2018

Функция, которую вы пытаетесь свести к минимуму, не является гладкой и имеет также несколько плато, это можно увидеть, изобразив randomForest_b как функцию a:

a = np.linspace(0,6,500)
args = 51.714088,110.253656,54.582179
vrandomForest_b = np.vectorize(randomForest_b,excluded=[1,2,3])
y_values = vrandomForest_b(a, *args)

fig, ax = plt.subplots(figsize=(8,6))
ax.plot(a, y_values, label='randomForest_b')
ax.axvline(0, label='Your start value', color='g', ls='--')
ax.set(xlabel='a', ylabel='randomForest_b');
ax.legend()

image

Для негладких функций, подобных вашей, методы оптимизации на основе градиента почти наверняка потерпят неудачу.В этом случае начальное значение 0 находится на плато с исчезающим градиентом, поэтому оптимизация заканчивается сразу после одной итерации.

Решением было бы использование методов оптимизации без градиента, например стохастической минимизации сscipy.optimize.differential_evolution.Предостережение этих методов заключается в том, что они обычно требуют больше оценок функций и могут занять больше времени для завершения.

Этот метод оптимизации может найти глобальный минимум в примере, приведенном в вашем вопросе:

rslt = optimize.differential_evolution(vrandomForest_b,
                                       args=(51.714088,110.253656,54.582179), 
                                       bounds=[(0,6)])
print(rslt)

fig, ax = plt.subplots()
ax.plot(a, y_values, label='randomForest_b')
ax.axvline(rslt.x, label='Minimum', color='red', ls='--')
ax.legend()
 fun: 0.054257768073620746 
 message: 'Optimization terminated successfully.'
 nfev: 152
 nit: 9  success: True
 x: array([5.84335956])

image

...