Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/ja/guide/migrate/tf1_vs_tf2.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

TensorFlow 1.x ず TensorFlow 2 の比范 - 動䜜ず API

内郚では、TensorFlow 2 は TF1.x ずは根本的に異なるプログラミングパラダむムに埓っおいたす。

このガむドでは、動䜜ず API に関する TF1.x ず TF2 の基本的な違いず、これらすべおが移行過皋にどのように関連するかに぀いお説明したす。

䞻な倉曎点の党䜓的な抂芁

基本的に、TF1.x ず TF2 は、実行TF2 では eager、倉数、制埡フロヌ、テン゜ル圢状、およびテン゜ル等䟡比范に関しお、異なる䞀連のランタむム動䜜を䜿甚したす。TF2 ず互換性を持たせるには、コヌドが TF2 動䜜の完党なセットず互換性がある必芁がありたす。移行䞭に、これらの動䜜のほずんどを tf.compat.v1.enable_* たたは tf.compat.v1.disable_* API を介しお個別に有効たたは無効にするこずができたす。1 ぀の䟋倖は、コレクションの削陀です。これは、Eager execution の有効化/無効化の副䜜甚です。

TensorFlow 2 の抂芁は次のずおりです。

  • 冗長な API を削陀したす。

  • API の䞀貫性を高めたす。䟋えば、統合 RNN や統合オプティマむザなどです。

  • セッションよりも関数を優先し、グラフずコンパむルの自動制埡䟝存関係を提䟛する tf.function ずずも に Eager execution がデフォルトで有効になっおいる Python ランタむムずの統合を改善したす。

  • グロヌバルグラフコレクションを非掚奚にしたす。

  • ReferenceVariables よりも ResourceVariables を䜿甚しお、倉数の同時実行のセマンティクスを倉曎したす。

  • 関数ベヌスの埮分可胜な制埡フロヌ制埡フロヌ v2をサポヌトしたす。

  • tf.compat.v1.Dimension オブゞェクトの代わりに int を保持するように TensorShape API を簡玠化したす。

  • テン゜ルの等䟡性の仕組みを曎新したす。TF1.x では、テン゜ルず倉数の == 挔算子がオブゞェクト参照の等䟡性をチェックしたす。TF2 では、倀の等䟡性をチェックしたす。さらに、テン゜ル/倉数はハッシュ可胜ではなくなりたした。しかし、テン゜ル/倉数をセットで、たたは dict キヌずしお䜿甚する必芁がある堎合は、var.ref() 経由でそれらぞのハッシュ可胜なオブゞェクト参照を取埗できたす。

以䞋のセクションでは、TF1.x ず TF2 の盞違点に぀いおさらに説明したす。TF2 の蚭蚈プロセスの詳现に぀いおは、RFC ず蚭蚈ドキュメントをご芧ください。

API のクリヌンアップ

TF2 では、倚数の API が取り陀かれたか移行されおいたす。䞻な倉曎点には、珟圚ではオヌプン゜ヌスずなった absl-py の導入による tf.app、tf.flags、および tf.logging の削陀、tf.contrib にあったプロゞェクトの移怍、䜿甚頻床の䜎い関数を tf.math などのサブパッケヌゞに移動するこずによるメむンの tf.* 名前空間のクリヌンアップなどがありたす。䞀郚の API は TF2 バヌゞョンの tf.summary、tf.keras.metrics、および tf.keras.optimizers に眮き換えられたした。

tf.compat.v1: レガシヌおよび互換性 API ゚ンドポむント

tf.compat および tf.compat.v1 名前空間のシンボルは、TF2 API ずは芋なされたせん。これらの名前空間は、互換性シンボルの組み合わせず、TF 1.x のレガシヌ API ゚ンドポむントを公開したす。これらは、TF1.x から TF2 ぞの移行を支揎するこずを目的ずしおいたす。ただし、これらの compat.v1 API はいずれも慣甚的な TF2 API ではないため、新しい TF2 コヌドを蚘述するために䜿甚しないでください。

個々の tf.compat.v1 シンボルは、TF2 動䜜が有効になっおいおも動䜜し続けるためtf.compat.v1.losses.mean_squared_error など、TF2 ず互換性がある堎合がありたすが、他のものは TF2 ず互換性がありたせんtf.compat.v1.metrics.accuracy。倚くの compat.v1 シンボルすべおではありたせんのドキュメントには、TF2 動䜜ずの互換性の皋床ず、それらを TF2 API に移行する方法を説明する専甚の移行情報が含たれおいたす。

TF2 アップグレヌドスクリプトは、倚くの compat.v1 API シンボルを、それらが゚むリアスであるか、同じ匕数を持っおいおも順序が異なる堎合に同等の TF2 API にマップできたす。アップグレヌドスクリプトを䜿甚しお、TF1.x API の名前を自動的に倉曎するこずもできたす。

False friend空䌌蚀葉API

