1. 程式人生 > >領近點梯度下降法、交替方向乘子法、次梯度法使用例項(Python實現)

領近點梯度下降法、交替方向乘子法、次梯度法使用例項(Python實現)

簡述

凸優化會很詳細地講解這三個演算法,這個學期剛好有這門課。
這裡以期末的大作業的專案中的一個題目作為講解。

題目

考慮線性測量b=Ax+e,其中b為50維的測量值,A為50*100維的測量矩陣,x為100維的未知稀疏向量且稀疏度為5,e為50維的測量噪聲。從b和A中恢復x的一範數規範化最小二乘法模型(任務!!)
m i n

A x b 2 2
+ ( p / 2 ) x
1 min||Ax-b||_2^2 +(p/2)||x||_1

  • p為非負的正則化引數。
  • 提示:
    在本實驗中,設x的真值中的非零元素 服從標準正態分佈,A中的元素服從標準正態分佈,e中的元素服從均值為0,方差為0.1的高斯分佈。

要求使用的演算法:

  • 鄰近點梯度下降法
  • 交替方向乘子法
  • 次梯度法

實驗部分

生成資料

  • generate-data.py
  • 儲存資料到二進位制檔案中
import numpy as np
import random
ASize = (50, 100)
XSize = 100
A = np.random.normal(0, 1, ASize)
X = np.zeros(XSize)
e = np.random.normal(0, 0.1, 50)
XIndex = random.sample(list(range(XSize)), 5)  # 5 稀疏度
for xi in XIndex:
    X[xi] = np.random.randn()

b = np.dot(A, X) + e

np.save("A.npy", A)
np.save("X.npy", X)
np.save("b.npy", b)

鄰近點梯度下降法

m i n f 0 ( x ) = s ( x ) + r ( x ) min f_0(x) = s(x) + r(x)

  • s為光滑項
  • r為非光滑項

演算法過程:

x k + 1 2 = x k α s ( x k ) x k + 1 = a r g m i n x r ( x ) + 1 2 α x x k + 1 2 2 x^{k+\frac{1}{2} } = x^k - \alpha * \nabla{s(x^k)} \\ x^{k+1} = argmin_x{r(x) +\frac{1}{2*\alpha} || x-x^{k+\frac{1}{2}}||^2}

解析:

這一問本質上就是Lasso的鄰近點梯度下降問題。
代入之前的演算法過程,得到下面的結果(相比於原來的Lasso簡單的變下就好了~)

x k + 1 2 = x k 2 α A T ( A x k b ) x k + 1 = a r g m i n x { ( p 2 ) x 1 + 1 2 α x x k + 1 2 2 } x^{k+\frac{1}{2} } = x^k - 2* \alpha * A^T(Ax^k-b) \\ x^{k+1} = argmin_x{ \{(\frac{p}{2})||x||_1+\frac{1}{2*\alpha} || x-x^{k+\frac{1}{2}}||^2} \}

  • 求解argmin的方法–軟門限法

關於光滑的部分,直接求導,在不光滑的部分,就求次梯度。
然後關於每個分量部分不進行。可以參照程式碼中的片段,在中間就為0,在區間之外就是對應的一個正數~

實現領近點梯度法

import numpy as np

A = np.load('A.npy')
b = np.load('b.npy')
X = np.load('X.npy')

ASize = (50, 100)
BSize = 50
XSize = 100
alpha = 0.001
P_half = 0.01
Xk = np.zeros(XSize)
zero = np.zeros(XSize)
while True:
    Xk_half = Xk - alpha * np.dot(A.T, np.dot(A, Xk) - b)
    # 軟門限運算元
    Xk_new = zero.copy()
    for i in range(XSize):
        if Xk_half[i] < - alpha * P_half:
            Xk_new[i] = Xk_half[i] + alpha * P_half
        elif Xk_half[i] > alpha * P_half:
            Xk_new[i] = Xk_half[i] - alpha * P_half
    if np.linalg.norm(Xk_new - Xk, ord=2) < 1e-5:
        break
    else:
        Xk = Xk_new.copy()

print(Xk)
print(X)

附加上畫圖的程式碼

