稀疏表示中KL1p库的配置及Demo

最近打算在研究中尝试稀疏编码。稀疏表示的理论知识这里不具体补充,有兴趣的可以查看下面这篇用稀疏表示做人脸识别的文章,讲得很清楚。
http://blog.csdn.net/xiaoshengforever/article/details/14002843

稀疏表示中的关键是求解L2范数或者L1范数。L2范数的求解很简单,一个公式就搞定了; L1范数的求解就要复杂多了,求解的方式也有很多种。笔者做了实验后发现用L1求解出的结果确实比用L2求解出的结果稀疏多了。
通常求解L1范数都要借助第三方包。网上求解L1的MATLAB包比较多,但是C++包却相对很少,搜索后发现了KL1p这个好东西。

kl1p是一个压缩感知方面的C++库,里面封装了很多压缩感知方法,在稀疏表(SRC)示中主要是借助它来求取l1范数最小化问题。它的官方:http://kl1p.sourceforge.net/home.html 目前的版本是0.4.2

KL1p的配置

  1. 下载
    从上述官网下载KL1p包,不能访问的话可以从这里下载。下载后解压到D:\KL1p-0.4.2目录下。
  2. 编译生成库文件
    在目录D:\KL1p-0.4.2\build\win下用VS2010打开KLab.vcxproj文件进行编译,注意在Debug模式和Release模式下都要进行编译。编译成功后在D:\KL1p-0.4.2\bin\win目录会生成两个库文件,分别是KLab.lib和KLab_d.lib。带_d的库文件表示用于Debug。
    这里写图片描述
  3. 配置VS
    配置主要分为头文件配置和库文件配置。
    配置头文件:新建一个项目,然后点击项目属性,在“配置属性->C/C++->常规”中找到附加包含目录。然后添加如下图所示的几个目录。
    这里写图片描述
    配置库文件: 在属性对话框“配置属性->连接器->常规”中找到“附加库目录”,在其中加入以下条目:D: \KL1p-0.4.2\bin\win;
    这里写图片描述
    然后在属性对话框“配置属性->链接器->输入”的“附加依赖项”中,加入以下条目:
    KLab_d.lib(Release中则用KLab.lib)
    至此,配置已经完成,可以直接编代码测试了!!!
  4. 修改运行时库(可选)
    在完成前面三部的配置后,有可能编译代码时出现链接错误,编译不成功的情况。此时还需要修改一下运行时库。在属性对话框中“配置属性->C/C++ ->代码生成”中找到“运行库“,选择“多线程调试 (/MTd)”
    这里写图片描述

说明:从KL1p的配置可以看到,在KL1p在求解矩阵时实际上是通过Armadillo库来实现的,关于Armadillo库的矩阵操作手册可在这个网站查询:
http://arma.sourceforge.net/docs.html

最后给一个完整Demo程序

//KL1p Demo
#include"armadillo"
#include <KL1pInclude.h>
#include <KL1p.h>

