Translate

2017年2月22日水曜日

旧バージョンのTensorFlowコードを 1.0 で動作するように変更する

TensorFlow Dockerコンテナを作り直したら
タグlatest-py3を指定していたため、
最新のTensorFlow 1.0に変わってしまった。

0.12で動いていたコードが動作しなくなった。

実際には、

TensorFlowのSeq2Seqモデルでチャットボットっぽいものを作ってみた
http://qiita.com/sanshirookazaki/items/128bf1b5a898ad5c18f1

をちょっと手直しして動かしていたのだけど..

・パッケージ移動
  tensorflow.models.rnn.rnn_cell → tensorflow.contrib.rnn.core_rnn_cell
 tensorflow.models.rnn.seq2seq → tensorflow.contrib.legacy_seq2seq

・シグニチャ変更
 legacy_seq2seq.model_with_buckets() の引数からボキャブラリサイズが消える。
 代わりにlegacy_seq2seq.embedding_attention_seq2seq() の引数にembedding_sizeを指定する型式に。


..っていうか、Attention付きSeqence-to-Sequnece がもはや legacy_seq2seq なの?!
ってほうに驚いたが、話を戻して..

TensorFlow 1.0 になったのが2月15日だから、いろんなところで「ギャッ!」と叫んでいてもおかしくないのに..みんな静かなのは何故だろう..

なんとか楽して修正したい..とおもって本家ページを覗いてみたら

Transitioning to TensorFlow 1.0
https://www.tensorflow.org/install/migration

なるページを見つけた。

以下、勝手翻訳の内容だ。
(At your own riskで参照のこと)
---------

TensorFlow 1.0 への移行


TensorFlow 1.0のAPIは、すべて後方互換性のある方法で変更されています。 つまり、TensorFlow 0.nで動作するTensorFlowプログラムは、必ずしもTensorFlow 1.0では動作しません。 私たちは内部的に一貫したAPIを保証するためにこのAPIを変更し、1.Nのライフサイクル全体にわたって後方修正の変更を行うつもりはありません。

このガイドでは、APIの主な変更点と、TensorFlow 1.0のプログラムを自動的にアップグレードする方法について説明します。 このガイドでは、変更の手順を説明するだけでなく、変更の理由を説明します。

アップグレードする方法


コードを1.0に自動的に移植したい場合は、tf_upgrade.py スクリプトを試してみてください。 このスクリプトは多くのケースを処理しますが、手動による変更が必要な場合もあります。 このスクリプトをGitHubツリーから入手してください。


1つの 0.n TensorFlow ソースファイルを 1.0 に変換するには、次の形式のコマンドを入力します。


$ python tf_upgrade.py --infile 入力ファイル --outfile 出力ファイル

たとえば、次のコマンドは、 test.py という名前の 0.10 TensorFlow プログラムを test_1.0.py という名前の 1.0 TensorFlow プログラムに変換します:

$ python tf_upgrade.py --infile test.py --outfile test_1.0.py

たとえば、次のコマンドは /home/user/cool ディレクトリにあるすべての 0.n TensorFlow プログラムを変換し、 /home/user/cool_1.0 ディレクトリに 1.0 コードを作成します。


$ python tf_upgrade.py --intree /home/user/cool --outtree /home/user/cool_1.0


制限事項


注意すべき制限事項がいくつかあります:
 

  • tf.reverse() インスタンスは手動で修正する必要があります。 tf_upgrade.py スクリプトは stdout report.txt ファイルの tf.reverse() について警告します。
  • 並べ替えられた引数では、 tf_upgrade.py はコードの最小限の再フォーマットを試みるため、実際の引数の順序を自動的に変更することはできません。 代わりに、 tf_upgrade.py は、キーワード引数を導入することによって、関数呼び出しを順序に依存しないようにします。
  • tf.get_variable_scope().reuse_variables() のような構築はうまくいかないでしょう。 これらの行を削除し、次のような行に置き換えることをお勧めします。
   with tf.variable_scope(tf.get_variable_scope(), reuse=True):
     ...
  • tf.pack および tf.unpack と同様に、 TensorArray.pack および TensorArray.unpack は、 TensorArray.stack および TensorArray.unstack に名前が変更されました。 しかし、 TensorArray.pack および TensorArray.unpack は、それらが tf 名前空間に間接的に関連しているので、語彙的に検出することはできません。 e.g. foo = tf.TensorArray(); foo.unpack()