在這裡插入圖片描述

  • 藍色的是演算法最優值的距離(最終的收斂點的距離
  • 黃色的是預測的真實值的距離(一開始生成的資料
  • 距離都用的是二範數
import matplotlib.pyplot as plt
import numpy as np

A = np.load('A.npy')
b = np.load('b.npy')
X = np.load('X.npy')

ASize = (50, 100)
BSize = 50
XSize = 100
alpha = 0.005
P_half = 0.01
Xk = np.zeros(XSize)
zero = np.zeros(XSize)

X_opt_dst_steps = []
X_dst_steps = []
while True:
    Xk_half = Xk - alpha * np.dot(A.T, np.dot(A, Xk) - b)
    # 軟門限運算元
    Xk_new = zero.copy()
    for i in range(XSize):
        if Xk_half[i] < - alpha * P_half:
            Xk_new[i] = Xk_half[i] + alpha * P_half
        elif Xk_half[i] > alpha * P_half:
            Xk_new[i] = Xk_half[i] - alpha * P_half
    X_dst_steps.append(np.linalg.norm(Xk_new - X, ord=2))
    X_opt_dst_steps.append(Xk_new)
    if np.linalg.norm(Xk_new - Xk, ord=2) < 1e-5:
        break
    else:
        Xk = Xk_new.copy()

print(Xk)
print(X)

X_opt = X_opt_dst_steps[-1]

for i, data in enumerate(X_opt_dst_steps):
    X_opt_dst_steps[i] = np.linalg.norm(data - X_opt, ord=2)
plt.title("Distance")
plt.plot(X_opt_dst_steps, label='X-opt-distance')
plt.plot(X_dst_steps, label='X-real-distance')
plt.legend()
plt.show()

交替方向乘子法

m i n f 1 ( x ) + f 2 ( y ) s . t . A x + B y = d min f_1(x)+f_2(y) \\ s.t. Ax+By=d

演算法過程:

( x k + 1 , y k + 1 ) = a r g m i n x , y { L c ( x , y , v k ) } v k + 1 = v k + c ( A x k + 1 + B y k + 1 ) (x^{k+1}, y^{k+1}) = argmin_{x, y} \{L_c(x, y, v^k)\} \\ v^{k+1} =v^k +c(Ax^{k+1} + B y^{k+1})

相關推薦

梯度下降交替方向梯度使用例項Python實現

簡述 凸優化會很詳細地講解這三個演算法,這個學期剛好有這門課。 這裡以期末的大作業的專案中的一個題目作為講解。 題目 考慮線性測量b=Ax+e,其中b為50維的測量值,A為50*100維的測量矩陣,x為100維的未知稀疏向量且稀疏度為5,e為50維的測量噪聲。從b和A中恢復x

:IP分割問題python實現

今天群裏有個朋友出了個題,是一家公司的面試題,題目如下(補充:對於ip0開頭的也是無效的,如分割後001.1.1.1這種是不可以的):   分析:這裏我們舉一個最簡單的例子1.1.1.12.2.2.2。首先能想到的解決方法肯定是使用循環了,我們可以寫2個循環嵌套(有點像冒泡排序)從第0個位置截取1個,從

分別用遞迴迴圈bisect實現二叉查詢python實現

1、遞迴實現二叉查詢 def binary_search_recursion(lst,target,low,high): if high < low: return None middle = (low + high)//2 if lst[middl

順序高斯消元Python實現

main python實現 ber seq rev div 順序 inf break # coding: utf8 import numpy as np # 設置矩陣 def getInput(): matrix_a = np.mat([[2, 3, 11,

關於遞迴的總結——漢諾塔素因數的求解Python實現

在Python函式的學習中,再次對函式的遞迴感到了迷惑,都說遞迴邏輯清晰,應用簡單,但是在應用中卻總有些不理解的地方,甚至感到很疑惑,在此進行總結,希望能理解。首先看一下階乘的遞迴求法: def getNum(num): if num > 1: result =

凸優化:ADMM(Alternating Direction Method of Multipliers)交替方向演算法

最近開始對凸優化(convex optimization)開始感興趣,接下來我會寫一系列關於凸優化(convex optimization)的內容。 本文主要對ADMM(Alternating Direction Method of Multipli

雙門限語音端點檢測Python實現

寫在前面 花了幾天時間寫完了第一個視聽覺訊號處理的實驗,其實還挺簡單的,在這裡分享一下。 本文介紹一下利用雙門限法進行語音端點檢測的方法,該方法主要利用了語音的短時能量和短時過零率,關於這兩個語音特徵如何求解,前兩篇文章已經介紹過了(短時能量和短時過零率),這裡

爬山實現 八皇后問題 Python 實現

本文主要簡單闡述爬山法的基本演算法思想,並給出用此演算法實現八皇后問題詳細過程 最基本的爬上搜索演算法表示:(節選自《人工智慧》第二版): function HILL-CLIMBING(problem) return a state thate is a locak

資料結構-二叉樹1以及前序中序後序遍歷python實現

上篇文章我們介紹了樹的概念,今天我們來介紹一種特殊的樹——二叉樹,二叉樹的應用很廣,有很多特性。今天我們一一來為大家介紹。 二叉樹 顧名思義,二叉樹就是隻有兩個節點的樹,兩個節點分別為左節點和右節點,特別強調,即使只有一個子節點也要區分它是左節點還是右節點。 常見的二叉樹有一般二叉樹、完全二叉樹、滿二叉樹、線

用高斯下降解多元一次方程組C++實現

昨天演算法上機出了一道求多元一次方程組的題目,大神們早早就提交了,而我弄了很久,然而並不能在規定時間內完成。究其原因,是線性代數的知識已經忘光了。痛定思痛,我決定把這個題目弄出來,上傳到CSDN部落格,以警醒我日後仍需多加用功。 本文的程式碼涉及到以下幾個

[C++] 動態規劃之矩陣連最長公共序列最大子段和最長單調遞增序列

每次 種子 () return 避免 amp 可能 text com 一、動態規劃的基本思想   動態規劃算法通常用於求解具有某種最優性質的問題。在這類問題中,可能會有許多可行解。每一個解都對應於一個值,我們希望找到具有最優值的解。   將待求解問題分解成若幹個子問題,先求

基礎:整數拆分問題Golang實現

text else lang mod mark numbers com cti ase 一個整數總能夠拆分為2的冪的和。比如: 7=1+2+4 7=1+2+2+2 7=1+1+1+4 7=1+1+1+2+2 7=1+1+1+1+1+2 7=1

循環鏈表的創建插入刪除逆序顯示C++實現

i++ pos str pre hide mar add 這樣的 itl 對於單鏈表,因為每一個結點僅僅存儲了向後的指針。到了尾標誌就停止了向後鏈的操作,這樣,其中某一結點就無法找到它的前驅結點了。 對於單鏈表的操作大家能夠看我的這篇博客http://

基礎:刪除字符串中出現次數最少的字符Golang實現

cfb 出現次數 英文字母 clas har str 長度 == tracking 描寫敘述: 實現刪除字符串中出現次數最少的字符。若多個字符出現次數一樣,則都刪除。輸出刪除這些單詞後的字符串。 字符串中其他字符保持原來的順序。 輸入: 字符串僅僅包括小

【算學習】雙調歐幾裏得旅行商問題動態規劃(轉)

png .com 16px 我們 pan 子結構 最小 而且 復雜度 雙調歐幾裏得旅行商問題是一個經典動態規劃問題。《算法導論(第二版)》思考題15-1和北京大學OJ2677都出現了這個題目。 旅行商問題描述:平面上n個點,確定一條連接各點的最短閉合旅程。這個解的一般形式

查找算Java實現

pac binary while n) println pub ret gin 需要 1、二分查找算法 package other; public class BinarySearch { /* * 循環實現二分查找算法arr 已排好序的數

排序算入門之希爾排序java實現

入門 介紹 插入 一次 變化 shells ngx i++ ava 希爾排序是對插入排序的改進。插入排序是前面元素已經有序了,移動元素是一個一個一次往後移動,當插入的元素比前面排好序的所有元素都小時,則需要將前面所有元素都往後移動。希爾排序有了自己的增量,可以理

排序算入門之快速排序java實現

大小 ava 相對 其余 時間 個數 技術分享 算法 元素交換   快速排序也是一種分治的排序算法。快速排序和歸並排序是互補的:歸並排序將數組分成兩個子數組分別排序,並將有序的子數組歸並以將整個數組排序,會需要一個額外的數組;而快速排序的排序方式是當兩個子數組都有序

數據結構與算—插入排序Java實現

數據結構 算法 Java 插入排序 [toc] 插入排序 程序代碼 package com.uplooking.bigdata.datastructure; import java.util.Arrays; public class InsertSort { public st

數據結構與算—冒泡排序Java實現

數據結構 算法 Java 冒泡排序 [toc] 冒泡排序 程序代碼 package com.uplooking.bigdata.datastructure; import java.util.Arrays; public class BubbleSort { public st