鲁棒线性回归问题,使用MindOpt也可优化

简介: 本篇我们讲述的是Linear Regression线性回归中的鲁棒线性回归。鲁棒回归又称为稳健回归,是统计学稳健估计的方法之一,主要思路是对离群点十分敏感的最小二乘回归中的的函数进行修改。

回归分析是一种预测技术,目的是建立 自变量x(向量)和 相关变量y(标量)之间的关系。目前有七种常见的回归分析:Linear Regression线性回归(本篇)、Logistic Regression逻辑回归、Polynomial Regression多项式回归、Stepwise Regression逐步回归、Ridge Regression岭回归、Lasso Regression套索回归、ElasticNet回归。


本篇我们讲述的是Linear Regression线性回归中的鲁棒线性回归。鲁棒回归又称为稳健回归,是统计学稳健估计的方法之一,主要思路是对离群点十分敏感的最小二乘回归中的的函数进行修改。


下文我们将讲述一个例子,来展示MindOpt优化鲁棒线性回归问题(含源代码)。

问题描述


学生的行为习惯和测试成绩之间的关系。线性回归使用线性函数 image.png 来描述这种关系(更准确地说法是仿射函数)。向量 image.png 表示“梯度”,标量 image.png 表示“截距”。通过 image.png 次观测 image.png ,我们可以估计出 image.pngimage.png的值。


普通的最小二乘回归(least-squares regression)对“离群观测”很敏感。仅一个离群观测就会影响对 image.png
image.png的估计。而鲁棒回归则不受少数离群观测的影响。


假设“离群观测”的数量相对 image.png而言很少,其他正常观测又很准确。则我们应该使用鲁棒线性回归去恢复真实的 image.pngimage.png


image.png


相比最小二乘回归,鲁棒回归可以更好地抵御(但不也能完全消除)离群观测的影响。


通过变换和引入变量 image.png ,我们可以把这个问题转化为线性规划:


image.png


为了编程方便,我们将变量放在不等式一侧,非变量参数放在另一侧:


image.png


等价的矩阵形式


x1, ..., xm 作为行放入矩阵 X,将 y_1, ..., y_m 作为元素放在列向量 y 中。令 1 为元素为1的向量。原始鲁棒线性回归问题可以简写为image.png.


通过变换,我们可以把这个问题转化为线性规划:


image.png


产生数据


我们通过生成随机数据,验证鲁棒线性回归的有效性。现在随机产生真正的 image.png
image.png


image.png


再使用它们产生 image.png 次正确观测:


image.png


外加 image.png 次离群观测:


image.png


因为观测的次序对鲁棒线性回归没有任何影响,所以不失一般性,我们将离群观测放在最后。


我们在下面的代码里面会实现数据生成的过程。

使用MindOpt求解器的API


直接采用求解器的API,需要查阅API文档来理解API的意思,没有建模语言可读性高。请参阅https://solver.damo.alibaba.com/doc/html/API%20reference/API-python/index.html来查看PythonAPI的使用说明。


关于Python的例子,在文档的5.建模与优化求解章节有Python的示例。这里是个LP的问题,我们可以参考:https://solver.damo.alibaba.com/doc/html/model/lp/linear%20optimization-python.html


下面我们分两种方式描述在本平台环境中的运行方法:

方法1:cell中直接输入代码运行

请运行下面cell中的代码,点击本窗口上面的播放△运行,或者摁shift+enter键运行:

# LP_5_RobustRegression.py
from mindoptpy import *
import numpy as np
import random
def simulateData(dimension=4,m_observations=15,is_write_data = False,output_dir = ""):
    # use time to seed the random number generator
    random.seed(time.time())
    # randomly generate vector a and scalar b
    d = dimension 
    true_a = np.random.randn(d) * np.sqrt([d])
    true_b = np.random.randn(1)[0]
    # randomly generate observations (x[i],y[i]), i = 1,...,m with 10% outliers
    m = m_observations
    X = np.zeros((m,d))
    y = np.zeros((m,1))
    for i in range(m):
        X[i,] = np.random.randn(d)
        if i < np.floor(0.9*m):
            y[i] = np.inner(true_a,X[i,]) + true_b
        else:
            y[i] = np.random.randn(1)
    #print("true_a:\n",true_a)
    #print("true_b:\n",true_b)
    #print("X:\n",X)
    #print("y:\n",y)
    if is_write_data:      
        f_true_a = open(output_dir+"true_a.txt", "w")  
        L = ["{}\n".format(true_a[i]) for i in range(len(true_a))]
        f_true_a.writelines(L)
        f_true_b = open(output_dir+"true_b.txt", "w")  
        L = ["{}\n".format(true_b)]
        f_true_b.writelines(L)
        f_X = open(output_dir+"X.txt", "w")  
        L = ["{}\n".format(X[i]) for i in range(len(X))]
        f_X.writelines(L)
        f_y = open(output_dir+"y.txt", "w")  
        L = ["{}\n".format(y[i]) for i in range(len(y))]
        f_y.writelines(L)
    return true_a,true_b,X,y
