2016-09-25 7 views
1

私は少し深い学習をしており、すべての隠れたレイヤーの値を取得したいと思います。だから私はこのような関数を書き終わる:Pythonでreduceとmapを組み合わせる最もクリーンな方法

def forward_pass(x, ws, bs): 
    activations = [] 
    u = x 
    for w, b in zip(ws, bs): 
     u = np.maximum(0, u.dot(w)+b) 
     activations.append(u) 
    return activations 

私は中間の値を取得していなかった場合、私ははるかに少ない冗長な形式を使用したい:

out = reduce(lambda u, (w, b): np.maximum(0, u.dot(w)+b), zip(ws, bs), x) 

バムを。すべての1行、いいとコンパクト。しかし、私は中間値のいずれかを保つことはできません。

私のケーキ(すてきなコンパクトな1ライナー)を食べ、それを食べる方法は何ですか(中間値を返します)?

編集:これまでの私の結論:Pythonの2.xで
は、このためのクリーンワンライナーはありません。
Python 3にはitertools.accumulateがありますが、reduceのように、「初期」入力を受け付けないため、まだ実際にはクリーンではありません。

activations = [u=np.maximum(0, u.dot(w)+b) for w, b in zip(ws, bs) from u=x] 

また、通常、単にすべての輸入が行われた後、何もしないの周りに座っていることfromキーワードに有益な仕事を与えるだろう:Pythonの4で
は、私はここに、「MAP-減らすの理解」を要求します。

+1

そして、あなたが維持したいあなた '中間values'はどれですか? – Divakar

+0

'x'、' ws'、 'bs'、特にそれらの寸法について教えてください。多分、サンプルセットでさえ、出力あります。 – hpaulj

+0

'(w、b)'は私に構文エラーを与えています(Py3) – hpaulj

答えて

0

Python 2.xでは、このためにクリーンな1ライナーはありません。

itertools.accumulateがありますが、reduceのように「初期」入力を受け付けないため、まだそれほどクリーンではありません。

ここでは、組み込みの理解構文ではないものの、ジョブを実行する機能があります。

def reducemap(func, sequence, initial=None, include_zeroth = False): 
    """ 
    A version of reduce that also returns the intermediate values. 
    :param func: A function of the form x_i_plus_1 = f(x_i, params_i) 
     Where: 
      x_i is the value passed through the reduce. 
      params_i is the i'th element of sequence 
      x_i_plus_i is the value that will be passed to the next step 
    :param sequence: A list of parameters to feed at each step of the reduce. 
    :param initial: Optionally, an initial value (else the first element of the sequence will be taken as the initial) 
    :param include_zeroth: Include the initial value in the returned list. 
    :return: A list of length: len(sequence), (or len(sequence)+1 if include_zeroth is True) containing the computed result of each iteration. 
    """ 
    if initial is None: 
     val = sequence[0] 
     sequence = sequence[1:] 
    else: 
     val = initial 
    results = [val] if include_zeroth else [] 
    for s in sequence: 
     val = func(val, s) 
     results.append(val) 
    return results 

テスト:

assert reducemap(lambda a, b: a+b, [1, 2, -4, 3, 6, -7], initial=0) == [1, 3, -1, 2, 8, 1] 
assert reducemap(lambda a, b: a+b, [1, 2, -4, 3, 6, -7]) == [3, -1, 2, 8, 1] 
assert reducemap(lambda a, b: a+b, [1, 2, -4, 3, 6, -7], include_zeroth=True) == [1, 3, -1, 2, 8, 1] 
2

一般にitertools.accumulate()は、reduce()の処理を行いますが、中間値も示します。つまり、累積は開始の値をサポートしていないので、あなたのケースでは適用されません。

例:

>>> import operator, functools, itertools 
>>> functools.reduce(operator.mul, range(1, 11)) 
3628800 
>>> list(itertools.accumulate(range(1, 11), operator.mul)) 
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800] 
2

dotを使用すると、1つのまたは複数のnumpyのアレイを使用していると言われます。だから私はみます:1件の評価から次へと渡された中間値uは、リストの内包がトリッキーになりこと

In [32]: functools.reduce(lambda u, wb: np.maximum(0, 
        u.dot(wb[0])+wb[1]), zip(ws, bs), x) 
Out[32]: 
array([[ 2577, 3321, 4065], 
     [ 7599, 9801, 12003], 
     [12621, 16281, 19941]]) 

In [28]: b=np.array([1,2,3]) 
In [29]: x=np.arange(9).reshape(3,3) 
In [30]: ws=[x,x,x] 

In [31]: forward_pass(x,ws,bs) 
Out[31]: 
[array([[ 16, 19, 22], 
     [ 43, 55, 67], 
     [ 70, 91, 112]]), 
array([[ 191, 248, 305], 
     [ 569, 734, 899], 
     [ 947, 1220, 1493]]), 
array([[ 2577, 3321, 4065], 
     [ 7599, 9801, 12003], 
     [12621, 16281, 19941]])] 

PY3では、私はとしてreduceソリューションを記述する必要があります。

accumulateは最初の項目を先頭に使用します。私はその後、私はwsbsに余分開始値を追加する必要が

def foo(u, wb): 
    if u[0] is None: u=x # x from global 
    return np.maximum(0, u.dot(wb[0])+wb[1]) 

のような機能を持つことを回避することができます。

In [56]: list(itertools.accumulate(zip([None,x,x,x], np.array([0,1,2,3])), foo)) 
Out[56]: 
[(None, 0), 
array([[ 16, 19, 22], 
     [ 43, 55, 67], 
     [ 70, 91, 112]]), 
array([[ 191, 248, 305], 
     [ 569, 734, 899], 
     [ 947, 1220, 1493]]), 
array([[ 2577, 3321, 4065], 
     [ 7599, 9801, 12003], 
     [12621, 16281, 19941]])] 

ここでは、外部uを使用して、リスト内包バージョンです:

In [66]: u=x.copy() 
In [67]: def foo1(wb): 
    ...:  v = np.maximum(0, u.dot(wb[0])+wb[1]) 
    ...:  u[:]=v 
    ...:  return v 
    ...: 
In [68]: [foo1(wb) for wb in zip(ws,bs)] 
Out[68]: 
[array([[ 16, 19, 22], 
     [ 43, 55, 67], 
     [ 70, 91, 112]]), 
array([[ 191, 248, 305], 
     [ 569, 734, 899], 
     [ 947, 1220, 1493]]), 
array([[ 2577, 3321, 4065], 
     [ 7599, 9801, 12003], 
     [12621, 16281, 19941]])] 

元のループよりも実質的な利点はありません。appendです。

numpy.ufuncaccumulateメソッドを持っていますが、これはカスタムPython関数では使いにくいものです。したがって、np.maximum.accumulateがありますが、私はこのケースでどのように使用できるかわかりません。 (またnp.cumsumnp.add.accumulateである)。

+0

徹底的な答えをありがとう。内部numpyアキュムレータは、wsの異なる要素が異なる次元を持つことができるので、実際には有用ではありません。クリーンな解決策がないようです。 – Peter

関連する問題