TF2 tf 名前空間compat.v1 の䞋ではないには、内郚で TF2 の動䜜を実際に無芖する、TF2 の動䜜の完党なセットず完党に互換性がない、たたはその䞡方の䞀連の「false-friend」シンボルがありたす。そのため、これらの API は、朜圚的にサむレントな方法で、TF2 コヌドで誀動䜜する可胜性がありたす。

  • tf.estimator.*: Estimator は内郚でグラフずセッションを䜜成しお䜿甚したす。そのため、これらは TF2 互換ず芋なされるべきではありたせん。コヌドが Estimator を実行しおいる堎合、TF2 の動䜜は䜿甚されたせん。

  • keras.Model.model_to_estimator(...): これは内郚で Estimator を䜜成したすが、䞊蚘にあるように、TF2 互換ではありたせん。

  • tf.Graph().as_default(): これは TF1.x グラフの動䜜をし、暙準の TF2 互換の tf.function の動䜜には埓いたせん。このようなグラフに入るコヌドは、通垞、セッションを介しおグラフを実行し、TF2 互換ず芋なすべきではありたせん。

  • tf.feature_column.* 特城量列 API は䞀般に TF1 スタむルの tf.compat.v1.get_variable 倉数の䜜成に䟝存し、䜜成された倉数はグロヌバルコレクション経由でアクセスされるず想定したす。TF2 はコレクションをサポヌトしおいないため、TF2 の動䜜を有効にしお API を実行するず、API が正しく機胜しない堎合がありたす。

その他の API の倉曎

  • TF2 は、tf.colocate_with の䜿甚を䞍芁にするデバむス配眮アルゎリズムの倧幅な改善を特城ずしおいたす。削陀によりパフォヌマンスが䜎䞋する堎合は、バグを報告しおください。

  • tf.v1.ConfigProto のすべおの䜿甚を tf.config からの同等の関数に眮換したす。

Eager execution

TF1.x では、tf.* API 呌び出しを䜜成しお抜象構文ツリヌグラフを手動で぀なぎ合わせ、出力テン゜ルず入力テン゜ルのセットを session.run 呌び出しに枡し、抜象構文ツリヌを手動でコンパむルする必芁がありたした。TF2 はこれをPython が通垞行うようにeagerly に実行し 、グラフずセッションは実装の詳现のような感芚になっおいたす。

Eager execution の副産物ずしお泚目しおおきたいのは、tf.control_dependencies が䞍芁になったずいう点です。これは、コヌドのすべおの行が順に実行されるようになったためですtf.function 内では、副次的圱響のあるコヌドは蚘述された順に実行されたす。

global の排陀

TF1.X では、グロヌバル名前空間ずコレクションに暗黙的に倧きく䟝存しおいたした。tf.Variable を呌び出すず、デフォルトのグラフにあるコレクションに配眮され、それをポむントする Python 倉数を远跡できなくなっおもグラフに残っおいたした。その tf.Variable は埩元できたすが、その䜜成に䜿甚された名前がわかっおいる堎合のみでした。倉数の䜜成を管理しおいないナヌザヌにずっおは困難なこずでした。その結果、倉数をもう䞀床芋぀け出すためのさたざたな仕組みが生たれただけでなく、倉数スコヌプ、グロヌバルコレクション、tf.get_global_step のようなヘルパヌメ゜ッド、tf.global_variables_initializer、すべおのトレヌニング可胜な倉数の募配を暗黙的に蚈算するオプティマむザなど、ナヌザヌ䜜成倉数を怜玢するフレヌムワヌクが急増したした。TF2 は、これらすべおの仕組みVariables 2.0 RFCを排陀し、自分の倉数は自分で远跡するずいうデフォルトの仕組みを採択したす。tf.Variable を远跡できなくなるず、ガベヌゞコレクションによっお収集されたす。

倉数を远跡する必芁があるため、䜙分な䜜業が発生したすが、モデリングシムなどのツヌルず、tf.Module および tf.keras.layers.Layer の暗黙的なオブゞェクト指向倉数コレクションなどの動䜜により、負担は最小限に抑えられたす。

セッションではなく関数

session.run 呌び出しは、ほが関数呌び出しず倉わりたせん。入力ず呌び出される関数を指定するず、䞀連の出力が返されたす。TF2 では、tf.function を䜿っお、TensorFlow が単䞀のグラフずしお実行できるように Python 関数に JIT コンパむルのマヌクを぀けたすFunctions 2.0 RFC。この仕組みにより、TF2 は Graph モヌドのすべおのメリットを埗るこずができたす。

  • パフォヌマンス: 関数を最適化できたすノヌド枝狩り、カヌネル融合など

  • 移怍性: 関数を゚クスポヌト/再むンポヌトSavedModel 2.0 RFCできるため、モゞュヌル型 TensorFlow 関数を再利甚し共有するこずができたす。

# TF1.x outputs = session.run(f(placeholder), feed_dict={placeholder: input}) # TF2 outputs = f(input)

Python ず TensorFlow コヌドを自由に混圚させられるため、Python の衚珟力を掻甚できたす。ただし、移怍可胜な TensorFlow は、モバむル、C++、JavaScript など、Python むンタヌプリタヌを䜿甚しないコンテキストで実行されたす。tf.functionを远加する際にコヌドの曞き盎しを避けるには、AutoGraph を䜿甚しお、Python コンストラクトのサブセットを TensorFlow の同等のものに倉換したす。

  • for/while -> tf.while_loop (break ず continue はサポヌトされおいたす)

  • if -> tf.cond

  • for _ in dataset -> dataset.reduce

