2022年度第8回卒研セミナー(2022/06/09)

関連サイトと資料

確認1

Resnet50モデルの概要を確認。

from torchvision import models
import os
  
# proxy
os.environ["http_proxy"] = "http://ccproxyz.kanagawa-it.ac.jp:10080"
os.environ["https_proxy"] = "http://ccproxyz.kanagawa-it.ac.jp:10080"
  
model = models.resnet50(pretrained=True)
print(model)
  
#model.fc = nn.Linear(2048, 2) # 出力の数=2にする
#model = model.to(device) # GPUを使うときはGPUメモリ上に乗せる
#return model
    

ResNet(
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (relu): ReLU(inplace=True)
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (layer1): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (downsample): Sequential(
        (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (2): Bottleneck(
      (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
  )
  (layer2): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (downsample): Sequential(
        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (2): Bottleneck(
      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (3): Bottleneck(
      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
  )
  (layer3): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (downsample): Sequential(
        (0): Conv2d(512, 1024, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (2): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (3): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (4): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (5): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
  )
  (layer4): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (downsample): Sequential(
        (0): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (2): Bottleneck(
      (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
  (fc): Linear(in_features=2048, out_features=1000, bias=True)
)
    

確認2

Resnet50モデルの最終部が適切に変更されているか確認。

from torch import nn
from torchvision import models
import os
  
# proxy
os.environ["http_proxy"] = "http://ccproxyz.kanagawa-it.ac.jp:10080"
os.environ["https_proxy"] = "http://ccproxyz.kanagawa-it.ac.jp:10080"
  
model = models.resnet50(pretrained=True) 
model.fc = nn.Linear(2048, 2) # 出力の数=2にする
print(model)
    

ResNet(
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (relu): ReLU(inplace=True)
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (layer1): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (downsample): Sequential(
        (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (2): Bottleneck(
      (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
  )
  (layer2): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (downsample): Sequential(
        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (2): Bottleneck(
      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (3): Bottleneck(
      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
  )
  (layer3): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (downsample): Sequential(
        (0): Conv2d(512, 1024, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (2): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (3): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (4): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (5): Bottleneck(
      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
  )
  (layer4): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (downsample): Sequential(
        (0): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): Bottleneck(
      (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
    (2): Bottleneck(
      (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
    )
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
  (fc): Linear(in_features=2048, out_features=2, bias=True)
)
    

確認3

Resnet50モデルをGPUに移動できるか確認。

import torch
from torch import nn
from torchvision import models
import os
  
USE_DEVICE = 'cuda:0' if torch.cuda.is_available() else 'cpu'
device = torch.device(USE_DEVICE)

# proxy
os.environ["http_proxy"] = "http://ccproxyz.kanagawa-it.ac.jp:10080"
os.environ["https_proxy"] = "http://ccproxyz.kanagawa-it.ac.jp:10080"
  
model = models.resnet50(pretrained=True) 
model.fc = nn.Linear(2048, 2) # 出力の数=2にする
model = model.to(device) # GPUを使うときはGPUメモリ上に乗せる
    

確認4

ここまでは正常動作していることを確認した。 (BATCH_SIZEを1にして)データを1個読み込んでみたが、プログラムが正常終了しない(いつまでも終了しない)。

import numpy as np
import pandas as pd
import torch
from torch import utils
import os
from PIL import Image
from sklearn.model_selection import train_test_split
from torchvision import transforms
  
USE_DEVICE = 'cuda:0' if torch.cuda.is_available() else 'cpu'
device = torch.device(USE_DEVICE)
  
INPUT_DIR = 'forest-path-movie-dataset-main/forest-path-movie-dataset-main/'
  
# PyTorchの内部を決定論的に設定する
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
  
# 乱数を初期化する関数
def init_seed():
    np.random.seed(0)
    torch.manual_seed(0)
  
# PyTorchの流儀でデータセットをクラスで定義する
class MyDataset:
    def __init__(self, X, y, valid=False):
        # 初期化 Xはファイル名のリスト、yは人物が写っているかどうかのリスト
        self.X = X
        self.y = y
        if not valid: # 学習用ならDAを含んだtransoformを作る
            trans = [
                transforms.Resize((224,224)),
                transforms.ColorJitter(brightness=1.0),
                transforms.RandomGrayscale(0.1),
                transforms.ToTensor(),
                transforms.RandomErasing(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
            ]
        else: # 評価時にはDAを含まないtransoformを作る
            trans = [
                transforms.Resize((224,224)),
                transforms.ToTensor(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                     std=[0.229, 0.224, 0.225])
            ]
        self.trans = transforms.Compose(trans)
  
    def __len__(self):
        # データセットの長さを返す
        return len(self.X)
  
    def __getitem__(self, pos):
        # posの場所にあるデータを返す
        f = INPUT_DIR + self.X[pos] # ファイルパス
        X = Image.open(f) # ファイルを読み込む
        X = self.trans(X) # DAしてtensorにする
        y = self.y[pos]
        return X, y
  
# データセットの定義ファイルを読み込む
df = pd.read_csv(INPUT_DIR+'all_file2.csv')
  
# シーン毎に分割するので、groupbyして取り出す
file, person = [], []
for g in df.groupby(df.scene):
    file.append(g[1].file.values.tolist())
    person.append(g[1].person.values.tolist())
  
# シーン毎に学習用と評価用データに分ける   
train_X, test_X, train_y, test_y = [], [], [], []
for i in range(len(file)):
    trainX, testX, trainy, testy = train_test_split(file[i], person[i], test_size=0.3, random_state=0)
    train_X.append(trainX)
    test_X.append(testX)
    train_y.append(trainy)
    test_y.append(testy)
  
# 全てのシーン内のデータを繋げた配列にする
train_X = sum(train_X, [])
train_y = sum(train_y, [])
test_X = sum(test_X, [])
test_y = sum(test_y, [])
    
# 学習時と評価時のバッチサイズ
BATCH_SIZE = 1
BATCH_SIZE_VALID = 4
# データの読み込みスレッドの数
NUM_WORKERS = 2
  
train_ds = MyDataset(train_X, train_y)
  
data_loader = utils.data.DataLoader(train_ds, batch_size=BATCH_SIZE, shuffle=True, num_workers=NUM_WORKERS)
  
init_seed()

loop_num = 0
for X, y in data_loader: # 画像を読み込んでtensorにする
    loop_num = loop_num + 1
    print(f'学習:{loop_num}')
    break

  

確認5

データ拡張を行うクラス(MyTransform)とデータを読み込むクラス(MyDataset)を分けてみた。 なお、MyDatasetをtorch.utils.data.Datasetのサブクラスにしてみた。 他のPyTocrh参考書籍では、 torch.utils.data.DataLoaderの引き数として渡すMyDatasetクラスはtorch.utils.data.Datasetクラスを継承していたので気になっていた。 まずは、画像を直接読み込み、MyTransformで変換が正常に行われているかを確認した。 以下のプログラムを実行するには、matplotlibライブラリをインストールする必要がある。

import numpy as np
import pandas as pd
import torch
from torch import utils
import os
from PIL import Image
from sklearn.model_selection import train_test_split
from torchvision import transforms
from torch.utils.data import Dataset
import matplotlib.pyplot as plt
  
USE_DEVICE = 'cuda:0' if torch.cuda.is_available() else 'cpu'
device = torch.device(USE_DEVICE)
  
INPUT_DIR = 'forest-path-movie-dataset-main/forest-path-movie-dataset-main/'
  
# PyTorchの内部を決定論的に設定する
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
  
# 乱数を初期化する関数
def init_seed():
    np.random.seed(0)
    torch.manual_seed(0)
  
class MyTransform:
    def __init__(self):
        self.data_transform = {
            'train': transforms.Compose([
                transforms.Resize((224,224)),
        #        transforms.ColorJitter(brightness=1.0),
                transforms.RandomGrayscale(0.1),
                transforms.ToTensor(),
                transforms.RandomErasing(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
            ]),
            'val': transforms.Compose([
                transforms.Resize((224,224)),
                transforms.ToTensor(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                     std=[0.229, 0.224, 0.225])
            ])
        }
    
    def __call__(self, img, phase='train'):
        return self.data_transform[phase](img)
  
# PyTorchの流儀でデータセットをクラスで定義する
class MyDataset(Dataset):
    def __init__(self, X, y, transform, phase='train'):
        # 初期化 Xはファイル名のリスト、yは人物が写っているかどうかのリスト
        self.X = X
        self.y = y
        self.transform = transform
        self.phase = phase
  
    def __len__(self):
        # データセットの長さを返す
        return len(self.X)
  
    def __getitem__(self, pos):
        # posの場所にあるデータを返す
        f = INPUT_DIR + self.X[pos] # ファイルパス
        print(f'pos={pos}, f={f}')
        X = Image.open(f) # ファイルを読み込む
        X = self.transform(X, self.phase) # DAしてtensorにする
        y = self.y[pos]
        return X, y
  
# データセットの定義ファイルを読み込む
df = pd.read_csv(INPUT_DIR+'all_file2.csv')
  
# シーン毎に分割するので、groupbyして取り出す
file, person = [], []
for g in df.groupby(df.scene):
    file.append(g[1].file.values.tolist())
    person.append(g[1].person.values.tolist())
  
# シーン毎に学習用と評価用データに分ける   
train_X, test_X, train_y, test_y = [], [], [], []
for i in range(len(file)):
    trainX, testX, trainy, testy = train_test_split(file[i], person[i], test_size=0.3, random_state=0)
    train_X.append(trainX)
    test_X.append(testX)
    train_y.append(trainy)
    test_y.append(testy)
  
# 全てのシーン内のデータを繋げた配列にする
train_X = sum(train_X, [])
train_y = sum(train_y, [])
test_X = sum(test_X, [])
test_y = sum(test_y, [])
    
init_seed()
f = INPUT_DIR + train_X[0]
print(f)
img = Image.open(f)
plt.imshow(img)
plt.show()
  
transform = MyTransform()
img_transformed = transform(img, phase='train')
img_transformed = img_transformed.numpy().transpose((1,2,0))
img_transformed = np.clip(img_transformed, 0, 1)
plt.imshow(img_transformed)
plt.show()
    

確認6

MyDatasetから1個だけ画像を取り出して、異常がないか確認した。

import numpy as np
import pandas as pd
import torch
from torch import utils
import os
from PIL import Image
from sklearn.model_selection import train_test_split
from torchvision import transforms
from torch.utils.data import Dataset
import matplotlib.pyplot as plt
  
USE_DEVICE = 'cuda:0' if torch.cuda.is_available() else 'cpu'
device = torch.device(USE_DEVICE)
  
INPUT_DIR = 'forest-path-movie-dataset-main/forest-path-movie-dataset-main/'
  
# PyTorchの内部を決定論的に設定する
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
  
# 乱数を初期化する関数
def init_seed():
    np.random.seed(0)
    torch.manual_seed(0)
  
class MyTransform:
    def __init__(self):
        self.data_transform = {
            'train': transforms.Compose([
                transforms.Resize((224,224)),
        #        transforms.ColorJitter(brightness=1.0),
                transforms.RandomGrayscale(0.1),
                transforms.ToTensor(),
                transforms.RandomErasing(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
            ]),
            'val': transforms.Compose([
                transforms.Resize((224,224)),
                transforms.ToTensor(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                     std=[0.229, 0.224, 0.225])
            ])
        }
    
    def __call__(self, img, phase='train'):
        return self.data_transform[phase](img)
  
# PyTorchの流儀でデータセットをクラスで定義する
class MyDataset(Dataset):
    def __init__(self, X, y, transform, phase='train'):
        # 初期化 Xはファイル名のリスト、yは人物が写っているかどうかのリスト
        self.X = X
        self.y = y
        self.transform = transform
        self.phase = phase
  
    def __len__(self):
        # データセットの長さを返す
        return len(self.X)
  
    def __getitem__(self, pos):
        # posの場所にあるデータを返す
        f = INPUT_DIR + self.X[pos] # ファイルパス
        print(f'pos={pos}, f={f}')
        X = Image.open(f) # ファイルを読み込む
        X = self.transform(X, self.phase) # DAしてtensorにする
        y = self.y[pos]
        return X, y
  
# データセットの定義ファイルを読み込む
df = pd.read_csv(INPUT_DIR+'all_file2.csv')
  
# シーン毎に分割するので、groupbyして取り出す
file, person = [], []
for g in df.groupby(df.scene):
    file.append(g[1].file.values.tolist())
    person.append(g[1].person.values.tolist())
  
# シーン毎に学習用と評価用データに分ける   
train_X, test_X, train_y, test_y = [], [], [], []
for i in range(len(file)):
    trainX, testX, trainy, testy = train_test_split(file[i], person[i], test_size=0.3, random_state=0)
    train_X.append(trainX)
    test_X.append(testX)
    train_y.append(trainy)
    test_y.append(testy)
  
# 全てのシーン内のデータを繋げた配列にする
train_X = sum(train_X, [])
train_y = sum(train_y, [])
test_X = sum(test_X, [])
test_y = sum(test_y, [])
    
init_seed()
train_ds = MyDataset(train_X, train_y, transform=MyTransform(), phase='train')
pos = 0
print(train_ds.__getitem__(pos)[0].size())
    

確認7

BATCH_SIZEを16にして、torch.utils.data.DataLoaderからデータが供給されるか確認した。 DataLoaderクラスのオブジェクトを生成する時に、num_workersの値は与えずにデフォルト値を使うことにした。

import numpy as np
import pandas as pd
import torch
from torch import utils
import os
from PIL import Image
from sklearn.model_selection import train_test_split
from torchvision import transforms
from torch.utils.data import Dataset
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
  
USE_DEVICE = 'cuda:0' if torch.cuda.is_available() else 'cpu'
device = torch.device(USE_DEVICE)
  
INPUT_DIR = 'forest-path-movie-dataset-main/forest-path-movie-dataset-main/'
  
# PyTorchの内部を決定論的に設定する
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
  
# 乱数を初期化する関数
def init_seed():
    np.random.seed(0)
    torch.manual_seed(0)
  
class MyTransform:
    def __init__(self):
        self.data_transform = {
            'train': transforms.Compose([
                transforms.Resize((224,224)),
        #        transforms.ColorJitter(brightness=1.0),
                transforms.RandomGrayscale(0.1),
                transforms.ToTensor(),
                transforms.RandomErasing(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
            ]),
            'val': transforms.Compose([
                transforms.Resize((224,224)),
                transforms.ToTensor(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                     std=[0.229, 0.224, 0.225])
            ])
        }
    
    def __call__(self, img, phase='train'):
        return self.data_transform[phase](img)
  
# PyTorchの流儀でデータセットをクラスで定義する
class MyDataset(Dataset):
    def __init__(self, X, y, transform, phase='train'):
        # 初期化 Xはファイル名のリスト、yは人物が写っているかどうかのリスト
        self.X = X
        self.y = y
        self.transform = transform
        self.phase = phase
  
    def __len__(self):
        # データセットの長さを返す
        return len(self.X)
  
    def __getitem__(self, pos):
        # posの場所にあるデータを返す
        f = INPUT_DIR + self.X[pos] # ファイルパス
        print(f'pos={pos}, f={f}')
        X = Image.open(f) # ファイルを読み込む
        X = self.transform(X, self.phase) # DAしてtensorにする
        y = self.y[pos]
        return X, y
  
# データセットの定義ファイルを読み込む
df = pd.read_csv(INPUT_DIR+'all_file2.csv')
  
# シーン毎に分割するので、groupbyして取り出す
file, person = [], []
for g in df.groupby(df.scene):
    file.append(g[1].file.values.tolist())
    person.append(g[1].person.values.tolist())
  
# シーン毎に学習用と評価用データに分ける   
train_X, test_X, train_y, test_y = [], [], [], []
for i in range(len(file)):
    trainX, testX, trainy, testy = train_test_split(file[i], person[i], test_size=0.3, random_state=0)
    train_X.append(trainX)
    test_X.append(testX)
    train_y.append(trainy)
    test_y.append(testy)
  
# 全てのシーン内のデータを繋げた配列にする
train_X = sum(train_X, [])
train_y = sum(train_y, [])
test_X = sum(test_X, [])
test_y = sum(test_y, [])
    
# 学習時と評価時のバッチサイズ
BATCH_SIZE = 16
  
init_seed()
train_ds = MyDataset(train_X, train_y, transform=MyTransform(), phase='train')
data_loader = DataLoader(train_ds, batch_size=BATCH_SIZE, shuffle=True)
  
loop_num = 0
print(f'loop_num={loop_num}')
for X, y in data_loader: # 画像を読み込んでtensorにする
    loop_num = loop_num + 1
    print(f'学習:{loop_num}')
    

学習プログラム(改良版) - 正常動作するようになった

使用したGPU処理に要した時間
GeForce RTX20802時間22分
GeForce GTX1050Ti5時間55分

import numpy as np
import pandas as pd
import itertools
import shutil
from PIL import Image
import os
  
import torch
from torch import nn, utils, optim
from torch.utils.data import DataLoader
from torch.utils.data import Dataset
from torchvision import transforms, models
from sklearn.metrics import f1_score, accuracy_score
from sklearn.model_selection import train_test_split
  
# proxy
os.environ["http_proxy"] = "http://ccproxyz.kanagawa-it.ac.jp:10080"
os.environ["https_proxy"] = "http://ccproxyz.kanagawa-it.ac.jp:10080"
    

# GPUを使うかどうか
USE_DEVICE = 'cuda:0' if torch.cuda.is_available() else 'cpu'
device = torch.device(USE_DEVICE)
# データがあるディレクトリ
INPUT_DIR = 'forest-path-movie-dataset-main/forest-path-movie-dataset-main/'
    

# PyTorchの内部を決定論的に設定する
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
  
# 乱数を初期化する関数
def init_seed():
    np.random.seed(0)
    torch.manual_seed(0)
  
# 一時ディレクトリを作成
if not os.path.isdir('tmp'):
    os.mkdir('tmp')
    

# データセットの定義ファイルを読み込む
df = pd.read_csv(INPUT_DIR+'all_file2.csv')
  
# シーン毎に分割するので、groupbyして取り出す
file, person = [], []
for g in df.groupby(df.scene):
    file.append(g[1].file.values.tolist())
    person.append(g[1].person.values.tolist())
    

# シーン毎に学習用と評価用データに分ける   
train_X, test_X, train_y, test_y = [], [], [], []
for i in range(len(file)):
    trainX, testX, trainy, testy = train_test_split(file[i], person[i], test_size=0.3, random_state=0)
    train_X.append(trainX)
    test_X.append(testX)
    train_y.append(trainy)
    test_y.append(testy)  
    

# 全てのシーン内のデータを繋げた配列にする
train_X = sum(train_X, [])
train_y = sum(train_y, [])
test_X = sum(test_X, [])
test_y = sum(test_y, [])
    

class MyTransform:
    def __init__(self):
        self.data_transform = {
            'train': transforms.Compose([
                transforms.Resize((224,224)),
                transforms.ColorJitter(brightness=1.0),
                transforms.RandomGrayscale(0.1),
                transforms.ToTensor(),
                transforms.RandomErasing(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
            ]),
            'val': transforms.Compose([
                transforms.Resize((224,224)),
                transforms.ToTensor(),
                transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                     std=[0.229, 0.224, 0.225])
            ])
        }
    
    def __call__(self, img, phase='train'):
        return self.data_transform[phase](img)
    

class MyDataset(Dataset):
    def __init__(self, X, y, transform, phase='train'):
        # 初期化 Xはファイル名のリスト、yは人物が写っているかどうかのリスト
        self.X = X
        self.y = y
        self.transform = transform
        self.phase = phase
  
    def __len__(self):
        # データセットの長さを返す
        return len(self.X)
  
    def __getitem__(self, pos):
        # posの場所にあるデータを返す
        f = INPUT_DIR + self.X[pos] # ファイルパス
        X = Image.open(f) # ファイルを読み込む
        X = self.transform(X, self.phase) # DAしてtensorにする
        y = self.y[pos]
        return X, y
    

def get_model(): # ニューラルネットワークのモデルを返す関数
    # ModelZOOからモデルをダウンロードして最後の層だけを入れ替える
    model = models.resnet50(pretrained=True)
    model.fc = nn.Linear(2048, 2) # 出力の数=2にする
    model = model.to(device) # GPUを使うときはGPUメモリ上に乗せる
    return model
    

def get_optim(model, lr): # 勾配降下法のアルゴリズムを返す関数
    params = model.parameters() # 学習させるパラメーター
    optimizer = optim.SGD(params, lr=lr,  momentum=0.9) # 学習率を設定
    return optimizer
    

def get_loss(weight): # 損失関数を返す関数
    # 不均衡なデータを学習させるために、クラス毎のウェイトを設定する
    weight = torch.tensor([1.0-weight,weight], dtype=torch.float)
    weight = weight.to(device) # GPUを使うときはGPUメモリ上に乗せる
    loss = nn.CrossEntropyLoss(weight=weight) # ウェイト付きのCrossEntropy
    return loss
    

def get_score(true_valid, pred_valid): # 評価スコアを返す関数
    # 評価スコアは、全体の他に時間帯毎にも作成するのでディクショナリを用意する
    timezone = {'daytime':([],[]),'twilight':([],[]),'midnight':([],[])}
    # 認識結果を時間帯毎に仕分けする
    for i, filename in enumerate(test_X):
        w = df[df.file==filename].when.values[0]
        timezone[w][0].append(true_valid[i])
        timezone[w][1].append(pred_valid[i])
    # 時間帯毎のF1スコアをディクショナリに入れる
    score = {k:f1_score(v[0], v[1]) for k,v in timezone.items()}
    # 全体のF1スコアをディクショナリに入れる
    score['total'] = f1_score(true_valid, pred_valid)
    # 認識が極端に偏ってないか見るために、認識値の平均も求める
    score['average'] = np.mean(pred_valid)
    return score
    

# 学習時と評価時のバッチサイズ
BATCH_SIZE = 16
BATCH_SIZE_VALID = 4
# 試行時の学習エポック数
NUM_EPOCHS = 3
# 評価で試す学習率
LR_TESTS = [1e-3,2e-4,5e-5]
# 試すウェイトは、人物の方が分散が大きいので、クラス1側を0.5より少なくする
WEIGHT_TESTS = [0.1,0.2,0.3,0.4,0.5]
    

# 学習用と評価用にデータセットを作る
train_ds = MyDataset(train_X, train_y, transform=MyTransform(), phase='train')
val_ds = MyDataset(test_X, test_y, transform=MyTransform(), phase='val')
  
# 複数スレッドでファイルを読み込みつつデータを取り出すDataLoaderを作る
data_loader = DataLoader(train_ds, batch_size=BATCH_SIZE, shuffle=True)
data_loader_v = DataLoader(val_ds, batch_size=BATCH_SIZE_VALID, shuffle=False)
    

# 試行時の最も評価が良かったスコアのリスト
best_scores = []
# 学習率とウェイトを変えながら試行する
for t, (lr, weight) in enumerate(itertools.product(LR_TESTS, WEIGHT_TESTS)):
    # 試行毎に乱数を初期化してからニューラルネットワークを作成する
    init_seed()
    model = get_model() # ニューラルネットワークを作成
    # 学習のためのアルゴリズムを取得
    optimizer = get_optim(model, lr)
    loss = get_loss(weight)
  
    # 現在の学習率とウェイトで試行する
    print(f'test #{t} lr={lr} weight={weight}')
    scores = [] # 各エポック終了時のスコア
  
    # 学習ループ
    for epoch in range(NUM_EPOCHS):
        print(f'epoch={epoch}')
        total_loss = [] # 各バッチ実行時の損失値
        model.train() # モデルを学習用に設定する
        print('train mode!')
        loop_num = 0
        for X, y in data_loader: # 画像を読み込んでtensorにする
            loop_num = loop_num + 1
            print(f'学習:{loop_num}')
            X = X.to(device) # GPUを使うときはGPUメモリ上に乗せる
            y = y.to(device) # GPUを使うときはGPUメモリ上に乗せる
  
            # ニューラルネットワークを実行して損失値を求める
            losses = loss(model(X), y)
  
            # 新しいバッチ分の学習を行う
            optimizer.zero_grad() # 一つ前の勾配をクリア
            losses.backward() # 損失値を逆伝播させる
            optimizer.step() # 新しい勾配からパラメーターを更新する
  
            # 損失値を保存しておく
            total_loss.append(losses.detach().cpu().numpy())
  
        # 評価
        with torch.no_grad():
            # 評価時の損失値と正解/認識結果を入れるリスト
            total_loss_v = []
            true_valid = []
            pred_valid = []
  
            model.eval() # モデルを推論用に設定する
            for i, (X, y) in enumerate(data_loader_v):
                X = X.to(device) # GPUを使うときはGPUメモリ上に乗せる
                y = y.to(device) # GPUを使うときはGPUメモリ上に乗せる
  
                res = model(X) # ニューラルネットワークの実行
                losses = loss(res, y) # 評価データの損失値
  
                # 正解データを保存
                y = y.detach().cpu().numpy() # CPUメモリに入れてnumpy化
                true_valid.extend(y.tolist())
                # 認識結果を保存
                res = res.detach().cpu().numpy() # CPUメモリに入れてnumpy化
                pred_valid.extend(res.argmax(axis=1).tolist())
  
                # 損失値を保存しておく
                total_loss_v.append(losses.detach().cpu().numpy())
  
        # エポック終了時のスコアを求める
        total_loss = np.mean(total_loss) # 各バッチの損失の平均
        total_loss_v = np.mean(total_loss_v) # 各バッチの損失の平均
        score = get_score(true_valid, pred_valid) # 評価スコア
        scores.append(score['total']) # スコアを保存しておく
        # エポック終了時のスコアを表示する
        print(f'epoch #{epoch}: train_loss:{total_loss} valid_loss:{total_loss_v} score:{score}')
        # エポック終了時のモデルを保存しておく
        torch.save(model.state_dict(), f'tmp/checkpoint{epoch}.pth')
  
    # 現在の学習率とウェイトで最も良かったモデルをコピーして保存しておく
    best_epoch = np.argmax(scores)
    shutil.copyfile(f'tmp/checkpoint{best_epoch}.pth',f'tmp/test{t}_best.pth')
    # 現在の学習率とウェイトで最も良かったモデルを損失値しておく
    best_scores.append(scores[best_epoch])
  
    # GPUメモリをGCする
    del model, optimizer, loss, X, y, res, losses
    torch.cuda.empty_cache()
  
# 最も良かった学習率とウェイトでのモデルをコピーする
best_of_best = np.argmax(best_scores)
shutil.copyfile(f'tmp/test{best_of_best}_best.pth', 'chapt02-model1.pth')
  
# 一時ディレクトリを削除
shutil.rmtree('tmp')
    

GeForce RTX2080での動作結果

GeForce GTX1050Tiでの動作結果