15

大きな編集:

================

わかりやすくするために、古い結果を削除し、新しい結果に置き換えます。質問は同じです: Cython と Numba の両方を正しく使用していますか? また、コードをどのように改善できますか? (すべてのコードと結果がここにある、より新しくて必要最小限の一時的な IPython ノートブックがあります)

1)

Cython、Numba、および CPython に最初は違いがなかった理由が分かったと思います。

入力としてnumpy配列:

x = np.asarray([x_i*np.random.randint(8,12)/10 for x_i in range(n)])

リストの代わりに:

x = [x_i*random.randint(8,12)/10 for x_i in range(n)]

データ入力として Numpy 配列を使用したベンチマーク

ここに画像の説明を入力

Python リストを入力として使用したベンチマーク

ここに画像の説明を入力

2)

関数を明示的なループに置き換えましたzip()が、大きな違いはありませんでした。コードは次のようになります。

CPython

def py_lstsqr(x, y):
    """ Computes the least-squares solution to a linear matrix equation. """
    len_x = len(x)
    x_avg = sum(x)/len_x
    y_avg = sum(y)/len(y)
    var_x = 0
    cov_xy = 0
    for i in range(len_x):
        temp = (x[i] - x_avg)
        var_x += temp**2
        cov_xy += temp*(y[i] - y_avg)
    slope = cov_xy / var_x
    y_interc = y_avg - slope*x_avg
    return (slope, y_interc) 

シトン

%load_ext cythonmagic

%%cython
def cy_lstsqr(x, y):
    """ Computes the least-squares solution to a linear matrix equation. """
    cdef double x_avg, y_avg, var_x, cov_xy,\
         slope, y_interc, x_i, y_i
    cdef int len_x
    len_x = len(x)
    x_avg = sum(x)/len_x
    y_avg = sum(y)/len(y)
    var_x = 0
    cov_xy = 0
    for i in range(len_x):
        temp = (x[i] - x_avg)
        var_x += temp**2
        cov_xy += temp*(y[i] - y_avg)
    slope = cov_xy / var_x
    y_interc = y_avg - slope*x_avg
    return (slope, y_interc)

ナンバー

from numba import jit

@jit
def numba_lstsqr(x, y):
    """ Computes the least-squares solution to a linear matrix equation. """
    len_x = len(x)
    x_avg = sum(x)/len_x
    y_avg = sum(y)/len(y)
    var_x = 0
    cov_xy = 0
    for i in range(len_x):
        temp = (x[i] - x_avg)
        var_x += temp**2
        cov_xy += temp*(y[i] - y_avg)
    slope = cov_xy / var_x
    y_interc = y_avg - slope*x_avg
    return (slope, y_interc)
4

2 に答える 2

1

組み込みの sum() を使用すると、問題が発生する可能性があります。

Numba でより高速に実行される線形回帰コードを次に示します。

@numba.jit
def ols(x, y):
    """Simple OLS for two data sets."""
    M = x.size

    x_sum = 0.
    y_sum = 0.
    x_sq_sum = 0.
    x_y_sum = 0.

    for i in range(M):
        x_sum += x[i]
        y_sum += y[i]
        x_sq_sum += x[i] ** 2
        x_y_sum += x[i] * y[i]

    slope = (M * x_y_sum - x_sum * y_sum) / (M * x_sq_sum - x_sum**2)
    intercept = (y_sum - slope * x_sum) / M

    return slope, intercept
于 2015-04-18T11:13:30.900 に答える