質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
DataSet

DataSetは、ADO.NETアーキテクチャのコンポーネントです。データベースから取得したレコードをメモリ領域に格納するクラスを指します。データの保持やテーブル間のリレーション・制約といった保持も可能です。

PyTorch

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。

CNN (Convolutional Neural Network)

CNN (Convolutional Neural Network)は、全結合層のみではなく畳み込み層とプーリング層で構成されるニューラルネットワークです。画像認識において優れた性能を持ち、畳み込みニューラルネットワークとも呼ばれています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Q&A

解決済

2回答

4000閲覧

ImageFolderで自作データセットを作成し、PyTorchでCNNをしたい

k_0fall

総合スコア7

DataSet

DataSetは、ADO.NETアーキテクチャのコンポーネントです。データベースから取得したレコードをメモリ領域に格納するクラスを指します。データの保持やテーブル間のリレーション・制約といった保持も可能です。

PyTorch

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。

CNN (Convolutional Neural Network)

CNN (Convolutional Neural Network)は、全結合層のみではなく畳み込み層とプーリング層で構成されるニューラルネットワークです。画像認識において優れた性能を持ち、畳み込みニューラルネットワークとも呼ばれています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

1グッド

0クリップ

投稿2022/01/02 19:46

編集2022/01/03 20:18

前提・実現したいこと

ImageFolderを使って自作データセットを作成し、PyTorchでCNNを行いたいと思うのですが、エラーが出てしまいます。

発生している問題・エラーメッセージ

Traceback (most recent call last): File "/Users/○○○/Desktop/△△△_data/cnn.py", line 125, in <module> train_loss_list, test_loss_list = run(30, optimizer, criterion, device) File "/Users/○○○/Desktop/△△△_data/cnn.py", line 73, in run train_loss = train_epoch(model, optimizer, criterion, train_loader, device) File "/Users/○○○/Desktop/△△△_data/cnn.py", line 46, in train_epoch outputs = model(images) File "/usr/local/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1102, in _call_impl return forward_call(*input, **kwargs) File "/Users/○○○/Desktop/△△△_data/cnn.py", line 33, in forward x = x.view(-1, 16*5*5) RuntimeError: shape '[-1, 400]' is invalid for input of size 2080832

該当のソースコード

python3

