白话压缩感知(含Matlab代码)


压缩感知介绍

压缩感知(Compressive Sensing,CS),有时也叫成Compressive Sampling。相对于传统的奈奎斯特采样定理——要求采样频率必须是信号最高频率的两倍或两倍以上(这就要求信号是带限信号,通常在采样前使用低通滤波器使信号带限),压缩感知则利用数据的冗余特性,只采集少量的样本还原原始数据。

这所谓的冗余特性,借助MLSS2014马毅老师的课件上的例子来说明,

data_property

因为自然界的数据都存在局部低维结构、周期性、对称性等,因此,传统的固定采样率的采样方法必然存在信息冗余。由于信息冗余的存在,我们就知道有数据压缩那么一门学科。既然这样,为什么要把冗余的数据也采进来,再进行压缩呢,能不能不把冗余的数据采集进来?

压缩感知的思路就是:在采集的过程中就对数据进行了压缩,而且这种压缩能保证不失真(低失真)的恢复原始数据,这与传统的先2倍频率采集信号→存储→再压缩的方式不同,可以降低采集信号的存储空间和计算量。

好了,那么就来了解一下压缩感知的具体模型。

1. 稀疏表示

使用压缩感知理论首先要求信号能表示为稀疏信号,如x=[1 0 0 0 1 0],其中只有2个1,可认为是稀疏的。我们将信号通过一个矩阵映射到稀疏空间,

设信号x为N维,即,则为NxN维稀疏表达矩阵,s即是将x进行稀疏表示后的Nx1维向量,其中大部分元素值为0。稀疏表示的原理就是通过线性空间映射,将信号在稀疏空间进行表示。

比如,信号

在时域是非稀疏的,但做傅里叶变换表示成频域后,只有少数几个点为非0(如下图)。则该信号的时域空间为非稀疏,频域空间为稀疏空间,组成的矩阵。一般为正交矩阵。

example1

若稀疏表示后的结果s中只有k个值不为0,则称x的稀疏表示为k-Sparse。上图对x的频域稀疏表示就是2-Sparse。

2. 感知测量

压缩感知的目的是在采集信号时就对数据进行压缩,大牛们的思路集中到了数据采集上——既然要压缩,还不如就从大量的传感器中只使用其中很少的一部分传感器,采集少量的冗余度低的数据。这就是感知测量的通俗的说法,用表达式表示

其中的x就是稀疏表示中的信号,为MxN维的感知矩阵(M表示测量信号的维度),y则表示M(M远小于N才有意义)个传感器的直接测量,因此维度为Mx1。

将稀疏表示过程和感知测量过程综合起来:

Sparse

数学描述

对于压缩感知模型,其中每个量的维度一定要了解(通过维度的变化来理解压缩感知很有效):

yax

从感知测量中知道:M就是测量的维度(M远小于N)。

压缩感知的原信号恢复问题描述为:

由已知条件:

(1) 测量值y,且,其中e为噪声引入

(2) s为k-Sparse信号(k未知)

求解目标:k尽可能小的稀疏表示信号s及对应的

用数学形式描述为:

e可以看成告诉随机噪声,e~N(0,δ2)。

即是要求s使s的0范数(非0值的个数)最小,但0范数优化问题是很难求解的,于是一帮大牛就证明求解1范数也能逼近和上面相同的效果,而求解2范数及其更高的范数则结果相差越来越大(有些人在研究介于0范数与1范数之间的范数求解方法)。因此可转化为1范数求解:

由拉格朗日乘子法,上面的最优问题可转化成:

上面的最小值求解问题就可以直接通过凸优化解得结果了。

程序分析

先下载CVX或spams工具箱,下面的matlab程序分别使用了时域稀疏信号和频域稀疏信号进行测试,两种不同在于时域稀疏信号不用稀疏表达矩阵(因此稀疏表达矩阵使用单位阵即可),而频域稀疏信号则需要先通过稀疏表达矩阵将信号在频域进行稀疏表示,再压缩感知后进行恢复时也要进行反FFT变换到时域。

关于M的选取:测量数M>=K*log(N/K),K是稀疏度,N信号长度,可以近乎完全重构

clc
clear all
close all

%% 产生原始信号及相关参数
n = 512;                          % 信号长度
s = 25;                           % 稀疏度(从下面知道,分时域和频域的情况)
m = 5*s;                          % 测量长度 M>=S*log(N/S)
freq_sparse = 0;                  % 信号频域稀疏则为1

if freq_sparse
    t = [0: n-1]';
    f = cos(2*pi/256*t) + sin(2*pi/128*t);   % 产生频域稀疏的信号
else
    tmp = randperm(n);    
    f = zeros(n,1);
    f(tmp(1:s)) = randn(s,1);     % 产生时域稀疏的信号
end

%% 产生感知矩阵和稀疏表示矩阵
Phi = sqrt(1/m) * randn(m,n);     % 感知矩阵(测量矩阵)
% A = get_A_fourier(n, m);

y = Phi * f;                      % 通过感知矩阵获得测量值
                                  % Psi 将信号变换到稀疏域
if freq_sparse                    % 信号频域可以稀疏表示
    Psi = inv(fft(eye(n,n)));     % 傅里叶正变换,频域稀疏正交基(稀疏表示矩阵)
