閉じる

Pythonで始めるディープラーニング(深層学習) TensorFlow/PyTorch入門

ディープラーニングをPythonで始めるなら、まずは定番のTensorFlowとPyTorchを小さく動かして仕組みを体験するのが近道です。

本記事では、環境構築からGPU確認、画像分類の最小例、学習・評価・推論・保存までを初心者の方でも着実に進められる順序で丁寧に解説します。

ディープラーニング入門

ディープラーニングとは

直観的なイメージ

ディープラーニングは、多層のニューラルネットワークがデータから自動的に特徴を学習し、分類や回帰などのタスクを解く手法です。

画像ではエッジや質感、形状などを層を重ねながら抽象化して捉えます。

特徴量設計を人が細かく作らなくても、データと学習アルゴリズムが適切なら高い性能を発揮します。

用語の最小セット

まずは次の語だけ押さえておくと理解が進みます。

epoch(学習データを何周するか)、batch size(一度に学習へ渡すサンプル数)、loss(損失。どれだけ間違えているか)、optimizer(損失を小さくするための更新則)、overfitting(過学習。訓練には強いが汎化が弱い状態)です。

TensorFlowとPyTorchの違い

概観比較

両者はできることの多くが重なりますが、設計思想や書き味に違いがあります。

どちらを選んでも学びは活きます。

観点TensorFlowPyTorch
設計哲学産業利用を意識したエコシステムが広い。tf.kerasで高レベルに記述しやすい直感的なPythonライクな記述。研究・プロトタイピングで人気
実装スタイルmodel.compilefit中心で宣言的に書ける低レベルの訓練ループを自分で書きやすく柔軟
可視化TensorBoardが標準的torch.utils.tensorboardwandbなど自由
デプロイTF ServingTF Liteが充実TorchScriptTorchServeが選択肢

どちらを選ぶべきか

まずはどちらか一方で小さく成功体験を積み、必要に応じてもう一方も触るのが近道です。

Kerasの高レベルAPIで素早く成果を出したいならTensorFlow、トレーニングループを理解しながら柔軟に書きたいならPyTorchが向いています。

学習の流れ

全体のステップ

ディープラーニングの基本的な流れは、(1)データ準備、(2)モデル定義、(3)損失と最適化の設定、(4)学習(訓練ループ)、(5)評価、(6)推論と保存、の順です。

この流れはフレームワークが変わっても普遍です。

最初の目標設定

本記事では、手書き数字データ(MNIST)を使った画像分類の最小例をTensorFlowとPyTorchの両方で実装し、学習から保存・推論まで一気通貫で体験します。

環境構築とインストール

Pythonの準備

仮想環境の作成(venv)

プロジェクトごとに依存を分離するため仮想環境を使います。

以下は共通的な手順です。

Shell
# 1) プロジェクト用ディレクトリを作成
mkdir dl-intro && cd dl-intro

# 2) 仮想環境を作成と有効化 (Windows)
python -m venv .venv
.venv\Scripts\activate

#    macOS/Linux
# python3 -m venv .venv
# source .venv/bin/activate

# 3) パッケージ管理ツールを最新化
python -m pip install --upgrade pip setuptools wheel

パッケージの更新

ビルド不要のホイール配布を利用するため、pipsetuptoolsを最新化しておくとトラブルが少なくなります。

TensorFlowのインストール

CPU版のインストール

まずはCPU版で問題なく動くことを確認するとスムーズです。

Shell
pip install --upgrade tensorflow

GPU版のインストール

GPU対応は環境依存が大きいです。

新しめのTensorFlowではextrasでCUDA/CuDNN付きのインストールが可能です。

Shell
# 例: 近年のTensorFlowでCUDA/CuDNNを同時に入れる
pip install "tensorflow[and-cuda]"

注意(主にWindows)

Windows では tensorflow[and-cuda] の依存パッケージ nvidia-nccl-cu12 のホイールが提供されていないため、pip が解決に失敗します。

NCCL は Linux 向けの通信ライブラリで、Windows 版は公開されていません。そのためWindowsを使用する場合はWSL2 + Ubuntuの環境下で開発してください。

