💭

ChatGPT4oにディープラーニングを教わる(CRNN)

2024/06/20に公開

レシートの文字読み取りなどで使われるモデルであるCRNNについて勉強してみたく、ChatGPT先生に教わったのでそのログ。ちなみに機械学習はオライリーの「ゼロから作る~」の1巻を軽く読んだ程度でほぼ素人です。chatgpt もそんなに触っていないので、プロンプトも微妙かもです

サンプルプログラムを出してもらう

すごい雑なプロンプトでサンプルのプログラムを出してもらう

CRNNを用いたMNISTの画像判別のモデルをPythonを用いて出力してください

すると pytorch を用いたCRNNモデルのプログラムを出してくれた
出してくれたが、そのプログラムが問題ないかわからないので、出力してくれたコードをコピペして評価してもらう。

以下のプログラムは画像分類を行えるようにするCRNNモデルのプログラムです。このプログラムが問題なく学習を行えるか、もしくはプログラムの不備がないかを検証してください。検証した結果、指摘があるばあいはその項目を出力して、何もない場合は何もありませんと出力してください

冗長な気もする。。(全体的にプロンプトは雑です)
いくつか改善点があるらしく直してくれた。なんで直したのか理由も聞いてなんとなく納得。

そして直してくれたものがこちら

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import torchvision
import torchvision.transforms as transforms

# CRNNモデルの定義
class CRNN(nn.Module):
    def __init__(self, num_classes=10):
        super(CRNN, self).__init__()
        
        # CNNパート
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
        
        # RNNパート
        self.rnn = nn.LSTM(input_size=64*7, hidden_size=128, num_layers=2, batch_first=True, bidirectional=True)
        
        # 全結合層
        self.fc = nn.Linear(128*2, num_classes)
    
    def forward(self, x):
        # CNNの順伝播
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        
        # (バッチサイズ, チャネル, 高さ, 幅) -> (バッチサイズ, 高さ, チャネル*幅)
        x = x.view(x.size(0), x.size(2), -1)
        
        # RNNの順伝播
        x, _ = self.rnn(x)
        
        # 最後のタイムステップの出力を取得
        x = x[:, -1, :]
        
        # 全結合層
        x = self.fc(x)
        return x

# ハイパーパラメータ
batch_size = 64
learning_rate = 0.001
num_epochs = 10

# データ変換
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

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

train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)

# モデル、損失関数、オプティマイザの定義
model = CRNN(num_classes=10).to(torch.device('cuda' if torch.cuda.is_available() else 'cpu'))
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# トレーニングループ
for epoch in range(num_epochs):
    model.train()
    for images, labels in train_loader:
        images, labels = images.to(torch.device('cuda' if torch.cuda.is_available() else 'cpu')), labels.to(torch.device('cuda' if torch.cuda.is_available() else 'cpu'))
        
        # 順伝播
        outputs = model(images)
        loss = criterion(outputs, labels)
        
        # 逆伝播とオプティマイザのステップ
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    
    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

# テストループ
model.eval()
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images, labels = images.to(torch.device('cuda' if torch.cuda.is_available() else 'cpu')), labels.to(torch.device('cuda' if torch.cuda.is_available() else 'cpu'))
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

    print(f'Test Accuracy: {100 * correct / total:.2f}%')

学習結果の評価

手元で実行すると以下のような感じで損失の結果とテストデータでの検証結果を出してくれる

Epoch [1/10], Loss: 0.0030
Epoch [2/10], Loss: 0.0940
Epoch [3/10], Loss: 0.0233
Epoch [4/10], Loss: 0.0028
Epoch [5/10], Loss: 0.0608
Epoch [6/10], Loss: 0.1550
Epoch [7/10], Loss: 0.0371
Epoch [8/10], Loss: 0.0046
Epoch [9/10], Loss: 0.0067
Epoch [10/10], Loss: 0.0007
Test Accuracy: 99.08%

問題なく学習できているのはわかるが、エポック6で若干損失が大きいのがなんとなく気になったので質問

ありがとうございます
以下の内容は上記プログラムを実行して得られた学習結果です。以下の内容を評価してください。また、評価する中に Epoch 6 の Loss が他の Epoch と比較して若干高い理由を考察して出力してください。

評価結果は以下のような感じ

学習結果の評価
エポックごとの損失値:

各エポックの最終的な損失値が提供されています。
初期のエポックでは損失が徐々に減少し、その後エポック6で一時的に増加していますが、エポック7以降は再び減少傾向にあります。
最終エポックでは非常に低い損失値(0.0007)を達成しています。
テスト精度:

