在优化问题中使用神经网络

时间:2019-07-09 00:06:17

标签: machine-learning optimization keras scipy neural-network

我正在尝试使用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的神经网络表示的最小值。此示例的完整代码可以在秒内找到。 3

1。神经网络的创建和训练

首先,我为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')

随后,我生成训练数据并训练模型:

# 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)

训练结束后,我测试了模型的准确性。为此,我使用test(100)(有关test函数的定义,请参见下面的 sec。3 中的完整代码),对于我的特定模型,我得到的平均误差为0.00517似乎是一个不错的结果。

2。最小化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)

我的模型的结果如下:

>>> 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])

使用F(x)的神经网络表示形式,优化器立即陷入困境。使用确切的功能F(x) = 4*var(x),优化器可以找到正确的结果。

全局优化

我正在考虑尝试使用全局优化器,而不是本地优化器。首先,我尝试使用shgo中的scipy.optimize,因为它支持约束,但是,即使使用了确切的函数,它似乎也找不到最低的F(x)(有关此信息的更多详细信息可以找到问题here)。因此,我尝试了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)])

我得到的结果如下:

>>> 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]

通过使用F(x)的神经网络逼近获得的结果已经比局部优化的情况更好,但是仍然不是最优的。问题不在于从最后一行可以看出,该模型实际上预测了发生在点res2_ML.x处的最小值,因为对于正确向量res2_ex.x的模型预测实际上较低。我还尝试在tol=1e-12的调用中使用differential_evolution,以提高结果的准确性,但没有任何明显的改善。

3。完整的代码

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())

更新

我在tol方法的differential_evolution参数中犯了一个错误。非常感谢 Romeo Valentin 指出了这一点。我已在秒内更正了此错误。 3 。正确使用tol参数肯定会改善改善differential_evolution的结果。

此外,在关于github上的shgo优化器的issue之后,事实证明,如果使用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')

使用这种采样方法,结果是完美的:

>>> res3_ML.success
True

>>> res3_ML.x
array([0.5, 0.5, 0.5, 0.5, 0.5, 0.5])

我已在{strong> sec中将使用shgo的最小化添加到完整代码中。 3 。

我认为这个问题已基本解决。但是,我仍然想知道,我的神经网络是否真的是执行此类任务的正确选择,或者是否存在更高级的结构或激活函数,可以产生更平滑的函数近似值。

0 个答案:

没有答案