TensorFlow テンソル操作
テンソルはTensorFlowにおける中核のデータ構造であり、多次元配列の拡張概念と理解できます。
機械学習では、ほとんどすべてのデータが最終的にテンソル形式で表現されて処理されます。
テンソルの基本特性
- データ型(dtype):すべてのテンソルには特定のデータ型があり、例えばtf.float32、tf.int64などがあります。
- 形状(shape):テンソルの各次元のサイズを示します。例えば(2,3)は2行3列の行列を表します。
- デバイス位置(device):テンソルがCPU上に格納されるかGPU上に格納されるかを示します。
テンソルの次元
- 0次元テンソル:スカラー(scalar)、例えば
tf.constant(5) - 1次元テンソル:ベクトル(vector)、例えば
tf.constant([1,2,3]) - 2次元テンソル:行列(matrix)、例えば
tf.constant([[1,2],[3,4]]) - 3次元及以上:高階テンソル、例えば
tf.ones((2,3,4))2つの3×4行列を表します
テンソルを作成する一般的な方法
1. Pythonリスト/NumPy配列から作成
例
import tensorflow as tf
import numpy as np
# Pythonリストから作成
tensor_from_list = tf.constant([[1, 2], [3, 4]])
# NumPy配列から作成
numpy_array = np.array([[5, 6], [7, 8]])
tensor_from_numpy = tf.constant(numpy_array)
import numpy as np
# Pythonリストから作成
tensor_from_list = tf.constant([[1, 2], [3, 4]])
# NumPy配列から作成
numpy_array = np.array([[5, 6], [7, 8]])
tensor_from_numpy = tf.constant(numpy_array)
2. 特殊な値のテンソルを作成
例
# 全ゼロテンソル
zeros = tf.zeros((2, 3)) # 2行3列の全0行列
# 全1テンソル
ones = tf.ones((3, 2)) # 3行2列の全1行列
# 単位行列
eye = tf.eye(3) # 3×3の単位行列
# 特定の値で埋める
filled = tf.fill((2, 2), 7) # 2×2行列、すべての要素が7
zeros = tf.zeros((2, 3)) # 2行3列の全0行列
# 全1テンソル
ones = tf.ones((3, 2)) # 3行2列の全1行列
# 単位行列
eye = tf.eye(3) # 3×3の単位行列
# 特定の値で埋める
filled = tf.fill((2, 2), 7) # 2×2行列、すべての要素が7
3. ランダムテンソルの作成
例
# 一様分布の乱数
uniform = tf.random.uniform((2, 2), minval=0, maxval=1)
# 正規分布の乱数
normal = tf.random.normal((3, 3), mean=0, stddev=1)
# ランダムな並べ替え
shuffled = tf.random.shuffle(tf.constant([1, 2, 3, 4, 5]))
uniform = tf.random.uniform((2, 2), minval=0, maxval=1)
# 正規分布の乱数
normal = tf.random.normal((3, 3), mean=0, stddev=1)
# ランダムな並べ替え
shuffled = tf.random.shuffle(tf.constant([1, 2, 3, 4, 5]))
テンソルの基本操作
1. 数学演算
例
a = tf.constant([[1, 2], [3, 4]])
b = tf.constant([[5, 6], [7, 8]])
# 要素ごとの加算
add = tf.add(a, b) # または演算子オーバーロード a + b
# 要素ごとの乗算
mul = tf.multiply(a, b) # または a * b
# 行列乗算
matmul = tf.matmul(a, b) # または a @ b
# その他の数学演算
sqrt = tf.sqrt(tf.cast(a, tf.float32)) # 平方根(浮動小数点型に変換する必要がある)
b = tf.constant([[5, 6], [7, 8]])
# 要素ごとの加算
add = tf.add(a, b) # または演算子オーバーロード a + b
# 要素ごとの乗算
mul = tf.multiply(a, b) # または a * b
# 行列乗算
matmul = tf.matmul(a, b) # または a @ b
# その他の数学演算
sqrt = tf.sqrt(tf.cast(a, tf.float32)) # 平方根(浮動小数点型に変換する必要がある)
2. 形状操作
例
tensor = tf.constant([[1, 2, 3], [4, 5, 6]])
# 形状を取得
shape = tensor.shape # (2, 3) を返す
# 形状の変更(reshape)
reshaped = tf.reshape(tensor, (3, 2)) # 3行2列に変更
# 転置(transpose)
transposed = tf.transpose(tensor) # 3行2列になる
# 次元の拡張(expand_dims)
expanded = tf.expand_dims(tensor, axis=0) # 形状が(2,3)から(1,2,3)に変更
# 形状を取得
shape = tensor.shape # (2, 3) を返す
# 形状の変更(reshape)
reshaped = tf.reshape(tensor, (3, 2)) # 3行2列に変更
# 転置(transpose)
transposed = tf.transpose(tensor) # 3行2列になる
# 次元の拡張(expand_dims)
expanded = tf.expand_dims(tensor, axis=0) # 形状が(2,3)から(1,2,3)に変更
3. インデックスとスライス
例
tensor = tf.constant([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 単一要素の取得
elem = tensor[1, 2] # 2行3列目の要素を取得(値は6)
# スライス操作
row = tensor[1, :] # 2行目のすべての要素を取得 [4,5,6]
col = tensor[:, 1] # 2列目のすべての要素を取得 [2,5,8]
sub = tensor[0:2, 1:] # 1-2行、2-3列を取得 [[2,3],[5,6]]
# 単一要素の取得
elem = tensor[1, 2] # 2行3列目の要素を取得(値は6)
# スライス操作
row = tensor[1, :] # 2行目のすべての要素を取得 [4,5,6]
col = tensor[:, 1] # 2列目のすべての要素を取得 [2,5,8]
sub = tensor[0:2, 1:] # 1-2行、2-3列を取得 [[2,3],[5,6]]
テンソルのブロードキャスト機構
ブロードキャスト(Broadcasting)は、異なる形状のテンソル演算を処理するためのTensorFlowの重要な機構であり、小さいテンソルを自動的に拡張して大きいテンソルの形状に一致させます。
ブロードキャストの規則
- 最後の次元から前方に向かって比較します
- 2つの次元は、等しいか、一方が1であるか、一方が存在しないかのいずれかでなければなりません
- 欠落しているか1である次元でコピーして拡張します
ブロードキャストの例
例
# ベクトル(3,)とスカラー()の加算
a = tf.constant([1, 2, 3])
b = tf.constant(2)
c = a + b # 結果は[3,4,5]、bは[2,2,2]にブロードキャストされる
# 行列(3,1)とベクトル(3,)の加算
d = tf.constant([[1], [2], [3]])
e = tf.constant([10, 20, 30])
f = d + e # dは[[1,1,1],[2,2,2],[3,3,3]]にブロードキャストされる
# 結果は[[11,21,31],[12,22,32],[13,23,33]]
a = tf.constant([1, 2, 3])
b = tf.constant(2)
c = a + b # 結果は[3,4,5]、bは[2,2,2]にブロードキャストされる
# 行列(3,1)とベクトル(3,)の加算
d = tf.constant([[1], [2], [3]])
e = tf.constant([10, 20, 30])
f = d + e # dは[[1,1,1],[2,2,2],[3,3,3]]にブロードキャストされる
# 結果は[[11,21,31],[12,22,32],[13,23,33]]
テンソルの集約操作
よく使われる集約関数
例
tensor = tf.constant([[1, 2, 3], [4, 5, 6]])
# 合計
sum_all = tf.reduce_sum(tensor) # 全要素の合計 → 21
sum_axis0 = tf.reduce_sum(tensor, 0) # 第0次元(行)に沿って合計 → [5,7,9]
sum_axis1 = tf.reduce_sum(tensor, 1) # 第1次元(列)に沿って合計 → [6,15]
# 平均を求める
mean_all = tf.reduce_mean(tensor) # 全要素の平均 → 3.5
# 最大値/最小値
max_val = tf.reduce_max(tensor) # 最大値 → 6
min_val = tf.reduce_min(tensor) # 最小値 → 1
# 論理演算
any_true = tf.reduce_any(tensor > 4) # 4より大きい要素があるか → True
all_true = tf.reduce_all(tensor > 0) # すべての要素が0より大きいか → True
# 合計
sum_all = tf.reduce_sum(tensor) # 全要素の合計 → 21
sum_axis0 = tf.reduce_sum(tensor, 0) # 第0次元(行)に沿って合計 → [5,7,9]
sum_axis1 = tf.reduce_sum(tensor, 1) # 第1次元(列)に沿って合計 → [6,15]
# 平均を求める
mean_all = tf.reduce_mean(tensor) # 全要素の平均 → 3.5
# 最大値/最小値
max_val = tf.reduce_max(tensor) # 最大値 → 6
min_val = tf.reduce_min(tensor) # 最小値 → 1
# 論理演算
any_true = tf.reduce_any(tensor > 4) # 4より大きい要素があるか → True
all_true = tf.reduce_all(tensor > 0) # すべての要素が0より大きいか → True
実践練習
練習1:テンソルの作成と操作
例
# 1. 要素値が0〜10の3×3のランダム行列を作成
random_matrix = tf.random.uniform((3, 3), minval=0, maxval=10, dtype=tf.int32)
# 2. その行列の転置を計算
transposed_matrix = tf.transpose(random_matrix)
# 3. 行列と転置行列の積を計算
product = tf.matmul(random_matrix, transposed_matrix)
# 4. 積行列の対角要素の合計を計算
diag_sum = tf.reduce_sum(tf.linalg.diag_part(product))
random_matrix = tf.random.uniform((3, 3), minval=0, maxval=10, dtype=tf.int32)
# 2. その行列の転置を計算
transposed_matrix = tf.transpose(random_matrix)
# 3. 行列と転置行列の積を計算
product = tf.matmul(random_matrix, transposed_matrix)
# 4. 積行列の対角要素の合計を計算
diag_sum = tf.reduce_sum(tf.linalg.diag_part(product))
練習2:ブロードキャスト機構の応用
例
# 1. 4×1の行列と1×4のベクトルを作成
matrix = tf.constant([[1], [2], [3], [4]])
vector = tf.constant([10, 20, 30, 40])
# 2. ブロードキャスト機構を使ってそれらの和を計算
broadcast_sum = matrix + vector
# 3. 結果の形状と値を検証
print("形状:", broadcast_sum.shape) # (4,4)になるはず
print("結果:", broadcast_sum.numpy())
matrix = tf.constant([[1], [2], [3], [4]])
vector = tf.constant([10, 20, 30, 40])
# 2. ブロードキャスト機構を使ってそれらの和を計算
broadcast_sum = matrix + vector
# 3. 結果の形状と値を検証
print("形状:", broadcast_sum.shape) # (4,4)になるはず
print("結果:", broadcast_sum.numpy())