うまくいかないときはまずCPU版で動作確認し、GPUは段階的に導入します。

PyTorchのインストール

CPU版のインストール

PyTorchは配布チャネルが分かれています。

CPU版は次のように入れます。

Shell
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu

GPU版のインストール

使用するCUDAバージョンに応じたインデックスURLを選びます。

以下はCUDA 12.1向けの例です。

Shell
# CUDA 12.6 向けの例
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
PyTorchはWindowsネイティブ対応

PyTorch は Windows ネイティブで GPU (CUDA) 対応版を導入できます。

TensorFlow と違って、PyTorch は Windows 用の CUDA ホイールを公式で配布しています。なので以下のようなコマンドで問題ありません:

なお、古いホイールはインストールできない場合があります。

PyTorch公式にて、現時点で正しくインストールできるコマンドが更新されているはずなので、そちらを参考にしてください。

どのコマンドを使うべきかは公式の「Get Started」ページでOS/CUDAを選択して決めるのが確実です。

GPUの確認

TensorFlowとPyTorchのGPU検出

PythonからGPUが見えているかを確かめます。

当然ですが、GPU対応版のTensorflow、PyTorchの導入が必須です。CPU版はGPUを認識できない(CPUでしか処理できない)ので注意しましょう。

Python
# gpu_check.py
# TensorFlow と PyTorch の GPU 検出を一括で確認します
import sys

print("Python:", sys.version)

try:
    import tensorflow as tf
    gpus_tf = tf.config.list_physical_devices("GPU")
    print("[TensorFlow] GPUs:", gpus_tf)
except Exception as e:
    print("[TensorFlow] Import/Check error:", e)

try:
    import torch
    print("[PyTorch] cuda.is_available:", torch.cuda.is_available())
    if torch.cuda.is_available():
        print("[PyTorch] device name:", torch.cuda.get_device_name(0))
        print("[PyTorch] cuda version:", torch.version.cuda)
except Exception as e:
    print("[PyTorch] Import/Check error:", e)
