CNN回帰モデルの学習を収束させたい
以下の画像を入力として数値を出力するCNN回帰モデルを作りたい。
画像の下に記載されている数字がラベルになります。
このように差がはっきりと分かる入力画像に対してだと、ほぼ100%の正解率になると思っているのですが、
学習結果が収束しません。
改善点をアドバイスいただけるとありがたいです。
発生している問題
損失が以下のように推移し、約60epoch移行は精度が向上しません。
200epoch目の結果は以下のような状態で、正解ラベルが0.1から0.9の間だとすると、ほとんど正解とは言えない状況です。
(outputsがモデルの出力結果、labelsが正解データ)
outputs: tensor([[0.4102]], grad_fn=<AddmmBackward>) labels: tensor([0.9000]) loss: 0.2399456799030304 outputs: tensor([[0.5098]], grad_fn=<AddmmBackward>) labels: tensor([0.1000]) loss: 0.16796395182609558 outputs: tensor([[0.2965]], grad_fn=<AddmmBackward>) labels: tensor([0.6000]) loss: 0.09208495169878006 outputs: tensor([[0.3554]], grad_fn=<AddmmBackward>) labels: tensor([0.3000]) loss: 0.003064962802454829 [200, 4] loss: 0.126
該当のソースコード
- 画像を一枚ずつロードし、2乗誤差を計算してモデルをアップデート
- モデルはAlexnetの最後にfc層を付け加えて、回帰モデルにしたもの
- optimizerはAdamを使用
python
1import pandas as pd 2from PIL import Image 3import matplotlib.pyplot as plt 4import csv 5 6import torch 7import torch.nn as nn 8import torch.optim as optim 9from torchvision import models, transforms 10from torch.utils.data import Dataset, DataLoader, random_split 11 12from models.alexnet_reg import AlexNet 13 14 15class ImageDataset(Dataset): 16 def __init__(self, csv_file, transform=None): 17 self.csv = pd.read_csv(csv_file) 18 self.transform = transform 19 20 def __len__(self): 21 return len(self.csv) 22 23 def __getitem__(self, idx): 24 img_path = self.csv.at[idx.item(), 'img'] 25 label = self.csv.at[idx.item(), 'mu'] 26 img = Image.open(img_path) 27 28 if self.transform: 29 img = self.transform(img) 30 31 return img, label 32 33 34def train(model, train_dataset): 35 n_epoch = 200 36 train_loader = DataLoader(train_dataset, batch_size=1, shuffle=True, num_workers=1) 37 38 criterion = nn.MSELoss() 39 optimizer = optim.Adam(model.parameters()) 40 model.train() 41 losses = [] 42 43 for epoch in range(n_epoch): 44 running_loss = 0.0 45 for i, data in enumerate(train_loader, 0): 46 inputs, labels = data 47 optimizer.zero_grad() 48 labels = labels.type(torch.FloatTensor) 49 50 outputs = model(inputs) 51 print('outputs:', outputs) 52 print('labels:', labels) 53 loss = criterion(outputs, labels) 54 print('loss:', loss.item()) 55 loss.backward() 56 optimizer.step() 57 58 running_loss += loss.item() 59 # if i % 10 == 9: 60 # print('[%d, %5d] loss: %.3f' % 61 # (epoch + 1, i + 1, running_loss / 10)) 62 # running_loss = 0.0 63 64 print('[%d, %5d] loss: %.3f' % 65 (epoch + 1, i + 1, running_loss / 4)) 66 losses.append(running_loss/4) 67 68 with open('losses.csv', 'w') as f: 69 writer = csv.writer(f, lineterminator='/n') 70 writer.writerow(losses) 71 72 plt.plot(losses) 73 plt.title('MSELoss') 74 plt.xlabel('epoch') 75 plt.ylabel('loss') 76 plt.show() 77 78def main(): 79 transform = transforms.Compose( 80 [transforms.Resize(224), 81 transforms.ToTensor()] 82 ) 83 dataset = ImageDataset(csv_file='./data/dataset00/dataset00.csv', transform=transform) 84 85 train_size = int(1.0 * len(dataset)) 86 valid_size = len(dataset) - train_size 87 train_dataset, valid_dataset = random_split(dataset, [train_size, valid_size]) 88 print('train_size:', train_size, ', valid_size:', valid_size) 89 90 model = AlexNet() 91 train(model, train_dataset) 92 93 94if __name__ == '__main__': 95 main() 96
python
1import torch.nn as nn 2from torchvision import models 3 4 5class AlexNet(nn.Module): 6 def __init__(self): 7 super(AlexNet, self).__init__() 8 self.alexnet = models.alexnet(pretrained=True) 9 self.classifier2 = nn.Sequential( 10 nn.Dropout(), 11 nn.Linear(1000, 256), 12 nn.ReLU(inplace=True), 13 nn.Dropout(), 14 nn.Linear(256, 64), 15 nn.ReLU(inplace=True), 16 nn.Dropout(), 17 nn.Linear(64, 16), 18 nn.ReLU(inplace=True), 19 nn.Dropout(), 20 nn.Linear(16, 1) 21 ) 22 23 def forward(self, x): 24 x = self.alexnet(x) 25 x = self.classifier2(x) 26 return x 27
試したこと
補足情報(FW/ツールのバージョンなど)
torch==1.0.1.post2
torchvision==0.2.2.post3

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/03/26 02:58
2019/03/26 11:58