コードを手動でアップグレード


tf_upgrade.py を実行する代わりに、コードを手動でアップグレードすることができます。 このドキュメントの残りの部分では、 TensorFlow 1.0 で行われた後方互換性のない変更の包括的な一覧を示します。

Variables


Variable 関数はより一貫性があり、混乱も少なくなっています。
 

  • tf.VARIABLES
  • tf.GLOBAL_VARIABLES に名前を変更する必要があります。
  • tf.all_variables
  • tf.global_variables に名前を変更する必要があります。
  • tf.initialize_all_variables
  • tf.global_variables_initializer に名前を変更する必要があります。
  • tf.initialize_local_variables
  • tf.local_variables_initializer に名前を変更する必要があります。
  • tf.initialize_variables 
  • tf.variables_initializer に名前を変更する必要があります。


サマリ関数


サマリ関数は、 tf.summary 名前空間の下で統合されています。
 

  • tf.audio_summary
  • tf.summary.audio に名前を変更する必要があります。
  • tf.contrib.deprecated.histogram_summary
  • tf.summary.histogramに名前を変更する必要があります。
  • tf.contrib.deprecated.scalar_summary
  • tf.summary.scalarに名前を変更する必要があります。
  • tf.histogram_summary
  • tf.summary.histogramに名前を変更する必要があります。
  • tf.image_summary
  • tf.summary.imageに名前を変更する必要があります。
  • tf.merge_all_summaries
  • tf.summary.merge_allに名前を変更する必要があります。
  • tf.merge_summary
  • tf.summary.mergeに名前を変更する必要があります。
  • tf.scalar_summary
  • tf.summary.scalarに名前を変更する必要があります。
  • tf.train.SummaryWriter
  • tf.summary.FileWriterに名前を変更する必要があります。


数値の違い


整数除算と tf.floordiv はフローリングのセマンティクスを使用するようになりました。これは、 np.dividenp.mod の結果をそれぞれ tf.divide tf.mod と一致させるためです。さらに、 NumPy と一致させるために tf.round によって使用される丸めアルゴリズムを変更しました。

  • tf.div
  • tf.divide 除算のセマンティクスは、 Python セマンティクスに完全に一致するように変更されました。つまり、 Python3 の / と Python 2の将来の除算モードは常に浮動小数点数を生成し、 // は床除算を生成します。しかし、 tf.div でも整数床除算されます。 Cスタイルの切り捨てセマンティクスを強制するには、 tf.truncatediv を使用する必要があります。
  • プロモーションのためにPythonのセマンティクスに従った tf.divide を使用するようコードを変更することを検討してください。


  • tf.mod
  • tf.mod セマンティクスは Python セマンティクスに合わせて変更されました。特に、整数には床関数のセマンティクスが使用されます。 Cスタイルの切り捨て mod (剰余)を使いたい場合は、 tf.truncatemod を使います。

除算の古い動作と新しい動作は、以下の表のとおりです:
TF 0.11 (py2)TF 0.11 (py3)TF 1.0 (py2)TF 1.0 (py3)
tf.div(3,4)0000
tf.div(-3,4)00-1-1
tf.mod(-3,4)-3-311
-3/40-0.75-1-0.75
-3/4tf.divide(-3,4)N/AN/A-0.75-1


丸め演算(rounding)の古い動作と新しい動作は、以下の表のとおりです:

InputPythonNumPyC++ round()TensorFlow 0.11(floor(x+.5))TensorFlow 1.0
-3.5-4-4-4-3-4
-2.5-2-2-3-2-2
-1.5-2-2-2-1-2
-0.500-100
0.500110
1.522222
2.522332
3.544444

NumPyの名前マッチング