if __name__ == "__main__":
    # --- Create simulation data ---------------
    d = 4
    m = 15
    true_a,true_b,X,y = simulateData(d,m)
    #--- MindOpt Step 1. Initialize an empty optimization model ---    
    model = MdoModel()
    try:
        #--- MindOpt Step 2. Set model inputs ---
        # Change to minimization problem.
        model.set_int_attr("MinSense", 1)
        # add variables, specify their low bounds, upper bounds, and cost coefficients
        # set objective: minimize_{a,b,c} 0'a + 0b + 1'c
        INF = MdoModel.get_infinity()
        var_a = []
        for j in range(d):
            var_a.append(model.add_var(-INF, INF, 0.0)) # low bnd, upr bnd, 0 cost coeff
        var_b = model.add_var(-INF, INF, 0) # low bnd, upr bnd, 0 cost coeff
        var_c = []
        for i in range(m):
            var_c.append(model.add_var(-INF, INF, 1.0)) # low bnd, upr bnd, cost coeff = 1.0
        # Add constraints row by row
        for i in range(m):
            # compute a'x[i,]
            expr = MdoExprLinear()
            for j in range(d):
                expr += X[i,j]*var_a[j]
            # add: y[i] <= a'x[i,] + b + c[i]
            model.add_cons(y[i], INF, expr + var_b + var_c[i])
            # add: a'x[i,] + b - c[i] <= y[i]
            model.add_cons(-INF, y[i], expr + var_b - var_c[i])
        #--- MindOpt Step 3. Set solver parameters ---
        model.set_int_param("Method", 2)  # as an example, set to run the interior-point method
        model.set_int_param("NumThreads", 2)  # as an example, set to run 2 threads
        # ------Step3. Solve the problem and populate the result.-------
        model.solve_prob()
        model.display_results()
        time.sleep(0.01) #for print
        status_code, status_msg = model.get_status()
        if status_msg == "OPTIMAL":
            print("----\n")
            print("The solver terminated with an OPTIMAL status (code {0}).".format(status_code))
            print("目标函数总收益是: {0}".format(model.get_real_attr("PrimalObjVal")))
            print("\n----------------\nCompare var_a to true_a, and var_b to true_b:\n----------------")
            # Compare var_a to true_a, and var_b to true_b; Display residuals
            # Display solutions a[0],...,a[d-1]
            print('\n{0:<5} {1:>9} {2:>9}'.format('Entry','True','Soln'))
            for j in range(d):
                print('{0:>5} {1:>9f} {2:>9f}'.format('a['+'%s'%j+']', true_a[j],
                var_a[j].get_real_attr('PrimalSoln')))
            # Display solution b
            print('\n{0:<5} {1:>9} {2:>9}'.format(' ','True','Soln'))
            print('{0:>5} {1:>9f} {2:>9f}'.format('b', true_b, var_b.get_real_attr('PrimalSoln')))
            print("\n----------------\nShow Residual(c value):\n----------------")
            # Display solutions c[0],...,c[m]
            print('\n{0:>11} {1:>9}'.format('Observation','Residual'))
            for i in range(m):
                print('{0:>11d} {1:>9f}'.format(i, var_c[i].get_real_attr('PrimalSoln')))
        else:
            print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))
    except MdoError as e:
        print("Received Mindopt exception.")
        print(" - Code : {}".format(e.code))
        print(" - Reason : {}".format(e.message))
    except Exception as e:
        print("Received exception.")
        print(" - Reason : {}".format(e))
    finally:
        # MindOpt Step 5. Free the model.
        model.free_mdl()

运行后得到如下结果:

Start license validation (current time : 01-MAR-2023 20:59:47).
License validation terminated. Time : 0.002s
Model summary.
 - Num. variables     : 20
 - Num. constraints   : 30
 - Num. nonzeros      : 180
 - Bound range        : [5.6e-01,9.6e+00]
 - Objective range    : [1.0e+00,1.0e+00]
 - Matrix range       : [3.5e-02,2.3e+00]
Presolver started.
Presolver terminated. Time : 0.000s
Interior point method started.
 Iter         PrimObj         DualObj PrimFea DualFea  GapFea      Mu   Time
    0 +0.00000000e+00 -3.05311332e-15 2.2e+00 3.7e-02 3.6e+02 1.2e+01   0.01s
    1 +3.87012911e+01 +1.10363647e+01 7.4e-02 1.0e-04 2.5e+00 1.2e+00   0.01s
    2 +2.30985411e+01 +1.91163774e+01 2.0e-04 5.5e-06 2.1e-01 1.3e-01   0.01s
    3 +1.98974978e+01 +1.98777823e+01 5.6e-07 1.5e-08 1.0e-03 6.6e-04   0.01s
    4 +1.98802551e+01 +1.98802008e+01 1.5e-09 4.2e-11 2.7e-06 1.8e-06   0.01s
    5 +1.98802076e+01 +1.98802075e+01 4.3e-12 1.2e-13 7.5e-09 5.0e-09   0.02s
Terminated.
 - Method             : Interior point method.
 - Primal objective   : 1.9880207641660E+01
 - Dual objective     : 1.9880207492544E+01
 - Num. threads       : 2
 - Num. iterations    : 5
 - Solver details     : Solver terminated with a primal/dual optimal status.
    Iteration       Objective       Dual Inf.     Primal Inf.     Time
            0     1.98802e+01      0.0000e+00      0.0000e+00     0.02s    pushes: P(0) D(8)
            8     1.98802e+01      0.0000e+00      0.0000e+00     0.02s    
Interior point method terminated. Time : 0.027s
Optimizer summary.
 - Optimizer used     : Interior point method
 - Optimizer status   : OPTIMAL
 - Total time         : 0.028s
Solution summary.       Primal solution
 - Objective          : 1.9880207511e+01 
----
The solver terminated with an OPTIMAL status (code 1).
目标函数总收益是: 19.880207510885242
----------------
Compare var_a to true_a, and var_b to true_b:
----------------
Entry      True      Soln
 a[0]  3.381614  3.381614
 a[1]  2.077166  2.077166
 a[2]  1.788548  1.788548
 a[3]  1.662762  1.662762
           True      Soln
    b -2.102494 -2.102494
----------------
Show Residual(c value):
----------------
Observation  Residual
          0  0.000000
          1  0.000000
          2  0.000000
          3  0.000000
          4  0.000000
          5  0.000000
          6  0.000000
          7  0.000000
          8  0.000000
          9  0.000000
         10  0.000000
         11  0.000000
         12  0.000000
         13 11.513372
         14  8.366835
OpenBLAS WARNING - could not determine the L2 cache size on this system, assuming 256k

方法2:命令行直接运行.py文件


上面是直接在cell中运行所有的脚本,我们也可以建立个新文档,将Python代码存在src/python_src文件夹的LP_5_RobustRegression.py文件。然后在Launcher中打开Terminal,执行python xx.py文件来运行。


您也可以下载本.py文件,在自己的电脑上安装MindOpt求解器,然后在自己电脑的环境运行。


Luancher可以点击左上角的+打方块打开,Terminal在最下方,如截图示意。打开的窗口可以拖动调整位置。

image.png


然后在Terminal命令行里运行如下指令:


cd src/python_src
python LP_5_RobustRegression.py


运行得到的结果,特性类似算法1,由于每次数据随机生成的,所以数据不一样:

image.png

求解结果


本案例的数据是随机生成的,因此每次结果会不一样,但是从结果的True原值和鲁棒线性回归的结果Soln几乎一样,拟合度很好。


如下面是一个示例的结果打印。


Optimizer summary.
 - Optimizer used     : Interior point method
 - Optimizer status   : OPTIMAL
 - Total time         : 0.013s
Solution summary.       Primal solution
 - Objective          : 9.7151651023e+00 