1from pathlib import Path 2 3from torch.utils.data import DataLoader, Dataset 4from torchvision import transforms 5from PIL import Image 6 7import torch 8import torch.nn as nn 9import torch.nn.functional as F 10import torch.optim as optim 11import torchvision.transforms as transforms 12 13import matplotlib.pyplot as plt 14 15from torchvision.datasets import ImageFolder 16 17class Net(nn.Module): 18 def __init__(self): 19 super().__init__() 20 self.conv1 = nn.Conv2d(3, 6, 5) # 畳み込み層:(入力チャンネル数, フィルタ数、フィルタサイズ) 21 # 出力画像サイズ28 22 self.pool = nn.MaxPool2d(2, 2) # プーリング層:(領域のサイズ, ストライド) 23 # 出力画像サイズ14 24 self.conv2 = nn.Conv2d(6, 16, 5) 25 # 出力画像サイズ5 26 self.fc1 = nn.Linear(16*5*5, 256) # 全結合層 27 self.dropout = nn.Dropout(p=0.5) # ドロップアウト:(p=ドロップアウト率) 28 self.fc2 = nn.Linear(256, 10) 29 30 def forward(self, x): 31 x = self.pool(F.relu(self.conv1(x))) 32 x = self.pool(F.relu(self.conv2(x))) 33 x = x.view(-1, 16*5*5) 34 x = F.relu(self.fc1(x)) 35 x = self.dropout(x) 36 x = self.fc2(x) 37 return x 38 39 40def train_epoch(model, optimizer, criterion, dataloader, device): 41 train_loss = 0 42 model.train() 43 for i, (images, labels) in enumerate(dataloader): 44 images, labels = images.to(device), labels.to(device) 45 optimizer.zero_grad() 46 outputs = model(images) 47 loss = criterion(outputs, labels) 48 loss.backward() 49 optimizer.step() 50 train_loss += loss.item() 51 train_loss = train_loss / len(train_loader.dataset) 52 return train_loss 53 54 55def inference(model, optimizer, criterion, dataloader, device): 56 model.eval() 57 test_loss=0 58 59 with torch.no_grad(): 60 for i, (images, labels) in enumerate(test_loader): 61 images, labels = images.to(device), labels.to(device) 62 outputs = model(images) 63 loss = criterion(outputs, labels) 64 test_loss += loss.item() 65 test_loss = test_loss / len(test_loader.dataset) 66 return test_loss 67 68 69def run(num_epochs, optimizer, criterion, device): 70 train_loss_list = [] 71 test_loss_list = [] 72 for epoch in range(num_epochs): 73 train_loss = train_epoch(model, optimizer, criterion, train_loader, device) 74 test_loss = inference(model, optimizer, criterion, test_loader, device) 75 76 print(f'Epoch [{epoch+1}], train_Loss : {train_loss:.4f}, test_Loss : {test_loss:.4f}') 77 train_loss_list.append(train_loss) 78 test_loss_list.append(test_loss) 79 return train_loss_list, test_loss_list 80 81 82if __name__ == '__main__': 83 # Transform を作成する。 84 transform = transforms.Compose([transforms.Resize(256), transforms.ToTensor()]) 85 # Dataset を作成する。 86 dataset = ImageFolder('/Users/○○○/Desktop/△△△_data/□□□_dataset', transform) 87 # DataLoader を作成する。 88 dataloader = DataLoader(dataset, batch_size=3) 89 90 #for batch in dataloader: 91 # print(batch.shape) 92 93 # グラフのスタイルを指定 94 plt.style.use('seaborn-darkgrid') 95 96 # 正規化 97 normalize = transforms.Normalize(mean=(0.0, 0.0, 0.0), std=(1.0, 1.0, 1.0)) 98 # Tensor化 99 to_tensor = transforms.ToTensor() 100 101 train_ratio = 0.8 102 train_size = int(train_ratio * len(dataset)) 103 val_size = len(dataset) - train_size 104 data_size = {"train":train_size, "val":val_size} 105 train_dataset, test_dataset = torch.utils.data.random_split(dataset, [train_size, val_size]) 106 107 transform_train = transforms.Compose([to_tensor, normalize]) 108 transform_test = transforms.Compose([to_tensor, normalize]) 109 110 batch_size = 64 111 train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True) 112 test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False) 113 dataloaders = {"train":train_loader, "val":test_loader} 114 115 model = Net() 116 117 device = torch.device("cpu") 118 119 # 損失関数の設定 120 criterion = nn.CrossEntropyLoss() 121 122 # 最適化手法を設定 123 optimizer = optim.Adam(model.parameters()) 124 125 train_loss_list, test_loss_list = run(30, optimizer, criterion, device) 126 127 num_epochs=30 128 fig, ax = plt.subplots(figsize=(8, 6), dpi=100) 129 ax.plot(range(num_epochs), train_loss_list, c='b', label='train loss') 130 ax.plot(range(num_epochs), test_loss_list, c='r', label='test loss') 131 ax.set_xlabel('epoch', fontsize='20') 132 ax.set_ylabel('loss', fontsize='20') 133 ax.set_title('training and test loss', fontsize='20') 134 ax.grid() 135 ax.legend(fontsize='25') 136 plt.show() 137 138 correct = 0 139 total = 0 140 model.eval() # 評価モード 141 for i, (images, label) in enumerate(test_loader): 142 images, label = images.to(device), label.to(device) 143 prediction = model(images) 144 correct += (prediction.argmax(1) == label).sum().item() 145 total += len(images) 146 print(f"正解率: {(correct/total)*100:.3f} %") 147

該当のデータセット

./□□□_dataset ├── 0 │ ├── 0_0.png │ ├── 0_1.png │ ├── ・・・ │ ├── 0_10.png ├── 1 │ ├── 1_0.png │ ├── 1_1.png │ ├── ・・・ │ ├── 1_10.png ├── 2 │ ├── 2_0.png │ ├── 2_1.png │ ├── ・・・ │ ├── 2_10.png
UAE👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tiitoi

2022/01/03 03:11

パスは合っていますか? 画像パスの一覧が取得できていれば、dataset.img_paths の値を print したときに中身があるはずですがどうでしょうか?
k_0fall

2022/01/03 05:18

print(dataset.img_paths)で確認したところ、 [] という出力になってしまい、正しく画像を読み込めていなかったです。 内容としては、 ./△△△△△_dataset ├── 0 │ ├── 0_0.png │ ├── 0_1.png │ ├── ・・・ │ ├── 0_10.png ├── 1 │ ├── 1_0.png │ ├── 1_1.png │ ├── ・・・ │ ├── 1_10.png ├── 2 │ ├── 2_0.png │ ├── 2_1.png │ ├── ・・・ │ ├── 2_10.png という構造にして、合計30枚の画像を読み込む予定です。
guest

回答2

0

ベストアンサー

./△△△△△_dataset ├── 0 │ ├── 0_0.png │ ├── 0_1.png │ ├── ・・・ │ ├── 0_10.png ├── 1 │ ├── 1_0.png │ ├── 1_1.png │ ├── ・・・ │ ├── 1_10.png ├── 2 │ ├── 2_0.png │ ├── 2_1.png │ ├── ・・・ │ ├── 2_10.png

このような構造であれば、ImageFolder を自作する必要はないです。
torchvision.datasets.ImageFolder をお使いください。

