为什么interp1d抛出LinAlgError(“SVD没有收敛”)?

时间:2014-08-12 16:20:20

标签: python scipy interpolation spline

我有一系列2维点(所以:(x,y)坐标),我希望通过它拟合三次样条。因此,我将序列分为两个序列xsys,其中包含以下属性:

  • len(xs) = len(ys) > 4
  • xs正在严格增加

因此通过这些点应该存在三次样条曲线。但我仍然得到一个错误:

#!/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”)以及如何解决?

我的系统

我在Linux Mint 16 Petra上有numpy版本1.8.1,scipy版本0.14.0Python 2.7.5+

1 个答案:

答案 0 :(得分:1)

正如在https://github.com/scipy/scipy/issues/3868中发现的,这是LAPACK版本3.4.2 DGESDD例程中的一个错误,正如纯Fortran测试用例所示https://gist.github.com/anonymous/5e2d8e1be3d63a2d9975

使用LAPACK版本3.4.1或3.5.0时,问题不存在。

要解决此问题,请手动下载并安装较新的LAPACK程序包(例如,对于packages.ubuntu.com/liblapack3中的Ubuntu衍生程序),或者只是将Linux发行版升级到较新版本。