web-dev-qa-db-ja.com

Python用のerf()の簡単に利用可能な実装はありますか?

エラー関数erfを自分で実装することはできますが、したくないのです。 pythonこの関数の実装を含む外部依存関係のないパッケージはありますか? this が見つかりましたが、これはもっと大きなパッケージの一部であるようです(そしてどれかさえ明確ではありません!)。

49
rog

V.2.7以降。標準mathモジュールにはerf関数が含まれています。これが最も簡単な方法です。

http://docs.python.org/2/library/math.html#math.erf

62
golobor

Pythonの数値関数にはSciPyをお勧めしますが、依存関係のない関数が必要な場合は、エラーが1.5 * 10未満の関数を使用します。-7 すべての入力に対して。

def erf(x):
    # save the sign of x
    sign = 1 if x >= 0 else -1
    x = abs(x)

    # constants
    a1 =  0.254829592
    a2 = -0.284496736
    a3 =  1.421413741
    a4 = -1.453152027
    a5 =  1.061405429
    p  =  0.3275911

    # A&S formula 7.1.26
    t = 1.0/(1.0 + p*x)
    y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*math.exp(-x*x)
    return sign*y # erf(-x) = -erf(x)

アルゴリズムは 数学関数ハンドブック 、式7.1.26から来ています。

47
John D. Cook

numpy (Pythonで効率的なマトリックスを使用するため)および scipy (numpyを使用するMatlabツールボックスの代替)をダウンロードすることをお勧めします。 erf関数はscipyにあります。

>>>from scipy.special import erf
>>>help(erf)

Pylabで定義されたerf関数を使用することもできますが、これはnumpyとscipyで計算した結果のプロットを目的としています。これらのソフトウェアのオールインワンインストールが必要な場合は、 Python Enthoughtディストリビューション を直接使用できます。

25
Mapad

純粋なpython実装はmpmathモジュールにあります( http://code.google.com/p/mpmath/

Doc文字列から:

_>>> from mpmath import *
>>> mp.dps = 15
>>> print erf(0)
0.0
>>> print erf(1)
0.842700792949715
>>> print erf(-1)
-0.842700792949715
>>> print erf(inf)
1.0
>>> print erf(-inf)
-1.0
_

大きな実xの場合、\mathrm{erf}(x)は1に非常に急速に近づきます。

_>>> print erf(3)
0.999977909503001
>>> print erf(5)
0.999999999998463
_

エラー関数は奇妙な関数です::

_>>> nprint(chop(taylor(erf, 0, 5)))
[0.0, 1.12838, 0.0, -0.376126, 0.0, 0.112838]
_

:func:erfは、任意精度の評価を実装し、複素数をサポートします。

_>>> mp.dps = 50
>>> print erf(0.5)
0.52049987781304653768274665389196452873645157575796
>>> mp.dps = 25
>>> print erf(1+j)
(1.316151281697947644880271 + 0.1904534692378346862841089j)
_

関連関数

大規模なerfcに対してより正確な:func:xも参照してください。また、\exp(t^2)の逆導関数を提供する:func:erfiも参照してください。

フレネル積分:func:fresnelsおよび:func:fresnelcもエラー関数に関連しています。

8

10 ^ 5 erf呼び出しを行う関数があります。私のマシンで...

scipy.special.erfは、6.1sで時間を調整します

erf数学関数ハンドブックには8.3秒かかります

erf Numerical Recipes 6.2には9.5秒かかります

(3回の平均、上記のポスターから取られたコード)。

6
meteore

私自身の質問に答えるために、私はJavaウェブ上のどこかで見つけたバージョンから適応した以下のコードを使用することになりました:

# from: http://www.cs.princeton.edu/introcs/21function/ErrorFunction.Java.html
# Implements the Gauss error function.
#   erf(z) = 2 / sqrt(pi) * integral(exp(-t*t), t = 0..z)
#
# fractional error in math formula less than 1.2 * 10 ^ -7.
# although subject to catastrophic cancellation when z in very close to 0
# from Chebyshev fitting formula for erf(z) from Numerical Recipes, 6.2
def erf(z):
    t = 1.0 / (1.0 + 0.5 * abs(z))
        # use Horner's method
        ans = 1 - t * math.exp( -z*z -  1.26551223 +
                            t * ( 1.00002368 +
                            t * ( 0.37409196 + 
                            t * ( 0.09678418 + 
                            t * (-0.18628806 + 
                            t * ( 0.27886807 + 
                            t * (-1.13520398 + 
                            t * ( 1.48851587 + 
                            t * (-0.82215223 + 
                            t * ( 0.17087277))))))))))
        if z >= 0.0:
            return ans
        else:
            return -ans
6
rog

より高いパフォーマンスを目指している人への注意:可能であれば、ベクトル化。

import numpy as np
from scipy.special import erf

def vectorized(n):
    x = np.random.randn(n)
    return erf(x)

def loopstyle(n):
    x = np.random.randn(n)
    return [erf(v) for v in x]

%timeit vectorized(10e5)
%timeit loopstyle(10e5)

結果を与える

# vectorized
10 loops, best of 3: 108 ms per loop

# loops
1 loops, best of 3: 2.34 s per loop
4
8one6