【问题标题】:Quadratic Programming in python using data from octave使用来自八度音程的数据在 python 中进行二次规划
【发布时间】:2019-08-05 14:16:14
【问题描述】:

我正在将部分 MATLAB 程序转换为 Python 和 Octave。

我正在使用 Octave 生成​​两个矩阵,然后使用 oct2py 将这些矩阵导入 python。我的问题的根源是 MATLAB 中的这些行(H_combinedf_combined 下面)

handles.options =optimset('algorithm','interior-point-convex','Display','off','TolFun',1e-15,'TolX',1e-10,'MaxFunEvals', 1E5);

handles.x_ridge_combined = quadprog(H_combined, f_combined, [], [], [], [], handles.lb_re, handles.ub_re, handles.x_re_0, handles.options);

目前,我正在寻找一种在 Python 或 Octave 中产生类似输出但无济于事的解决方案。

我尝试使用 Octave 的 optim 中的 quadprog,但是我在 x_ridge_combined 上得到了 120, 1, 1, 1, ..., 1 的输出,而不是我期望的各种浮点值。我已经验证H_combinedf_combined 与在MATLAB 中运行时完全相同,但我认为在Octave 中quadprog 的工作方式不一样。

在尝试了 Octave 方法后,我尝试将值导入 Python 以尝试使用 quadprog 包。

尝试quadprog

print(quadprog.solve_qp(H,f))

产生错误

ValueError: Buffer has wrong number of dimensions (expected 1, got 2)

Hf的类型和形状如下:

<class 'numpy.ndarray'> #H
(123, 123)
<class 'numpy.ndarray'> #f
(1, 123)

有人知道我为什么会收到这些错误吗?或者关于如何从 MATLAB 翻译该行的任何其他建议?

【问题讨论】:

  • 快速阅读,我认为您最好提供更多信息。您的 matlab 原始代码和您组合的 python/octave 替代之间的分歧点似乎是 quadprog。给定完全相同的输入,python/octave quadprog 都不会产生与 matlab 相同的输出。那是对的吗?你能发布你正在使用的输入吗?如果这些是大型数据集,您能否生成一个产生相同错误的较小示例?我知道这需要一些工作......
  • matlab中的quadprog行和octave中的一样吗?
  • 尝试使用 matlab 和 octave 中记录的示例来检查结果octave.sourceforge.io/optim/function/quadprog.html
  • 在不同的matlab-octave上检查这个线程,虽然我不确定你的情况lists.gnu.org/archive/html/help-octave/2015-09/msg00120.html
  • 或者查看这些其他例子来比较mathworks.com/help/optim/ug/quadprog.html

标签: python matlab octave cvxopt quadprog


【解决方案1】:

尝试使用cvxopt_quadprog。作者声称它模仿了 MATLAB quadprog,它应该以同样的方式接受参数:

def quadprog(H, f, L=None, k=None, Aeq=None, beq=None, lb=None, ub=None):
    """
    Input: Numpy arrays, the format follows MATLAB quadprog function: https://www.mathworks.com/help/optim/ug/quadprog.html
    Output: Numpy array of the solution
    """

这个错误很可能是因为你的f 是矩阵 [1x123],而它应该是长度为 [123] 的向量。你可以尝试重塑它:

f = f.reshape(f.shape[1])

【讨论】:

  • 我同意reshape 解决方案。应该适用于原始代码 =)
【解决方案2】:

是的,尽管 cvxopt_quadprog 的问题在于它对于时间序列的大型迭代优化来说要慢得多,因为它每次都会检查问题是否是 PSD,这就是我希望使用 quad_prog 的原因,这已被证明要快得多。参考:https://github.com/stephane-caron/qpsolvers

