web-dev-qa-db-ja.com

変数としてカスタムテンソルを持つTensorFlow 2.0 Kerasレイヤー

TF 1.xでは、カスタム変数を使用してレイヤーを構築することが可能でした。次に例を示します。

import numpy as np
import tensorflow as tf

def make_custom_getter(custom_variables):
    def custom_getter(getter, name, **kwargs):
        if name in custom_variables:
            variable = custom_variables[name]
        else:
            variable = getter(name, **kwargs)
        return variable
    return custom_getter

# Make a custom getter for the dense layer variables.
# Note: custom variables can result from arbitrary computation;
#       for the sake of this example, we make them just constant tensors.
custom_variables = {
    "model/dense/kernel": tf.constant(
        np.random.Rand(784, 64), name="custom_kernel", dtype=tf.float32),
    "model/dense/bias": tf.constant(
        np.random.Rand(64), name="custom_bias", dtype=tf.float32),
}
custom_getter = make_custom_getter(custom_variables)

# Compute hiddens using a dense layer with custom variables.
x = tf.random.normal(shape=(1, 784), name="inputs")
with tf.variable_scope("model", custom_getter=custom_getter):
    Layer = tf.layers.Dense(64)
    hiddens = Layer(x)

print(Layer.variables)

構築された稠密層の出力される変数は、custom_variables辞書で指定したカスタムテンソルになります。

[<tf.Tensor 'custom_kernel:0' shape=(784, 64) dtype=float32>, <tf.Tensor 'custom_bias:0' shape=(64,) dtype=float32>]

これにより、custom_variablesで提供されたテンソルを重みとして直接使用するレイヤー/モデルを作成できるため、custom_variablesが依存する可能性のあるすべてのテンソルに関してレイヤー/モデルの出力をさらに区別できます(特に modulating sub-netsparameter generationmeta-learning などに機能を実装するのに役立ちます)。

変数スコープを使用すると、スコープ内のすべてのグラフ作成をカスタムゲッターにネストし、パラメーターとして提供されたテンソルの上にモデルを作成することが簡単になります。セッションと変数のスコープはTF 2.0では推奨されなくなったため(そしてその低レベルのものがすべてtf.compat.v1に移動されました)、ベストプラクティスKerasとTF 2.0を使用して上記を実装するには?

(関連 GitHubの問題

5
maruan

以下のコメントに基づいて回答

あなたが持っているとすると:

_kernel = createTheKernelVarBasedOnWhatYouWant() #shape (784, 64)
bias = createTheBiasVarBasedOnWhatYouWant() #shape (64,)
_

Denseからコードをコピーする簡単な関数を作成します。

_def custom_dense(x):
    inputs, kernel, bias = x

    outputs = K.dot(inputs, kernel)
    outputs = K.bias_add(outputs, bias, data_format='channels_last')
    return outputs
_

Lambdaレイヤーで関数を使用します。

_layer = Lambda(custom_dense)
hiddens = layer([x, kernel, bias])
_

警告:kernelおよびbiasは、Kerasレイヤーから生成するか、kernel = Input(tensor=the_kernel_var)およびbias = Input(tensor=bias_var)から生成する必要があります


上記の警告が適切でない場合は、次のようにkernelおよびbias "from outside"をいつでも使用できます。

_def custom_dense(inputs):
    outputs = K.dot(inputs, kernel) #where kernel is not part of the arguments anymore
    outputs = K.bias_add(outputs, bias, data_format='channels_last')
    return outputs

layer = Lambda(custom_dense)
hiddens = layer(x)
_

この最後のオプションでは、モデルの保存/読み込みが少し複雑になります。

古い答え

おそらく、Keras Denseレイヤーを使用し、標準的な方法で重みを設定する必要があります。

_layer = tf.keras.layers.Dense(64, name='the_layer')
layer.set_weights([np.random.Rand(784, 64), np.random.Rand(64)])
_

これらの重みをトレーニングできないようにする必要がある場合は、設定したケラスモデルをコンパイルする前に:

_model.get_layer('the_layer').trainable=False
_

テンソルとして変数に直接アクセスする場合は、次のとおりです。

_kernel = layer.kernel    
bias = layer.bias
_

他にもたくさんのオプションがありますが、それはあなたの正確な意図に依存しますが、質問では明確ではありません。

2
Daniel Möller