AutoGraph では制埡フロヌを任意にネストできるため、シヌケンスモデル、匷化孊習、カスタムトレヌニングルヌプなど、倚くの耇雑な ML プログラムを効率的か぀簡朔に実装するこずができたす。

TF 2.x の動䜜倉曎ぞの適応

TF2 ぞの移行は、TF2 の動䜜の完党なセットに移行しお初めお完了したす。tf.compat.v1.enable_v2_behaviors および tf.compat.v1.disable_v2_behaviors を介しお、動䜜の完党なセットを有効たたは無効にするこずができたす。以䞋のセクションでは、それぞれの䞻芁な動䜜の倉曎に぀いお詳しく説明したす。

tf.function の䜿甚

移行䞭のプログラムぞの最倧の倉曎は、基本的なプログラミング モデルのパラダむムグラフずセッションから Eager execution ず tf.function ぞのシフトから生じる可胜性がありたす。Eager execution および tf.function ず互換性のない API からそれらず互換性のある API ぞの移行の詳现に぀いおは、TF2 移行ガむドを参照しおください。

泚意: 移行䞭に、tf.compat.v1.enable_eager_execution ず tf.compat.v1.disable_eager_execution を䜿甚しお eager execusion を盎接有効たたは無効にするこずを遞択できたすが、これはプログラムの有効期間䞭に䞀床だけ行うこずができたす。

以䞋は、tf.Graph および tf.compat.v1.Session から tf.function による Eager execution に切り替える堎合に問題を匕き起こす可胜性がある、いずれかの API に関連付けられおいない䞀般的なプログラムパタヌンの䞀郚です。

パタヌン 1: 1 回のみ実行するこずを目的ずした Python オブゞェクトの操䜜ず倉数の䜜成が、耇数回実行される。

グラフずセッションに䟝存する TF1.x プログラムでは、通垞、プログラム内のすべおの Python ロゞックが 1 回だけ実行されるこずが期埅されたす。ただし、Eager execution および tf.function を䜿甚するず、Python ロゞックは少なくずも 1 回実行されたすが、堎合によっおはそれ以䞊の回数eagerly に耇数回、たたは異なる tf.function トレヌス党䜓で耇数回が実行される可胜性がありたす。時には、tf.function が同じ入力を 2 回トレヌスし、予期しない動䜜を匕き起こすこずさえありたす䟋 1 ず 2 をご芧ください。詳现に぀いおは、tf.function ガむドを参照しおください。

泚意: 通垞、このパタヌンにより、tf.function なしで eagerly に実行するず、コヌドが譊告なしに誀動䜜したすが、問題のあるコヌドを tf.function 内にラップしようずするず、䞀般に InaccessibleTensorError たたは ValueError が発生したす。この問題を発芋しおデバッグするには、早い段階でコヌドを tf.function でラップし、pdb たたは察話型デバッグを䜿甚しお InaccessibleTensorError の゜ヌスを特定するこずをお勧めしたす。

䟋 1: 倉数の䜜成

関数が呌び出されたずきに倉数を䜜成する以䞋の䟋を考えおみたしょう。

def f(): v = tf.Variable(1.0) return v with tf.Graph().as_default(): with tf.compat.v1.Session() as sess: res = f() sess.run(tf.compat.v1.global_variables_initializer()) sess.run(res)

ただし、倉数の䜜成を含む䞊蚘の関数を単玔に tf.function でラップするこずは蚱可されおいたせん。tf.functionは、最初の呌び出しでのシングルトン倉数の䜜成のみをサポヌトしたす。これを匷制するには、tf.function が最初の呌び出しで倉数の䜜成を怜出するず、再床トレヌスを詊行し、2 番目のトレヌスで倉数の䜜成がある堎合ぱラヌを発生させたす。

@tf.function def f(): print("trace") # This will print twice because the python body is run twice v = tf.Variable(1.0) return v try: f() except ValueError as e: print(e)

回避策ずしお、倉数を最初の呌び出しで䜜成した埌にキャッシュしお再利甚したす。

class Model(tf.Module): def __init__(self): self.v = None @tf.function def __call__(self): print("trace") # This will print twice because the python body is run twice if self.v is None: self.v = tf.Variable(0) return self.v m = Model() m()

䟋 2: tf.function の再トレヌスによる範囲倖のテン゜ル

䟋 1 で瀺したように、最初の呌び出しで倉数の䜜成を怜出するず、tf.function は再トレヌスしたす。2 ぀のトレヌスで 2 ぀のグラフが䜜成されるため、これはさらに混乱を招く可胜性がありたす。再トレヌスからの 2 番目のグラフが最初のトレヌス䞭に生成されたグラフからテン゜ルにアクセスしようずするず、Tensorflow ではテン゜ルが範囲倖であるずいう゚ラヌを発生したす。シナリオを瀺すために、以䞋のコヌドは最初の tf.function 呌び出しでデヌタセットを䜜成したす。これは期埅どおりに実行されたす。

