[英]Finding the optimal combination of inputs which return maximal output for a black box model
在我的工作中将 ANN 应用于回归任务时,我面临的挑战之一是,为了找到给定输入范围的最佳输出,我必须为我的模型提供一个多维网格,然后简单地选择最高的价值。 然而,这总体上是一个计算成本非常高的解决方案。 下面文字的长度可能很吓人,但这只是我试图更好地解释它。
让我用其他词来解释。 假设我的 ANN 有 9 个输入,然后我想检查哪些特征值组合可以返回最高结果。 我目前正在通过创建一个 9D 网格并简单地预测每个样本的值然后确定最佳行来克服这个问题。 然而,这需要大量的时间来工作。 因此,如果可能的话,我正在寻找一种能够更有效地达到这个最佳输出值的方法。
在代码中,它看起来像这样:(只是一个简单的虚构示例,在 python 中不太现实):
import numpy as np
from itertools import product
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
import tensorflow.keras
from keras.models import Sequential
from keras.layers import Dense
import pandas as pd
import math
x1 = np.linspace(0,20,6)
x2 = np.linspace(0,20,6)
X = pd.DataFrame((product(*[x1,x2])))
y1 = 5*np.cos(np.deg2rad(X[0]))
y2 = 5 - 1*np.exp((-X[0]**2/np.deg2rad(10)**2)*np.cos(np.deg2rad(X[1])))
y = np.array([y1 + y2]).T
设置黑盒模型,在本例中为神经网络
x_scaler = MinMaxScaler()
y_scaler = MinMaxScaler()
X_scaled = x_scaler.fit_transform(X)
y_scaled = y_scaler.fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_scaled, test_size=0.2, random_state=0)
model = Sequential()
model.add(Dense(100, input_dim = 2, activation = 'relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(1, activation = 'relu'))
model.compile(optimizer = 'Adam', loss = 'mean_squared_error')
epochs_hist = model.fit(X_train, y_train, epochs = 100, batch_size = 50, validation_split = 0.2)
现在我拟合了我的模型,我将在多个间隔内使用网格网格,以便在指定范围内找到最佳值:
x1_pred = np.linspace(0,20,21)
x2_pred = np.linspace(0,20,21)
X_pred = pd.DataFrame((product(*[x1_pred,x2_pred])))
X_pred_test = x_scaler.fit_transform(X_pred)
y_pred = model.predict(X_pred_test)
y_pred = y_scaler.inverse_transform(y_pred)
因此,假设我为达到最优值做了类似的事情,但在这种情况下有 9 个输入,那么很明显该计算在计算上是不可行的。 因此,我的问题是如何找到返回黑盒模型(如 ANN)最大输出的最佳输入组合。
这是一个如何从模型中获得“最佳结果”的示例。 重要的部分是optimize
、 _get_simplex
和_call_model
。 通过这样做,您可以减少模型所需的调用量。
from sklearn.ensemble import GradientBoostingRegressor
import numpy as np
from scipy.optimize import minimize
from copy import copy
class Example:
def __init__(self):
self.X = np.random.random((10000, 9))
self.y = self.get_y()
self.clf = GradientBoostingRegressor()
self.fit()
def get_y(self):
# sum of squares, is minimum at x = [0, 0, 0, 0, 0 ... ]
return np.array([[self._func(i)] for i in self.X])
def _func(self, i):
return sum(i * i)
def fit(self):
self.clf.fit(self.X, self.y)
def optimize(self):
x0 = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
initial_simplex = self._get_simplex(x0, 0.1)
result = minimize(fun=self._call_model,
x0=np.array(x0),
method='Nelder-Mead',
options={'xatol': 0.1,
'initial_simplex': np.array(initial_simplex)})
return result
def _get_simplex(self, x0, step):
simplex = []
for i in range(len(x0)):
point = copy(x0)
point[i] -= step
simplex.append(point)
point2 = copy(x0)
point2[-1] += step
simplex.append(point2)
return simplex
def _call_model(self, x):
prediction = self.clf.predict([x])
return prediction[0]
example = Example()
result = example.optimize()
print(result)
当然,如果你想最大化而不是最小化,你可以返回-prediction[0]
而不是prediction[0]
来欺骗 scipy。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.