线性规划之基追踪_python实现

非数学专业,本文不做理论推导及证明。
可进行指正说明探讨!!!
实时更新

最优化算法目录_python


一、线性规划

1.1 基追踪准则(BP)

解决重构压缩感知中的稀疏优化问题,实现对其 l 1 l_{1} l1范数的最小化问题。

1.问题重述

线性方程组:
A x = b Ax=b Ax=b
其中向量 x ∈ R n × 1 , b ∈ R m × 1 x \in R^{n \times 1},b \in R^{m \times 1} xRn×1bRm×1,矩阵 A 属 于 R m × n A属于R^{m \times n} ARm×n,并且向量b的维数远远小于向量x的维数,即为 m ≪ n m \ll n mn,因此方程(1)是欠正定的,存在无穷多个解,为“稀疏解”,即原始信号中有较多的零元素。(压缩感知)
x = [ 0 , 0 , 1 , 0 , . . . , 1 , 0 , 0 ] x=[0,0,1,0,...,1,0,0] x=[0,0,1,0,...,1,0,0]

2.构造 l 0 l_{0} l0范数

构造一个128*256矩阵A,每个元素都服从高斯分布

精确解u只有10%的元素非零,每个非零元素也服从高斯分布。以上理论是为了确保u是方程组(1)唯一的非零元素最少的解,即u是 l 0 l_{0} l0范数问题的最优解:
m i n ∣ ∣ x ∣ ∣ 0 , s . t . A x = b . min ||x||_{0},\\ s.t. Ax=b. minx0,s.t.Ax=b.
其中 ∣ ∣ x ∣ ∣ 0 ||x||_{0} x0是指x中的非零元素的个数。由于 ∣ ∣ x ∣ ∣ 0 ||x||_{0} x0是不连续的函数,并且只能取整数,故问题3实际上为非确定多项式(non-deterministic polynomial,NP),求解困难。

因此定义 l 1 l_{1} l1范数, ∣ ∣ x ∣ ∣ 1 = ∑ i = 1 n ∣ x ∣ i ||x||_{1}= \sum_{i=1}^{n}|x|_{i} x1=i=1nxi,将上式替换到问题(3)中,得到等价于问题(1)的问题(称为 l 1 l_{1} l1范数优化问题,基追踪问题):
m i n   ∣ ∣ x ∣ ∣ 1 , s . t .   A x = b . min~||x||_{1},\\ s.t.~Ax=b. min x1,s.t. Ax=b.
通过证明,u也是 l 1 l_{1} l1范数优化问题(4)的唯一最优解。

3. l 1 l_{1} l1范数最小化问题转化为线性规划问题