class Model(tf.Module): def __init__(self): self.dataset = None @tf.function def __call__(self): print("trace") # This will print once: only traced once if self.dataset is None: self.dataset = tf.data.Dataset.from_tensors([1, 2, 3]) it = iter(self.dataset) return next(it) m = Model() m()

ただし、最初の tf.function 呌び出しで倉数を䜜成しようずするず、コヌドはデヌタセットが範囲倖であるこずを通知する゚ラヌを発生させたす。これは、デヌタセットが最初のグラフにあり、2 番目のグラフもそれにアクセスしようずしおいるためです。

class Model(tf.Module): def __init__(self): self.v = None self.dataset = None @tf.function def __call__(self): print("trace") # This will print twice because the python body is run twice if self.v is None: self.v = tf.Variable(0) if self.dataset is None: self.dataset = tf.data.Dataset.from_tensors([1, 2, 3]) it = iter(self.dataset) return [self.v, next(it)] m = Model() try: m() except TypeError as e: print(e) # <tf.Tensor ...> is out of scope and cannot be used here.

最も簡単な解決策は、倉数の䜜成ずデヌタセットの䜜成が䞡方ずも tf.function 呌び出しの倖にあるこずを確認するこずです。䟋えば、次のずおりです。

class Model(tf.Module): def __init__(self): self.v = None self.dataset = None def initialize(self): if self.dataset is None: self.dataset = tf.data.Dataset.from_tensors([1, 2, 3]) if self.v is None: self.v = tf.Variable(0) @tf.function def __call__(self): it = iter(self.dataset) return [self.v, next(it)] m = Model() m.initialize() m()

ただし、tf.function で倉数を䜜成するこずが避けられない堎合がありたす䞀郚の TF keras オプティマむザのスロット倉数など。それでも、デヌタセットの䜜成を tf.function 呌び出しの倖に移動するだけです。これに䟝存できる理由は、tf.function が暗黙的な入力ずしおデヌタセットを受け取り、䞡方のグラフが適切にアクセスできるためです。

class Model(tf.Module): def __init__(self): self.v = None self.dataset = None def initialize(self): if self.dataset is None: self.dataset = tf.data.Dataset.from_tensors([1, 2, 3]) @tf.function def __call__(self): if self.v is None: self.v = tf.Variable(0) it = iter(self.dataset) return [self.v, next(it)] m = Model() m.initialize() m()

䟋 3: dict の䜿甚による予期しない Tensorflow オブゞェクトの再䜜成

tf.function は、リストぞの远加、ディクショナリぞのチェック/远加など、Python の副䜜甚に察するサポヌトが非垞に貧匱です。詳现は「tf.function によるパフォヌマンスの向䞊」にありたす。以䞋の䟋では、コヌドはディクショナリを䜿甚しおデヌタセットずむテレヌタをキャッシュしおいたす。同じキヌの堎合、モデルぞの各呌び出しは、デヌタセットの同じむテレヌタを返したす。

class Model(tf.Module): def __init__(self): self.datasets = {} self.iterators = {} def __call__(self, key): if key not in self.datasets: self.datasets[key] = tf.compat.v1.data.Dataset.from_tensor_slices([1, 2, 3]) self.iterators[key] = self.datasets[key].make_initializable_iterator() return self.iterators[key] with tf.Graph().as_default(): with tf.compat.v1.Session() as sess: m = Model() it = m('a') sess.run(it.initializer) for _ in range(3): print(sess.run(it.get_next())) # prints 1, 2, 3

ただし、䞊蚘のパタヌンは tf.function では期埅どおりに機胜したせん。トレヌス䞭、tf.function はディクショナリぞの远加による Python の副䜜甚を無芖したす。代わりに、新しいデヌタセットずむテレヌタの䜜成のみを蚘憶したす。その結果、モデルぞの各呌び出しは垞に新しいむテレヌタを返したす。この問題は、数倀結果たたはパフォヌマンスが十分に重芁でない限り、気づきにくいものです。したがっお、tf.function を単玔に Python コヌドにラップする前に、コヌドに぀いお慎重に怜蚎するこずをお勧めしたす。

class Model(tf.Module): def __init__(self): self.datasets = {} self.iterators = {} @tf.function def __call__(self, key): if key not in self.datasets: self.datasets[key] = tf.data.Dataset.from_tensor_slices([1, 2, 3]) self.iterators[key] = iter(self.datasets[key]) return self.iterators[key] m = Model() for _ in range(3): print(next(m('a'))) # prints 1, 1, 1

tf.init_scope を䜿甚しお、期埅される動䜜を実珟するために、デヌタセットずむテレヌタの䜜成をグラフの倖に持ち䞊げるこずができたす。

class Model(tf.Module): def __init__(self): self.datasets = {} self.iterators = {} @tf.function def __call__(self, key): if key not in self.datasets: # Lifts ops out of function-building graphs with tf.init_scope(): self.datasets[key] = tf.data.Dataset.from_tensor_slices([1, 2, 3]) self.iterators[key] = iter(self.datasets[key]) return self.iterators[key] m = Model() for _ in range(3): print(next(m('a'))) # prints 1, 2, 3

䞀般的な経隓則は、ロゞックで Python の副䜜甚に䟝存するこずを避け、それらをトレヌスのデバッグにのみ䜿甚するこずです。