【讨论】:

    【解决方案3】:

    虽然有点超出范围,但我想将NLopt 项目投入使用。正如首字母缩写词所暗示的那样,它解决了非线性优化问题,但有很多 global/local, derivative-free/with explicit derivatives algorithms。我之所以要提到它,是因为它有一个用于 MATLAB、Octave + Python(和 C/C++,...)的接口。因此,用不同的语言重现解决方案变得非常容易(这就是我遇到它的原因);另外,这些算法实际上比 MATLAB 原生的更快(这是我自己的经验)。

    对于您的问题,我会选择BOBYQA(二次优化的有界优化或SLSQP(顺序最小二乘二次规划)。但是,您必须编写成本函数而不是交出矩阵

    The installation is easy via pip

    pip install nlopt
    

    检查一下

    import nlopt
    # run quick test. Look for "Passed: optimizer interface test"
    nlopt.test.test_nlopt()
    

    一些关于如何使用优化的快速代码:

    import numpy as np
    import nlopt
    
    obj = nlopt.opt(nlopt.LN_BOBYQA,5)
    obj.set_min_objective(fnc)
    
    obj.set_lower_bounds(lb)
    obj.set_upper_bounds(ub)
    
    def fnc(x, grad):
    
            """
            The return value should be the value of the function at the point x, 
            where x is a NumPy array of length n of the optimization parameters 
            (the same as the dimension passed to the constructor).
    
            In addition, if the argument grad is not empty, i.e. grad.size>0, then 
            grad is a NumPy array of length n which should (upon return) be set to 
            the gradient of the function with respect to the optimization parameters 
            at x. That is, grad[i] should upon return contain the partial derivative , 
            for , if grad is non-empty.
            """
            H = np.eye(len(x)) # extampe matrix
    
            cost = 0.5*x.transpose().dot( H.dot(x) )
            return float(cost) # make sure it is a number
    
    xopt = obj.optimize(x0)
    

    在 MATLAB 中,您只需将 DLL 添加到您的路径中。我为 BOBYQA 编写了一个简短的包装器来模仿 MATLAB 的界面(以防万一,您想用两种语言检查它=P - 让我知道,我在 MATLAB 中更经常使用它......因为包装器可能显示^^):

    function [x_opt, fval, exitflag] = BOBYQA(fnc,x0,lb,ub, varargin)
    % performes a constrained, derivative-free local optimization
    %
    % --- Syntax:
    % x_opt = BOBYQA(fnc,x0,lb,ub)
    % x_opt = BOBYQA(...,'MaxEval',10)
    % x_opt = BOBYQA(...,'MaxTime',5)
    % [x_opt, fval] = BOBYQA(...)
    % [x_opt, fval, exitflag] = BOBYQA(...)
    % 
    % --- Description:
    % x_opt = BOBYQA(fnc,x0,lb,ub)  takes a function handle 'func', an initial 
    %               value 'x0' and lower and upper boundary constraints 'lb' 
    %               and 'ub' as input. Performes a constrained local 
    %               optimization using the algorithm BOBYQA from Powell 
    %               http://www.damtp.cam.ac.uk/user/na/NA_papers/NA2009_06.pdf.
    %               Returns the optimal value 'x_opt'.
    % x_opt = BOBYQA(...,'MaxEval',10)optional input parameter that defines the
    %               maximum number of evaluations.
    % x_opt = BOBYQA(...,'MaxTime',5) optional input parameter that defines the
    %               maximum allowed time in seconds for the optimization. This 
    %               is a soft constraint and may be (slightly) broken.
    % [x_opt, fval] = BOBYQA(...) seconds return value is the optimal function 
    %               value.
    % [x_opt, fval, exitflag] = BOBYQA(...) third return value is the exitflag,
    %               see function NLoptExitFlag().
    % 
    % ------------------------------------------------------------------- 2017
    
    % NLOPT_LN_BOBYQA
    
    % --- parse input
    IN = inputParser;
    addParameter(IN,'MaxEval',10000, @(x)validateattributes(x,{'numeric'},{'positive'}));
    addParameter(IN,'MaxTime',60, @(x)validateattributes(x,{'numeric'},{'positive'}));
    parse(IN,varargin{:});
    
    % generic success code: +1
    %      stopval reached: +2
    %         ftol reached: +3
    %         xtol reached: +4
    %      maxeval reached: +5
    %      maxtime reached: +6
    % generic failure code: -1
    %    invalid arguments: -2
    %        out of memory: -3
    %     roundoff-limited: -4
    
        % set options
        opt = struct();
        opt.min_objective = fnc;
        opt.lower_bounds = lb;
        opt.upper_bounds = ub;
    
    
    
        % stopping criteria
        opt.maxtime = IN.Results.MaxTime; % s  % status = +6
    %     opt.fc_tol = FncOpt.STOP_FNC_TOL*ones(size(ParInit)); % +3
    %     opt.xtol_rel = FncOpt.STOP_XTOL_REL; % +4
    %     opt.xtol_abs = FncOpt.STOP_XTOL_ABS*ones(size(ParInit)); % +4
        opt.maxeval = IN.Results.MaxEval; % status = +5
    
        % call function
        opt.algorithm = 34;% eval('NLOPT_LN_BOBYQA');
    
        t_start = tic;
        [x_opt, fval, exitflag] = nlopt_optimize(opt,x0);
        dt = toc(t_start);
        fprintf('BOBYQA took %.5f seconds | exitflag: %d (%s)\n',dt,exitflag,NLoptExitFlag(exitflag))
    end
    
    function txt = NLoptExitFlag(exitflag)
    % generic success code: +1
    %      stopval reached: +2
    %         ftol reached: +3
    %         xtol reached: +4
    %      maxeval reached: +5
    %      maxtime reached: +6
    % generic failure code: -1
    %    invalid arguments: -2
    %        out of memory: -3
    %     roundoff-limited: -4
    
    switch exitflag
        case 1
            txt = 'generic success code';
        case 2
            txt = 'stopval reached';
        case 3
            txt = 'ftol reached';
        case 4
            txt = 'xtol reached';
        case 5
            txt = 'maxeval reached';
        case 6
            txt = 'maxtime reached';
        case -1
            txt = 'generic failure code';
        case -2
            txt = 'invalid arguments';
        case -3
            txt = 'out of memory';
        case -4
            txt = 'roundoff-limited';
        otherwise
            txt = 'undefined exitflag!';
    end
    end
    

    【讨论】:

      猜你喜欢
      • 2016-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多