针对问题(4),利用基追踪的定义,将问题(4)与线性规划(LP)联系起来。添加变量 α \alpha α,将其定义两个非负变量的差:
α = u − v ( u , v ≥ 0 ) \alpha=u-v(u,v\geq0) α=uv(u,v0)
根据约束条件 A x = b Ax=b Ax=b,可以将公式(5)改写成 A ( u − v ) = b A(u-v)=b A(uv)=b,即为:
[ A , − A ] [ u v ] = b [A,-A]\left[\begin{array}{l}u\\v\end{array}\right]=b [A,A][uv]=b
然后,根据范数的定义,目标函数可改写为:
∣ ∣ α ∣ ∣ 1 = ∑ i = 1 n ∣ α ∣ i = ∑ i = 1 n ∣ u i − v i ∣ ||\alpha||_{1}=\sum_{i=1}^{n}|\alpha|_{i}=\sum_{i=1}^{n}|u_{i}-v_{i}| α1=i=1nαi=i=1nuivi
目标函数中包含绝对值,根据证明有,对于有限维的向量范数 l 1 l_{1} l1范数最小化,即 m i n ∣ ∣ α ∣ ∣ 1 = ∑ i = 1 n ∣ α ∣ i min||\alpha||_{1}=\sum_{i=1}^{n}|\alpha|_{i} minα1=i=1nαi,可等价为下属线性规划问题:
m i n   e ( u + v ) u − v = α u , v ≥ 0 min~e(u+v)\\ u-v=\alpha\\ u,v\geq0 min e(u+v)uv=αu,v0
其中 e e e为1行n列元素全为1的向量。定义 x ∈ R m x\in R_{m} xRm,则可得到标准式的线性方程:
m i n   c T x , s . t .   A x = b , x ≥ 0 min~c^{T}x,\\ s.t.~Ax=b,\\ x\geq0 min cTx,s.t. Ax=b,x0
公式(9)中, c T x c^{T}x cTx是目标函数, A x = b Ax=b Ax=b是一组等式约束, x ≥ 0 x\geq0 x0定义边界。根据公式(5)、(6),对上式中的变量做出如下映射,使其满足公式(8):
m ⇔ 2 n ; x ⇔ [ u v ] ; c ⇔ [ 1 , 1 , , . . , 1 ] 1 × 2 n ; A ⇔ [ A , − A ] m\Leftrightarrow2n;x\Leftrightarrow\left[\begin{array}{l}u\\v\end{array}\right];c\Leftrightarrow[1,1,,..,1]_{1\times2n};A\Leftrightarrow[A,-A] m2n;x[uv];c[1,1,,..,1]1×2n;A[A,A]
根据公式(9)和(10),求解线性规划得到解 x 0 = [ u v ] x_{0}=\left[\begin{array}{l}u\\v\end{array}\right] x0=[uv],则问题(5)的解为:
α 0 = x 0 ( 1 : n ) − x 0 ( n + 1 : 2 n ) \alpha_{0}=x_{0}(1:n)-x_{0}(n+1:2n) α0=x0(1:n)x0(n+1:2n)

4.基于linprog的基追踪Python代码
import numpy as np
from scipy import optimize as op # 线性规划库
from scipy.sparse import coo_matrix # 稀疏矩阵
import matplotlib.pyplot as plt
from matplotlib import rcParams # 绘图参数

config = {
    "font.family": 'serif',
    "font.size": 12,  #字体大小12,即小四
    "pgf.rcfonts": False,
    "text.usetex": True,
    "pgf.preamble": [
        r"\usepackage{unicode-math}",
        r"\setmainfont{Times New Roman}",
        r"\usepackage{xeCJK}",
        r"\setCJKmainfont{SimSun}",
    ],
}
rcParams.update(config)
# 坐标轴的刻度设置向内(in)或向外(out)
plt.rcParams['xtick.direction'] = 'in'
plt.rcParams['ytick.direction'] = 'in'

def sprase_rand(m, n, p):
    '''
    产生一个m行n列的服从均匀分布的随机稀疏矩阵
    :param m: 行数
    :param n: 列数
    :param p: 非零元素在此矩阵中所占的比例
    :return:  ss.coo_matric对象。使用toarray()方法或todense()方法转换为matrix对象或是array对象
    '''
    if type(m) != int or type(n) != int:
        raise TypeError('Rows(m) and Columns(n) must be an interger!')
    if p <= 0 or p > 1:
        raise ValueError('p must in (0, 1] !')
    # Counts of non-zero elements in sparse-matrix
    count = int(m * n * p) # 非零元素的个数
    # 随机生成服从高斯分布的行与列
    # Indexs of non-zero elements in sparse-matrix
    rows = np.random.randint(0, m, count)
    cols = np.random.randint(0, n, count)
    # 把非零值data按着行坐标rows和纵坐标cols写成两个列表
    # Values of non-zero elements in sparse-matrix
    data = np.random.randn(len(rows)) # 创建服从高斯分布(Gaussian distribution)的矩阵
    return coo_matrix((data, (rows, cols)), shape=(m, n))


def BP_linprog(Phi, s):
    '''
	L1范数求解最优解
    :param Phi: A矩阵
    :param s: b向量
    :return: L1范数下的最优解 alpha
    '''
    s,Phi = np.array(s),np.array(Phi) # 转化数据类型
    if np.size(s,0) < np.size(s,1): # 调整s向量,确保为列向量
        s = s.T
    p = np.size(Phi,1) # 提取A的列长
    # 根据公式10求解c,A_new,b_new
    # according to section 3.1 of the reference
    c = np.ones([2*p,1])
    A_new = np.hstack([Phi,-Phi])
    b_new = s
    bounds = [(0,None) for i in range(2*p)]
    # 求解线性规划方程
    x0 = op.linprog(c, A_eq=A_new, b_eq=b_new, bounds=bounds,method='revised simplex')['x']
    alpha = x0[:p] - x0[p:] # 带入公式求解
    return np.array([alpha])