----
The solver terminated with an OPTIMAL status (code 1).
目标函数总收益是: 9.715165102347509
----------------
Compare var_a to true_a, and var_b to true_b:
----------------
Entry      True      Soln
 a[0]  2.710648  2.710648
 a[1]  0.477721  0.477721
 a[2]  1.164849  1.164849
 a[3]  0.251547  0.251547
           True      Soln
    b  0.878660  0.878660
----------------
Show Residual(c value):
----------------
Observation  Residual
          0  0.000000
          1  0.000000
          2  0.000000
          3  0.000000
          4  0.000000
          5  0.000000
          6  0.000000
          7  0.000000
          8  0.000000
          9  0.000000
         10  0.000000
         11  0.000000
         12  0.000000
         13  6.173857
         14  3.541308

联系我们

钉钉答疑群:32451444
钉钉活动群:18890022111
邮箱地址:solver.damo@list.alibaba-inc.com
更多更新通知:https://solver.damo.alibaba.com


相关文章
|
4月前
|
达摩院 开发者 容器
「达摩院MindOpt」优化形状切割问题(MILP)
在制造业,高效地利用材料不仅是节约成本的重要环节,也是可持续发展的关键因素。无论是在金属加工、家具制造还是纺织品生产中,原材料的有效利用都直接影响了整体效率和环境影响。
「达摩院MindOpt」优化形状切割问题(MILP)
|
4月前
|
人工智能 自然语言处理 达摩院
MindOpt 云上建模求解平台:多求解器协同优化
数学规划是一种数学优化方法,主要是寻找变量的取值在特定的约束情况下,使我们的决策目标得到一个最大或者最小值的决策。
|
2月前
|
人工智能 算法 调度
优化问题之如何选择合适的优化求解器
优化问题之如何选择合适的优化求解器
|
2月前
|
调度 决策智能
优化问题之优化求解器有哪些主要的评估特性
优化问题之优化求解器有哪些主要的评估特性
|
4月前
|
存储 达摩院 调度
「达摩院MindOpt」优化FlowShop流水线作业排班问题
在企业在面临大量多样化的生产任务时,如何合理地安排流水线作业以提高生产效率及确保交货期成为了一个重要的问题。
「达摩院MindOpt」优化FlowShop流水线作业排班问题
|
达摩院 调度
使用达摩院MindOpt优化交通调度_最大化通行量—线性规划问题
在数学规划中,网络流问题是指一类基于网络模型的流量分配问题。网络流问题的目标是在网络中分配资源,使得网络的流量满足一定的限制条件,并且使得某些目标函数最小或最大化。网络流问题通常涉及一个有向图,图中每个节点表示一个资源,每条边表示资源之间的关系。边上有一个容量值,表示该边上最多可以流动的资源数量。流量从源节点开始流出,经过一系列中间节点,最终到达汇节点。在这个过程中,需要遵守一定的流量守恒和容量限制条件。
|
10月前
|
API Python
MindOpt V1.0优化种植计划问题,新的建模方法
种植计划是指农业生产中针对不同农作物的种植时间、面积和种植方式等方面的规划安排。根据具体情况进行合理的规划和安排,以实现农作物的高产、优质和可持续发展。
MindOpt V1.0优化种植计划问题,新的建模方法
|
4月前
|
达摩院 自然语言处理 Java
MindOpt APL:一款适合优化问题数学建模的编程语言
本文将以阿里达摩院研发的MindOpt建模语言(MindOpt Algebra Programming Language, MindOptAPL,简称为MAPL)来讲解。MAPL是一种高效且通用的代数建模语言,当前主要用于数学规划问题的建模,并支持调用多种求解器求解。
|
达摩院 供应链 JavaScript
网络流:优化仓储物流调度问题-达摩院MindOpt
仓储物流调度是指在物流供应链中,对仓储和运输(运输路线、成本)进行协调和安排的过程。主要包含物流计划、运输调度、运发管理、库存管理等重要环节。随着网络、电商行业的迅速发展,仓储物流调度对于企业来说也非常重要,优秀的调度方案可以帮助降低库存成本、物流配送的效率、成本等等等,从而给企业带来降本增效。
网络流:优化仓储物流调度问题-达摩院MindOpt
MindOpt优化如何分散化风险并实现收益与风险最优配比问题
资产配置,投资组合是指通过分散投资资金的方式来规避投资过程中的风险。在实际的投资过程中,如何决定投资哪些产品来实现收益最大化和风险最小化是一个关键的问题。
MindOpt优化如何分散化风险并实现收益与风险最优配比问题