多くの関数が NumPy にマッチするように名前が変更されました。これは NumPy と TensorFlow の間の移行を可能な限り簡単にするために行われました。 関数が一致しない多くのケースがまだありますので、これは難しくて速いルールとは異なりますが、いくつかの共通の矛盾点を削除しました。
 

  • tf.inv
  • tf.reciprocal に名前を変更する必要があります。
  • これは、 NumPy の行列 inverse np.inv との混乱を避けるために行われました。

  • tf_list_diff
  • tf.setdiff1d に名前を変更する必要があります。

  • tf.listdiff
  • tf.setdiff1d に名前を変更する必要があります。

  • tf.mul
  • tf.multiply に名前を変更する必要があります。

  • tf.neg
  • tf.negative に名前を変更する必要があります。

  • tf.select
  • tf.where に名前を変更する必要があります。
  • tf.wherenp.where のように3つの引数または1つの引数をとるようになりました。

  • tf.sub
  • tf.subtractに名前を変更する必要があります。


NumPyの引数マッチング


特定の TensorFlow 1.0 メソッドの引数は、特定の NumPy メソッドの引数と一致するようになりました。 これを達成するために、 TensorFlow 1.0 はキーワード引数を変更し、いくつかの議論を並べ替えました。 特に、 TensorFlow 1.0 は次元ではなく軸を使用するようになりました。 TensorFlow 1.0 は、テンソルを変更する操作で最初にテンソル引数を保持することを目的としています( tf.concat の変更を参照してください)。

  • tf.argmax キーワード引数の次元をaxisに変更する必要があります。

  • tf.argmin
  • キーワード引数の次元をaxisに変更する必要があります。

  • tf.concat 
  • キーワード引数concat_dimの名前をaxisに変更する必要があります。
  • 引数はtf.concat(value、axis、name = 'concat')に並べ替えられています。

  • tf.count_nonzero 
  • キーワード引数reduction_indicesの名前をaxisに変更する必要があります。

  • tf.expand_dims 
  • キーワード引数のdimaxisに変更する必要があります。 

  • tf.reduce_all 
  • キーワード引数reduction_indicesの名前をaxisに変更する必要があります。

  • tf.reduce_any 
  • キーワード引数reduction_indicesの名前をaxisに変更する必要があります。 

  • tf.reduce_join 
  • キーワード引数reduction_indicesの名前をaxisに変更する必要があります。

  • tf.reduce_logsumexp 
  • キーワード引数reduction_indicesの名前をaxisに変更する必要があります。

  • tf.reduce_max 
  • キーワード引数reduction_indicesの名前をaxisに変更する必要があります。

  • tf.reduce_mean 
  • キーワード引数reduction_indicesの名前をaxisに変更する必要があります。

  • tf.reduce_min 
  • キーワード引数reduction_indicesの名前をaxisに変更する必要があります。

  • tf.reduce_prod 
  • キーワード引数reduction_indicesの名前をaxisに変更する必要があります。

  • tf.reduce_sum 
  • キーワード引数reduction_indicesの名前をaxisに変更する必要があります。 

  • tf.reverse 
  • tf.reverseはどの次元が逆転したかを制御するために1Dブールテンソルをとるのに使われました。今度は軸インデックスのテンソルを使用します。
  • たとえば、tf.reverse(a、[True、False、True])tf.reverse(a、[0、2])でなければなりません。

  • tf.reverse_sequence 
  • キーワード引数batch_dimの名前をbatch_axisに変更する必要があります。
  • キーワード引数seq_dimの名前をseq_axisに変更する必要があります。

  • tf.sparse_concat 
  • キーワード引数concat_dimの名前をaxisに変更する必要があります。

  • tf.sparse_reduce_sum 
  • キーワード引数reduction_axesの名前をaxisに変更する必要があります。

  • tf.sparse_reduce_sum_sparse 
  • キーワード引数reduction_axesの名前をaxisに変更する必要があります。 

  • tf.sparse_split 
  • キーワード引数split_dimの名前をaxisに変更する必要があります。
  • 引数はtf.sparse_split(keyword_required = KeywordRequired()、sp_input = None、num_split = None、axis = None、name = None、split_dim = None)に並べ替えられています。 

  • tf.split 
  • キーワード引数split_dimの名前をaxisに変更する必要があります。
  • キーワード引数num_splitの名前をnum_or_size_splitsに変更する必要があります。
  • 引数はtf.split(value、num_or_size_splits、axis = 0、num = None、name = 'split')に並べ替えられています。 

  • tf.squeeze 
  • キーワード引数squeeze_dimsの名前をaxisに変更する必要があります。 

  • tf.svd 
  • 引数はtf.svd(tensor, full_matrices = False, compute_uv=True, name = None)に並べ替えられています。


