基本的拉格朗日乘子法就是求函数f(x1,x2,...)在g(x1,x2,...)=0的约束条件下的极值的方法。其主要思想是将约束条件函数与原函数联系到一起,使能配成与变量数量相等的等式方程,从而求出得到原函数极值的各个变量的解。原函数加约束函数构成的一组方程组,用以求解变量组。

拉格朗日乘子(Lagrange multiplier)

假设需要求极值的目标函数(objective function)为f(x,y),限制条件为φ(x,y)=M

求出x,y,λ的值,代入即可得到目标函数的极值

扩展为多个变量的式子为:F(x1,x2,...,xn,λ)=f(x1,x2)-λg(x1,x2,...,xn)

则求极值点的方程为:

∂F/∂xi=0(i∈[1,n])

∂F/∂λ=g(x1,x2,...,xn)=0

参考代码如下:对求导后的构成三元一次线性方程组,采用增广矩阵来求解。

package sk.ml;import java.text.DecimalFormat;/*** 功能:拉格朗日乘子法,求解 f(x,y)=x^2+3xy+y^2最大值,约束条件x+y=100*     构造函数:F(x,y,λ)=f(x,y)+λg(x,y),其中g(x,y)=x+y-100*     求导:∂L/∂x=2x+3y+λ=0;∂L/∂y=2y+3x+λ=0;∂L/∂λ=x+y-100=0;*     用矩阵算法代码实现线性方程组求解x,y。* 作者:Jason.F* 时间:2017年1月18日*/
public class LagrangeMultiplier {//增广矩阵计算三元一次线性方程组static DecimalFormat df = new DecimalFormat("0.##");/**** 增广矩阵机型初等行变化的算法 * @param value         需要算的增广矩阵* @return 计算的结果*/public static double[][] mathDeterminantCalculation(double[][] value) throws Exception {// 当矩阵的行数大于2时for (int i = 0; i < value.length; i++) {// 检查数组对角线位置的数值是否是0,如果是零则对该数组进行调换,查找到一行不为0的进行调换if (value[i][i] == 0) {value = changeDeterminantNoZero(value, i, i);}for (int j = 0; j < i; j++) {// 让开始处理的行的首位为0处理为三角形式// 如果要处理的列为0则和自己调换一下位置,这样就省去了计算if (value[i][j] == 0) {continue;}// 如果要是要处理的行是0则和上面的一行进行调换if (value[j][j] == 0) {double[] temp = value[i];value[i] = value[i - 1];value[i - 1] = temp;continue;}double ratio = -(value[i][j] / value[j][j]);value[i] = addValue(value[i], value[j], ratio);}}return value;}/**** 将i行之前的每一行乘以一个系数,使得从i行的第i列之前的数字置换为0* @param currentRow 当前要处理的行* @param frontRow i行之前的遍历的行* @param ratio  要乘以的系数* @return 将i行i列之前数字置换为0后的新的行*/public static double[] addValue(double[] currentRow, double[] frontRow,double ratio) throws Exception {for (int i = 0; i < currentRow.length; i++) {currentRow[i] += frontRow[i] * ratio;currentRow[i] = Double.parseDouble(df.format(currentRow[i]));}return currentRow;}/*** 指定列的位置是否为0,查找第一个不为0的位置的行进行位置调换,如果没有则返回原来的值* @param determinant  需要处理的行列式* @param line  要调换的行* @param row  要判断的列*/public static double[][] changeDeterminantNoZero(double[][] determinant,int line, int row) throws Exception {for (int j = line; j < determinant.length; j++) {// 进行行调换if (determinant[j][row] != 0) {double[] temp = determinant[line];determinant[line] = determinant[j];determinant[j] = temp;return determinant;}}return determinant;}/*** 将系数矩阵和方程值的矩阵进行合并成增广矩阵* @param coefficient   系数矩阵* @param value  方程值* @return 增广矩阵*/public static double[][] transferMatrix(double[][] coefficient,double[] value) {double[][] temp = new double[coefficient.length][coefficient[0].length + 1];if (coefficient.length != value.length) {return temp;}// 将方程值添加到系数矩阵中for (int i = 0; i < coefficient.length; i++) {for (int j = 0; j < coefficient[0].length; j++) {temp[i][j] = coefficient[i][j];}}for (int i = 0; i < value.length; i++) {temp[i][temp[i].length - 1] = value[i];}return temp;}/*** 检查有效的行数,看非零行的个数* @param value  需要检查的数组* @return 非零行的个数*/public static int effectiveMatrix(double[][] value) {for (int i = value.length - 1; i > -1; i--) {for (int j = 0; j < value[i].length; j++) {if (value[i][j] != 0) {return i + 1;}}}return 0;}/*** 当方程组有解的时候计算方程组的解* @param mathMatrix  方程组的增广矩阵* @return 方程组的解*/private static double[] calculationResult(double[][] mathMatrix) {// 有解时方程组的个数等于方程组的未知数double[] result = new double[mathMatrix.length];for (int i = mathMatrix.length - 1; i > -1; i--) {double temp = 0;for (int j = mathMatrix[i].length; j > 0; j--) {// 第一个为方程的解,需要将解赋值给临时变量if (mathMatrix[i][j - 1] != 0) {if (j == mathMatrix[i].length) {temp = mathMatrix[i][j - 1];} else if (j - 1 > -1 && result[j - 1] != 0) {temp -= mathMatrix[i][j - 1] * result[j - 1];} else {result[i] = temp / mathMatrix[i][j - 1];continue;}}}}return result;}public static void main(String[] args) {// 方程的未知数的个数 int n = 3;double x=0;double y=0;//记录x,y值用于计算目标函数最大值double[][] ratio = { { 2,3,1 },{ 3,2,1 }, {1,1,0}};// 系数矩阵double[] value ={ 0,0,100 };// 方程的解try {// 转换成增广矩阵并进行初等行变化double[][] mathMatrix = mathDeterminantCalculation(transferMatrix(ratio, value));// 找出非零行的个数int checkMatrixRow = effectiveMatrix(mathMatrix);// 根据未知数的个数和方程组非零行的个数来判断当前方程组的解的情况if (n > checkMatrixRow) {System.out.println("未知数有" + n + "个,消元法后获取的阶梯方程组有"+ checkMatrixRow + "个方程,少于未知数个数,所以该方程有无数组解");} else if (n < checkMatrixRow) {System.out.println("未知数有" + n + "个,消元法后获取的阶梯方程组有"+ checkMatrixRow + "个方程,多于未知数个数,所以该方程有无解");} else {//System.out.println("未知数有" + n + "个,消元法后获取的阶梯方程组有"+ checkMatrixRow + "个方程,等于未知数个数,所以该方程有解");double[] result = calculationResult(mathMatrix);//for (int i = 0; i < result.length; i++) {//System.out.println("方程组的解为x" + (i + 1) + "="+ df.format(result[i]));x=result[0];y=result[1];//}}System.out.println("在x="+df.format(x)+"和y="+df.format(y)+"时,目标函数取得最大值:"+df.format(x*x+3*x*y+y*y));} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

执行结果:

在x=50和y=50时,目标函数取得最大值:12500

机器学习知识点(六)增广矩阵求解拉格朗日乘子法的Java实现相关推荐

