1

実験中に生成されたデータを処理するプログラムをPythonで作成していますが、データの傾きを推定する必要があります。私はこれを非常にうまく行うコードを書きましたが、それはひどく遅いです(そして私はあまり辛抱強くありません)。このコードがどのように機能するかを説明しましょう。

1)サイズdxの小さなデータを取得します(3つのデータポイントから開始)

2)差(すなわち| y(x + dx)-y(x-dx)|)が特定の最小値(40x標準偏差のノイズ)よりも大きいかどうかを評価します。

3)差が十分に大きい場合は、OLS回帰を使用して勾配を計算します。差が小さすぎると、dxが増加し、この新しいdxでループをやり直します。

4)これはすべてのデータポイントで継続されます

[さらに下の更新されたコードを参照してください]

約100kの測定値のデータサイズの場合、これには約40分かかりますが、プログラムの残りの部分(このビットよりも多くの処理を実行します)には約10秒かかります。これらの操作を行うにはもっと効率的な方法があると確信しています。皆さん、私を助けてくれませんか?

ありがとう

編集:

さて、私は二分探索のみを使用して問題を解決し、許可されるステップ数を200に制限しました。すべての人の入力に感謝し、最も役立つ答えを選択しました。

最終的に更新されたコード:

def slope(self, data, time):
    (wave1, wave2) = wt.dwt(data, "db3")
    std = 2*np.std(wave2)
    e = std/0.05
    de = 5*std
    N = len(data)
    slopes = np.ones(shape=(N,))
    data2 = np.concatenate((-data[::-1]+2*data[0], data, -data[::-1]+2*data[N-1]))
    time2 = np.concatenate((-time[::-1]+2*time[0], time, -time[::-1]+2*time[N-1]))
    for n in xrange(N+1, 2*N):     
        left = N+1
        right = 2*N
        for i in xrange(200):
            mid = int(0.5*(left+right))
            diff = np.abs(data2[n-mid+N]-data2[n+mid-N])
            if diff >= e:
                if diff < e + de:  
                    break
                right = mid - 1
                continue
            left = mid + 1
        leftlim = n - mid + N
        rightlim = n + mid - N
        y = data2[leftlim:rightlim:int(0.05*(rightlim-leftlim)+1)]
        x = time2[leftlim:rightlim:int(0.05*(rightlim-leftlim)+1)]
        xavg = np.average(x)
        yavg = np.average(y)
        xlen = len(x)
        slopes[n-N] = (np.dot(x,y)-xavg*yavg*xlen)/(np.dot(x,x)-xavg*xavg*xlen)
    return np.array(slopes) 
4

3 に答える 3

0

これを最適化する方法は、データのいくつかのプロパティによって異なりますが、ここにいくつかのアイデアがあります。

  1. コードのプロファイリングを試しましたか?Pythonプロファイラーの1つを使用すると、最も時間がかかっているものに関する有用な情報を得ることができます。多くの場合、作成したばかりのコードには1つの最大のボトルネックがあり、それがどの部分であるかが常に明らかであるとは限りません。プロファイリングを使用すると、それを把握して、最初に主要なボトルネックを攻撃できます。

  2. の典型的な値を知っていますiか?何らかのアイデアがある場合はi、0より大きい値から始めるか(@vhallacで説明)、またはi大きく増やすことで処理を高速化できます。の値が大きい場合は、一度に2または3ずつi増やします。isの分布のiテールが長い場合は、毎回2倍にしてみてください。等

  3. 最小二乗回帰を行うときにすべてのデータが必要ですか?その関数呼び出しがボトルネックである場合は、範囲内の一部のデータのみを使用することで、関数呼び出しを高速化できる場合があります。たとえば、特定の時点でi、データに十分な大きさの(ノイズを超える)変化を確認するには、200である必要があるとします。ただし、勾配を適切に見積もるのに400ポイントすべてが必要なわけではありません。start:end範囲内で等間隔に配置された、10ポイントまたは20ポイントを使用するだけで十分であり、コードが大幅に高速化される可能性があります。

于 2012-11-25T19:50:15.970 に答える
0

あなたのコメントは、ikが与えられたときにik +1を推定するためのより良い方法を見つける必要があることを示唆しています。の値に関する知識がない場合、単純なアルゴリズムになります。data

の各反復で、前の値のnままにして、値が。未満であるかどうかを確認します。そうである場合は、以前の値のままにして、現在のように1ずつ増やして新しい値を見つけます。それ以上の場合は、でバイナリ検索を実行して適切な値を見つけます。二分探索を転送することもできますが、知識がなくても適切な候補の上限を見つけるのは難しい場合があります。このアルゴリズムは、現在の推定方法よりもパフォーマンスが低下することはありません。iabs(data[start]-data[end])eiidata

dataそれが一種の滑らかで(突然のジャンプがなく、したがってすべての値に対して滑らかなプロットである)、単調に増加することがわかっている場合はi、代わりに値を1ずつ減らすことで、バイナリ検索を逆方向の検索に置き換えることができます。

于 2012-11-25T20:34:38.387 に答える
0

私はPythonを使用して同様の分析を行っており、いくつかの提案があります。私はあなたのコードの詳細を見ませんでした、あなたの問題の声明だけに。

1)サイズdxの小さなデータを取得します(3つのデータポイントから開始)

2)差(すなわち| y(x + dx)-y(x-dx)|)が特定の最小値(40x標準偏差のノイズ)よりも大きいかどうかを評価します。

3)差が十分に大きい場合は、OLS回帰を使用して勾配を計算します。差が小さすぎると、dxが増加し、この新しいdxでループをやり直します。

4)これはすべてのデータポイントで継続されます

実行が遅い理由のより明白な理由は、おそらくNumpyのVECTORIZED(配列ベースの操作)の性質を使用できる場合に、コードのLOOPINGの性質であると思います。

ステップ1では、ポイントのペアを取得する代わりに、直接 `data [3:] --data [-3:]を実行して、単一の配列操作ですべての違いを取得できます。

numpy.argwhere(data > threshold)ステップ2では、ループ内のすべての要素をテストする代わりに、配列ベースのテストの結果を使用できます。

ステップ3は私には概念的に間違っているように聞こえます。差が小さすぎると増加するとおっしゃっていますdx。ただし、差が小さい場合、実際には小さいため、結果の勾配は小さくなります。次に、小さな値を取得することは正しい結果でありdx、「より良い」結果を得るために人為的に増やすことは、あなたが望むものではないかもしれません。まあ、それは実際にはあなたが望むものかもしれませんが、あなたはこれを考慮する必要があります。データ全体にわたる固定の勾配を計算しdx、結果の勾配の配列を取得して、関心領域を選択することをお勧めします(たとえば、を使用しdata_slope[numpy.argwhere(data_slope > minimum_slope)]ます。

お役に立てれば!

于 2012-11-28T16:01:12.007 に答える