簡略化された数学演算


バッチバージョンの数学演算は削除されました。今や機能はバッチ処理されていないバージョンに含まれています。同様に、 tf.complex_abs はその機能を tf.abs に移動しました。

  • tf.batch_band_part
  • tf.band_partに名前を変更する必要があります。

  • tf.batch_cholesky
  • tf.choleskyに名前を変更する必要があります。

  • tf.batch_cholesky_solve
  • tf.cholesky_solveに名前を変更する必要があります。

  • tf.batch_fft
  • tf.fftに名前を変更する必要があります。

  • tf.batch_fft3d
  • tf.fft3dに名前を変更する必要があります。

  • tf.batch_ifft
  • tf.ifftに名前を変更する必要があります。

  • tf.batch_ifft2d
  • tf.ifft2dに名前を変更する必要があります。

  • tf.batch_ifft3d
  • tf.ifft3dに名前を変更する必要があります。

  • tf.batch_matmul
  • tf.matmulに名前を変更する必要があります。

  • tf.batch_matrix_determinant
  • tf.matrix_determinantに名前を変更する必要があります。

  • tf.batch_matrix_diag
  • tf.matrix_diagに名前を変更する必要があります。

  • tf.batch_matrix_inverse
  • tf.matrix_inverseに名前を変更する必要があります。

  • tf.batch_matrix_solve
  • tf.matrix_solveに名前を変更する必要があります。

  • tf.batch_matrix_solve_ls
  • tf.matrix_solve_lsに名前を変更する必要があります。

  • tf.batch_matrix_transpose
  • tf.matrix_transposeに名前を変更する必要があります。

  • tf.batch_matrix_triangular_solve
  • tf.matrix_triangular_solveに名前を変更する必要があります。

  • tf.batch_self_adjoint_eig
  • tf.self_adjoint_eigに名前を変更する必要があります。

  • tf.batch_self_adjoint_eigvals
  • tf.self_adjoint_eigvalsに名前を変更する必要があります。

  • tf.batch_set_diag
  • tf.set_diagに名前を変更する必要があります。

  • tf.batch_svd
  • tf.svdに名前を変更する必要があります。

  • tf.complex_abs 
  • tf.absに名前を変更する必要があります。


その他の変更点


次のような変更が加えられました。



  • tf.image.per_image_whitening
  • tf.image.per_image_standardizationに名前を変更する必要があります。

  • tf.nn.sigmoid_cross_entropy_with_logits 
  • 引数はtf.nn.sigmoid_cross_entropy_with_logits(_sentinel = None、labels = None、logits = None、name = None)に並べ替えられています。

  • tf.nn.softmax_cross_entropy_with_logits 
  • 引数はtf.nn.softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, dim=-1, name=None)に並べ替えられています。

  • tf.nn.sparse_softmax_cross_entropy_with_logits 
  • 引数はtf.nn.sparse_softmax_cross_entropy_with_logits(_sentinel = None、labels = None、logits = None、name = None)に並べ替えられています。

  • tf.ones_initializer 
  •  関数呼び出し、すなわちtf.ones_initializer()に変更する必要があります。

  • tf.pack
  • tf.stackに名前を変更する必要があります。

  • tf.round
  • tf.roundのセマンティクスは、Bankerの丸めと一致するようになりました。

  • tf.unpack
  • tf.unstackに名前を変更する必要があります。

  • tf.zeros_initializer 
  • 関数呼び出し、すなわちtf.zeros_initializer()に変更する必要があります。


以上

------

なるほど、tf_upgrade.py っていうツールを用意していたのね。
でも、それだけじゃ直しきらないからその分はココにある通り直してね..
か..