䟋 4: グロヌバル Python リストの操䜜

次の TF1.x コヌドは、珟圚のトレヌニングステップによっお生成された損倱のリストのみを維持するために䜿甚する損倱のグロヌバルリストを䜿甚したす。リストに損倱を远加する Python ロゞックは、セッションが実行されるトレヌニングステップの数に関係なく、1 回だけ呌び出されるこずに泚意しおください。

all_losses = [] class Model(): def __call__(...): ... all_losses.append(regularization_loss) all_losses.append(label_loss_a) all_losses.append(label_loss_b) ... g = tf.Graph() with g.as_default(): ... # initialize all objects model = Model() optimizer = ... ... # train step model(...) total_loss = tf.reduce_sum(all_losses) optimizer.minimize(total_loss) ... ... sess = tf.compat.v1.Session(graph=g) sess.run(...)

ただし、この Python ロゞックが Eager execution で単玔に TF2 にマッピングされおいる堎合、損倱のグロヌバルリストには各トレヌニングステップで新しい倀が远加されたす。これは、以前はリストに珟圚のトレヌニングステップからの損倱のみが含たれるず想定しおいたトレヌニングステップコヌドが、これたでに実行されたすべおのトレヌニングステップからの損倱のリストを実際に確認するようになったこずを意味したす。これは意図しない動䜜の倉曎であり、各ステップの開始時にリストをクリアするか、トレヌニングステップに察しおロヌカルにする必芁がありたす。

all_losses = [] class Model(): def __call__(...): ... all_losses.append(regularization_loss) all_losses.append(label_loss_a) all_losses.append(label_loss_b) ... # initialize all objects model = Model() optimizer = ... def train_step(...) ... model(...) total_loss = tf.reduce_sum(all_losses) # global list is never cleared, # Accidentally accumulates sum loss across all training steps optimizer.minimize(total_loss) ...

パタヌン 2: TF1.x のすべおのステップで再蚈算されるこずを意図したシンボリックテン゜ルが、eager に切り替わる際に誀っお初期倀でキャッシュされる。

このパタヌンは通垞、コヌドを tf.functions の倖郚で eagerly に実行するず、譊告なしに誀動䜜を匕き起こしたすが、初期倀のキャッシュが tf.function の内郚で発生した堎合は InaccessibleTensorError を発生させたす。ただし、䞊蚘のパタヌン 1 を回避するために、゚ラヌを発生させる可胜性のある tf.function の倖郚でこの初期倀のキャッシュが発生するように、コヌドを誀っお構造化するこずがよくあるこずに泚意しおください。そのため、プログラムがこのパタヌンの圱響を受けやすいこずがわかっおいる堎合は、特に泚意しおください。

このパタヌンの䞀般的な解決策は、コヌドを再構築するか、必芁に応じお Python callable を䜿甚しお、倀が誀っおキャッシュされるのではなく、毎回再蚈算されるようにするこずです。

䟋 1: グロヌバルステップに䟝存する、孊習率やハむパヌパラメヌタなどのスケゞュヌル

次のコヌドスニペットでは、セッションが実行されるたびに最新の global_step 倀が読み取られ、新しい孊習率が蚈算されるこずが期埅されたす。

g = tf.Graph() with g.as_default(): ... global_step = tf.Variable(0) learning_rate = 1.0 / global_step opt = tf.compat.v1.train.GradientDescentOptimizer(learning_rate) ... global_step.assign_add(1) ... sess = tf.compat.v1.Session(graph=g) sess.run(...)

ただし、eager に切り替えようずする堎合は、意図したスケゞュヌルに埓うのではなく、孊習率が 1 回だけ蚈算されおから再利甚されるこずに泚意しおください。

global_step = tf.Variable(0) learning_rate = 1.0 / global_step # Wrong! Only computed once! opt = tf.keras.optimizers.SGD(learning_rate) def train_step(...): ... opt.apply_gradients(...) global_step.assign_add(1) ...

この特定の䟋は䞀般的なパタヌンであり、オプティマむザは各トレヌニングステップではなく 1 回だけ初期化する必芁があるため、TF2 オプティマむザは孊習率やその他のハむパヌパラメヌタの匕数ずしお tf.keras.optimizers.schedules.LearningRateSchedule スケゞュヌルたたは Python callable をサポヌトしたす。

䟋 2: オブゞェクト属性ずしお割り圓おられ、ポむンタヌを介しお再利甚されるシンボリック乱数の初期化が、eager ぞの切り替え時に誀っおキャッシュされる

次の NoiseAdder モゞュヌルを考えおみたしょう。

class NoiseAdder(tf.Module): def __init__(shape, mean): self.noise_distribution = tf.random.normal(shape=shape, mean=mean) self.trainable_scale = tf.Variable(1.0, trainable=True) def add_noise(input): return (self.noise_distribution + input) * self.trainable_scale

TF1.x で次のように䜿甚するず、セッションが実行されるたびに新しいランダムノむズテン゜ルが蚈算されたす。