else                              % 信号时域可以稀疏表示
    Psi = eye(n, n);              % 时域稀疏正交基
end
A = Phi * Psi;                    % 恢复矩阵 A = Phi * Psi

%% 优化方法1:使用CVX工具进行凸优化
addpath('../../cvx-w64/cvx/');
cvx_startup;                            % 设置cvx环境
cvx_begin
    variable xp(n) complex;               % 如果xp是复数,则添加complex,否则不加
    minimize (norm(xp, 1));
    subject to
        A * xp == y;      
cvx_end

%% 优化方法2:使用spams工具箱进行优化
% addpath('spams-matlab/build');
% param.L = 100;
% param.eps = 0.001;
% param.numThreads = -1;
% 
% A=A./repmat(sqrt(sum(A.^2)),[size(A,1) 1]);
% xp = mexOMP(y, A, param);       % 正交匹配追踪法Orthogonal Matching Pursuit

%% 对比原信号和
if freq_sparse
    xp = real(ifft(full(xp)));           % 傅里叶逆变换
else

end
plot(f+noise);
hold on
plot(real(xp), 'r.');
legend('Original', 'Recovered');
  1. 设程序中的freq_sparse = 0时,观察时域稀疏信号的恢复结果为

    time

    在恢复时域稀疏信号时,所使用的测量矩阵Phi为初始化的随机阵,因为本身时域就稀疏,而算法直接在时域进行恢复,所以稀疏表达矩阵就是单位阵Psi=E。上面的时域稀疏恢复结果显得没有误差是因为没有给原始信号添加噪声。

  2. 设程序中的freq_sparse = 1时,观察频域稀疏信号的恢复结果为

    freq

    在恢复时域稀疏信号时,所使用的测量矩阵Phi为初始化的随机阵,因为信号只在频域稀疏,所以稀疏变换矩阵为傅里叶变换基,所以稀疏表达矩阵就是Psi = inv(fft(eye(n,n)))。同理,上面的频域稀疏恢复结果显得没有误差是因为没有给原始信号添加噪声。

  3. 上面都是没有添加噪声的算法结果,我们给信号添加一些噪声,以时域信号为例,

    if freq_sparse
        t = [0: n-1]';
        f = cos(2*pi/256*t) + sin(2*pi/128*t);   % 产生频域稀疏的信号
    else
        tmp = randperm(n);    
        f = zeros(n,1);
        f(tmp(1:s)) = randn(s,1);     % 产生时域稀疏的信号
    end
    
    noise = random('norm', 0, 0.01, [n 1]);
    f = f + noise;                    % 添加噪声
    
    %% Remaining code not changed
    

    从下图的恢复结果看,已经能看到一些恢复误差了,

    err

  • 38
    点赞
  • 345
    收藏
    觉得还不错? 一键收藏
  • 60
    评论
机器学习中最常用的数学工具是线性代数、微积分和概率论。下面是一些基本的数学概念和 Python 代码示例: 1. 向量和矩阵 向量是一列数字,矩阵是一个二维数组。在 Python 中,可以使用 NumPy 库来创建和操作向量和矩阵。 ```python import numpy as np # 创建向量 v = np.array([1, 2, 3]) # 创建矩阵 m = np.array([[1, 2], [3, 4], [5, 6]]) # 矩阵乘法 result = np.dot(m, v) print(result) ``` 2. 梯度下降 梯度下降是一种优化算法,用于最小化损失函数。在 Python 中,可以使用 NumPy 和 SciPy 库来实现梯度下降算法。 ```python import numpy as np from scipy.optimize import minimize # 定义损失函数 def loss_function(w, X, y): y_hat = np.dot(X, w) return np.mean((y_hat - y) ** 2) # 定义梯度函数 def gradient(w, X, y): y_hat = np.dot(X, w) return np.dot(X.T, y_hat - y) / len(y) # 使用梯度下降算法求解 X = np.array([[1, 2], [3, 4], [5, 6]]) y = np.array([1, 2, 3]) w0 = np.zeros(X.shape[1]) res = minimize(loss_function, w0, args=(X, y), jac=gradient) print(res.x) ``` 3. 偏导数和梯度 偏导数是多元函数中某个变量的导数,梯度是多元函数的导数向量。在 Python 中,可以使用 SymPy 库来计算偏导数和梯度。 ```python from sympy import symbols, diff # 定义符号变量和函数 x, y = symbols('x y') f = x ** 2 + y ** 3 # 计算偏导数 df_dx = diff(f, x) df_dy = diff(f, y) print(df_dx, df_dy) # 计算梯度 grad = [diff(f, var) for var in [x, y]] print(grad) ``` 4. 概率分布和随机变量 概率分布是随机变量可能取值的概率分布。在 Python 中,可以使用 SciPy 库来计算概率分布和随机变量。 ```python from scipy.stats import norm # 定义正态分布 mu, sigma = 0, 1 dist = norm(mu, sigma) # 计算概率密度函数和累积分布函数 x = np.linspace(-3, 3, 1000) pdf = dist.pdf(x) cdf = dist.cdf(x) # 生成随机变量 samples = dist.rvs(1000) ``` 以上是一些基本的数学概念和 Python 代码示例。在机器学习中,还会涉及到更高级的数学工具,如矩阵分解、优化理论、贝叶斯统计等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值