- 投稿日:2020-04-26T21:49:46+09:00
【画像分類】犬の表情分析
1.はじめに
動物の表情分析に興味本位で手を出してみた。
2.参考文献
"Kerasで「笑っている犬」と「怒っている犬」を判別する機械学習モデルを作る"
https://qiita.com/ariera/items/545d48c961170a7840753.内容
3-1.データ前処理
# 画像を読み込んで、行列に変換する関数を定義 from keras.preprocessing.image import load_img, img_to_array def img_to_traindata(file, img_rows, img_cols, rgb): if rgb == 0: img = load_img(file, color_mode = "grayscale", target_size=(img_rows,img_cols)) # grayscaleで読み込み else: img = load_img(file, color_mode = "rgb", target_size=(img_rows,img_cols)) # RGBで読み込み x = img_to_array(img) x = x.astype('float32') x /= 255 return x # 学習データ、テストデータ生成 import glob, os img_rows = 224 # 画像サイズはVGG16のデフォルトサイズとする img_cols = 224 nb_classes = 2 # 怒っている、笑っているの2クラス img_dirs = ["./dog_angry", "./dog_smile"] # 怒っている犬、笑っている犬の画像を格納したディレクトリ X_train = [] Y_train = [] X_test = [] Y_test = [] for n, img_dir in enumerate(img_dirs): img_files = glob.glob(img_dir+"/*.jpg") # ディレクトリ内の画像ファイルを全部読み込む for i, img_file in enumerate(img_files): # ディレクトリ(文字種)内の全ファイルに対して x = img_to_traindata(img_file, img_rows, img_cols, 1) # 各画像ファイルをRGBで読み込んで行列に変換 if i < 8: # 1~8枚目までを学習データ X_train.append(x) # 学習用データ(入力)に画像を変換した行列を追加 Y_train.append(n) # 学習用データ(出力)にクラス(怒=0、笑=1)を追加 else: # 9枚目以降をテストデータ X_test.append(x) # テストデータ(入力)に画像を変換した行列を追加 Y_test.append(n) # テストデータ(出力)にクラス(怒=0、笑=1)を追加 import numpy as np # 学習、テストデータをlistからnumpy.ndarrayに変換 X_train = np.array(X_train, dtype='float') Y_train = np.array(Y_train, dtype='int') X_test = np.array(X_test, dtype='float') Y_test = np.array(Y_test, dtype='int') # カテゴリカルデータ(ベクトル)に変換 from keras.utils import np_utils Y_train = np_utils.to_categorical(Y_train, nb_classes) Y_test = np_utils.to_categorical(Y_test, nb_classes) # 作成した学習データ、テストデータをファイル保存 np.save('models/X_train_2class_120.npy', X_train) np.save('models/X_test_2class_120.npy', X_test) np.save('models/Y_train_2class_120.npy', Y_train) np.save('models/Y_test_2class_120.npy', Y_test) # 作成したデータの型を表示 print(X_train.shape) print(Y_train.shape) print(X_test.shape) from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D # 【パラメータ設定】 batch_size = 20 epochs = 30 input_shape = (img_rows, img_cols, 3) nb_filters = 32 # size of pooling area for max pooling pool_size = (2, 2) # convolution kernel size kernel_size = (3, 3) # 【モデル定義】 model = Sequential() model.add(Conv2D(nb_filters, kernel_size, # 畳み込み層 padding='valid', activation='relu', input_shape=input_shape)) model.add(Conv2D(nb_filters, kernel_size, activation='relu')) # 畳み込み層 model.add(MaxPooling2D(pool_size=pool_size)) # プーリング層 model.add(Conv2D(nb_filters, kernel_size, activation='relu')) # 畳み込み層 model.add(MaxPooling2D(pool_size=pool_size)) # プーリング層 model.add(Dropout(0.25)) # ドロップアウト(過学習防止のため、入力と出力の間をランダムに切断) model.add(Flatten()) # 多次元配列を1次元配列に変換 model.add(Dense(128, activation='relu')) # 全結合層 model.add(Dropout(0.2)) # ドロップアウト model.add(Dense(nb_classes, activation='sigmoid')) # 2クラスなので全結合層をsigmoid # モデルのコンパイル model.compile(loss='binary_crossentropy', # 2クラスなのでbinary_crossentropy optimizer='adam', # 最適化関数のパラメータはデフォルトを使う metrics=['accuracy']) # 【各エポックごとの学習結果を生成するためのコールバックを定義(前回より精度が良い時だけ保存)】 from keras.callbacks import ModelCheckpoint import os model_checkpoint = ModelCheckpoint( filepath=os.path.join('models','model_2class120_{epoch:02d}.h5'), monitor='val_accuracy', mode='max', save_best_only=True, verbose=1) print("filepath",os.path.join('models','model_.h5')) # 【学習】 result = model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(X_test, Y_test), callbacks=[model_checkpoint],validation_split=0.1)3-2.学習
from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D # 【パラメータ設定】 batch_size = 20 epochs = 30 input_shape = (img_rows, img_cols, 3) nb_filters = 32 # size of pooling area for max pooling pool_size = (2, 2) # convolution kernel size kernel_size = (3, 3) # 【モデル定義】 model = Sequential() model.add(Conv2D(nb_filters, kernel_size, # 畳み込み層 padding='valid', activation='relu', input_shape=input_shape)) model.add(Conv2D(nb_filters, kernel_size, activation='relu')) # 畳み込み層 model.add(MaxPooling2D(pool_size=pool_size)) # プーリング層 model.add(Conv2D(nb_filters, kernel_size, activation='relu')) # 畳み込み層 model.add(MaxPooling2D(pool_size=pool_size)) # プーリング層 model.add(Dropout(0.25)) # ドロップアウト(過学習防止のため、入力と出力の間をランダムに切断) model.add(Flatten()) # 多次元配列を1次元配列に変換 model.add(Dense(128, activation='relu')) # 全結合層 model.add(Dropout(0.2)) # ドロップアウト model.add(Dense(nb_classes, activation='sigmoid')) # 2クラスなので全結合層をsigmoid # モデルのコンパイル model.compile(loss='binary_crossentropy', # 2クラスなのでbinary_crossentropy optimizer='adam', # 最適化関数のパラメータはデフォルトを使う metrics=['accuracy']) # 【各エポックごとの学習結果を生成するためのコールバックを定義(前回より精度が良い時だけ保存)】 from keras.callbacks import ModelCheckpoint import os model_checkpoint = ModelCheckpoint( filepath=os.path.join('models','model_2class120_{epoch:02d}_{val_acc:.3f}.h5'), monitor='val_acc', mode='max', save_best_only=True, verbose=1) # 【学習】 result = model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(X_test, Y_test), callbacks=[model_checkpoint])3-3.分類
from keras.models import load_model from keras.preprocessing.image import load_img, img_to_array import matplotlib.pyplot as plt model = load_model('models/model_2class120_04.h5') model.summary() def img_to_traindata(file, img_rows, img_cols, rgb): if rgb == 0: img = load_img(file, color_mode = "grayscale", target_size=(img_rows,img_cols)) # grayscaleで読み込み else: img = load_img(file, color_mode = "rgb", target_size=(img_rows,img_cols)) # RGBで読み込み x = img_to_array(img) x = x.astype('float32') x /= 255 return x import numpy as np img_rows = 224 # 画像サイズはVGG16のデフォルトサイズとする img_cols = 224 ## 画像読み込み filename = "dog_smile/n02085936_37.jpg" x = img_to_traindata(filename, img_rows, img_cols, 1) # img_to_traindata関数は、学習データ生成のときに定義 x = np.expand_dims(x, axis=0) ## どのクラスかを判別する preds = model.predict(x) pred_class = np.argmax(preds[0]) print("識別結果:", pred_class) print("確率:", preds[0]) from keras import backend as K import cv2 # モデルの最終出力を取り出す model_output = model.output[:, pred_class] # 最後の畳込み層を取り出す last_conv_output = model.get_layer('conv2d_3').output #'block5_conv3').output # 最終畳込み層の出力の、モデル最終出力に関しての勾配 grads = K.gradients(model_output, last_conv_output)[0] # model.inputを入力すると、last_conv_outputとgradsを出力する関数を定義 gradient_function = K.function([model.input], [last_conv_output, grads]) # 読み込んだ画像の勾配を求める output, grads_val = gradient_function([x]) output, grads_val = output[0], grads_val[0] # 重みを平均化して、レイヤーのアウトプットに乗じてヒートマップ作成 weights = np.mean(grads_val, axis=(0, 1)) heatmap = np.dot(output, weights) heatmap = cv2.resize(heatmap, (img_rows, img_cols), cv2.INTER_LINEAR) heatmap = np.maximum(heatmap, 0) heatmap = heatmap / heatmap.max() heatmap = cv2.applyColorMap(np.uint8(255 * heatmap), cv2.COLORMAP_JET) # ヒートマップに色をつける heatmap = cv2.cvtColor(heatmap, cv2.COLOR_BGR2RGB) # 色をRGBに変換 img = plt.imread(filename, cv2.IMREAD_UNCHANGED) print(img.shape) # (330, 440, 4) fig, ax = plt.subplots() ax.imshow(img) plt.show()4.分類結果
2020-04-26 21:12:46.904489: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x7fded852e7f0 initialized for platform Host (this does not guarantee that XLA will be used). Devices: 2020-04-26 21:12:46.904528: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Host, Default Version Model: "sequential_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_1 (Conv2D) (None, 222, 222, 32) 896 _________________________________________________________________ conv2d_2 (Conv2D) (None, 220, 220, 32) 9248 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 110, 110, 32) 0 _________________________________________________________________ conv2d_3 (Conv2D) (None, 108, 108, 32) 9248 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 54, 54, 32) 0 _________________________________________________________________ dropout_1 (Dropout) (None, 54, 54, 32) 0 _________________________________________________________________ flatten_1 (Flatten) (None, 93312) 0 _________________________________________________________________ dense_1 (Dense) (None, 128) 11944064 _________________________________________________________________ dropout_2 (Dropout) (None, 128) 0 _________________________________________________________________ dense_2 (Dense) (None, 2) 258 ================================================================= Total params: 11,963,714 Trainable params: 11,963,714 Non-trainable params: 0 _________________________________________________________________ 識別結果: 1 確率: [0.27252397 0.6845933 ] (375, 500, 3)5.今後の課題
精度をあげるための問題点を絞り込む必要がある。
- 投稿日:2020-04-26T16:57:45+09:00
Windows10へTensorFlow2をインストールする
はじめに
4月になって、新しいPCを購入しました。
またゼロからTensorFlow環境を構築したので記録を残します。
ということで、何も入っていない状態からのインストールです。環境
- OS : Windows 10 64bit
- Python : Python 3.7.7
- TensorFlow : 2.1.0
- jupyterlab : 2.1.1
- CUDA : 10.1 update 2
- cuDNN : 7.6.5
- GPU NVIDIA GeForce MX250
TensorFlow2 の動作要件
TensorFlow2 の動作要件は、https://www.tensorflow.org/install?hl=jaから確認できます。
- Windows 7 以上
Windows10にインストールするので問題なし。- Python 3.5–3.7
Python 3.7系の最新である、Python 3.7.7 をインストールします。インストールするツールのバージョンはhttps://www.tensorflow.org/install/gpu#pip_packageで確認します。
TensorFlow2の場合は下記の要件になります。
- TensorFlow 2.1.0 以降は CUDA 10.1 に対応しています。
最新は10.2ですが、10.1にします。- CUDA 10.1の場合、VIDIA GPU ドライバ は 418.x 以降が必要です。
これは、「NVIDIA コントロール パネル」で確認できます。低い場合はアップデートします。- cuDNN は7.6 以降が必要です。
7.6.5をインストールします。Python 3.7.7 のインストール
https://www.python.org/から、「Downloads」-「All releases」と選択します。
各バージョンのリストがあるので、Python 3.7.7 の Download をクリックします。
Files の一覧から「Windows x86-64 executable installer」をクリックしてダウンロードします。
ダウンロードしたファイルを実行して、インストールします。インストールが完了したら、下記を実行してバージョンを確認します。
>python -V Python 3.7.7CPUの拡張命令セットの確認
こちらを参考に、CPUの拡張命令セットを確認します。
得られた結果は下記です。
Vendor ID : GenuineIntel CPU name : Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz Microarchitecture : kabylake Vector instructions supported: SSE : Yes SSE2 : Yes SSE3 : Yes SSSE3 : Yes SSE4.1 : Yes SSE4.2 : Yes SSE4a : -- AVX : Yes AVX2 : Yes BMI1 : Yes BMI2 : YesAVX2に対応しているので、TensorFlowは1.6以上をインストール可能です。
現時点で最新のバージョンをインストールします。GPUの確認
念のために、GPUを確認しておきます。
購入時点ですでに、「NVIDIA コントロール パネル」がインストールされていたので、これを使用します。
- デスクトップで右クリックして「NVIDIA コントロール パネル」を選択します。
- 「ヘルプ」メニューから「システム情報」を選択します。
- 「グラフィックス カード情」に「GeForce MX250」と書かれています。
※「グラフィックス カード情」は、「情報」の脱字ではないです。本当にこのように表示されています。Visual Studio 2017 のインストール
https://docs.nvidia.com/cuda/archive/10.1/cuda-installation-guide-microsoft-windows/index.htmlに、CUDA 10.1で必要なものが書かれています。
Visual Studioが必要で、「Table 2. Windows Compiler Support in CUDA 10.1」の表にサポートされているVisual Studioのバージョンが書かれています。
Visual Studio 2019 は、Preview releasesなので、Visual Studio 2017をインストールします。
https://visualstudio.microsoft.com/ja/downloads/からダウンロードします。
「古いバージョンのダウンロード」をクリックします。
「2017」を展開して、右側の「ダウンロード」をクリックする。Microsoft アカウントでログインして、ダウンロードします。
今回は、「Visual Studio Community 2017 (version 15.9)」ダウンロードしました。
ダウンロードした「vs_Community.exe」をダブルクリックしてVisual Studio Installer を起動します。
「C++によるデスクトップ開発」を選択して「インストール」をクリックします。CUDA 10.1 update 2 のインストール
NVIDIA CUDA Toolkit をダウンロードします。
https://developer.nvidia.com/cuda-toolkit-archiveにアクセスします。
「CUDA Toolkit 10.1 update2 Archive」を選択して、ダウンロードします。「Installer Type」は、ネットワークインストーラーを選択しました。(19.9MB)
ちなみにフルインストーラーだと2.5GBのファイルをダウンロードします。ダウンロードした「cuda_10.1.243_win10_network.exe」をダブルクリックして、インストールします。
cuDNN 7.6.5 のインストール
cuDNNは、https://developer.nvidia.com/cudnnからダウンロードします。
「Download cuDNN v7.6.5 (November 5th, 2019), for CUDA 10.1」を展開して、
「cuDNN Library for Windows 10」をダウンロードします。ダウンロードした「cudnn-10.1-windows10-x64-v7.6.5.32.zip」を解凍して、
中にあるCUDAディレクトリを任意のディレクトリに置きます。CUDAを置いたディレクトリをシステム環境変数に設定します。
環境変数名 path CUDNN_PATH c:\tf\CUDA PATHの最後に追加 c:\tf\CUDA\bin ※CUDAディレクトリを「c:\tf\」に置いた場合。
pip のバージョンアップ
TensorFlow2 をインストールするためには、pip 19.0より新しいバージョンが必要です。
バージョンが低いようなら、バージョンアップします。pip install -U pipTensorFlow2 のインストール
下記コマンドだけでOKです。
>pip install tensorflow動作確認を行います。
まずは、下記のファイルを作成します。tensotflow_test.pyimport tensorflow as tf import os print(tf.__version__) print(tf.keras.__version__) print(tf.random.normal([5, 5]))実行します。
環境変数 TF_CPP_MIN_LOG_LEVEL は、余計なメッセージを表示しないためのものです。>set TF_CPP_MIN_LOG_LEVEL=2 >python tensorflow_test.py 2.1.0 2.2.4-tf tf.Tensor( [[ 0.9073535 -0.30908114 -1.1792291 -0.03576818 -0.350677 ] [-0.30494577 0.0393485 -1.7498294 0.01919838 -0.881274 ] [-0.8610118 -1.6675215 -0.9653552 0.4389885 -0.06305566] [-0.6703128 0.85750896 1.0951182 0.029854 1.1836303 ] [ 0.5926097 0.5141883 -0.84746957 0.668688 0.30143082]], shape=(5, 5), dtype=float32)TensorFlowとKerasのバージョンが表示され、5x5 の乱数も表示されました。
TensorFlowも2.1.0 がインストールされていることが確認できました。jupyterlab のインストール
何かと便利なjupyterlab をインストールします。
>pip install jupyterlabjupyterlab をバックグラウンドで起動します。
>start /b jupyter lab
起動すると、自動的にブラウザでjupyterlab へつながります。
自動的につながらない場合は、ブラウザで
http://localhost:8888/lab
へアクセスます。
tokenは、jupyterlab 起動時のメッセージに書かれています。最後に
TensorFlow2の実行環境ができました。
ゼロからのインストールだと、すんなり完了しました。
後にバージョンアップを行うときが怖いですが、今はこの環境で楽しみます。
- 投稿日:2020-04-26T16:34:49+09:00
[Tensorflow] tensorflowでarray_to_imgの使い方
- 投稿日:2020-04-26T00:40:24+09:00
[TensorFlow 2] グラフモードでTensorの中身を確認する方法
はじめに
TensorFlow (2.x) で学習時の損失関数やデータセットの変換部分に自作関数を使うときに、「思ったとおりの値が入っているのかな?」と確認しようと思って
print()
を呼び出しても、値が出力されないときがあります。
tfdbg
などのデバッガーを使えば良いのでしょうが、もっとシンプルに、いわゆる「printデバッグ」をする方法をご紹介します。
tfdbg
については→tfdbg を使って Keras の nan や inf を潰す - Qiita検証環境
- Ubuntu 18.04
- Python 3.6.9
- TensorFlow 2.1.0 (CPU)
以下のコードでは、↓が書かれているものとします。
import tensorflow as tfTensor に対して print() した場合の挙動
TensorFlow 2.xでは Eager Execution がデフォルトになりましたので、インタプリタで
Tensor
を組み立てている限りは、普通にprint()
すればTensor
の値が表示されますし、.numpy()
でndarray
として値を得ることもできます。値を確認できる場合
x = tf.constant(10) y = tf.constant(20) z = x + y print(z) # tf.Tensor(30, shape=(), dtype=int32) print(z.numpy()) # 30値を確認できない場合 (1)
学習・評価時に逐次
Tensor
の値を評価すると遅いので、@tf.function
デコレータをつけることにより、グラフモードで処理する関数を定義することができます。グラフモードで定義した演算は計算グラフとしてまとめて(Pythonの外で)処理されるため、計算過程の値を見ることができません。@tf.function def dot(x, y): tmp = x * y print(tmp) return tf.reduce_sum(tmp) x = tf.constant([1, 2]) y = tf.constant([3, 1]) w = tf.constant([0, 2]) print(dot(x, y)) print(dot(x, w)) # Tensor("mul:0", shape=(2,), dtype=int32) # tf.Tensor(5, shape=(), dtype=int32) # tf.Tensor(4, shape=(), dtype=int32)
dot()
の外で計算結果を出力することはできますが、中では値を見ることができません。
しかも、dot()
を複数回呼び出しても、中のprint()
は基本的にはグラフを解析するタイミングで1回しか実行されません。もちろん、この場合は
@tf.function()
を取り除けば値が見えるようにはなります。def dot(x, y): tmp = x * y print(tmp) return tf.reduce_sum(tmp) x = tf.constant([1, 2]) y = tf.constant([3, 1]) w = tf.constant([0, 2]) print(dot(x, y)) print(dot(x, w)) # tf.Tensor([3 2], shape=(2,), dtype=int32) # tf.Tensor(5, shape=(), dtype=int32) # tf.Tensor([0 4], shape=(2,), dtype=int32) # tf.Tensor(4, shape=(), dtype=int32)値を確認できない場合 (2)
tf.data.Dataset
に対するmap()
処理や、Kerasで自作の損失関数を使用する場合など、暗黙のうちにグラフモードで実行される場合があります。この場合は@tf.function
をつけていなくてもprint()
で途中の値を見ることができません。def fourth_power(x): z = x * x print(z) z = z * z return z ds = tf.data.Dataset.range(10).map(fourth_power) for i in ds: print(i) # Tensor("mul:0", shape=(), dtype=int64) # tf.Tensor(0, shape=(), dtype=int64) # tf.Tensor(1, shape=(), dtype=int64) # tf.Tensor(16, shape=(), dtype=int64) # :tf.print()
グラフモードで実行されている処理の中で
Tensor
の値を確認するにはtf.print()
を使用します。
tf.print | TensorFlow Core v2.1.0以下のように、値を表示することもできますし、
tf.shape()
を使ってTensor
の次元やサイズを表示することもできます。自作関数の中で、なぜか次元やサイズが合わないと怒られてしまうときのデバッグにもご利用ください。@tf.function def dot(x, y): tmp = x * y tf.print(tmp) tf.print(tf.shape(tmp)) return tf.reduce_sum(tmp) x = tf.constant([1, 2]) y = tf.constant([3, 1]) w = tf.constant([0, 2]) print(dot(x, y)) print(dot(x, w)) # [3 2] # [2] # tf.Tensor(5, shape=(), dtype=int32) # [0 4] # [2] # tf.Tensor(4, shape=(), dtype=int32)
Dataset.map()
のデバッグをしたい時でもtf.print()
を使えば大丈夫です。def fourth_power(x): z = x * x tf.print(z) z = z * z return z ds = tf.data.Dataset.range(10).map(fourth_power) for i in ds: print(i) # 0 # tf.Tensor(0, shape=(), dtype=int64) # 1 # tf.Tensor(1, shape=(), dtype=int64) # 4 # tf.Tensor(16, shape=(), dtype=int64) # :tf.print() がうまく動かない例
では何も考えず
Tensor
の中身はtf.print()
で出力すればよいのかというと、実はそうでもないのです。
tf.print()
が実行されるのは、実際に処理が計算グラフとして実行されるときです。
つまり、計算を実行するまでもなくグラフ解析時点で型や次元が一致しないことが分かってエラーが発生する場合、tf.print()
の処理は実行されません。ややこしいですね…。@tf.function def add(x, y): z = x + y tf.print(z) # このprintは実行されない return z x = tf.constant([1, 2]) y = tf.constant([3, 4, 5]) ret = add(x, y) # ValueError: Dimensions must be equal, but are 2 and 3 for 'add' (op: 'AddV2') with input shapes: [2], [3].このようなケースでは、逆に普通の
print()
を使って、目的の形状のデータが渡ってきているか確認するのがよいでしょう。@tf.function def add(x, y): print(x) # このprintは計算グラフ解析時に実行される print(y) z = x + y return z x = tf.constant([1, 2]) y = tf.constant([3, 4, 5]) ret = add(x, y) # Tensor("x:0", shape=(2,), dtype=int32) # Tensor("y:0", shape=(3,), dtype=int32) # ValueError: Dimensions must be equal, but are 2 and 3 for 'add' (op: 'AddV2') with input shapes: [2], [3].自作関数の中で変数を更新する方法
例えば、グラフモードで自作関数が呼び出された回数をカウントし、何回目の呼び出しかを表示することを考えます。
ダメな例
count = 0 @tf.function def dot(x, y): global count tmp = x * y count += 1 tf.print(count, tmp) return tf.reduce_sum(tmp) x = tf.constant([1, 2]) y = tf.constant([3, 1]) w = tf.constant([0, 2]) print(dot(x, y)) print(dot(x, w)) # 1 [3 2] # tf.Tensor(5, shape=(), dtype=int32) # 1 [0 4] # tf.Tensor(4, shape=(), dtype=int32)2回目にも「1」が表示されてしまいます。
Pythonコードとしてのcount += 1
がグラフ解析時に1回しか実行されないことによります。うまく動く例
以下のように
tf.Variable()
とassign_add()
などを使うのが正解です。
tf.Variable | TensorFlow Core v2.1.0count = tf.Variable(0) @tf.function def dot(x, y): tmp = x * y count.assign_add(1) tf.print(count, tmp) return tf.reduce_sum(tmp) x = tf.constant([1, 2]) y = tf.constant([3, 1]) w = tf.constant([0, 2]) print(dot(x, y)) print(dot(x, w)) # 1 [3 2] # tf.Tensor(5, shape=(), dtype=int32) # 2 [0 4] # tf.Tensor(4, shape=(), dtype=int32)参考記事
tf.function で性能アップ | TensorFlow Core(公式ドキュメント)