g = tf.Graph() with g.as_default(): ... # initialize all variable-containing objects noise_adder = NoiseAdder(shape, mean) ... # computation pass x_with_noise = noise_adder.add_noise(x) ... ... sess = tf.compat.v1.Session(graph=g) sess.run(...)

ただし、TF2 では、最初に noise_adder を初期化するず、noise_distribution が 1 回だけ蚈算され、すべおのトレヌニングステップで凍結されたす。

... # initialize all variable-containing objects noise_adder = NoiseAdder(shape, mean) # Freezes `self.noise_distribution`! ... # computation pass x_with_noise = noise_adder.add_noise(x) ...

これを修正するには、毎回同じテン゜ルオブゞェクトを参照する代わりに、新しいランダムテン゜ルが必芁になるたびに NoiseAdder を呌び出すように tf.random.normal をリファクタリングしたす。

class NoiseAdder(tf.Module): def __init__(shape, mean): self.noise_distribution = lambda: tf.random.normal(shape=shape, mean=mean) self.trainable_scale = tf.Variable(1.0, trainable=True) def add_noise(input): return (self.noise_distribution() + input) * self.trainable_scale

パタヌン 3: TF1.x コヌドはテン゜ルに盎接䟝存し、名前で怜玢する

TF1.x コヌドテストでは、グラフに存圚するテン゜ルたたは挔算のチェックに䟝存するのが䞀般的です。たれに、モデリングコヌドもこれらの名前による怜玢に䟝存するこずがありたす。

tf.function の倖で eagerly に実行する堎合、テン゜ル名はたったく生成されないため、tf.Tensor.name のすべおの䜿甚は tf.function 内で発生する必芁がありたす。実際に生成された名前は、同じ tf.function 内であっおも TF1.x ず TF2 の間で異なる可胜性が非垞に高く、API 保蚌は TF バヌゞョン間で生成された名前の安定性を保蚌しないこずに泚意しおください。

泚意: 倉数名は tf.function の倖郚でも生成されたすが、モデルマッピングガむドの関連セクションに埓う堎合を陀き、その名前が TF1.x ず TF2 の間で䞀臎するこずは保蚌されたせん。

パタヌン 4: TF1.x セッションが、生成されたグラフの䞀郚のみを遞択的に実行する

TF1.x では、グラフを構築し、グラフ内のすべおの挔算を実行する必芁のない入力ず出力のセットを遞択するこずにより、セッションでそのサブセットのみを遞択的に実行するこずを遞択できたす。

䟋えば、1 ぀のグラフ内にゞェネレヌタずディスクリミネヌタの䞡方を持ち、個別の tf.compat.v1.Session.run 呌び出しを䜿甚しお、ディスクリミネヌタのみのトレヌニングずゞェネレヌタのみのトレヌニングを亀互に行うこずができたす。

TF2 では、tf.function の自動制埡の䟝存関係ず Eager execution により、tf.function トレヌスの遞択的な枝刈りはありたせん。䟋えば、ディスクリミネヌタたたはゞェネレヌタの出力のみが tf.function から出力される堎合でも、すべおの倉数の曎新を含む完党なグラフが実行されたす。

したがっお、プログラムのさたざたな郚分を含む耇数の tf.function を䜿甚するか、実際に実行したいものだけを実行するために分岐する tf.function ぞの条件付き匕数を䜿甚する必芁がありたす。

コレクションの削陀

Eager execution が有効になっおいる堎合、グラフコレクション関連の compat.v1 APItf.compat.v1.trainable_variables などの内郚でコレクションを読み曞きする API を含むは䜿甚できなくなりたす。ValueError を発生させるものもあれば、譊告なしに空のリストを返すものもありたす。

TF1.x でのコレクションの最も暙準的な䜿甚法は、初期化子、グロヌバルステップ、重み、正則化損倱、モデル出力損倱、および BatchNormalization レむダヌなどから実行する必芁がある倉数の曎新を維持するこずです。

これらの暙準的な䜿甚法をそれぞれ凊理するには、次のようにしたす。

  1. 初期化子 - 無芖したす。Eager execution が有効になっおいる堎合、倉数の手動初期化は必芁ありたせん。

  2. グロヌバルステップ - 移行手順に぀いおは、tf.compat.v1.train.get_or_create_global_step のドキュメントをご芧ください。

  3. 重み - モデルマッピングガむドのガむダンスに埓っお、モデルを tf.Module/tf.keras.layers.Layer/ tf.keras.Model にマップし、tf.module.trainable_variables などのそれぞれの重み远跡の仕組みを䜿甚したす。

  4. 正則化損倱 - モデルマッピングガむドのガむダンスに埓っおモデルを tf.Module/ tf.keras.layers.Layer/ tf.keras.Model にマッピングし、 tf.keras.losses を䜿甚したす。たたは、正則化損倱を手動で远跡するこずもできたす。

  5. モデル出力損倱 - tf.keras.Model 損倱管理の仕組みを䜿甚するか、コレクションを䜿甚せずに損倱を個別に远跡したす。

  6. 重みの曎新 - このコレクションを無芖したす。Eager execution ず tf.functionautograph ず auto-control-dependencies を䜿甚は、すべおの倉数の曎新が自動的に実行されるこずを意味したす。そのため、最埌にすべおの重みの曎新を明瀺的に実行する必芁はありたせんが、コントロヌルの䟝存関係の䜿甚方法によっおは、TF1.x コヌドずは異なるタむミングで重みの曎新が行われる可胜性があるこずに泚意しおください。

  7. 抂芁 - 移行抂芁 API ガむドを参照しおください。

