levmar库给出了一个很好的LM算法实现。可是在处理实际问题中,我们要求解的参数可能非常多,而且这些参数之间关联性不大,这就造成了输入到LM算法的Jacobian矩阵规模很大,而且非常sparse。如果直接传给LM算法,很可能out of memery。这也是levmar的sparse版本sparseLM产生的动机。
相较于levmar,sparseLM依赖于更多的库来处理稀疏性,因此无论是c++版本还是matlab版本,sparseLM的编译要繁琐一些。
首先,下载最新版本的sparseLM,我用的是1.3。sparseLM中推荐使用cholmod库作为sparse solver,这个库是在linux/unix下开发的,移植到win系统下非常不方便。官方的做法使用cygwin(一个在win系统上运行的unix虚拟环境)来编译。由于这个过程非常折腾,我选择了另外一种更简便的方法,下载win系统下编译好的cholmod库。原始的下载地址已经被墙了,我将下载后的文件上传到了csdn上(地址)。
和levmar一样,lapack/blas也是需要的。同样我也是使用win下编译好的文件(地址)。
以上几步做好之后,用cmake打开sparseLM源代码所在目录,设置好build的目录。configure之后,将几个变量的值改成相应的目录名和lib文件名。接着,在msvc环境下编译,会出现这个错误error C2485: '__restrict' : unrecognized extended attribute。Ctri F 搜索#define restrict __restrict,在compiler.h中找到这个宏定义,注释掉这个宏。之后编译成功。
最后,进入matlab目录,进行mex编译。首先编译 sparselm_spsolvr.c,我本机的mex命令是:
mex -IE:\library\sparselm-1.3\ sparselm_spsolvr.c
然后编译 sparselm.c,我的mex命令是:
mex -DHAVE_LARGE_ARRAYS -IE:\library\sparselm-1.3\ sparselm.c -LE:\library\sparselm-1.3\build\Release\ -LE:\library\cholmod\lib\ -LE:\library\lapack-MD-release\ -lsplm -llibcholmod -llibamd -llibcamd -llibcolamd -llibccolamd -llapack_win32_MD -lblas_win32_MD -llibmetis_CHOLMOD
这个mex命令虽然很长,其实并不复杂,我前一篇文章也有介绍类似的mex命令(地址)。简单解释下:
-IE:\library\sparselm-1.3\ #include文件目录
-LE:\library\sparselm-1.3\build\Release\ splm.lib所在目录
-LE:\library\cholmod\lib\ libcholmod.lib libamd.lib libcamd.lib libcolamd.lib libccolamd.lib llibmetis_CHOLMOD.lib所在目录
-LE:\library\lapack-MD-release\ llapack_win32_MD.lib lblas_win32_MD.lib所在目录
后面都是以上lib文件的声明,主要不要加.lib后缀。
将两个dll,lapack_win32_MD.dll和blas_win32_MD.dll拷贝到matlab工作目录,运行splmdemo.m,如果能得到结果,则编译成功。