実行結果
Python: 3.11.6 (main, ...)
[TensorFlow] GPUs: [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
[PyTorch] cuda.is_available: True
[PyTorch] device name: NVIDIA GeForce RTX 4080 SUPER
[PyTorch] cuda version: 12.6

インストールのつまずき対策

代表的な原因と手当

インストールがうまくいかない原因の多くはPythonのバージョンとビルド済みホイールの対応不一致CUDA/CuDNNの不整合です。

次の観点で順に切り分けます。

  • Python 3.10~3.11が現状では無難です。python --versionで確認し、必要なら環境を作り直します。
  • まずはCPU版で動作確認し、次にGPU版へ移行します。
  • NVIDIA GPUの場合、nvidia-smiでドライバの状態を確認します。
  • どうしてもエラーが続く場合はpip cache purgeでキャッシュをクリアし、再インストールします。
  • Apple Siliconはtensorflow-macostensorflow-metalの組み合わせを利用するケースがあります。OSのサポート状況に注意します。

TensorFlowの基本

テンソルとレイヤー

テンソルの作成と基本演算

TensorFlowの基本データ構造はテンソルです。

NumPy配列に似ています。

Python
# tf_tensor_basics.py
import tensorflow as tf

# 定数テンソル
a = tf.constant([[1, 2], [3, 4]], dtype=tf.float32)
b = tf.ones((2, 2))

# 基本演算
c = a + b
d = tf.matmul(a, b)

print("a:", a.numpy())
print("b:", b.numpy())
print("c = a + b:", c.numpy())
print("d = a @ b:", d.numpy())
実行結果
a: [[1. 2.]
 [3. 4.]]
b: [[1. 1.]
 [1. 1.]]
c = a + b: [[2. 3.]
 [4. 5.]]
d = a @ b: [[3. 3.]
 [7. 7.]]

レイヤーの基本

Kerasレイヤーでネットワークを簡潔に組み立てられます。

Python
# tf_layers_basic.py
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# シンプルな全結合ネットワーク
model = keras.Sequential([
    layers.Input(shape=(4,)),           # 入力は4次元ベクトル
    layers.Dense(8, activation="relu"), # 隠れ層
    layers.Dense(3, activation="softmax") # 出力は3クラス
])

model.summary()
実行結果
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #
=================================================================
 dense (Dense)               (None, 8)                 40
 dense_1 (Dense)             (None, 3)                 27
=================================================================
Total params: 67
Trainable params: 67
Non-trainable params: 0
_________________________________________________________________

データ読み込み

MNISTデータの取得と前処理

Kerasは代表的なデータセットを内蔵しています。

ここでは手書き数字のMNISTを使います。

Python
# tf_data_mnist.py
import tensorflow as tf
from tensorflow.keras import datasets

# データのロード
(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()

# スケーリングとチャンネル次元の追加(28x28 -> 28x28x1)
x_train = (x_train / 255.0).astype("float32")[..., None]
x_test  = (x_test  / 255.0).astype("float32")[..., None]

print("x_train:", x_train.shape, x_train.dtype)
print("y_train:", y_train.shape, y_train.dtype)
print("x_test:", x_test.shape)
実行結果
x_train: (60000, 28, 28, 1) float32
y_train: (60000,) uint8
x_test: (10000, 28, 28, 1)

画像分類の最小例

小さなCNNで学習

最小限のCNNを定義して学習します。

Python
# tf_mnist_minimal_cnn.py
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, datasets

# 1) データ
(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()
x_train = (x_train / 255.0).astype("float32")[..., None]
x_test  = (x_test  / 255.0).astype("float32")[..., None]

# 2) モデル定義
model = keras.Sequential([
    layers.Input(shape=(28, 28, 1)),
    layers.Conv2D(16, 3, activation="relu"),
    layers.MaxPooling2D(),
    layers.Conv2D(32, 3, activation="relu"),
    layers.MaxPooling2D(),
    layers.Flatten(),
    layers.Dense(64, activation="relu"),
    layers.Dense(10, activation="softmax"),
])

# 3) コンパイル(損失と最適化の設定)
model.compile(
    optimizer="adam",
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"]
)

# 4) 学習
history = model.fit(
    x_train, y_train,
    validation_split=0.1, # 10%を検証に使う
    epochs=3,
    batch_size=128,
    verbose=2
)
実行結果
Epoch 1/3
422/422 - 2s - 5ms/step - accuracy: 0.9131 - loss: 0.3030 - val_accuracy: 0.9765 - val_loss: 0.0859
Epoch 2/3
422/422 - 1s - 3ms/step - accuracy: 0.9762 - loss: 0.0793 - val_accuracy: 0.9813 - val_loss: 0.0656
Epoch 3/3
422/422 - 1s - 3ms/step - accuracy: 0.9827 - loss: 0.0566 - val_accuracy: 0.9860 - val_loss: 0.0513

学習と評価

テストデータでの評価

学習後に未知データで性能を確認します。

Python
# tf_evaluate.py
import tensorflow as tf
from tensorflow.keras import datasets, layers, models

# ここでは学習済み model を簡潔に再作成して評価のみ例示
(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()
x_test  = (x_test / 255.0).astype("float32")[..., None]

# モデルは学習済みのものを想定(上のスクリプトで作った model を再利用する想定)
# ここでは簡易に同じ構造を定義し直してロードの章で重みを復元します。
print("テストデータで評価を実施します。")
実行結果
テストデータで評価を実施します。

上記はプレースホルダーです。

実際の評価は次の保存・推論の節で学習済みモデルを読み込みつつ行います。

推論と保存

モデルの保存、ロード、推論

Kerasではmodel.saveで1行保存できます。

推論も簡単です。

Python
# tf_save_infer.py
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, datasets

# 学習(最短で1エポックだけ回して保存例を示す)
(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()
x_train = (x_train / 255.0).astype("float32")[..., None]
x_test  = (x_test  / 255.0).astype("float32")[..., None]

model = keras.Sequential([
    layers.Input(shape=(28, 28, 1)),
    layers.Conv2D(16, 3, activation="relu"),
    layers.MaxPooling2D(),
    layers.Flatten(),
    layers.Dense(10, activation="softmax"),
])
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
model.fit(x_train, y_train, epochs=1, batch_size=256, verbose=0)

# 1) 保存
model.save("mnist_cnn.keras")

# 2) ロード
loaded = keras.models.load_model("mnist_cnn.keras")

# 3) 推論(最初のテスト画像で予測)
logits = loaded.predict(x_test[:1], verbose=0)  # 1枚だけ
pred = np.argmax(logits, axis=1)[0]
print("Predicted:", pred, " / True:", int(y_test[0]))
実行結果
Predicted: 7  / True: 7

Keras形式(.keras)で保存しておくと再現や共有が容易です。

必要に応じてSavedModelHDF5形式も利用できます。

PyTorchの基本

テンソルと勾配

TensorとAutograd

PyTorchではテンソルが自動微分の履歴を持つため、勾配計算が自然に書けます。

Python
# torch_autograd_basics.py
import torch

# requires_grad=True にすると勾配が追跡される
x = torch.tensor([2.0, 3.0], requires_grad=True)
W = torch.tensor([[1.0, -1.0]], requires_grad=True)  # 1x2 の行列
y = W @ x  # 行列ベクトル積 -> 形状(1,)
loss = (y - 1.0).pow(2).mean()  # シンプルな二乗誤差

loss.backward()  # 勾配計算

print("y:", y.item())
print("d(loss)/dW:", W.grad)
print("d(loss)/dx:", x.grad)
実行結果
y: -1.0
d(loss)/dW: tensor([[ -8., -12.]])
d(loss)/dx: tensor([-4.,  4.])

データ読み込み

torchvisionでMNISTを取得

データセットと変換はtorchvisionが便利です。

Python
# torch_data_mnist.py
import torch
from torchvision import datasets, transforms

# テンソル化 + 0.1307, 0.3081 はMNISTの平均と標準偏差
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])

train_ds = datasets.MNIST(root="./data", train=True, download=True, transform=transform)
test_ds  = datasets.MNIST(root="./data", train=False, download=True, transform=transform)

train_loader = torch.utils.data.DataLoader(train_ds, batch_size=128, shuffle=True)
test_loader  = torch.utils.data.DataLoader(test_ds,  batch_size=256)

print("train size:", len(train_ds), "/ test size:", len(test_ds))
実行結果
train size: 60000 / test size: 10000

画像分類の最小例

小さなCNNモデルと学習ループ

PyTorchでは訓練ループを自分で書くので仕組みを理解しやすいです。

Python
# torch_mnist_minimal_cnn.py
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import datasets, transforms

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 1) データ
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])
train_ds = datasets.MNIST(root="./data", train=True, download=True, transform=transform)
test_ds  = datasets.MNIST(root="./data", train=False, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_ds, batch_size=128, shuffle=True)
test_loader  = torch.utils.data.DataLoader(test_ds,  batch_size=256)

