TMu*_*r83 6 optimization machine-learning scipy neural-network keras
我正在尝试使用Keras来建立一个神经网络,该网络应该近似一个未知函数F(x)
。F(x)
然后应使用所得的神经网络近似值来求和的最小值G(x) + F(x)
,其中G(x)
有一些任意函数。我当前面临的问题是,神经网络逼近F(x)
不够平滑,因此局部优化器陷入了微小的局部极小值中。对于能改善结果或解决此问题的任何想法,我将深表感谢。
让我说明上非常简单的例子问题:我会尽量教神经网络的功能F(x) = 4*var(x)
与x = [x1,...,xN]
和0 <= xi <= 1
,这里var(x)
是指矢量的变化x
。随后,我将尝试查找F(x)
约束条件下x
具有给定均值的神经网络表示的最小值。此示例的完整代码可以在sec中找到。3以下。
首先,我为以下近似创建一个神经网络F(x)
:
N = 6 # Dimension of input vector x
# Set up the neural network
model = Sequential()
model.add(Dense(50, activation='sigmoid', input_dim=N))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='mse')
Run Code Online (Sandbox Code Playgroud)
随后,我生成训练数据并训练模型:
# Generate training data
n_train = 100000 # Number of training samples
X_train = random((n_train, N))
y_train = 4*X_train.var(axis=1)
# Train the model
model.fit(X_train, y_train, epochs=100, batch_size=32, validation_split=0.2)
Run Code Online (Sandbox Code Playgroud)
训练完成后,我测试模型的准确性。为此,我使用了test(100)
(关于test
函数的定义,请参见下面第3节中的完整代码),对于我的特定模型,我得到的平均误差0.00517
似乎是一个很好的结果。
F(x)
对于神经网络,F(x)
我想在x
具有给定平均值的约束下找到其最小值。为了达到这个目的,我将尝试当地的优化minimize
以及全球优化differential_evolution
的scipy.optimize
。
我试图F(x)
在约束下尽量减少mean(x) = 0.5
。显然F_min = 0
,对于均匀分布,将获得精确的结果,即在给定约束下的最小方差x = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
。我故意选择一个错误的起始向量x0
,以检查优化器是否可以找到其最小的方法:
# Constraint
avg = 0.5 # Given average value of x
cons = {'type': 'eq', 'fun': lambda x: x.mean()-avg}
# Start vector
x0 = avg * np.array([2, 2, 2, 0, 0, 0])
# Minimization of neural-network representation
res_ML = minimize(lambda x: model.predict([[x]]), x0,
bounds=N*[(0, 1)], constraints=cons)
# Minimization of the exact function
res_ex = minimize(lambda x: 4*x.var(), x0,
bounds=N*[(0, 1)], constraints=cons)
Run Code Online (Sandbox Code Playgroud)
我的模型的结果如下:
>>> res_ML.success
True
>>> res_ML.x
array([1., 1., 1., 0., 0., 0.])
>>> res_ex.x
array([0.5, 0.5, 0.5, 0.5, 0.5, 0.5])
Run Code Online (Sandbox Code Playgroud)
使用的神经网络表示形式F(x)
,优化器立即陷入困境。使用确切的功能F(x) = 4*var(x)
,优化器可以找到正确的结果。
我正在考虑尝试使用全局优化器,而不是本地优化器。首先,我尝试使用shgo
from,scipy.optimize
因为它支持约束,但是,F(x)
即使使用了确切的函数,它似乎也找不到最小值(有关此问题的更多详细信息,请参见此处)。因此我尝试了differential_evolution
。由于differential_evolution
不支持约束,因此我mean(x) = 0.5
使用惩罚函数来强制执行条件:
# Minimization of neural-network representation
res2_ML = differential_evolution(lambda x: model.predict([[x]]) +
1e3*(np.mean(x)-avg)**2, bounds=N*[(0, 1)])
# Minimization of the exact function
res2_ex = differential_evolution(lambda x: 4*x.var() + 1e3*(np.mean(x)-avg)**2,
bounds=N*[(0, 1)])
Run Code Online (Sandbox Code Playgroud)
我得到的结果如下:
>>> res2_ML.success
True
>>> res2_ML.x
array([0.50276561, 0.49869386, 0.49310187, 0.49895304, 0.4987404 ,
0.50770651])
>>> res2_ex.x
array([0.5, 0.5, 0.5, 0.5, 0.5, 0.5])
>>> [float(model.predict([[x]])) for x in (res2_ML.x, res2_ex.x)]
[0.05173008516430855, 0.05170735716819763]
Run Code Online (Sandbox Code Playgroud)
通过使用神经网络逼近获得的结果F(x)
已经比局部优化情况下更好,但是仍然不是最优的。问题不在于该模型实际上预测了res2_ML.x
从最后一行可以看到的最小点,因为针对正确矢量的模型预测res2_ex.x
实际上更低。我也曾尝试tol=1e-12
在呼叫中使用differential_evolution
,以提高结果的准确性,但没有任何明显的改善。
import numpy as np
from numpy.random import random
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
from scipy.optimize import minimize, differential_evolution
# Parameters
N = 6 # Lenght of input vectors
n_train = 100000 # Number of training samples
# Generate training data
X_train = random((n_train, N))
y_train = 4*X_train.var(axis=1)
# Set up and train the neural network
model = Sequential()
model.add(Dense(50, activation='sigmoid', input_dim=N))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='mse')
model.fit(X_train, y_train, epochs=100, batch_size=32, validation_split=0.2)
# ############################ Local Optimization #############################
# Constraint
avg = 0.5 # Given average value of x
cons = {'type': 'eq', 'fun': lambda x: x.mean()-avg}
# Start vector
x0 = avg * np.array([2, 2, 2, 0, 0, 0])
# Minimization of neural-network representation
res_ML = minimize(lambda x: model.predict([[x]]), x0,
bounds=N*[(0, 1)], constraints=cons)
# Minimization of the exact function
res_ex = minimize(lambda x: 4*x.var(), x0,
bounds=N*[(0, 1)], constraints=cons)
# ########################### Global Optimization #############################
# Minimization of neural-network representation using differential_evolution
res2_ML = differential_evolution(lambda x: model.predict([[x]]) +
1e3*(np.mean(x)-avg)**2, bounds=N*[(0, 1)],
tol=1e-6)
# Minimization of neural-network representation using shgo
res3_ML = shgo(lambda x: model.predict([[x]]), bounds=N*[(0, 1)],
constraints=cons, sampling_method='sobol')
# Minimization of the exact function
res2_ex = differential_evolution(lambda x: 4*x.var() + 1e3*(np.mean(x)-avg)**2,
bounds=N*[(0, 1)])
# ############################# Helper Function ###############################
def test(n_test):
'''
Function for testing the model.
'''
x = random((n_test, N)) # Test data
pred = model.predict([x]) # Model prediction
exct = 4*x.var(axis=1) # Exact values
diff = np.abs(pred.flatten()-exct) # Difference
# Print the test results to screen
print('\npred. | exact | diff.')
print('---------------------------')
for k in range(n_test):
print('%.5f | %.5f | %.5f' % (pred[k], exct[k], diff[k]))
print('---------------------------')
print(' avg. error | %.5f' % diff.mean())
Run Code Online (Sandbox Code Playgroud)
我tol
为该differential_evolution
方法的参数弄错了。非常感谢罗密欧·瓦伦丁指出这一点。我已在几秒钟内纠正了此错误。3。tol
正确使用参数肯定可以改善的结果differential_evolution
。
此外,在github上发布了有关优化器的问题后shgo
,事实证明shgo
,如果使用sobol
采样方法,则优化器运行良好:
# Minimization of neural-network representation using shgo
res3_ML = shgo(lambda x: model.predict([[x]]), bounds=N*[(0, 1)],
constraints=cons, sampling_method='sobol')
Run Code Online (Sandbox Code Playgroud)
使用这种采样方法,结果是完美的:
>>> res3_ML.success
True
>>> res3_ML.x
array([0.5, 0.5, 0.5, 0.5, 0.5, 0.5])
Run Code Online (Sandbox Code Playgroud)
我将最小化使用添加shgo
到了完整的代码中。3。
我认为这个问题已经基本解决。但是,我仍然想知道,我的神经网络是否真的适合此类任务,或者是否存在更高级的结构或激活函数,从而可以得出更平滑的函数近似值。
归档时间: |
|
查看次数: |
163 次 |
最近记录: |