Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Matlab和Python中fmin和fminsearch结果的差异_Python_Matlab_Scipy Optimize - Fatal编程技术网

Matlab和Python中fmin和fminsearch结果的差异

Matlab和Python中fmin和fminsearch结果的差异,python,matlab,scipy-optimize,Python,Matlab,Scipy Optimize,我的目标是对一些衰变数据(通过CPMG的核磁共振T2衰变)执行逆拉普拉斯变换。为此,我们提供了CONTIN算法。这个算法很简单,而且效果很好。我想将这段代码改编成Python。问题的核心是使用scipy.optimize.fmin,它不会以任何类似于Matlab的fminsearch的方式最小化均方偏差(MSD)。后者的结果是很好的最小化,而前者则不是 我已经用Python一行一行地阅读了我的改编代码,以及原始的Matlab。我检查了每个矩阵和每个输出。我用它来确定临界点在fmin中。我还尝试了

我的目标是对一些衰变数据(通过CPMG的核磁共振T2衰变)执行逆拉普拉斯变换。为此,我们提供了CONTIN算法。这个算法很简单,而且效果很好。我想将这段代码改编成Python。问题的核心是使用
scipy.optimize.fmin
,它不会以任何类似于Matlab的
fminsearch
的方式最小化均方偏差(MSD)。后者的结果是很好的最小化,而前者则不是

我已经用Python一行一行地阅读了我的改编代码,以及原始的Matlab。我检查了每个矩阵和每个输出。我用它来确定临界点在
fmin
中。我还尝试了
scipy.optimize.minimize
和其他最小化算法,但没有一个能给出一点令人满意的结果

我已经为Python和Matlab制作了两个MWE,以使其对所有人都具有可复制性。示例数据来自matlab函数的文档。如果这是一段很长的代码,我很抱歉,但我真的不知道如何在不牺牲可读性和清晰性的情况下缩短它。我试着让线条尽可能地吻合。我正在Windows8.1上使用Python 3.7.3、ScipyV1.3.0、Numpy1.16.2、MatlabR2018B。这是一个相对较新的Anaconda安装(约束条件中的0): g=np.abs(g) g0=g 打印('新猜测',g) 打印('g'的最终msd',msdfit) #形象化的适合 plt.plot(s,g,label='初始近似') plt.plot(np.logspace(-3,6,11),np.array([0,0,10.1625,25.1974,21.8711,1.6377,7.3895,8.736,1.4256,0,0]),label='Distribution to match') plt.xscale('log') plt.legend() plt.show() Matlab:

%目标:匹配此分发
g0=[0 0 10.1625 25.1974 21.8711 1.6377 7.3895 8.736 1.4256 0];
s0=对数空间(-3,6,长度(g0));
t=linspace(0.01500100)';
[sM,tM]=meshgrid(s0,t);
A=exp(-tM./sM);
rng(1);
%使用一些随机噪声从初始分布创建数据。
数据=A*g0+0.07*rand(尺寸(t));
%参数和功能启动
alpha=1e-2;%正则化参数
s=日志空间(-3,6,20);%x ILT
g0=个(大小);%ILT y的初始猜测值
y=数据;%含噪数据
options=optimset('MaxFunEvals',1e8,'MaxIter',1e8);%fminsearch的约束
约束={'g>0','zero_at_the_extrements'};%MSD约束
R=零(长度(g0)-2,长度(g0));
w=个数(y(:));
[sM,tM]=网格网格(s,t);
A=exp(-tM./sM);
g0=g0*sum(y)/sum(A*g0);%对分布进行“更好的猜测”
disp('输入数据的msd:')
显示(msd(g0、y、A、alpha、R、w、约束))
对于k=1:5
[g,msdfit]=fminsearch(@msd,g0,options,y,A,alpha,R,w,约束);
if ismember(“极端情况下为零”,约束)
g(1)=0;
g(end)=0;
结束
如果ismember('g>0',约束)
g=abs(g);
结束
g0=g;
结束
disp(“新猜测”)
显示(g)
disp(‘g’的最终msd’)
显示(msdfit)
%形象化的适合
半对数X(s,g)
等等
半对数x(对数空间(-3,6,11),[0 0 10.1625 25.1974 21.8711 1.6377 7.3895 8.736 1.4256 0])
图例(‘一次近似’、‘匹配分布’)
拖延
函数out=msd(g,y,A,alpha,R,w,约束)
%msd:均方偏差;这是函数
%这必须通过fminsearch最小化
%约束和任何“先验”知识
if ismember(“极端情况下为零”,约束)
g(1)=0;
g(end)=0;
结束
如果ismember('g>0',约束)
g=abs(g);%对于每个i必须是g(i)>=0
结束
r=diff(diff(g(1:end));%g的二阶导数
yfit=A*g;
%加权平方残差和
VAR=总和(w.*(y-yfit)。^2);
%正则化子
REG=α^2*和((r-r*g)。^2);
%要最小化的输出
out=VAR+REG;
结束
下面是Python中的优化

下面是Matlab中的优化

我在开始之前检查了g0的MSD输出,两者都给出了2651的值。最小化后,Python上升到4547,Matlab下降到0.1381


我认为问题是以下之一。这是在我的实现中,也就是说,我使用了
fmin
错误,或者我有一些其他的段落出错了,但我不知道是什么。事实上,MSD增加了,而它本应使用最小化函数来减少,这是一个糟糕的事实。阅读文档,scipy实现是不同的与Matlab不同(他们使用Lagarias中描述的Nelder-Mead方法),而scipy使用原始Nelder-Mead)。也许这影响很大?或者也许我最初的猜测对scipy的算法来说太糟糕了?

所以,我发布这篇文章已经有很长时间了,但我想分享我最后学到的东西和做的事情

CPMG数据的拉普拉斯逆变换有点用词不当,更恰当地称之为反演。一般问题是求解第一类Fredholm积分。一种方法是Tikhonov正则化方法。事实证明,你可以很容易地用numpy描述这个问题,并用一个scipy包解决它,所以我不必用这个“重新发明”轮子

我使用了所示的解决方案,这里的名称反映了该解决方案

def tikhonov_regularized_inversion(
    kernel: np.ndarray, alpha: float, data: np.ndarray
) -> np.ndarray:
    data = data.reshape(-1, 1)
    I = alpha * np.eye(*kernel.shape)
    C = np.concatenate([kernel, I], axis=0)
    d = np.concatenate([data, np.zeros_like(data)])
    x, _ = nnls(C, d.flatten())
这里,
kernel
是一个包含所有可能的指数衰减曲线的矩阵,我的解决方案判断我收到的数据中每个衰减曲线的贡献。首先,我将数据堆叠为一列,然后用零填充,创建向量
d
。然后,我将内核堆叠在一个对角线矩阵上,该矩阵包含正则化参数
alpha
,沿着对角线,大小与内核相同。最后,我调用方便的
nnls
,它是
scipy.optimize
中的一个非负最小二乘解算器。这是因为没有理由有负面贡献,只有没有贡献


这解决了我的问题,它既快捷又方便。

所以,我发布这篇文章已经有很长时间了,但我想分享我最终学到的东西和做的事情

反圈