# 2) モデル定義
class SmallCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 16, 3)  # 1x28x28 -> 16x26x26
        self.pool  = nn.MaxPool2d(2)      # 16x26x26 -> 16x13x13
        self.conv2 = nn.Conv2d(16, 32, 3) # 32x11x11
        self.fc1   = nn.Linear(32*5*5, 64)
        self.fc2   = nn.Linear(64, 10)
    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))  # -> (32, 5, 5)
        x = torch.flatten(x, 1)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

model = SmallCNN().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
criterion = nn.CrossEntropyLoss()

# 3) 学習ループ
def train_epoch(model, loader, optimizer, criterion):
    model.train()
    running_loss, correct, total = 0.0, 0, 0
    for x, y in loader:
        x, y = x.to(device), y.to(device)
        optimizer.zero_grad()
        logits = model(x)
        loss = criterion(logits, y)
        loss.backward()
        optimizer.step()
        running_loss += loss.item() * x.size(0)
        pred = logits.argmax(dim=1)
        correct += (pred == y).sum().item()
        total += y.size(0)
    return running_loss/total, correct/total

def evaluate(model, loader, criterion):
    model.eval()
    loss_sum, correct, total = 0.0, 0, 0
    with torch.no_grad():
        for x, y in loader:
            x, y = x.to(device), y.to(device)
            logits = model(x)
            loss = criterion(logits, y)
            loss_sum += loss.item() * x.size(0)
            pred = logits.argmax(dim=1)
            correct += (pred == y).sum().item()
            total += y.size(0)
    return loss_sum/total, correct/total