まあないよりましか。

ついでに tf_upgrade.py のありか

TensorFlow Python API Upgrade Utility
https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tools/compatibility

のトップページだけ翻訳したのが、以下の内容。
(こちらも at your own risk でお願いします)
------

TensorFlow Python APIアップグレードユーティリティ


このツールを使用すると、既存の TensorFlow Python スクリプトをアップグレードできます。このスクリプトは単一の Python ファイルで実行できます:

$ tf_upgrade.py --infile foo.py --outfile foo-upgraded.py


修正できないエラーのリストを出力します。ディレクトリツリー上で実行することもできます。

$ tf_upgrade.py --intree coolcode --outtree coolcode-upgraded


いずれの場合も、レポートを破棄する。変更の詳細は次のようになります。

third_party/tensorflow/tools/compatibility/test_file_v0.11.py Line 125

Renamed keyword argument from `dim` to `axis`
Renamed keyword argument from `squeeze_dims` to `axis`

    Old:                   [[1, 2, 3]], dim=1), squeeze_dims=[1]).eval(),
                                        ~~~~    ~~~~~~~~~~~~~
    New:                   [[1, 2, 3]], axis=1), axis=[1]).eval(),
                                        ~~~~~    ~~~~~

警告


このスクリプトを実行する前に、コードの一部を手動で更新しないでください。特に、 tf.concat tf.split のような引数を並べ替えた関数は、引数に不一致を示すキーワード引数をスクリプトが誤って追加する原因になります。

このスクリプトは実際に引数を並べ替えません。その代わりに、スクリプトは、引数が並べ替えられた関数にキーワード引数を追加します。

このスクリプトは、すべての機能をアップグレードすることはできません。 1つの顕著な例は tf.reverse() であり、テンソルの bool ではなくインデックスのリストを取るように変更されています。スクリプトがこれを検出すると、これを stdout(およびレポート)に報告し、手動で修正することができます。たとえば、 tf.reverse(a, [False, True, True]) がある場合は、手動で tf.reverse(a, [1, 2]) に変更する必要があります。

このスクリプトは標準の Python パッケージのみを使用するように設計されているため、このスクリプトでは扱えない構文もあります。スクリプトが「必要なキーワード引数を挿入できませんでした。(A necessary keyword argument failed to be inserted.)」で失敗した場合または 「辞書検索でキーワードを見つけることができませんでした。手動で修正してください。(Failed to find keyword lexicographically. Fix manually.)}で失敗した場合、 @machrisaa's fork of this script を試してみてください。@machrisaaRedBaron Pythonリファクタリングエンジン を使用しています。このエンジンは、このスクリプトがベースになっている組み込みの @ast@ モジュールより構文要素をより確実にローカライズできます。

以上

---------

なるほど..

でも、さっきのコードは自前で直しちゃったしな..

次の機会にでも使ってみるか..




でも、TensorFlowを去年からやってる人は
Python2 → Python3 にいつ代えるか問題
という大問題をかかえてるし..

なんたってサンプルがpython2 前提が多かったもんだから
python2 ではじめた人が以外に多くって、
CentOSやUbuntuのデフォルトも python3 へうつってきているのだけど
Python2 と Python3 は文字コードの処理で動きが違うんだよなあ..
asciiコードでなんとかなる欧米人は良いだろうけど、
日本語データをコーパスにしている日本人にはキツイのよ..

でもDockerHub側も tensorflow/tensorflow に移動になったタイミングかはわからないけど、
Python3のコンテナも登場したしなあ..

しかも先日のDev Summitでしれっと、こんなのだしてたし..



これって、つまりcontribからcoreのほうへパッケージ大移動が今後も続くってことじゃん..


..やっぱKerasとEstimatorだな..

0 件のコメント:

既存アプリケーションをK8s上でコンテナ化して動かす場合の設計注意事項メモ

既存アプリをK8sなどのコンテナにして動かすには、どこを注意すればいいか..ちょっと調べたときの注意事項をメモにした。   1. The Twelve Factors (日本語訳からの転記) コードベース   バージョン管理されている1つのコードベースと複数のデプロイ 依存関係 ...