研究生导师的方向是压缩感知,导师让我这个暑假将压缩感知尽可能的搞懂,方便开学之后研究工作。
压缩感知网上资料很多,压缩感知就是将稀疏向量通过一个压缩矩阵压缩,使其存储的数据量减少,在通过压缩感知的算法吧原先的稀疏向量求解出来。具体细节网上文献也很多,我就不多赘述。这篇文章主要是对于压缩感知中一个常用算法正交匹配跟踪算法的python代码实现。
关于正交匹配跟踪算法代码实现的文章我打算写三篇,写这三篇文章的初衷是我发现网上关于OMP算法的代码很少,有也是要么matlab实现,要么是python2.7实现的。基本没看到有人用python3.6去实现,所以打算自己实现一遍。第一篇主要是求解单一向量;第二篇是某个信号的回复,比如多个三角函数的叠加信号;最后一篇将是图片的信号的恢复。
这个代码首先是参考一篇举例文章实现的,要看懂我的代码一定要去看这篇文章:
英文原版:https://korediantousman.staff.telkomuniversity.ac.id/files/2017/08/main-1.pdf
中文版:https://zhuanlan.zhihu.com/p/52276805
'''
这个代码主要实现了《Introduction to Orthogonal Matching Pursuit》举得例子
作者:Kyda
时间:7.18.2019
'''
import numpy as np
import numpy.linalg as lg
def get_matri_new_plus(A):
'''
求A矩阵的伪逆
:param A: 输入矩阵
:return A_new: 求解的伪逆矩阵
'''
A_new = A.T.dot(A)
if A_new.ndim < 2:
A_new = 1 / A_new
A_new = A_new * A.T
else:
A_new = lg.inv(A_new)
A_new = A_new.dot(A.T)
return A_new
def get_A_ba(A):
'''
求解A_ba,也就是矩阵列向量单位化
:param A: 输入矩阵
:return A_new: 返回列向量单位后的矩阵
'''
A_new = A.T
for row in range(A_new.shape[0]):
norm2 = lg.norm(A_new[row], ord=2) # 求向量的2范数
A_new[row] /= norm2 # 单位化
return A_new
def find_pos_VecInMatrix(A, v):
'''
求解某个向量在矩阵中的相应行位置
:param A: 输入矩阵
:param v: 输入向量
:return pos: 位置
'''
A_rownum = A.shape[0] # 矩阵行的数量
for pos in range(A_rownum):
if (v==A[pos]).all(): # 判断向量v和矩阵中的某一行是否相等
return pos
x = np.array([0, 8, 1, 2])
A = np.array([[-0.8, 0.3, 1, 0.4],
[-0.2, 0.4, -0.3, -0.4],
[0.2, 1, -0.1, 0.8]])
N = A.shape[0] # 矩阵行的数量
y = A.dot(x) # 获取y
r = y # 初始化残差residue
A_ba = get_A_ba(A.copy()) # 初始化A矩阵
A_ba1 = A_ba # 复制
A_new = None
L_p = None
pos_selected_v = [] # 用于存储被选择向量的在矩阵A中位置
for times in range(N):
w = A_ba.dot(r) # 求剩余向量的贡献
pos = np.argmax(abs(w)) # 找到贡献最大值的对应位置
b_k = A_ba[pos] # 求最大贡献值所对应的向量, 即最大贡献向量
A_ba = np.delete(A_ba, pos, axis=0) # 删除A_ba向量中的最大贡献向量
pos1 = find_pos_VecInMatrix(A_ba1, b_k) # 在找到最大贡献向量在原有矩阵中的位置
pos_selected_v.append(pos1) # 保存
if A_new is None: # 将最大贡献向量(未单位化的)加入A_new矩阵
A_new = A.T[pos1]
else:
A_new = np.c_[A_new, A.T[pos1]]
A_new_plus = get_matri_new_plus(A_new) # 求A_new_plus
L_p = A_new_plus.dot(y) # 解最小二乘解
r = y - A_new.dot(L_p) # 求残差
x_ans = [0] * (N+1) # 初始化求解向量
for item in range(N): # 将求出来的值写入求解向量
pos = pos_selected_v[item]
x_r = L_p[item]
x_ans[pos] = round(x_r, 2)
print(x_ans)