为什么interp1d会抛出LinAlgError("SVD未收敛")?
我有一组二维点,也就是(x,y)坐标,我想通过这些点画一条三次样条曲线。为了做到这一点,我把这组点分成了两个序列,分别是xs
和ys
,它们有以下几个特点:
len(xs) = len(ys) > 4
,也就是说这两个序列的长度相等,并且都大于4xs
是严格递增的,也就是说每个值都比前一个值大
理论上来说,应该能通过这些点画出一条三次样条曲线。但是我还是遇到了一个错误:
#!/usr/bin/env python
import numpy
import scipy
from scipy.interpolate import interp1d
import sys
print("Python: %s" % sys.version)
print("numpy: %s" % numpy.__version__)
print("scipy: %s " % scipy.__version__)
print("numpy config:")
numpy.show_config()
xs = [0, 31, 39, 48, 58, 75, 91, 108, 127, 141, 158, 175, 194, 208, 224, 241, 258, 291, 310, 343, 379, 427, 444, 459, 493, 526, 560, 580, 626, 659, 693, 726, 759, 793, 826, 859, 893, 926, 958, 993, 1025, 1059, 1093, 1125, 1159, 1193, 1224, 1257, 1278, 1310, 1343, 1379, 1410, 1443, 1478, 1512, 1558, 1662, 1815, 1823, 1831, 1845, 1860, 1876]
ys = [0.7072243346007605, 0.6996197718631179, 0.6844106463878327, 0.6730038022813688, 0.6577946768060836, 0.6159695817490495, 0.5665399239543726, 0.5019011406844106, 0.43346007604562736, 0.3840304182509506, 0.3041825095057034, 0.2623574144486692, 0.23574144486692014, 0.20532319391634982, 0.155893536121673, 0.11406844106463879, 0.07984790874524715, 0.026615969581749048, 0.0076045627376425855, 0.0, 0.0, 0.0038022813688212928, 0.022813688212927757, 0.053231939163498096, 0.12927756653992395, 0.17870722433460076, 0.22433460076045628, 0.24334600760456274, 0.30798479087452474, 0.33840304182509506, 0.376425855513308, 0.3840304182509506, 0.376425855513308, 0.3574144486692015, 0.3041825095057034, 0.2509505703422053, 0.21292775665399238, 0.1520912547528517, 0.12167300380228137, 0.09885931558935361, 0.09125475285171103, 0.09125475285171103, 0.11787072243346007, 0.1596958174904943, 0.20152091254752852, 0.24714828897338403, 0.28517110266159695, 0.3155893536121673, 0.33840304182509506, 0.3688212927756654, 0.39543726235741444, 0.44106463878326996, 0.4828897338403042, 0.5057034220532319, 0.5247148288973384, 0.5285171102661597, 0.532319391634981, 0.5361216730038023, 0.5475285171102662, 0.5627376425855514, 0.5779467680608364, 0.5893536121673004, 0.6007604562737643, 0.6083650190114068]
print("xs length: %i" % len(xs))
print("ys length: %i" % len(ys))
print("Is xs strictly increasing? %r" % all(x < y for x, y in zip(xs, xs[1:])))
xs = numpy.array(xs)
fx = interp1d(xs, ys, kind='cubic')
输出结果是:
./test.py
Python: 2.7.5+ (default, Feb 27 2014, 19:37:08)
[GCC 4.8.1]
numpy: 1.8.1
scipy: 0.14.0
numpy config:
lapack_info:
NOT AVAILABLE
lapack_opt_info:
NOT AVAILABLE
blas_info:
NOT AVAILABLE
atlas_threads_info:
NOT AVAILABLE
blas_src_info:
NOT AVAILABLE
atlas_blas_info:
NOT AVAILABLE
lapack_src_info:
NOT AVAILABLE
openblas_info:
NOT AVAILABLE
atlas_blas_threads_info:
NOT AVAILABLE
blas_mkl_info:
NOT AVAILABLE
blas_opt_info:
NOT AVAILABLE
atlas_info:
NOT AVAILABLE
lapack_mkl_info:
NOT AVAILABLE
mkl_info:
NOT AVAILABLE
xs length: 64
ys length: 64
Is xs strictly increasing? True
Traceback (most recent call last):
File "./test.py", line 23, in <module>
fx = interp1d(xs, ys, kind='cubic')
File "/usr/local/lib/python2.7/dist-packages/scipy/interpolate/interpolate.py", line 412, in __init__
self._spline = splmake(x, y, order=order)
File "/usr/local/lib/python2.7/dist-packages/scipy/interpolate/interpolate.py", line 2110, in splmake
coefs = func(xk, yk, order, conds, B)
File "/usr/local/lib/python2.7/dist-packages/scipy/interpolate/interpolate.py", line 1800, in _find_smoothest
u, s, vh = np.dual.svd(B)
File "/usr/local/lib/python2.7/dist-packages/scipy/linalg/decomp_svd.py", line 103, in svd
raise LinAlgError("SVD did not converge")
numpy.linalg.linalg.LinAlgError: SVD did not converge
我的问题是:为什么interp1d
会报错LinAlgError(“SVD did not converge”)
,我该怎么解决这个问题呢?
我的系统信息
我使用的是numpy
版本1.8.1,scipy
版本0.14.0
,Python 2.7.5+
,操作系统是Linux Mint 16 Petra。
1 个回答
1
在这个链接 https://github.com/scipy/scipy/issues/3868 中发现,这是LAPACK版本3.4.2的一个错误,具体是在DGESDD这个功能上,相关的测试案例可以在这里找到 https://gist.github.com/anonymous/5e2d8e1be3d63a2d9975。
这个问题在LAPACK版本3.4.1或3.5.0中是不存在的。
要解决这个问题,你可以手动下载并安装一个更新的LAPACK包(比如对于Ubuntu系统,可以从 packages.ubuntu.com/liblapack3
下载),或者直接把你的Linux系统升级到一个更新的版本。