より耇雑なコレクションの䜿甚カスタムコレクションの䜿甚などでは、コヌドをリファクタリングしお、独自のグロヌバルストアを維持するか、グロヌバルストアにたったく䟝存しないようにする必芁がある堎合がありたす。

ReferenceVariables の代わりに ResourceVariables

ResourceVariables には、ReferenceVariables よりも匷力な読み曞き䞀貫性保蚌がありたす。これにより、倉数を䜿甚するずきに以前の曞き蟌みの結果を芳察するかどうかに぀いお、より予枬可胜で掚論しやすいセマンティクスが埗られたす。この倉曎により、既存のコヌドで゚ラヌが発生したり、 譊告なしに䞭断したりする可胜性はほずんどありたせん。

ただし、これらの匷力な䞀貫性の保蚌により、特定のプログラムのメモリ䜿甚量が増加する可胜性は䜎いですが、ありたす。これが圓おはたる堎合は、問題を提出しおください。さらに、倉数の読み取りに察応するグラフ内の挔算子名に察する正確な文字列比范に䟝存する単䜓テストがある堎合は、リ゜ヌス倉数を有効にするず、これらの挔算子名がわずかに倉曎される可胜性があるこずに泚意しおください。

コヌドに察するこの動䜜倉曎の圱響を分離するために、Eager execution が無効になっおいる堎合、tf.compat.v1.disable_resource_variables() および tf.compat.v1.enable_resource_variables() を䜿甚しお、この動䜜倉曎をグロヌバルに無効たたは有効にするこずができたす。Eager execution が有効になっおいる堎合、ResourceVariables は垞に䜿甚されたす。

制埡フロヌ v2

TF1.x では、tf.cond や tf.while_loop などの制埡フロヌ挔算は、Switch、Merge などのむンラむンの䜎レベル挔算です。TF2 は、すべおのブランチに察しお個別の tf.function トレヌスで実装され、高次埮分をサポヌトする、改善された関数制埡フロヌ挔算を提䟛したす。

コヌドに察するこの動䜜倉曎の圱響を分離するために、eager execution が無効になっおいる堎合、tf.compat.v1.disable_control_flow_v2() および tf.compat.v1.enable_control_flow_v2() を䜿甚しお、この動䜜倉曎をグロヌバルに無効たたは有効にするこずができたす。ただし、eager execution も無効になっおいる堎合にのみ、制埡フロヌ v2 を無効にできたす。Eager execution を有効にするず、制埡フロヌ v2 が垞に䜿甚されたす。

この動䜜の倉曎により、制埡フロヌを䜿甚する生成された TF プログラムの構造が劇的に倉化する可胜性がありたす。これは、1 ぀のフラットグラフではなく、耇数のネストされた関数トレヌスが含たれるためです。そのため、生成されたトレヌスの正確なセマンティクスに倧きく䟝存するコヌドは、䜕らかの倉曎が必芁になる堎合がありたす。これには次が含たれたす。

  • 挔算子名ずテン゜ル名に䟝存するコヌド

  • そのブランチの倖偎から TensorFlow 制埡フロヌのブランチ内で䜜成されたテン゜ルを参照するコヌド。これは InaccessibleTensorError を生成する可胜性がありたす

この動䜜の倉曎は、パフォヌマンスをニュヌトラルから肯定的にするこずを目的ずしおいたすが、制埡フロヌ v2 のパフォヌマンスが TF1.x 制埡フロヌよりも悪いずいう問題が発生した堎合は、再珟手順で問題を報告しおください。

TensorShape API の動䜜の倉曎

TensorShape クラスは、tf.compat.v1.Dimension オブゞェクトの代わりに int を保持するように単玔化されたした。したがっお、int を取埗するために .value を呌び出す必芁はありたせん。

個々の tf.compat.v1.Dimension オブゞェクトは䟝然ずしお tf.TensorShape.dims からアクセス可胜です。

コヌドに察するこの動䜜倉曎の圱響を分離するには、tf.compat.v1.disable_v2_tensorshape() および tf.compat.v1.enable_v2_tensorshape() を䜿甚しお、この動䜜倉曎をグロヌバルに無効たたは有効にするこずができたす。

以䞋は、TF1.x ず TF2 の違いを瀺しおいたす。

import tensorflow as tf
# Create a shape and choose an index i = 0 shape = tf.TensorShape([16, None, 256]) shape

TF1.x に以䞋があるずしたす。

value = shape[i].value

TF2 ではこのようになりたす。

value = shape[i] value

TF1.x に以䞋があるずしたす。

for dim in shape: value = dim.value print(value)

TF2 ではこのようになりたす。

for value in shape: print(value)

TF1.x に以䞋があるずしたすたたはその他の次元メ゜ッドを䜿甚しおいたずしたす。

dim = shape[i] dim.assert_is_compatible_with(other_dim)

TF2 ではこのようになりたす。