モデルのテスト精度は99.08%と非常に高いです。
これは、モデルがMNISTデータセットの分類タスクに対して非常に高い性能を発揮していることを示しています。
Epoch 6の損失が高い理由の考察
エポック6の損失が他のエポックと比較して高い理由として、以下のような要因が考えられます:

ランダムな変動:

ミニバッチ学習の特性上、各エポックの損失はデータのシャッフルによってランダムな変動を伴うことがあります。
特に、あるミニバッチが難しいサンプルを多く含んでいた場合、一時的に損失が増加することがあります。
過剰な最適化:

モデルが特定のエポックで過剰にフィッティングし、次のエポックで若干の修正が入ることもあります。
これは、最適化プロセス中の一時的な不安定性として現れることがあります。
データの多様性:

ミニバッチごとのデータの分布や難易度の多様性も影響を与える可能性があります。
特に、エポック6では難易度の高いサンプルが多く含まれていた可能性があります。
結論
提供された学習結果は全体的に非常に良好です。エポック6の損失の増加は、主にランダムな変動やデータの多様性による一時的なものであり、トレーニングプロセスの一部として通常の範囲内にあると考えられます。最終的なテスト精度も非常に高いため、モデルは問題なく機能していると言えます。

エポック6で少し増えたけど、学習プロセスの中では問題ない範囲らしい。
あとエポックが高くなる理由を教えてくれるのもよい。
これでこのモデルは少なくともMNISTでは問題なく機能するモデルだと分かった

CRNN を詳しく知る

プログラムが問題なさそう?なので、このプログラムをもとに気になるところを質問していく。試しにCNNまわりの質問をしてみる。プログラム上にコメントを出力してくれているので、そのコメントをなんとなくプロンプト上で言及する。

上記プログラムにおける CNNパート について解説して下さい。

言及するとその個所について答えてくれた(長いので一部割愛)
概要からプログラムに沿った詳細を書いてくれ、最後にまとめを書いてくれた。

上から順にみて行って気になるところがあれば質問する。これを繰り返して理解を深めていく。
質問しすぎるとGPTが昔の文脈を忘れちゃうのかちょっと心配(最後にがっつり触ったのがGPT4が出たときだったので今は覚えててくれるのかも)

CRNNモデルのCNNパートの解説
CRNN(Convolutional Recurrent Neural Network)モデルのCNNパートは、入力画像から特徴量を抽出するために使用されます。この部分では、2つの畳み込み層とプーリング層を使用して、画像の空間的な情報を効率的に処理しています。以下に詳細を説明します。

CNNパートの構成
畳み込み層1(self.conv1):

nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
入力チャネル数: 1(グレースケール画像)
出力チャネル数: 32
カーネルサイズ: 3x3
ストライド: 1
パディング: 1
ReLU活性化関数:

F.relu(self.conv1(x))
畳み込み層の出力に非線形性を導入し、モデルの表現力を向上させます。
プーリング層1(self.pool):

...割愛

まとめ
CNNパートは、入力画像の空間的な特徴を抽出し、後続のRNNパートに渡すための重要な役割を果たしています。この段階で、画像の高次元の特徴がコンパクトに表現されるため、RNNパートが効率的に時系列情報を処理できるようになります。

最後に感謝する

ありがとうございます!

どういたしまして!他にも質問やサポートが必要なことがあれば、いつでもお知らせください。頑張ってくださいね!

まとめ

GPTが出力してくれたものを張り付けるだけの記事になってしまいました。
今回のように魅力的な特定のトピックを興味持って、そこから理解していく場合にChatGPTを用いるのは良さげでした。(GPTの出力を信頼しきれていないので、内容があっているかは不明ですが。。)
従来の勉強法だと、魅力的で興味を持つのですが、基礎的な部分までさかのぼって理解するのが結構大変(マンツーマンで先生に聞きまくるとか)だった感じがしていたり、逆に基礎的な部分からだとその知識を何に利用できるのか知ることができなかったりすることがあったので、興味を持った分野を自分のわかるレベルまで下げて解説して掘り下げてくれるChatGPTは学ぶのにめちゃいいなと思いました。

興味のあるトピックはある&右も左もわからない場合は、教師と生徒二人立ててその二人で特定の議題について議論させたり教えたりさせると、どのようなプロセスを経てその議題を理解していっているのか追えるのでよさそうだなとも思ったり
あとはプロンプト打つだけで GPT がコード書いたりしてアウトプットを出してくれるので何かやった気になれるのもよさげ
何か勉強したいことがあった際はいったん ChatGPT に聞いてみるの面白いよというお話でした。

Discussion