# 【入門】PyTorchでCNNを構築し分類タスクを解いてみよう！Kerasとの違いも見ていこう！

> 当サイト【スタビジ】の本記事では、ディープラーニングを実装するためのライブラリであるPyTorchについて解説していきます！TensorFlowやKerasとの違いをまとめつつ、最終的にPythonでPyTorchを使ってディープラーニングのモデルを構築していきます！

- URL: https://toukei-lab.com/pytorch
- 公開: 2023.11.15 / 更新: 2025.09.09
- サイト: スタビジ（https://toukei-lab.com）

:::talk{who="umatan"}
当サイト【スタビジ】の本記事では、ディープラーニングを実装するためのライブラリであるPyTorchについて解説していきます！TensorFlowやKerasとの違いをまとめつつ、最終的にPythonでPyTorchを使ってディープラーニングのモデルを構築していきます！
:::

こんにちは！データサイエンティストのウマたん([@statistics1012](https://twitter.com/statistics1012?lang=ja))です！

この記事ではディープラーニングを簡単に誰でも実装できる**PythonのライブラリPyTorch**について分かりやすく解説していきます！

ディープラーニングを実装するライブラリとしては他にもTensorFlowや[Keras](/keras)が有名ですが、最近ではPyTorchの人気が高まっています！

## PyTorchとKerasとTensorFlowの違いとは

PyTorchはFacebook（現Meta）の人工知能研究グループであるAI Research labによって開発されたライブラリ。

冒頭にも述べたとおり、実はディープラーニングを実装するライブラリの中にはPyTorch以外にもKerasやTensorFlowなどが存在します。

そこでPyTorchの特徴を理解するために、他のライブラリと比較していきましょう！

### 最新のモデル

昨今はAIの進化が非常に早く、色々なモデルが日々登場しています。

<https://toukei-lab.com/llm>

登場時点で最高レベルの精度を達成することをSOTA（State-of-the-Art）と言いますが、そんな<mark>SOTAを達成したような最新のモデルに関してはPyTorchで利用できる場合が多い</mark>です。

### カスタマイズ性

また、PyTorchでは**他のライブラリと比較して複雑なモデルを柔軟に作ることが可能**です。

そのため学術研究の領域ではKerasやTensorFlowよりもPyTorchが好まれて使われるケースが多いです。

私自身もアカデミックの世界にいましたが、結局アカデミックでは手法を改良して精度向上を試みることになるので、カスタマイズ性が高くないと手法改良ができません。

研究開発の領域では、<mark>数式展開部分から改良してモデルとして実装できるか</mark>が肝になってくるんです！

後ほどPyTorchを使ってディープラーニングのモデルを実装していきますよ！

:::talk{who="umatan"}
色々カスタマイズしたい場合はPyTorch！
:::

### 処理速度

また、処理速度の観点ではPyTorchはTensorFlowと同程度、<mark>Kerasが他2つと比較して遅め</mark>です。

:::talk{who="umatan"}
処理速度の面ではKerasは他2つに劣る！
:::

### コードの複雑さ

ここまでPyTorchの良さが際立っていましたが、その一方で**コードの見やすさはKerasに軍配**が上がります。

PyTorchは、カスタマイズ性が高い分Kerasと比較すると複雑で分かりにくいコードになりがちです。

例えば、Kerasで[CNN](/cnn)のモデルを構築し学習するコード（※全コードではなくモデル設計と学習部分のみピックアップ）は以下のようになるのですが、

```python
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

# モデルを構築
model.compile(optimizer=tf.optimizers.Adam(0.01), loss='categorical_crossentropy', metrics=['accuracy'])

# モデル学習
log = model.fit(train_x, train_y, epochs=3, batch_size=10, verbose=True,
                callbacks=[keras.callbacks.EarlyStopping(monitor='val_loss', 
                                                     min_delta=0, patience=10, 
                                                         verbose=1)],
                validation_data=(valid_x, valid_y))
```

これと同じような処理をPyTorchで記述すると以下のようになります。

```python
# モデルの定義
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.conv3 = nn.Conv2d(64, 64, 3, 1)
        self.fc1 = nn.Linear(3*3*64, 64)
        self.fc2 = nn.Linear(64, 10)

    def forward(self, x):
        x = torch.relu(self.conv1(x))
        x = nn.MaxPool2d(2)(x)
        x = torch.relu(self.conv2(x))
        x = nn.MaxPool2d(2)(x)
        x = torch.relu(self.conv3(x))
        x = torch.flatten(x, 1)
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

model = Net()

# 損失関数と最適化手法
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 学習プロセス
def train(model, train_loader, valid_loader, criterion, optimizer, epochs=3):
    for epoch in range(epochs):
        model.train()
        for data, target in train_loader:
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
        
        model.eval()
        valid_loss = 0
        correct = 0
        with torch.no_grad():
            for data, target in valid_loader:
                output = model(data)
                valid_loss += criterion(output, target).item()
                pred = output.argmax(dim=1, keepdim=True)
                correct += pred.eq(target.view_as(pred)).sum().item()

        valid_loss /= len(valid_loader.dataset)
        print(f'Epoch: {epoch+1}, Validation loss: {valid_loss}, Accuracy: {100. * correct / len(valid_loader.dataset)}%')

# 学習の実行
train(model, train_loader, valid_loader, criterion, optimizer)
```

<mark>Kerasだとディープラーニングの層を重ねる部分も学習部分も非常にシンプル</mark>なのですが、<mark>PyTorchだと少々複雑で可読性が低い</mark>ことが分かりますね！

とはいえ、コードのシンプルさとカスタマイズ性の高さはトレードオフなので目的によって使い分けるとよいでしょう！

:::talk{who="umatan"}
コードのシンプルさではKerasに軍配が上がる！
:::

## PyTorchを使ってディープラーニングを実装

ここまででPyTorchの特徴を他のライブラリと比較しながら見てきましたが、PyTorchについて知るためにはとりあえず手を動かして触ってみることが大事！

ということで、早速PyTorchを使って**ディープラーニングのモデルを構築**していきましょう！

先ほど少しモデル構築部分を紹介したCNN（畳み込みニューラルネットワーク）のアーキテクチャを使って[Mnist](/mnist)データを分類していきましょう！

Mnistは**Mixed National Institute of Standards and Technology database**の略で、手書き数字画像60,000枚とテスト画像10,000枚を集めた、画像データセット。

0～9の手書き数字が教師ラベルとして各画像に与えられています。

全体のコードは以下のようになります。

```python
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
from sklearn.model_selection import train_test_split
from torchvision import datasets, transforms

# データの前処理
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])

# MNISTデータセットのダウンロード
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)

# NumPy配列への変換
train_x = train_dataset.data.type(torch.FloatTensor)
train_y = train_dataset.targets
test_x = test_dataset.data.type(torch.FloatTensor)
test_y = test_dataset.targets

# Training set を学習データと検証データに8:2で分割する
train_x, valid_x, train_y, valid_y = train_test_split(train_x, train_y, test_size=0.2, random_state=0)

# データの整形と正規化
train_x = train_x.unsqueeze(1) / 255.0
valid_x = valid_x.unsqueeze(1) / 255.0
test_x = test_x.unsqueeze(1) / 255.0

# DataLoaderの作成
train_loader = DataLoader(TensorDataset(train_x, train_y), batch_size=10, shuffle=True)
valid_loader = DataLoader(TensorDataset(valid_x, valid_y), batch_size=10, shuffle=False)
test_loader = DataLoader(TensorDataset(test_x, test_y), batch_size=10, shuffle=False)

# モデルの定義
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.conv3 = nn.Conv2d(64, 64, 3, 1)
        self.fc1 = nn.Linear(3*3*64, 64)
        self.fc2 = nn.Linear(64, 10)

    def forward(self, x):
        x = torch.relu(self.conv1(x))
        x = nn.MaxPool2d(2)(x)
        x = torch.relu(self.conv2(x))
        x = nn.MaxPool2d(2)(x)
        x = torch.relu(self.conv3(x))
        x = torch.flatten(x, 1)
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

model = Net()

# 損失関数と最適化手法
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 学習プロセス
def train(model, train_loader, valid_loader, criterion, optimizer, epochs=3):
    for epoch in range(epochs):
        model.train()
        for data, target in train_loader:
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
        
        model.eval()
        valid_loss = 0
        correct = 0
        with torch.no_grad():
            for data, target in valid_loader:
                output = model(data)
                valid_loss += criterion(output, target).item()
                pred = output.argmax(dim=1, keepdim=True)
                correct += pred.eq(target.view_as(pred)).sum().item()

        valid_loss /= len(valid_loader.dataset)
        print(f'Epoch: {epoch+1}, Validation loss: {valid_loss}, Accuracy: {100. * correct / len(valid_loader.dataset)}%')

# 学習の実行
train(model, train_loader, valid_loader, criterion, optimizer)

# テストデータでの評価
model.eval()
correct = 0
with torch.no_grad():
    for data, target in test_loader:
        output = model(data)
        pred = output.argmax(dim=1, keepdim=True)
        correct += pred.eq(target.view_as(pred)).sum().item()

accuracy = correct / len(test_loader.dataset)
print(f'Test accuracy: {accuracy * 100}%')
```

コードの処理について順を追って見ていきましょう！

まず必要なライブラリをインポートしています。

以下の処理では、まずToTensor()で画像をPyTorchテンソルに変換し、Normalize()で正規化しています。

```python
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
```

PyTorchテンソルはPyTorchにおける基本的なデータ構造であり、多次元配列の形でデータを表します。

これは、データセットに含まれる画像データをPyTorchが扱える形式に変換するために必要なんです！

また、同時にToTensor()変換はピクセルの値を\[0, 255]の範囲から\[0.0, 1.0]の範囲に自動的にスケーリングします。

<mark>これは、ニューラルネットワークが\[0, 1]範囲の値を扱いやすいため、効果的な学習を促進するために重要になります。</mark>

:::talk{who="umatan"}
まぁとりあえずPyTorchのアーキテクチャに突っ込む前の準備ということだね！
:::

続いてMnistデータセットをダウンロードして前処理をかけたり学習データ・検証データに分けたり前準備をしていますね。

続いて、以下の処理でモデルの定義をしています。

```python
# モデルの定義
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.conv3 = nn.Conv2d(64, 64, 3, 1)
        self.fc1 = nn.Linear(3*3*64, 64)
        self.fc2 = nn.Linear(64, 10)

    def forward(self, x):
        x = torch.relu(self.conv1(x))
        x = nn.MaxPool2d(2)(x)
        x = torch.relu(self.conv2(x))
        x = nn.MaxPool2d(2)(x)
        x = torch.relu(self.conv3(x))
        x = torch.flatten(x, 1)
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

model = Net()
```

ちょっと分かりにくいのですが、def \_\_init\_\_(self)で畳み込み層であるConv2dや全結合層であるLinearのアーキテクチャを定義しています。

その上でdef forward(self, x)内で、実際に入力データxを層構造に通していく処理を作っています。

ここでは先ほど定義した畳み込み層や全結合層を使いながら活性関数である[Relu関数](/relu)やプーリング層の設定などをしています。

続いて以下の処理で[損失関数](/loss-function)と最適化手法を定義しています。

```python
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)
```

ディープラーニングの学習で最適なパラメータを求める際に必要です。

そしてやっと以下の部分で学習の処理です！

```python
# 学習プロセス
def train(model, train_loader, valid_loader, criterion, optimizer, epochs=3):
    for epoch in range(epochs):
        model.train()
        for data, target in train_loader:
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
        
        model.eval()
        valid_loss = 0
        correct = 0
        with torch.no_grad():
            for data, target in valid_loader:
                output = model(data)
                valid_loss += criterion(output, target).item()
                pred = output.argmax(dim=1, keepdim=True)
                correct += pred.eq(target.view_as(pred)).sum().item()

        valid_loss /= len(valid_loader.dataset)
        print(f'Epoch: {epoch+1}, Validation loss: {valid_loss}, Accuracy: {100. * correct / len(valid_loader.dataset)}%')

# 学習の実行
train(model, train_loader, valid_loader, criterion, optimizer)
```

この<mark>モデル学習部分がKerasと比較してかなり複雑</mark>になってます。

まず、model.train()とmodel.eval()で学習モードと検証モードで分けて処理を行います。

最初にmodel.train()で、事前に設計したモデル定義をもとにデータを出力し損失関数によって損失を計算しています。

そしてloss.backward()でバックプロパゲーション（[誤差逆伝播法](/backpropagation)）を使いモデルの重みを更新します。

その後model.eval()で検証データにおける精度を算出しています。

このコードの中では計算時間をおさえるためエポック数（試行回数）を3に設定しておりますのでアーリーストッピングを設定していませんが、エポック数が多い場合は検証モードにおいて精度が改善しない場合はエポックを止めるアーリーストッピングの処理を追加するとよいでしょう！

このコードを回した結果、分類精度は96.3％となりました！まずまずの精度でしょう！

このようにPyTorchはちょーっと複雑な部分もありますが、柔軟に様々なディープラーニングのモデルを構築することが可能です！

ぜひ色々試してみてください！

## PyTorch まとめ

ここまでご覧いただきありがとうございました！

本記事では、**PyTorch**について解説してきました。

PyTorchを使いこなしてディープラーニングを実装していきましょう！

ディープラーニングの様々なモデルを知りたい方は以下の記事を参考にしてみてください。

:::related
・[RNN](/rnn)\
・[AlexNet](/alexnet)\
・[ResNet](/resnet)\
・[Transformer](/transformer)
:::

さらに詳しくAIやデータサイエンスの勉強がしたい！という方は当サイト「スタビジ」が提供する[スタビジアカデミー](https://toukei-lab.com/achademy/)というサービスで体系的に学ぶことが可能ですので是非参考にしてみてください！

:::box
**AIデータサイエンス特化スクール「スタアカ」**

![スタアカ（スタビジアカデミー）のトップページ](/wp-content/uploads/2026/10/achademy-top.jpg)
:::

<table class="table">
<tbody>
<tr>
<th>【価格】</th>
<td>ライトプラン：1,280円/月（全コースが受講し放題）<br>
プレミアムプラン：129,800円（通常149,800円・買い切り）</td>
</tr>
<tr>
<th>【オススメ度】</th>
<td><span class="stars" role="img" aria-label="5点中5点" data-value="5"></span></td>
</tr>
<tr>
<th>【サポート体制】</th>
<td><span class="stars" role="img" aria-label="5点中4点" data-value="4"></span></td>
</tr>
<tr>
<th>【受講形式】</th>
<td>オンライン形式</td>
</tr>
<tr>
<th>【学習範囲】</th>
<td>統計学・機械学習・ディープラーニングを網羅的に学ぶ<br>
生成AI（LLM・RAG・プロンプトエンジニアリング）を学ぶ<br>
SQLとPythonを組み合わせて実データを使った様々なワークを行う<br>
実践的なビジネスフレームワークを学ぶ<br>
マーケティングの実行プラン策定</td>
</tr>
</tbody>
</table>

データサイエンティストとしての自分の経験をふまえてエッセンスを詰め込んだのがこちらのスタビジアカデミー、略して「[スタアカ](https://toukei-lab.com/achademy/)」！！

当メディアが運営するスクールです。

月額1,280円のライトプランで、統計学から機械学習・生成AIまで全コースが受講し放題です！

<mark>プレミアムプランでは、24時間以内の質問対応と現役データサイエンティストとの1on1（30分×4回）を実施します！</mark>

カリキュラム自体は、他のスクールと比較して圧倒的に良い自信があるのでぜひ受講してみてください！

他のスクールのカリキュラムはPythonでの機械学習実装だけに焦点が当たっているものが多く、実務に即した内容になっていないものが多いです。

<mark>そんな課題感に対して、実務で使うことの多いSQLや機械学習のビジネス導入プロセスの理解なども合わせて学べるボリューム満点のコース</mark>になっています！

Pythonが初めての人でも学べるようなカリキュラムにしておりますので是非チェックしてみてください！

ウォルマートのデータを使って商品の予測分析をしたり、実務で使うことの多いGoogleプロダクトのBigQueryを使って投球分析をしたり、データサイエンティストに必要なビジネス・マーケティングの基礎を学んでマーケティングプランを作ってもらったりする盛りだくさんの内容になってます！

:::box
**・BigQuery上でSQL、Google Colab上でPythonを使い野球の投球分析**\
**・世界最大手小売企業のウォルマートの実データを用いた需要予測**\
**・ビジネス・マーケティングの基礎を学んで実際の企業を題材にしたマーケティングプランの策定**\
**・生成AIのAPIを使ってチャットボットやAIエージェントを作る**
:::

::button[スタアカの受講はこちら]{href="https://toukei-lab.com/achademy/" note="＼今すぐ試す／"}