機械学習のExampleから覚えるPython(class:__call__)
今までPythonを感覚的に使っていたので、改めて文法を知ろうかなと。
その際にいま流行りの機械学習(深層学習)のExampleを例にすると
わかりやすいのかなと思ったので書いてみる。
※基本的には Python3.x系のつもりで記載してます
などで、class
について記載したのですが、
今回はその中でも独自モデル(Custom Model)を作る場合の記述について見てみます。
参考:https://www.tensorflow.org/guide/keras
Example
class MyModel(tf.keras.Model): def __init__(self, num_classes=10): super(MyModel, self).__init__(name='my_model') self.num_classes = num_classes # Define your layers here. self.dense_1 = layers.Dense(32, activation='relu') self.dense_2 = layers.Dense(num_classes, activation='sigmoid') def call(self, inputs): # Define your forward pass here, # using layers you previously defined (in `__init__`). x = self.dense_1(inputs) return self.dense_2(x) def compute_output_shape(self, input_shape): # You need to override this function if you want to use the subclassed model # as part of a functional-style model. # Otherwise, this method is optional. shape = tf.TensorShape(input_shape).as_list() shape[-1] = self.num_classes return tf.TensorShape(shape)
解説
class MyModel(tf.keras.Model):
tf.keras.Model
を継承
def __init__(self, num_classes=10): super(MyModel, self).__init__(name='my_model') self.num_classes = num_classes # Define your layers here. self.dense_1 = layers.Dense(32, activation='relu') self.dense_2 = layers.Dense(num_classes, activation='sigmoid')
コンストラクタ(初期化:__init__
)にて、レイヤをインスタンス。
def call(self, inputs): # Define your forward pass here, # using layers you previously defined (in `__init__`). x = self.dense_1(inputs) return self.dense_2(x)
call
関数で、forward
の動作を記載します。
さて、なぜcall
関数で?という疑問になりますよね?
tf.keras.Model
をおっていくとbase_layer.pyまでいきつきます。
base_layer
にある __call__
関数で、上記の call
がよばれることになります。
__call__
は組込み関数でクラスをインスタンスして、関数のように呼ばれたときに動きます。
例でいうと、以下のようになります。
model = MyModel
model() # この時に __call__ →...→ call
今回、TensorFlow/Keras を例にしてますが、PyTorchやChainerでも__call__
にて
Model or Layerを構築しています。
forward
やbackward
関数で実装というのもあるので、
各フレームワークにしたがって書きましょう。
def compute_output_shape(self, input_shape): # You need to override this function if you want to use the subclassed model # as part of a functional-style model. # Otherwise, this method is optional. shape = tf.TensorShape(input_shape).as_list() shape[-1] = self.num_classes return tf.TensorShape(shape)
コメントにあるとおり、書いてもいいし。というやつです。
まとめ
今回、call
からの__call__
についてでした。
機械学習のExampleから覚えるPython(@デコレータ)
今までPythonを感覚的に使っていたので、改めて文法を知ろうかなと。
その際にいま流行りの機械学習(深層学習)のExampleを例にすると
わかりやすいのかなと思ったので書いてみる。
※基本的には Python3.x系のつもりで記載してます
の時に書いてた
@keras_export('keras.datasets.mnist.load_data') def load_data(path='mnist.npz'):
の「@」デコレータについてです。
簡単にいうと
既存関数の処理の前後に自分自身で、処理を付け加える。
今回でいうと、load_data
関数の前後で何か処理やっているようです。
細かく見ていく
@keras_export('keras.datasets.mnist.load_data')
keras_export
は 先頭で以下で宣言されています。
from tensorflow.python.util.tf_export import keras_export
では、tf_export
はというと、
tf_export にて定義されてます。
その api_export はなんでしょうか。
class api_export(object): # pylint: disable=invalid-name """Provides ways to export symbols to the TensorFlow API."""
__init__
関数に書いてあるのをみる。
def __init__(self, *args, **kwargs): # pylint: disable=g-doc-args """Export under the names *args (first one is considered canonical). Args: *args: API names in dot delimited format. **kwargs: Optional keyed arguments. v1: Names for the TensorFlow V1 API. If not set, we will use V2 API names both for TensorFlow V1 and V2 APIs. overrides: List of symbols that this is overriding (those overrided api exports will be removed). Note: passing overrides has no effect on exporting a constant. api_name: Name of the API you want to generate (e.g. `tensorflow` or `estimator`). Default is `tensorflow`. allow_multiple_exports: Allow symbol to be exported multiple time under different names. """
ってことらしい。
今回でいうと、特に引数はなく単純に load_data
を呼んでいるみたい。
参考
機械学習のExampleから覚えるPython(型:データタイプ)
今までPythonを感覚的に使っていたので、改めて文法を知ろうかなと。
その際にいま流行りの機械学習(深層学習)のExampleを例にすると
わかりやすいのかなと思ったので書いてみる。
※基本的には Python3.x系のつもりで記載してます
Example
https://www.tensorflow.org/tutorials/ に記載されている
import tensorflow as tf mnist = tf.keras.datasets.mnist (x_train, y_train),(x_test, y_test) = mnist.load_data() x_train, x_test = x_train / 255.0, x_test / 255.0 model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(), tf.keras.layers.Dense(512, activation=tf.nn.relu), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(10, activation=tf.nn.softmax) ]) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(x_train, y_train, epochs=5) model.evaluate(x_test, y_test)
※本記事記載の時点のコードです。
型
上記Exampleでも、代入記述先(関数の返り値)には型:データタイプがあります。
それぞれ見ていきたいと思います。
mnist = tf.keras.datasets.mnist
>>> type(mnist) module
tf.keras.datasets.mnist は tensorflow/tensorflow/python/keras/datasets/mnist.pyのとおり importできるモジュール(パッケージ)になります。
(x_train, y_train),(x_test, y_test) = mnist.load_data()
>>> type(x_train) numpy.ndarray >>> x_train.dtype dtype('uint8')
numpyモジュールの多次元配列型になります。
更にデータタイプを dtype
で確認することができます。
データロード時は uint8
ですね。
x_train, x_test = x_train / 255.0, x_test / 255.0
>>> type(x_train) numpy.ndarray >>> x_train.dtype dtype('float64')
先ほどと同じくnumpyモジュールの多次元配列型になります。
ただし、255.0
という float型で除算しているためデータタイプは float64
になってます。
model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(), tf.keras.layers.Dense(512, activation=tf.nn.relu), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(10, activation=tf.nn.softmax) ])
>>> type(model) tensorflow.python.keras.engine.sequential.Sequential
こちらも、importできる Sequential
パッケージですね。
データタイプ
int
やfloat
になります。
必要そうなものを列挙してみます。
項目 | データタイプ |
---|---|
真理値判定 | bool |
数値型 | int, float, complex |
文字列 | str |
シーケンス型(配列) | list, tuple, range |
マッピング型 | dict |
データ型については、Pythonの公式ドキュメントも参考にしてください。
#ifや#defineの確認方法(プリプロセッサ)
昨日、#ifdef 追加の確認なんて目チェックで十分。なんてことを未来ある若者に適当な感じで言ってしまったを反省したのでメモとして書こうかなと。
今回は、プリプロセッサ処理後の結果で確認するという方法を書きます。
たぶん、今どきはIDEで #define
定義を指示すればコード上で色づけされるんだろうなと勝手に思ってます。
例えば、以下のmain.cpp
ファイルがあった場合
int main(int argc, char const* argv[]) { #ifdef TEST int value = 100; #else int value = 0; #endif // 何かの処理が続く return 0; }
あとは、gccのオプションに -E
をつけて標準出力に出す。
$ gcc -E main.cpp
実行結果は以下になります。
$ gcc -E main.cpp # 1 "main.cpp" # 1 "<built-in>" 1 # 1 "<built-in>" 3 # 336 "<built-in>" 3 # 1 "<command line>" 1 # 1 "<built-in>" 2 # 1 "main.cpp" 2 int main(int argc, char const* argv[]) { int value = 0; return 0; }
TEST
が有効になった場合の時も確認したいので、-D
にて指定します。
$ gcc -E -DTEST main.cpp # 1 "main.cpp" # 1 "<built-in>" 1 # 1 "<built-in>" 3 # 336 "<built-in>" 3 # 1 "<command line>" 1 # 1 "<built-in>" 2 # 1 "main.cpp" 2 int main(int argc, char const* argv[]) { int value = 100; return 0; }
とこんな感じで確認できます。
(色々読み込んでいると大量に出るけど...)
あと合わせて -C
とか -P
とかあるけど説明省略します。
参考URL
機械学習のExampleから覚えるPython(数値演算子)
今までPythonを感覚的に使っていたので、改めて文法を知ろうかなと。
その際にいま流行りの機械学習(深層学習)のExampleを例にすると
わかりやすいのかなと思ったので書いてみる。
※基本的には Python3.x系のつもりで記載してます
Example
https://www.tensorflow.org/tutorials/ に記載されている
import tensorflow as tf mnist = tf.keras.datasets.mnist (x_train, y_train),(x_test, y_test) = mnist.load_data() x_train, x_test = x_train / 255.0, x_test / 255.0 model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(), tf.keras.layers.Dense(512, activation=tf.nn.relu), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(10, activation=tf.nn.softmax) ]) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(x_train, y_train, epochs=5) model.evaluate(x_test, y_test)
※本記事記載の時点のコードです。
数値演算子
x_train, x_test = x_train / 255.0, x_test / 255.0
x_train
, x_test
データすべてに 255.0
の除算を行ってます。
これは、元の値が0-255の範囲で定義されているため、0-1に変換しています。
除算するまえであれば、以下のコードを入力すると uint8
と表示されると思います。
print(x_train.dtype)
では、除算後はというと float64
になっていると思います。
これは、255.0
という値が float64
と認識されているからになります。
正確には uint8
が float64
にキャストされて計算されています。
種類
演算子 | 例 | 説明 |
---|---|---|
+ | a + b | 足し算 |
– | a – b | 引き算 |
* | a*b | 掛け算 |
/ | a/b | 割り算 |
// | a//b | aをbで割った整数値(少数点以下削除 |
% | a%b | aをbで割った時の割り切れなかった余り |
** | a**n | aをn回掛けた数(べき乗) |
他にも ビット演算子
, 比較演算子
などありますが、
Exampleコードに出てきてから書こうと思います。