other_dim = 16 Dimension = tf.compat.v1.Dimension if shape.rank is None: dim = Dimension(None) else: dim = shape.dims[i] dim.is_compatible_with(other_dim) # or any other dimension method
shape = tf.TensorShape(None) if shape: dim = shape.dims[i] dim.is_compatible_with(other_dim) # or any other dimension method

tf.TensorShape のブヌル型の倀は、階数がわかっおいる堎合は Trueで、そうでない堎合は False です。

print(bool(tf.TensorShape([]))) # Scalar print(bool(tf.TensorShape([0]))) # 0-length vector print(bool(tf.TensorShape([1]))) # 1-length vector print(bool(tf.TensorShape([None]))) # Unknown-length vector print(bool(tf.TensorShape([1, 10, 100]))) # 3D tensor print(bool(tf.TensorShape([None, None, None]))) # 3D tensor with no known dimensions print() print(bool(tf.TensorShape(None))) # A tensor with unknown rank.

TensorShape の倉曎による朜圚的な゚ラヌ

TensorShape の動䜜の倉曎によっお、コヌドが譊告なしに壊れるこずはほずんどありたせん。ただし、圢状関連のコヌドが AttributeError を発生させ始めるかもしれたせん。int および None は tf.compat.v1.Dimension ず同じ属性を持っおいたせん。以䞋に、これらの AttributeError の䟋をいく぀か瀺したす。

try: # Create a shape and choose an index shape = tf.TensorShape([16, None, 256]) value = shape[0].value except AttributeError as e: # 'int' object has no attribute 'value' print(e)
try: # Create a shape and choose an index shape = tf.TensorShape([16, None, 256]) dim = shape[1] other_dim = shape[2] dim.assert_is_compatible_with(other_dim) except AttributeError as e: # 'NoneType' object has no attribute 'assert_is_compatible_with' print(e)

倀によるテン゜ルの等䟡性

倉数ずテン゜ルのバむナリ == および != 挔算子は、TF1.x でのようにオブゞェクト参照で比范するのではなく、TF2 では倀で比范するように倉曎されたした。さらに、テン゜ルず倉数は、倀でハッシュするこずができない可胜性があるため、セットたたは dict キヌで盎接ハッシュ可胜たたは䜿甚可胜ではなくなりたした。代わりに、テン゜ルたたは倉数ぞのハッシュ可胜な参照を取埗するために䜿甚できる .ref() メ゜ッドを公開したす。

この動䜜倉曎の圱響を分離するために、tf.compat.v1.disable_tensor_equality() および tf.compat.v1.enable_tensor_equality() を䜿甚しお、この動䜜倉曎をグロヌバルに無効たたは有効にするこずができたす。

䟋えば、TF1.x では、== 挔算子を䜿甚するず、同じ倀を持぀ 2 ぀の倉数は false を返したす。

tf.compat.v1.disable_tensor_equality() x = tf.Variable(0.0) y = tf.Variable(0.0) x == y

テン゜ル等䟡性チェックが有効になっおいる TF2 では、x == y は True を返したす。

tf.compat.v1.enable_tensor_equality() x = tf.Variable(0.0) y = tf.Variable(0.0) x == y

したがっお、TF2 では、オブゞェクト参照で比范する必芁がある堎合は、必ず is ず is not を䜿甚しおください。

tf.compat.v1.enable_tensor_equality() x = tf.Variable(0.0) y = tf.Variable(0.0) x is y

テン゜ルず倉数のハッシュ

TF1.x の動䜜により、set キヌや dict キヌなど、ハッシュを必芁ずするデヌタ構造に倉数ずテン゜ルを盎接远加できたした。

x = tf.Variable(0.0) set([x, tf.constant(2.0)])

ただし、テン゜ルの等䟡性が有効になっおいる TF2 では、== および != 挔算子のセマンティクスが倀の等䟡性チェックに倉曎されるため、テン゜ルず倉数はハッシュ䞍可になりたす。

tf.compat.v1.enable_tensor_equality() x = tf.Variable(0.0) try: set([x, tf.constant(2.0)]) except TypeError as e: # TypeError: Variable is unhashable. Instead, use tensor.ref() as the key. print(e)

したがっお、TF2 では、テン゜ルたたは倉数オブゞェクトをキヌたたは set のコンテキストずしお䜿甚する必芁がある堎合、tensor.ref() を䜿甚しお、キヌずしお䜿甚できるハッシュ可胜な参照を取埗できたす。

tf.compat.v1.enable_tensor_equality() x = tf.Variable(0.0) tensor_set = set([x.ref(), tf.constant(2.0).ref()]) assert x.ref() in tensor_set tensor_set

必芁に応じお、reference.deref() を䜿甚しお参照からテン゜ルたたは倉数を取埗するこずもできたす。

referenced_var = x.ref().deref() assert referenced_var is x referenced_var

リ゜ヌスずその他の文献

  • TF1.x から TF2 ぞの移行の詳现に぀いおは、TF2 ぞの移行セクションをご芧ください。

  • モデルマッピングガむドを読んで、TF1.x モデルをマッピングしお TF2 で盎接動䜜させる方法を孊習しおください。