複素数をサポートするNNを構築しています。現在、複雑なアクティベーションに取り組んでいます。Benjioの論文によると、これは良いものです。
ここで、bは学習するトレーニング可能なパラメーターです。そのため、このアクティベーションを行うための特別なレイヤーを構築しています。私はKerasを初めて使用し、すでに立ち往生しています。以下でこのコードを作成しましたが、ビルド関数でエラーが発生します。何が起こっているのかわかりません。テンプレートをコピーしようとしました。助けてください。
class modrelu(Layer):
def __init__(self, **kwargs):
super(modrelu, self).__init__(**kwargs)
def build(self):
self.b= K.variable(value=np.random.rand()-0.5, dtype='float64')
super(modrelu, self).build() # Be sure to call this at the end
def call(self, x):
assert isinstance(x, list)
ip_r, ip_i = x
comp= tf.complex(ip_r, ip_i )
ABS= tf.math.abs(comp)
ANG= tf.math.angle(comp)
ABS= K.relu( self.b + ABS)
op_r= ABS * K.sin(angle) #K.dot ??
op_i= ABS * K.cos(angle)
return [op_r, op_i]
def compute_output_shape(self, input_shape):
assert isinstance(input_shape, list)
shape_a, shape_b = input_shape
return [shape_a, shape_b]
私のコードへのコメント:初期化では何も追加しませんでした。インスタンス化されたときに入力を受け取らないアクティベーションレイヤーであるためです。
buildメソッドで、bを追加しようとしました。self.add_weightメソッドを使用する必要があるかどうかわかりません。理想的には、入力の次元と同じ数のbが必要です。
この呼び出しメソッドでは、私が何をしているのかかなり確信しています。簡単です。関数を実装しただけです。
最後のcompute_output_shapeは、テンプレートをコピーして貼り付けました。出力は入力と同じである必要があります。これは単なるアクティベーションレイヤーであるためです。
最後に、その価値の誤り、私はそれがナンセンスであることを知っています
TypeError Traceback (most recent call last)
<ipython-input-5-3101a9226da5> in <module>
1 a=K.variable(np.array([1,2]))
2 b=K.variable(np.array([3,4]))
----> 3 act([a,b])
~\AppData\Local\conda\conda\envs\python36\lib\site-packages\keras\engine\base_layer.py in __call__(self, inputs, **kwargs)
429 'You can build it manually via: '
430 '`layer.build(batch_input_shape)`')
--> 431 self.build(unpack_singleton(input_shapes))
432 self.built = True
433
TypeError: build() takes 1 positional argument but 2 were given
コードにはいくつかの問題があります。
まず、インタプリタから発生するエラーに対処する必要があります。
TypeError: build() takes 1 positional argument but 2 were given
build
この方法は、取るべきinput_shape
引数を。したがって、ビルドメソッドを次のように宣言する必要がありますbuild(self, input_shape)
2番目の問題は、build
メソッド内の変数の未定義の形状です。変数の形状を明示的に宣言する必要があります。あなたの場合、np.random.rand
配列はinput_shape
形でなければなりません。
もう1つの問題は[op_r, op_i]
、call
メソッドで2つの結果()を返そうとしていることです。私はKerasの専門家ではありませんが、私が知る限り、あなたはそれを行うことができません。すべてのKerasレイヤーには1つだけの出力が必要です。詳細については、こちらをご覧ください:https://github.com/keras-team/keras/issues/3061
ただし、tensorflowバックエンドを使用する場合は、複素数(tf.complex
)を使用して、複素数の実数(op_r
)とイメージ(op_i
)の両方の部分を返すことができます。
これは、modrelu
簡単な使用例を使用したレイヤーの実際の実装です。これは、KerasAPIの独自の実装とともに配布されるTensorFlow1.12.0用に書かれていますが、元のKerasに簡単に採用できると思います。
import tensorflow as tf
from tensorflow.python.keras import backend as K
from tensorflow.python.keras.engine import Layer
import numpy as np
class modrelu(Layer):
def __init__(self, **kwargs):
super(modrelu, self).__init__(**kwargs)
# provide input_shape argument in the build method
def build(self, input_shape):
# You should pass shape for your variable
self.b= K.variable(value=np.random.rand(*input_shape)-0.5,
dtype='float32')
super(modrelu, self).build(input_shape) # Be sure to call this at the end
def call(self, inputs, **kwargs):
assert inputs.dtype == tf.complex64
ip_r = tf.math.real(inputs)
ip_i = tf.math.imag(inputs)
comp = tf.complex(ip_r, ip_i )
ABS = tf.math.abs(comp)
ANG = tf.math.angle(comp)
ABS = K.relu(self.b + ABS)
op_r = ABS * K.sin(ANG) #K.dot ??
op_i = ABS * K.cos(ANG)
# return single tensor in the call method
return tf.complex(op_r, op_i)
real = tf.constant([2.25, 3.25])
imag = tf.constant([4.75, 5.75])
x = tf.complex(real, imag)
y = modrelu()(x)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(y))
PS:私は数学をチェックしなかったので、あなたは自分でそれをチェックするべきです。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加