使用Scipy的Keras BFGS训练最小化

时间:2016-07-19 06:09:26

标签: python scipy neural-network keras

我想使用BFGS训练在Keras中实现的前馈神经网络。为了查看是否可以完成,我使用scipy.optimize.minimize实现了一个Perceptron,代码如下。

from __future__ import print_function
import numpy as np
from scipy.optimize import minimize
from keras.models import Sequential
from keras.layers.core import Dense

# Dummy training examples
X = np.array([[-1,2,-3,-1],[3,2,-1,-4]]).astype('float')
Y = np.array([[2],[-1]]).astype('float')

model = Sequential()
model.add(Dense(1, activation='sigmoid', input_dim=4))

def loss(W):
    weightsList = [np.zeros((4,1)), np.zeros(1)]
    for i in range(4):
        weightsList[0][i,0] = W[i]
    weightsList[1][0] = W[4]
    model.set_weights(weightsList)
    preds = model.predict(X)
    mse = np.sum(np.square(np.subtract(preds,Y)))/len(X[:,0])
    return mse

# Dummy first guess
V = [1.0, 2.0, 3.0, 4.0, 1.0]
res = minimize(loss, x0=V, method = 'BFGS', options={'disp':True})
print(res.x)

但是,输出结果表明损失函数没有优化:

Using Theano backend.
Using gpu device 0: GeForce GTX 960M (CNMeM is disabled, cuDNN not available)
Optimization terminated successfully.
         Current function value: 2.499770
         Iterations: 0
         Function evaluations: 7
         Gradient evaluations: 1
[ 1.  2.  3.  4.  1.]

为什么这不起作用的任何想法?是因为我没有将渐变输入到minimize,在这种情况下无法计算数值近似值吗?

4 个答案:

答案 0 :(得分:11)

  

是因为我没有输入渐变来最小化,在这种情况下它无法计算数值近似值?

因为你没有输出渐变,所以scipy通过数值微分逼近它们。也就是说它评估X处的函数,然后是X + epsilon,以近似局部梯度。

但是epsilon足够小,以至于在theano转换为32位时,变化完全丧失了。起始猜测实际上并不是最小的,scipy只是这么认为,因为它看不到目标函数中的值没有变化。你只需要增加epsilon:

V = [1.0, 2.0, 3.0, 4.0, 1.0]
print('Starting loss = {}'.format(loss(V)))
# set the eps option to increase the epsilon used in numerical diff
res = minimize(loss, x0=V, method = 'BFGS', options={'eps':1e-6,'disp':True})
print('Ending loss = {}'.format(loss(res.x)))

给出了:

Using Theano backend.
Starting loss = 2.49976992001
Optimization terminated successfully.
         Current function value: 1.002703
         Iterations: 19
         Function evaluations: 511
         Gradient evaluations: 73
Ending loss = 1.00270344184

答案 1 :(得分:0)

输出表明您的起始值是最小值。我不确定keras是/是什么,但如果我是你,我会首先绘制你想要在每个维度上最小化的函数。我的猜测是这样做会让问题变得明显。

答案 2 :(得分:0)

您想使用keras后端函数来计算所需的渐变。

答案 3 :(得分:0)

要将Scipy优化器与keras一起使用,您需要实现一个循环,以便在每次迭代中,使用Keras根据损失函数计算梯度,然后使用该优化器更新神经网络权重。我写了一个https://github.com/pedro-r-marques/keras-opt的小型图书馆。

它的工作方式是覆盖Keras,Keras用于在给定梯度的情况下计算权重更新的图形。而不是通过后端图执行权重更新,而是在每个小批量的末尾累积梯度。在训练阶段结束时,权重将提供给优化器,优化器会提出新的全局权重更新。