  1. 机器学习--支持向量机(二)拉格朗日乘子法详解

    上节我们从线性回归模型出发详细阐述了支持向量的来源,以及为什么需要寻找支持向量,如何找到这决策函数等问题,最后问题转化为下面的求最大值问题: 先说明一下分类就是如果:          则被分为    ...

  2. 非线性规划的拉格朗日乘子法python编程python包编程

    非线性规划的拉格朗日乘子法&python编程&python包编程 一.拉格朗日乘子法 1.1 拉格朗日乘子法定义 1.2 KKT条件定义 1.3 拉格朗日乘子法手工推导例题 二.Pyt ...

  3. 【java机器学习】支持向量机之拉格朗日乘子法解释

    什么是拉格朗日乘子法 按照维基百科的定义,拉格朗日乘数法是一种寻找多元函数在其变量受到一个或多个条件的约束时的极值的方法.用数学式子表达为: 简单理解就是,我们要在满足 这个等式的前提下,求 函数的最 ...

  4. 求解最优化问题的方法:拉格朗日乘子法(Lagrange Multiplier) 和KKT条件

    在求解最优化问题中,拉格朗日乘子法(Lagrange Multiplier)和KKT(Karush Kuhn Tucker)条件是两种最常用的方法.在有等式约束时使用拉格朗日乘子法,在有不等约束时使用 ...