m, n = 128, 256
A = np.random.randn(m, n) # 128x256矩阵,每个元素服从Gauss随机分布
# 精确解u只有10%元素非零,每一个非零元素也服从高斯分布
# 可保证u是方程组唯一的非零元素最少的解
u = sprase_rand(n, 1, 0.1) # 稀疏矩阵
b = A * u

alpha = BP_linprog(A, b) # 求解alpha
# 残差:实际值与预测值之间差的平方之和,残差平方和越小,其拟合程度越好。
print('\n残差:', np.linalg.norm(alpha.T - u.toarray(), 2))
# 绘图
plt.figure(figsize = (8,6))
plt.xlabel('length')
plt.ylabel('RSS')
plt.plot(u.toarray(), 'r', linewidth = 1, label = 'Original') # 绘制原信号
plt.plot(alpha.T, 'b--', linewidth = 1, label = 'Recovery') # 绘制恢复信号
plt.grid()
plt.legend()
plt.show()
 # 绘制原信号
plt.plot(alpha.T, 'b--', linewidth = 1, label = 'Recovery') # 绘制恢复信号
plt.grid()
plt.legend()
plt.show()

输出结果:

  	残差: 8.146147562440153e-15

在这里插入图片描述

参考文献

最优化:建模、算法与理论/最优化计算方法
python创建稀疏矩阵
在Python中创建、生成稀疏矩阵(均匀分布、高斯分布)
稀疏优化L1范数最小化问题求解之基追踪准则(Basis Pursuit)——原理及其Python实现

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
追踪问题是机器学习中常见的优化问题之一,可以通过罚函数法来求解。下面是一个使用Python实现罚函数法解决追踪问题的示例: 假设我们有一个线性模型:$y=w_1x_1+w_2x_2+w_3x_3$,我们希望通过最小化误差来求解参数$w_1, w_2, w_3$。我们有一组训练数据$(x_1^1,x_2^1,x_3^1,y^1),(x_1^2,x_2^2,x_3^2,y^2),...,(x_1^n,x_2^n,x_3^n,y^n)$,其中$n$是样本数量。 定义罚函数为:$f(w_1,w_2,w_3)=\sum_{i=1}^n (y_i-(w_1x_1^i+w_2x_2^i+w_3x_3^i))^2+\lambda (|w_1|+|w_2|+|w_3|)$,其中$\lambda$是正则化参数。我们的目标是最小化罚函数。 下面是Python代码实现罚函数法解决追踪问题的示例: ```python import numpy as np # 定义训练数据 X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) y = np.array([5, 10, 15]) # 定义罚函数 def penalty_func(w, X, y, lamda): error = np.sum((y - np.dot(X, w)) ** 2) penalty = lamda * np.sum(np.abs(w)) return error + penalty # 最小化罚函数 def minimize_penalty_func(X, y, lamda): from scipy.optimize import minimize w0 = np.zeros(X.shape[1]) res = minimize(penalty_func, w0, args=(X, y, lamda)) return res.x # 测试 w = minimize_penalty_func(X, y, 0.1) print(w) ``` 在上面的代码中,我们使用了SciPy中的minimize函数来最小化罚函数。minimize函数需要传入三个参数:目标函数、初始参数w0和参数args。其中,args是一个元组,包含了除w0以外的其他参数。 我们定义了penalty_func函数来计算罚函数的值,然后将其作为目标函数传递给minimize函数。我们还定义了minimize_penalty_func函数来封装minimize函数的调用,使其更加方便使用。 在测试中,我们通过传递训练数据X和y以及正则化参数lamda来求解参数w。最终得到的w即为最优解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

眰恦I

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值