#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と認識されているからになります。

正確には uint8float64にキャストされて計算されています。

種類

演算子 説明
+ a + b 足し算
a – b 引き算
* a*b 掛け算
/ a/b 割り算
// a//b aをbで割った整数値(少数点以下削除
% a%b aをbで割った時の割り切れなかった余り
** a**n aをn回掛けた数(べき乗)

他にも ビット演算子, 比較演算子などありますが、
Exampleコードに出てきてから書こうと思います。

機械学習のExampleから覚えるPython(class:コンストラクタ)

今まで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)

※本記事記載の時点のコードです。

class

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)
])

tf.keras.models.Sequentialclassと呼ばれるもので定義されています。

実際のコードは こちらにあります。

@keras_export('keras.models.Sequential', 'keras.Sequential')
class Sequential(Model):

さて、前回の記事では Sequentialクラス Modelは継承(基底クラス)というお話でした。
では、Exampleコードに書かれている

  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)

の部分はどこにあたるのかを今回見ていきたいと思います。

コンストラク

Pythonでは、特殊な関数があります。
その一つが コンストラクタ: __init()__になります。
クラスがインスタンスされた際に自動で呼び出されます。

では、実際の実装のほうを見てみたいと思います。

  def __init__(self, layers=None, name=None):
    super(Sequential, self).__init__(name=name)
    self.supports_masking = True
    self._build_input_shape = None
    self._compute_output_and_mask_jointly = True

    self._layer_call_argspecs = {}

    # Add to the model any layers passed to the constructor.
    if layers:
      for layer in layers:
        self.add(layer)

実際のコードは こちら にあります。

self はクラス自身を指すので、引数としては無視してください。
では、クラスをインスタンス(宣言)時に引数として渡していた
tf.keras.layers.*** はどの引数に該当するかというと layers になります。

    # Add to the model any layers passed to the constructor.
    if layers:
      for layer in layers:
        self.add(layer)

つまり、コンストラクタ(初期化)で行っている処理は
layers が存在していれば(Noneでなければ)、layers の配列数だけ
クラス自身のadd関数を呼び出す です。

add関数が何をしているかは確認してもらえればと思います。

デコンストラク

クラスが削除される際に自動で呼び出されます。
デコンストラクタ: __del()__になります。

Sequentialクラスには実装がありませんね。
必要に応じて実装すればよいかと思いますが、あまり見た記憶がありません。

おまけ

TensorFlow公式ページでは、Kerasによる書き方がいくつか紹介されています。
独自のModelやLayerの書き方などもありますので、参考にすると良いかと思います。

今回のコンストラクタの話でいうと、このような書き方も記載されています。

model = tf.keras.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10,)))
model.add(layers.Dense(1, activation='sigmoid'))

引数なしで Sequentialクラスをインスタンスし、次行で add関数で Layerを追加している書き方になります。

機械学習のExampleから覚えるPython(class:継承)

今まで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)

※本記事記載の時点のコードです。

class

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)
])

tf.keras.models.Sequentialclassと呼ばれるもので定義されています。

実際のコードは こちらにあります。

@keras_export('keras.models.Sequential', 'keras.Sequential')
class Sequential(Model):

継承

class Sequential(Model):

このSequentialクラスは Modelクラスを継承しています。
Modelを「基底クラス」、Sequentialを「派生クラス」と言ったりします。

やっていることは、シンプルで Sequential = Model + Sequential独自 という形で
Modelの関数や変数を Sequentialでも使えます。

Exampleで記述している

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)

こちらの compilefitevaluate 関数は Sequentialのクラスコード内には記述がありません。
実際に記述されているのは Model にあります。

確認したい方は こちらを参照してください。

多重継承

基底クラスを複数宣言できるというお話です。

class DerivedClassName(Base1, Base2, Base3):
    <statement-1>
    .
    .
    .
    <statement-N>

参考

さて、あとはSequentialクラスをインスタンスしている部分(初期化)と
演算子(Exampleでは x_train / 255.0 )さえ理解すれば題目の
Exampleコードはすべて理解できたことになりますね!

機械学習の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から覚えるPython(関数呼び出し)にて、load_data 関数の引数 pathが呼び出し時に省略されていることが確認できました。

関数の引数については3つの指定ができます。

  • dafaultによる省略
  • 引数を入力(引数名無し)
  • 引数名を指定

defaultによる省略

関数定義側で、default値が設定している場合に
呼び出し側が default値で良い場合省略することができます。

  • 関数定義側
def load_data(path='mnist.npz'):
  • 呼び出し側
(x_train, y_train),(x_test, y_test) = mnist.load_data()

pathmnist.npzの値で処理されます。

引数を入力(引数名無し)

model.fit(x_train, y_train, epochs=5)

このコードを見てみます。
定義側はこのようになってます。

  def fit(self,
          x=None,
          y=None,
          batch_size=None,
          epochs=1,
          verbose=1,
          callbacks=None,
          validation_split=0.,
          validation_data=None,
          shuffle=True,
          class_weight=None,
          sample_weight=None,
          initial_epoch=0,
          steps_per_epoch=None,
          validation_steps=None,
          validation_freq=1,
          max_queue_size=10,
          workers=1,
          use_multiprocessing=False,
          **kwargs):

self は一旦無視していただいて、x_train, y_trainfit関数の
どの引数にあたるかというと、順番に設定しています。
つまり、以下のようになります。

#         x=x_train, y=y_train
model.fit(x_train, y_train, epochs=5)

引数名を指定

先ほどのコードの epochsの設定が該当します。

model.fit(x_train, y_train, epochs=5)

fit関数で定義されている epochsを指定して 5という値を入力しています。

可変長引数

関数の定義では、可変長引数 を定義することができます。
fit関数でも最後の引数に出てきていた **kwargsが該当します。

こちらのページが参考になると思いますので、リンク貼っときます。