机器学习知识点(六)增广矩阵求解拉格朗日乘子法的Java实现
生活随笔
收集整理的這篇文章主要介紹了
机器学习知识点(六)增广矩阵求解拉格朗日乘子法的Java实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
基本的拉格朗日乘子法就是求函數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实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习知识点(五)梯度下降法Java实
- 下一篇: Java实现海明距离简单计算