今天在将matlab中去趋势代码转换到python中时,发现两者spdiags(提取并创建稀疏带状和对角矩阵)有所不同
代码:
matlab:
spdiags(ones(632,1)*[1 -2 1],[0 1 2],632,634)
1、[1,-2,1]重复632行
2、生成的[632,634]矩阵里,对角线都是[1 -2 1]的第一个1(对角线意思是从左上 开始的对角,与是否为方阵无关),对角线右边第1个数都是-2,对角线右边第2个数都是1。
由此生成了要的稀疏对角矩阵
python
首先要明白matlab和python语言spdiags的不同,python中numpy中生成稀疏阵,是行检索生成,matlab是列检索生成。可见
https://stackoverflow.com/questions/31900043/spdiags-in-matlab-into-python
其中python矩阵生成了就必须有转置操作
由此python代码:
import scipy as sp
sp.sparse.spdiags((np.ones((632,1))*[1, -2, 1]).transpose(), [0, 1, 2], 632, 634)
按理说转置了是可以的,但经过排查发现最后两行有差错少了几个数(可能是对函数理解不到位)
最后python纠正代码如下:
#N=上面的634
D2 = sp.sparse.spdiags((np.ones((N-2,1))*[1, -2, 1]).transpose(), [0, 1, 2], N-2, N)
a = np.zeros((N-2,N),dtype=np.int)
a[N-4,N-2] = 1
a[N-3,N-2] = -2
a[N-3,N-1] = 1
D2 = D2 + a
花了我2个多小时,坑爹啊~
2020.6.1
我又来了,因为我代码放置的很乱,导致差点我自己写的代码都找不到,现在把这个函数全部代码都贴上来
matlab
function detrenddata=detrend(data)
%%去趋势
%%去趋势
N=length(data);
lambda = 400;
I = speye(N);
D2 = spdiags(ones(N-2,1)*[1 -2 1],[0 1 2],N-2,N);
trend = inv(I+lambda^2*D2'*D2)* data;
detrenddata = data-trend;
end
对应的python
len是green数据的长度,因为我一直len()出错,有缘人请指出我错在哪,我用python最大的感触就是明明是数组,却len不出来…
def detrend(green, len):
N = len
lamda = 400
I = np.eye(N)
green = np.array(green).reshape(len, 1)
D2 = sparse.spdiags((np.ones((N - 2, 1)) * [1, -2, 1]).transpose(), [0, 1, 2], N - 2, N)
a = np.zeros((N - 2, N), dtype=np.int)
a[N - 4, N - 2] = 1
a[N - 3, N - 2] = -2
a[N - 3, N - 1] = 1
D2 = D2 + a
trend = np.linalg.inv(I + math.pow(lamda, 2) * D2.transpose() * D2) * green
detrend_g = green - trend
return detrend_g
再也不装逼了~