TensorFlow の中心にあるデータ構造がテンソルです。テンソルは多次元配列を表現するオブジェクトで、NumPy の ndarray に似た役割を果たします。すべての計算はテンソルを通じて行われるため、その生成・変換・演算の基本を押さえておくことが重要です。
テンソルの生成
テンソルを生成する方法はいくつかあります。もっとも基本的なのは tf.constant を使う方法です。
import tensorflow as tf # スカラー(0次元テンソル) scalar = tf.constant(42) # ベクトル(1次元テンソル) vector = tf.constant([1, 2, 3]) # 行列(2次元テンソル) matrix = tf.constant([[1, 2], [3, 4]]) print(scalar.shape) # () print(vector.shape) # (3,) print(matrix.shape) # (2, 2)
テンソルには shape(形状)、dtype(データ型)、ndim(次元数)といった属性があります。これらを確認することで、テンソルの構造を把握できます。
特定のパターンで初期化されたテンソルを作るための関数も用意されています。
# すべて0のテンソル zeros = tf.zeros([3, 3]) # すべて1のテンソル ones = tf.ones([2, 4]) # 指定した値で埋めたテンソル filled = tf.fill([2, 3], 7.0) # 連番テンソル seq = tf.range(0, 10, 2) # [0, 2, 4, 6, 8]
ニューラルネットワークの重み初期化などでは、乱数テンソルもよく使います。
# 正規分布に従う乱数 normal = tf.random.normal([3, 3], mean=0.0, stddev=1.0) # 一様分布に従う乱数 uniform = tf.random.uniform([2, 2], minval=0, maxval=10)
テンソルの変換
テンソルの形状を変更するには tf.reshape を使います。要素数が一致していれば、自由に形状を変えられます。
original = tf.constant([1, 2, 3, 4, 5, 6]) # 2x3 の行列に変換 reshaped = tf.reshape(original, [2, 3]) print(reshaped) # [[1, 2, 3], # [4, 5, 6]] # -1 を指定すると自動計算 auto = tf.reshape(original, [3, -1]) print(auto) # [[1, 2], # [3, 4], # [5, 6]]
データ型の変換には tf.cast を使います。整数から浮動小数点への変換は、計算の都合上よく行われる操作です。
int_tensor = tf.constant([1, 2, 3]) float_tensor = tf.cast(int_tensor, dtype=tf.float32) print(float_tensor) # [1.0, 2.0, 3.0]
次元の追加や削除も頻繁に使う操作です。tf.expand_dims で次元を追加し、tf.squeeze で不要な次元を削除できます。
a = tf.constant([1, 2, 3]) print(a.shape) # (3,) # 先頭に次元を追加 expanded = tf.expand_dims(a, axis=0) print(expanded.shape) # (1, 3) # サイズ1の次元を削除 squeezed = tf.squeeze(expanded) print(squeezed.shape) # (3,)
テンソルの演算
TensorFlow では四則演算を直感的に記述できます。演算子のオーバーロードにより、Python の通常の演算子がそのまま使えます。
a = tf.constant([10, 20, 30]) b = tf.constant([1, 2, 3]) print(a + b) # [11, 22, 33] print(a - b) # [ 9, 18, 27] print(a * b) # [10, 40, 90] print(a / b) # [10.0, 10.0, 10.0]
行列の積は tf.matmul または @ 演算子で計算します。要素ごとの積(アダマール積)とは異なる点に注意してください。
a * b で計算する。同じ形状のテンソル同士で、対応する要素を掛け合わせる。結果の形状は入力と同じになる。
tf.matmul(a, b) または a @ b で計算する。線形代数の行列積で、(m, n) と (n, p) から (m, p) の結果を返す。
x = tf.constant([[1, 2], [3, 4]]) y = tf.constant([[5, 6], [7, 8]]) # 要素ごとの積 print(x * y) # [[ 5, 12], # [21, 32]] # 行列の積 print(x @ y) # [[19, 22], # [43, 50]]
ブロードキャスト
形状の異なるテンソル同士でも、一定のルールに従って自動的に形状を合わせて演算が行われます。これをブロードキャストと呼びます。
matrix = tf.constant([[1, 2, 3], [4, 5, 6]]) scalar = tf.constant(10) # スカラーが行列の各要素に適用される print(matrix + scalar) # [[11, 12, 13], # [14, 15, 16]] row = tf.constant([100, 200, 300]) # ベクトルが各行に適用される print(matrix + row) # [[101, 202, 303], # [104, 205, 306]]
ブロードキャストは便利ですが、意図しない形状の組み合わせでもエラーにならずに計算されてしまうことがあります。結果の形状が期待どおりかを確認する習慣をつけておくと安全です。
NumPy との相互変換
TensorFlow のテンソルと NumPy の配列は簡単に相互変換できます。データの前処理を NumPy で行い、モデルの計算を TensorFlow で行うといった使い分けがスムーズにできます。
import numpy as np # NumPy → TensorFlow np_array = np.array([1, 2, 3]) tf_tensor = tf.constant(np_array) # TensorFlow → NumPy back_to_np = tf_tensor.numpy() print(type(back_to_np)) # <class 'numpy.ndarray'>
.numpy() メソッドは Eager モードで実行している場合にのみ使えます。TensorFlow 2.x ではデフォルトで Eager モードが有効になっているため、特別な設定なしにこの変換を利用できます。
テンソルの基本操作を理解しておけば、モデル構築やデータ処理の際に迷うことが少なくなります。まずは生成・変換・演算に慣れ、必要に応じてブロードキャストや NumPy 連携を活用していきましょう。