  5. 机器学习基础:拉格朗日乘子法

    在凸优化问题中,拉格朗日乘子法是最常用的方法之一. 先看个例题:求目标函数 f(x,y)=x2+y2\mathrm{f}(\mathrm{x}, \mathrm{y})=\mathrm{x}^{2}+ ...

  6. 机器学习中的数学——拉格朗日乘子法(二):不等式约束与KKT条件

    分类目录:<算法设计与分析>总目录 相关文章: ·拉格朗日乘子法(一):等式约束的拉格朗日乘子法 ·拉格朗日乘子法(二):不等式约束与KKT条件 现在接着<拉格朗日乘子法(一):等式 ...

  7. 机器学习中的数学——拉格朗日乘子法(一):等式约束的拉格朗日乘子法

    分类目录:<机器学习中的数学>总目录 相关文章: ·拉格朗日乘子法(一):等式约束的拉格朗日乘子法 ·拉格朗日乘子法(二):不等式约束与KKT条件 拉格朗日乘子法是一种寻找多元函数在一组约 ...

  8. 转 机器学习系列 08:深入理解拉格朗日乘子法、KKT 条件和拉格朗日对偶性

    深度理解拉格朗日乘子法.KKT条件与线性规划对偶理论的微妙关系 https://blog.csdn.net/benzhujie1245com/article/details/85270058?utm_ ...

  9. 约束优化方法之拉格朗日乘子法与KKT条件

    来源:https://www.cnblogs.com/ooon/p/5721119.html 引言 本篇文章将详解带有约束条件的最优化问题,约束条件分为等式约束与不等式约束,对于等式约束的优化问题,可 ...

最新文章

  1. Computer:现代计算机操作系统的四大基本特性(并发/共享/虚拟/异步)
  2. 最短路 poj1125
  3. vue2项目使用codemirror插件实现代码编辑器功能
  4. YARP(Yet Another Reverse Proxy)是使用 .NET 构建的高度可定制的反向代理
  5. html写原生曲线图,HTML5 平滑的正弦波曲线图
  6. JMX学习笔记(一)-MBean
  7. JDBC——编程式事务的实现逻辑
  8. CodeForces Manthan 2011 D. Optical Experiment(动态规划)
  9. arraylist、map、queue、stack总结
  10. 一步一步学习Servlet输出HelloServlet详解
  11. 「一入 Java 深似海 」系列课程
  12. 排序算法部分知识点小结
  13. server2008r2经常蓝屏或者自动重启
  14. 【工控】脉冲当量怎么算?
  15. kmeans算法及python实现
  16. Python~numpy.random.seed()方法
  17. 图形_反走样技术总结
  18. js内公切线切点的计算
  19. 感激爸妈----您们辛苦了
  20. JS的特性:异步 + 事件驱动

热门文章

  1. 进程间的通信方式(一):共享内存
  2. oracle imp 错误604,oracle imp导入出错
  3. nginx运行php如何,ThinkPHP项目在Nginx上运行的配置问题
  4. 烦神的斐波那契洛谷-1306-斐波那契公约数
  5. windows安装Python模块:requests
  6. hihocoder1479 三等分
  7. CSS中clear属性的both、left和right浅析
  8. android 继承ListView实现滑动删除功能.
  9. linux 安全相关
  10. Qcom LK阶段如何使用ADC介绍