from pathlib import Path from PIL import Image from torch.utils.data import DataLoader, Dataset from torchvision import transforms from torchvision.datasets import ImageFolder # Transform を作成する。 transform = transforms.Compose([transforms.Resize(256), transforms.ToTensor()]) # Dataset を作成する。 dataset = ImageFolder("dataset1", transform)

Pytorch - 自作のデータセットを扱う Dataset クラスを作る方法

追記

必要なサイズがどのような数値が判断する方法などありましたらご教授頂けないでしょうか..

全結合層の直前までのモデルを作成し、希望のテンソルを入れて出力の形状を確認すればよいです。

python

1import torch 2import torch.nn as nn 3import torch.nn.functional as F 4 5 6class Net(nn.Module): 7 def __init__(self): 8 super().__init__() 9 self.conv1 = nn.Conv2d(3, 6, 5) 10 self.pool = nn.MaxPool2d(2, 2) 11 self.conv2 = nn.Conv2d(6, 16, 5) 12 13 def forward(self, x): 14 x = self.pool(F.relu(self.conv1(x))) 15 x = self.pool(F.relu(self.conv2(x))) 16 return x 17 18 19model = Net() 20 21x = torch.rand(1, 3, 224, 224) 22y = model(x) 23print(y.shape) # torch.Size([1, 16, 53, 53])

投稿2022/01/03 05:52

編集2022/01/05 04:26
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k_0fall

2022/01/03 17:25

ご回答ありがとうございます。 ImageFolderではない形にしても、同様のエラーが発生します。 データセットからラベルを無くし、以下のようにすべて同じディレクトリに配置したところ、別のエラーになりました。 ./△△△△△_dataset ├── 0_0.png ├── 0_1.png ├── ・・・ ├── 0_10.png ├── 1_0.png ├── 1_1.png ├── ・・・ ├── 1_10.png ├── 2_0.png ├── 2_1.png ├── ・・・ ├── 2_10.png torch.Size([3, 4, 256, 341]) torch.Size([3, 4, 256, 341]) torch.Size([3, 4, 256, 341]) torch.Size([3, 4, 256, 341]) torch.Size([3, 4, 256, 341]) torch.Size([3, 4, 256, 341]) torch.Size([3, 4, 256, 341]) torch.Size([3, 4, 256, 341]) torch.Size([3, 4, 256, 341]) torch.Size([3, 4, 256, 341]) torch.Size([2, 4, 256, 341]) Traceback (most recent call last): File "/Users/○○○○○/Desktop/●●_data/cnn.py", line 180, in <module> train_loss_list, test_loss_list = run(30, optimizer, criterion, device) File "/Users/○○○○○/Desktop/●●_data/cnn.py", line 111, in run train_loss = train_epoch(model, optimizer, criterion, train_loader, device) File "/Users/○○○○○/Desktop/●●_data/cnn.py", line 81, in train_epoch for i, (images, labels) in enumerate(dataloader): ValueError: too many values to unpack (expected 2)
tiitoi

2022/01/03 19:05

元のディレクトリ構造で、from torchvision.datasets import ImageFolder を使ってもエラーになりましたか? (自作したImageFolder ではなく)
k_0fall

2022/01/03 20:20

すみません、一度from torchvision.datasets import ImageFolderを使いましたが、エラーが出ています。 複雑になってしまったので、質問を更新しました。 エラー、ソースコード、ディレクトリは更新した通りの内容です。
tiitoi

2022/01/04 01:28

データセット読み込みのところは正常に動いています。 質問のコードはどこから持ってきたものなのでしょうか? 入力画像サイズをそのモデルで想定されている値にリサイズする必要があります。 ↓ にリサイズ処理を追加する必要がある transform_train = transforms.Compose([to_tensor, normalize]) transform_test = transforms.Compose([to_tensor, normalize])
k_0fall

2022/01/05 04:03

ありがとうございます! リサイズを試してみました。 その結果、エラーの1番下の「RuntimeError: shape '[-1, 400]' is invalid for input of size」の後の数字が2080832から、1213488に変わりました。 このエラーについて調べたところ、全結合層のサイズが関係しているそうです。 参考にしたソースコードはtorchvision.datasets.CIFAR10を想定して16*5*5というサイズだそうですが、自作のデータセットの場合は違うため、 self.fc1 = nn.Linear(16*5*5, 256) や x = x.view(-1, 16*5*5)の箇所を変える必要があるそうです。 必要なサイズがどのような数値が判断する方法などありましたらご教授頂けないでしょうか..
tiitoi

2022/01/05 04:24 編集

全結合層の直前までのモデルを作成して希望の入力サイズのテンソルを入れてみて、出力の形状を確認するとよいです。 回答に追記しました。
guest

0

ありがとうございます!
165353にすることで解決することができました。

投稿2022/01/06 05:39

k_0fall

総合スコア7

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問