for epoch in range(1, 4):
    tr_loss, tr_acc = train_epoch(model, train_loader, optimizer, criterion)
    te_loss, te_acc = evaluate(model, test_loader, criterion)
    print(f"Epoch {epoch}/3 - train loss:{tr_loss:.4f} acc:{tr_acc:.4f} - test loss:{te_loss:.4f} acc:{te_acc:.4f}")
実行結果
Epoch 1/3 - train loss:0.2191 acc:0.9368 - test loss:0.0662 acc:0.9803
Epoch 2/3 - train loss:0.0698 acc:0.9785 - test loss:0.0490 acc:0.9847
Epoch 3/3 - train loss:0.0507 acc:0.9846 - test loss:0.0431 acc:0.9864

このコードは、手書き数字(MNIST)を分類する小さなCNNをPyTorchで実装したものです。

まずMNISTデータを読み込み、画像をテンソル化&正規化します。

次に畳み込み層・プーリング層で特徴を抽出し、全結合層で0〜9の数字に分類します。

学習はクロスエントロピー損失とAdam最適化を使い、訓練とテストを繰り返して精度を表示します。

学習と評価

ここでは精度(accuracy)を使いましたが、実務では混同行列再現率・適合率・F1なども重要です。

PyTorchではtorchmetricsscikit-learnの関数と組み合わせて評価の幅を広げます。

推論と保存

PyTorchではstate_dictを保存するのが一般的です。

Python
# torch_save_infer.py
import torch
import torch.nn as nn
from torchvision import datasets, transforms

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# モデル定義(学習時と同じ構造)
class SmallCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 16, 3)
        self.pool  = nn.MaxPool2d(2)
        self.conv2 = nn.Conv2d(16, 32, 3)
        self.fc1   = nn.Linear(32*5*5, 64)
        self.fc2   = nn.Linear(64, 10)
    def forward(self, x):
        import torch.nn.functional as F
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = torch.flatten(x, 1)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 1) モデルの初期化と重みロード
model = SmallCNN().to(device)
# ここでは事前に torch.save(model.state_dict(), "mnist_cnn.pt") してある想定
# 学習済みの重みがない場合、この行はエラーになる点に注意してください
try:
    model.load_state_dict(torch.load("mnist_cnn.pt", map_location=device))
    model.eval()
except FileNotFoundError:
    print("mnist_cnn.pt が見つかりません。学習後に保存してから再実行してください。")

# 2) データの用意と単発推論
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])
test_ds = datasets.MNIST(root="./data", train=False, download=True, transform=transform)

x, y_true = test_ds[0]  # 先頭の1枚
x = x.unsqueeze(0).to(device)  # (1, 1, 28, 28)
with torch.no_grad():
    logits = model(x)
    pred = logits.argmax(dim=1).item()

print("Predicted:", pred, "/ True:", y_true)
実行結果
Predicted: 7 / True: 7

学習時のネットワーククラスと同じ構造でインスタンス化した上でstate_dictをロードする点がKerasとの大きな違いです。

まとめ

本記事では、TensorFlowとPyTorchの基本を同じ題材(MNIST)で対比しながら体験しました。

環境構築、GPU確認、テンソルの基本、データ読み込み、最小のCNNによる学習・評価、そしてモデルの保存と推論までを一通り押さえました。

どちらのフレームワークでも、流れはデータ準備→モデル定義→損失と最適化→学習→評価→保存・推論という共通パターンです。

最初はCPUで小さく成功し、必要になってからGPU対応に進めると挫折しにくいです。

次の一歩として、データ拡張や正則化、学習率スケジューラ、TensorBoardやメトリクスの拡充などに挑戦してみてください。

小さな成功を積み重ねることが、ディープラーニング上達の最短ルートです。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!