using namespace std;
using namespace kl1p;
using namespace arma;
int main()
{
    arma::mat featureMat;   //839*156
    featureMat.load("LBPPCANorFeatures.csv",csv_ascii);  
    arma::mat x0;          //1*156
    x0.load("test.csv",csv_ascii);
    //在读取的两个csv文件中,一个样本的特征占一行,所以需要取转置
    arma::mat A1 = featureMat.t(); 
    arma::mat y = x0.t();

    std::cout<<"Start of KL1p compressed-sensing example."<<std::endl;
    std::cout<<"Try to determine a sparse vector x "<<std::endl;
    std::cout<<"from an underdetermined set of linear measurements y=A*x, "<<std::endl;
    std::cout<<"where A is a random gaussian i.i.d sensing matrix."<<std::endl;

    klab::UInt32 n = A1.n_rows;     // Size of the original signal x0.
    klab::DoubleReal alpha = 0.5;   // Ratio of the cs-measurements.
    klab::DoubleReal rho = 0.1;     // Ratio of the sparsity of the signal x0.
    klab::UInt32 m = klab::UInt32(alpha*n); // Number of cs-measurements.
    klab::UInt32 k = klab::UInt32(rho*n);   // Sparsity of the signal x0 (number of non-zero elements).
    klab::UInt64 seed = 0;                  // Seed used for random number generation (0 if regenerate random numbers on each launch).
    bool bWrite = true;                 // Write signals to files ?


    // Display signal informations.
    std::cout<<"=============================="<<std::endl;
    std::cout<<"N="<<n<<" (signal size)"<<std::endl;
    std::cout<<"M="<<m<<"="<<std::setprecision(5)<<(alpha*100.0)<<"% (number of measurements)"<<std::endl;
    std::cout<<"K="<<k<<"="<<std::setprecision(5)<<(rho*100.0)<<"% (signal sparsity)"<<std::endl;
    std::cout<<"=============================="<<std::endl;

    kl1p::TMatrixOperator<klab::DoubleReal> * matrix = new kl1p::TMatrixOperator<klab::DoubleReal>(A1);
    klab::TSmartPointer<kl1p::TOperator<klab::DoubleReal, klab::DoubleReal> > * A2 =new klab::TSmartPointer<kl1p::TOperator<klab::DoubleReal, klab::DoubleReal> >(matrix);
    klab::TSmartPointer<kl1p::TOperator<klab::DoubleReal, klab::DoubleReal> >  A = *A2;

    klab::DoubleReal tolerance = 1e-3;  // Tolerance of the solution.
    arma::Col<klab::DoubleReal> x;      // Will contain the solution of the reconstruction.

    klab::KTimer timer;

    // Compute Basis-Pursuit.
    std::cout<<"[BasisPursuit] Start."<<std::endl;
    timer.start();
    kl1p::TBasisPursuitSolver<klab::DoubleReal> bp(tolerance);
    bp.solve(y, A, x);
    timer.stop();
    std::cout<<"[BasisPursuit] Done - SNR="<<std::setprecision(5)<<klab::SNR(x, x0)<<" - "
        <<"Time="<<klab::UInt32(timer.durationInMilliseconds())<<"ms"<<" - "
        <<"Iterations="<<bp.iterations()<<std::endl;
    if(bWrite)
        x.save("BasisPursuit-Signal.csv",csv_ascii);  // Write solution to a file.

    // Compute OMP.
    std::cout<<"------------------------------"<<std::endl;
    std::cout<<"[OMP] Start."<<std::endl;
    timer.start();
    kl1p::TOMPSolver<klab::DoubleReal> omp(tolerance);
    omp.solve(y, A, k, x);
    timer.stop();
    std::cout<<"[OMP] Done - SNR="<<std::setprecision(5)<<klab::SNR(x, x0)<<" - "
        <<"Time="<<klab::UInt32(timer.durationInMilliseconds())<<"ms"<<" - "
        <<"Iterations="<<omp.iterations()<<std::endl;
    if(bWrite)
        x.save("OMP-Signal.csv",csv_ascii);  // Write solution to a file.

    // Compute ROMP.
    std::cout<<"------------------------------"<<std::endl;
    std::cout<<"[ROMP] Start."<<std::endl;
    timer.start();
    kl1p::TROMPSolver<klab::DoubleReal> romp(tolerance);
    romp.solve(y, A, k, x);
    timer.stop();
    std::cout<<"[ROMP] Done - SNR="<<std::setprecision(5)<<klab::SNR(x, x0)<<" - "
        <<"Time="<<klab::UInt32(timer.durationInMilliseconds())<<"ms"<<" - "
        <<"Iterations="<<romp.iterations()<<std::endl;
    if(bWrite)
        x.save("ROMP-Signal.csv",csv_ascii);  // Write solution to a file.

    // Compute CoSaMP.
    std::cout<<"------------------------------"<<std::endl;
    std::cout<<"[CoSaMP] Start."<<std::endl;
    timer.start();
    kl1p::TCoSaMPSolver<klab::DoubleReal> cosamp(tolerance);
    cosamp.solve(y, A, k, x);
    timer.stop();
    std::cout<<"[CoSaMP] Done - SNR="<<std::setprecision(5)<<klab::SNR(x, x0)<<" - "
        <<"Time="<<klab::UInt32(timer.durationInMilliseconds())<<"ms"<<" - "
        <<"Iterations="<<cosamp.iterations()<<std::endl;
    if(bWrite)
        x.save("CoSaMP-Signal.csv",csv_ascii);  // Write solution to a file.

    // Compute Subspace-Pursuit.
    std::cout<<"------------------------------"<<std::endl;
    std::cout<<"[SubspacePursuit] Start."<<std::endl;
    timer.start();
    kl1p::TSubspacePursuitSolver<klab::DoubleReal> sp(tolerance);
    sp.solve(y, A, k, x);
    timer.stop();
    std::cout<<"[SubspacePursuit] Done - SNR="<<std::setprecision(5)<<klab::SNR(x, x0)<<" - "
        <<"Time="<<klab::UInt32(timer.durationInMilliseconds())<<"ms"<<" - "
        <<"Iterations="<<sp.iterations()<<std::endl;
    if(bWrite)
        x.save("SubspacePursuit-Signal.csv",csv_ascii);     // Write solution to a file.

    // Compute SL0.
    std::cout<<"------------------------------"<<std::endl;
    std::cout<<"[SL0] Start."<<std::endl;
    timer.start();
    kl1p::TSL0Solver<klab::DoubleReal> sl0(tolerance);
    sl0.solve(y, A, x);
    timer.stop();
    std::cout<<"[SL0] Done - SNR="<<std::setprecision(5)<<klab::SNR(x, x0)<<" - "
        <<"Time="<<klab::UInt32(timer.durationInMilliseconds())<<"ms"<<" - "
        <<"Iterations="<<sl0.iterations()<<std::endl;
    if(bWrite)
        x.save("SL0-Signal.csv",csv_ascii); // Write solution to a file.

    // Compute AMP.
    std::cout<<"------------------------------"<<std::endl;
    std::cout<<"[AMP] Start."<<std::endl;
    timer.start();
    kl1p::TAMPSolver<klab::DoubleReal> amp(tolerance);
    amp.solve(y, A, x);
    timer.stop();
    std::cout<<"[AMP] Done - SNR="<<std::setprecision(5)<<klab::SNR(x, x0)<<" - "
        <<"Time="<<klab::UInt32(timer.durationInMilliseconds())<<"ms"<<" - "
        <<"Iterations="<<amp.iterations()<<std::endl;
    if(bWrite)
        x.save("AMP-Signal.csv",csv_ascii); // Write solution to a file

    system("pause");
    return 0;
}

程序的执行结果如下:
这里写图片描述
从结果可以看到,不同的算法所需的求解时间不同。
下面详细看看不同算法求解出的结果。
BasicPursuit的计算结果:
Basis Pursuit
OMP的求解结果:
这里写图片描述
ROMP的求解结果:
这里写图片描述
CoSaMP的求解结果:
这里写图片描述
SubspacePursuit的求解结果:
这里写图片描述
SL0的求解结果:
这里写图片描述
AMP的求解结果:
这里写图片描述

从以上结果可以看到,不同的算法求解出的结果稀疏度有较大的差别。

完成Demo程序及数据下载地址:
http://download.csdn.net/detail/computerme/9309285

Reference:
http://blog.csdn.net/jianjian1992/article/details/49387477 例子讲解
http://blog.csdn.net/u013088062/article/details/44566667 配置过程
http://blog.csdn.net/xiaoshengforever/article/details/14002843 人脸识别

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值