1

私は主にこのノートブックの例gpflow SVGPに従って、おもちゃのデータセットでモデルを(大雑把に)トレーニングして保存しようとしています

を使用してモデルを保存するとpickle(これは推奨されませんが、これがここでの主な問題だとは思いません)、いくつかの異常であり、意図しない動作であると思われるものを発見しgpflow.utilities.freeze(model)ましたpickle model。エラーを取得します。呼び出した場合gpflow.utilities.freeze(model)(返された凍結モデルを破棄)、modelエラーなしでピクルすることができます。

再現するには

最小限の再現可能な例

import numpy as np
import gpflow
import tensorflow as tf
import pickle
rng = np.random.RandomState(123)

N = 10000  # Number of training observations
X = rng.rand(N, 1)
Y = rng.randn(N, 1)
data = (X, Y)

n_inducing_vars = 100
Z = X[:n_inducing_vars]
minibatch_size = 100
n_iterations = 100

#Define model object
model = gpflow.models.SVGP(gpflow.kernels.Matern12(), gpflow.likelihoods.Bernoulli(), inducing_variable=Z, num_data=N)

#Create minibatch object
data_minibatch = (
tf.data.Dataset.from_tensor_slices(data).prefetch(
    N).repeat().shuffle(N).batch(minibatch_size)
    )
data_minibatch_it = iter(data_minibatch)
model_objective = model.training_loss_closure(data_minibatch_it)

#Define optimiser
optimizer = tf.keras.optimizers.Adam(0.001)
#Optimise both variational parameters and kernel hyperparameters.
for step in range(n_iterations):
    optimizer.minimize(model_objective,
                       var_list=model.trainable_variables
                       )

freeze = False
if not freeze:
    # pickle doesn't work
    pickle.dump(model, open('test1', 'wb'))
else:
    # if following code is executed, pickle works fine
    _ = gpflow.utilities.freeze(model)  # ignore return value
    pickle.dump(model, open('test1', 'wb'))

スタック トレースまたはエラー メッセージ

TypeError                                 Traceback (most recent call last)
<ipython-input-6-3d5f537ca994> in <module>
----> 1 pickle.dump(model, open('test1', 'wb'))

TypeError: can't pickle HashableWeakRef objects

期待される動作

pickle が最初のインスタンスで機能することを期待していたとは言いませんtensorflow。一般に、関連するオブジェクトを保存する推奨される方法ではないことを知っているからです。ただし、最初のインスタンスでは失敗するが、2 番目のインスタンスでは成功するとは考えていません。コードベースを見ると、 mutatinggpflow.utilities.freeze(model)すべきではないと思いますがmodel、それはやっているようです。

システムインフォメーション

  • GPflow バージョン 2.0.0 ... 2.0.4 でテスト済み
  • TensorFlow バージョン: 2.1.0、tensorflow_probability 0.9.0
  • Python バージョン: Python 3.6.9

freezeそれを呼び出すと、model実際にmodelは「固定された」モデルに不可解に変換され、それが「一定の」プロパティを持つようになると思います ( https://gpflow.readthedocs.io/en/master/notebooks/intro_to_gpflow2.html#TensorFlow- saved_model ) を使用して、ピクルスにすることができます。

この問題について明確にしていただければ幸いです。

注: これissuegpflow github( https://github.com/GPflow/GPflow/issues/1493 ) に投稿しましたが、この問題はここでより広い gpflow コミュニティにブロードキャストする必要があると判断されました。

4

2 に答える 2

1

以下の行で何が起こるか見てみましょう。

if not freeze:
    # pickle doesn't work
    pickle.dump(model, open('test1', 'wb'))  # Line 1
else:
    # if following code is executed, pickle works fine
    gpflow.utilities.freeze(model)           # Line 2
    pickle.dump(model, open('test1', 'wb'))  # Line 3

Line 1トレーニングされたモデルには、TensorFlow 確率バイジェクターを、制約のある空間から制約のない空間へ、およびその逆のトランスフォーマーとして保持するインスタンスが含まれていますParameters。TFP bijector は、すべての順方向および逆方向の計算をキャッシュします。bijector のキャッシュはマップを使用して実装されます。ここで、キーは forward および inverse 関数のテンソル入力であり、値は同様にテンソルである返されるオブジェクトです。残念ながら、テンソル (np.arrays など) はハッシュできず、そのために TFPHashableWeakRefはテンソルのラッパーを実装しました。エラー メッセージ"TypeError: can't pickle HashableWeakRef objects"は誤解を招きます。それは実際にそれを意味しますHashableWeakRefまだ作成されていないオブジェクトへの参照であるため、python はそのインスタンスのコピーを作成できません。結果として、これらのオブジェクトはピクルできません。

Line 2にはfreeze、2 つの呼び出しで構成されるメソッドがあります。最初の呼び出しは bijector のコンテンツ、つまりキャッシュを削除し、2 番目の呼び出しはcopy.deepcopyです。背後にある魔法freezeは、参照を削除することです。はい、既存のオブジェクトを変更しますが、熱心な計算にもtf.functioned 関数にも影響しません。クリーニングがdeepcopy可能になります。

Line 3オブジェクトにはコピーする参照がないため、機能します。

この問題には、GPflow 内での報告と修正の長い追跡があります: TFP#547TFP#944GPflow#1479GPflow#1293GPflow#1338

これは、TensorFlow 確率で提案された修正です: TFP#947

于 2020-06-03T15:09:17.380 に答える