【Pytorch 실습】 CIFAR10 데이터셋. Dropout, Xivier Weight + ResNet18 사용하기

아래의 코드는 Kaggle 및 Git의 공개된 코드를 적극 활용한, 과거의 공부한 내용을 정리한 내용입니다.

【Pytorch 실습】 CIFAR10 데이터셋. Dropout, Xivier Weight + ResNet18 사용하기

1. Dropout 사용해보기

1. 데이터 Load

import torch
USE_CUDA = torch.cuda.is_available()
DEVICE = torch.device("cuda" if USE_CUDA else "cpu")
  • 공개적인 데이터를 다음과 같이 datasets.~~ 해보면 정말 많은 데이터가 있는 것을 확인할 수 있다.
  • Trainsforms.compose를 이용해서 Tensor형으로 바꿔주는 전처리를 해줄 수 있다.
  • Normalize(평균, 분산) -> RGV에 대해서 정규처리를 해줄 수 있다. ```python from torchvision import transforms, datasets train_loader = torch.utils.data.DataLoader( datasets.CIFAR10(“../data/CIFAR_10/”, train = True, download = True, transform = transforms.Compose([ transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])), batch_size = 64, shuffle = True)

test_loader = torch.utils.data.DataLoader( datasets.CIFAR10(“../data/CIFAR_10”, train = False, transform = transforms.Compose([ transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])), batch_size = 64 )


## 2. 모델 구현
- 드롭아웃을 하는 방법은 아래와 같다. 여기서는 Fully Connected layer에서 dropout을 사용했는데, 내부 동작원리는 간단하다. 
- layer의 node 중 랜덤하게 일정비율로 0으로 만들어 버리는 것이다. (node가 동작하지 않는다.) 이렇게 함으로써 간단하게 dropout을 구현할 수 있다. 
- 아래에서 사용한 변수 self.dropout_o = 0.2가 랜덤하게 노드를 잠그는 비율이다. 

```python
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
    
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(in_channels = 3, out_channels = 8, kernel_size = 3, padding = 1)
        self.conv2 = nn.Conv2d(in_channels = 8, out_channels = 16, kernel_size = 3, padding = 1)
        self.conv3 = nn.Conv2d(in_channels = 16, out_channels = 32, kernel_size = 3, padding = 1)
        self.conv4 = nn.Conv2d(in_channels = 32, out_channels = 64, kernel_size = 3, padding = 1)
        self.pool = nn.MaxPool2d(kernel_size = 2, stride = 2)
        self.fc1 = nn.Linear(2 * 2 * 64, 64)
        self.fc2 = nn.Linear(64, 32)
        self.fc3 = nn.Linear(32, 10)
        
        self.conv1_bn = nn.BatchNorm2d(8)
        self.conv2_bn = nn.BatchNorm2d(16)
        self.conv3_bn = nn.BatchNorm2d(32)
        self.conv4_bn = nn.BatchNorm2d(64)
        
        self.dropout_p = 0.2  # dropout 확률 
        
    def forward(self, x):
        x = self.conv1(x) # 32 * 32 * 3 -> 32 * 32 * 8
        x = self.conv1_bn(x)
        x = F.tanh(x)     # 32 * 32 * 8
        x = self.pool(x)  # 16 * 16 * 8
        
        x = self.conv2(x) # 16 * 16 * 8 -> 16 * 16 * 16
        x = self.conv2_bn(x)
        x = F.tanh(x)     # 16 * 16 * 16
        x = self.pool(x)  # 8  *  8 * 16
        
        x = self.conv3(x) # 8 * 8 * 16 -> 8 * 8 * 32
        x = self.conv3_bn(x)
        x = F.tanh(x)     # 8 * 8 * 32
        x = self.pool(x)  # 4 * 4 * 32
        
        x = self.conv4(x) # 4 * 4 * 32 -> 4 * 4 * 64
        x = self.conv4_bn(x)
        x = F.tanh(x)     # 4 * 4 * 64
        x = self.pool(x)  # 2 * 2 * 64
        
        x = x.view(-1, 2 * 2 * 64)
        x = self.fc1(x)
        x = F.dropout(x, p = self.dropout_p)  # actiavtion function 전후 상관 없다. 알아서..
        x = F.relu(x)
        x = self.fc2(x)
        x = F.dropout(x, p = self.dropout_p)
        x = F.relu(x)
        x = self.fc3(x)
        x = F.log_softmax(x, dim = 1)
        return x

print("DEVICE: ", DEVICE)
print("MODEL: ", model)

DEVICE:  cuda
MODEL:  CNN(
  (conv1): Conv2d(3, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (conv2): Conv2d(8, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (conv3): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (conv4): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (fc1): Linear(in_features=256, out_features=64, bias=True)
  (fc2): Linear(in_features=64, out_features=32, bias=True)
  (fc3): Linear(in_features=32, out_features=10, bias=True)
  (conv1_bn): BatchNorm2d(8, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (conv2_bn): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (conv3_bn): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (conv4_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)

3. 가중치 초기화 하기

  • 보통은 Transfer Learning을 통해서 가중치 초기화에 대해서 공부할 기회가 없지만 여기서는 가중치 초기화를 직접 해보았다.
  • 가중치를 초기화 하는 방법에는 Xavier와 He등이 있다. 여기서는 Xavier를 사용해 보았다. Relu를 사용한 모델에서는 He를 사용하는게 더 유리하다고 하다.
    ```python

import torch.nn.init as init def weight_init(m):

'''
이 주석을 풀면 Xavier, kaiming 에 대한 Initialization에 대한 상세 설정을 할 수 있다. 

Ref: https://pytorch.org/docs/stable/nn.init.html

init.uniform_(tensor, a = 0.0, b = 1.0) (a: Lower bound, b: Upper bound)
init.normal_(tensor, mean = 0.0, std = 1.0)
init.xavier_uniform_(tensor, gain = 1.0)
init.xavier_normal_(tensor, gain = 1.0)
init.kaiming_uniform_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu')
init.kaiming_normal_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu')
'''

if isinstance(m, nn.Conv2d):
    init.xavier_uniform_(m.weight.data)
    if m.bias is not None:
        init.normal_(m.bias.data)

elif isinstance(m, nn.BatchNorm2d):
    init.normal_(m.weight.data, mean=1, std=0.02)
    init.constant_(m.bias.data, 0)

elif isinstance(m, nn.Linear):
    init.xavier_uniform_(m.weight.data)
    init.normal_(m.bias.data)

model = CNN().to(DEVICE) model.apply(weight_init)

optimizer = optim.Adam(model.parameters(), lr = 0.001) print(“DEVICE: “, DEVICE) print(“MODEL: “, model)


## 4. 모델 학습 및 추론
```python
def train(model, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(DEVICE), target.to(DEVICE)
        optimizer.zero_grad()
        output = model(data)
        loss = F.cross_entropy(output, target)
        loss.backward()
        optimizer.step()
        
        if batch_idx % 100 == 0:
            print("Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}".format(
                epoch, 
                batch_idx * len(data), 
                len(train_loader.dataset), 
                100. * batch_idx / len(train_loader), 
                loss.item()))
def evaluate(model, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(DEVICE), target.to(DEVICE)
            output = model(data)
            test_loss += F.cross_entropy(output, target, reduction = "sum").item()
            prediction = output.max(1, keepdim = True)[1]
            correct += prediction.eq(target.view_as(prediction)).sum().item()
    
    test_loss /= len(test_loader.dataset)
    test_accuracy = 100. * correct / len(test_loader.dataset)
    return test_loss, test_accuracy
EPOCHS = 10
for epoch in range(1, EPOCHS + 1):
    train(model, train_loader, optimizer, epoch)
    test_loss, test_accuracy = evaluate(model, test_loader)
    print("[{}] Test Loss: {:.4f}, accuracy: {:.2f}%\n".format(epoch, test_loss, test_accuracy))
Train Epoch: 10 [0/50000 (0%)]	Loss: 1.137886
Train Epoch: 10 [6400/50000 (13%)]	Loss: 0.988332
Train Epoch: 10 [12800/50000 (26%)]	Loss: 0.784159
Train Epoch: 10 [19200/50000 (38%)]	Loss: 1.073874
Train Epoch: 10 [25600/50000 (51%)]	Loss: 1.101201
Train Epoch: 10 [32000/50000 (64%)]	Loss: 1.111024
Train Epoch: 10 [38400/50000 (77%)]	Loss: 0.956936
Train Epoch: 10 [44800/50000 (90%)]	Loss: 0.914141
[10] Test Loss: 1.0315, accuracy: 64.86%
print("CNN's number of Parameters: ", sum([p.numel() for p in model.parameters()]))
CNN's number of Parameters:  43626

2. ResNet 사용해보기

1. 데이터 Load

import torch
USE_CUDA = torch.cuda.is_available()
DEVICE = torch.device("cuda" if USE_CUDA else "cpu")
from torchvision import transforms, datasets
train_loader = torch.utils.data.DataLoader(
    datasets.CIFAR10("../data/CIFAR_10/",
                     train = True,
                     download = True,
                     transform = transforms.Compose([
                         transforms.RandomHorizontalFlip(),
                         transforms.ToTensor(),
                         transforms.Normalize((0.5, 0.5, 0.5),
                                              (0.5, 0.5, 0.5))])), batch_size = 64, shuffle = True)

test_loader = torch.utils.data.DataLoader(
    datasets.CIFAR10("../data/CIFAR_10",
                     train = False,
                     transform = transforms.Compose([
                         transforms.RandomHorizontalFlip(),
                         transforms.ToTensor(),
                         transforms.Normalize((0.5, 0.5, 0.5),
                                              (0.5, 0.5, 0.5))])), batch_size = 64 , shuffle = True)

2. ResNet 모델 구현하기

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

class BasicBlock(nn.Module): # bottlenexk 이라는 용어로도 많이 사용된다.
    def __init__(self, in_planes, planes, stride = 1):
        super(BasicBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size = 3, stride = stride, padding = 1, bias = False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size = 3, stride = 1, padding = 1, bias = False)
        self.bn2 = nn.BatchNorm2d(planes)
        
        self.shortcut = nn.Sequential()
        if stride != 1 or in_planes != planes:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_planes, planes, kernel_size = 1, stride = stride, bias = False),
                nn.BatchNorm2d(planes))
    
    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out += self.shortcut(x)
        out = F.relu(out)
        return out
    
class ResNet(nn.Module): # _ㄴmake_layer라는 용어로 많이 사용되니, 알아두기
    def __init__(self, num_classes = 10):
        super(ResNet, self).__init__()
        self.in_planes = 16
        
        self.conv1 = nn.Conv2d(3, 16, kernel_size = 3, stride = 1, padding = 1, bias = False)
        self.bn1 = nn.BatchNorm2d(16)
        self.layer1 = self._make_layer(16, 2, stride = 1)
        self.layer2 = self._make_layer(32, 2, stride = 2)
        self.layer3 = self._make_layer(64, 2, stride = 2)
        self.linear = nn.Linear(64, num_classes)
        
    def _make_layer(self, planes, num_blocks, stride):
        strides = [stride] + [1] * (num_blocks  - 1)
        layers = []
        for stride in strides:
            layers.append(BasicBlock(self.in_planes, planes, stride))
            self.in_planes = planes
        return nn.Sequential(*layers)
    
    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = F.avg_pool2d(out, 8)
        out = out.view(out.size(0), -1)
        out = self.linear(out)
        return out
model = ResNet().to(DEVICE)
optimizer = optim.Adam(model.parameters(), lr = 0.001)

print("DEVICE: ", DEVICE)
print("MODEL: ", model)

3. 학습 및 추론

def train(model, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(DEVICE), target.to(DEVICE)
        optimizer.zero_grad()
        output = model(data)
        loss = F.cross_entropy(output, target)
        loss.backward()
        optimizer.step()
        
        if batch_idx % 100 == 0:
            print("Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}".format(
                epoch, 
                batch_idx * len(data), 
                len(train_loader.dataset), 
                100. * batch_idx / len(train_loader), 
                loss.item()))
def evaluate(model, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(DEVICE), target.to(DEVICE)
            output = model(data)
            test_loss += F.cross_entropy(output, target, reduction = "sum").item()
            prediction = output.max(1, keepdim = True)[1]
            correct += prediction.eq(target.view_as(prediction)).sum().item()
    
    test_loss /= len(test_loader.dataset)
    test_accuracy = 100. * correct / len(test_loader.dataset)
    return test_loss, test_accuracy
EPOCHS = 3
for epoch in range(1, EPOCHS + 1):
    train(model, train_loader, optimizer, epoch)
    test_loss, test_accuracy = evaluate(model, test_loader)
    print("[{}] Test Loss: {:.4f}, accuracy: {:.2f}%\n".format(epoch, test_loss, test_accuracy))
Train Epoch: 3 [0/50000 (0%)]	Loss: 1.127532
Train Epoch: 3 [6400/50000 (13%)]	Loss: 1.081882
Train Epoch: 3 [12800/50000 (26%)]	Loss: 0.691810
Train Epoch: 3 [19200/50000 (38%)]	Loss: 0.759505
Train Epoch: 3 [25600/50000 (51%)]	Loss: 0.786468
Train Epoch: 3 [32000/50000 (64%)]	Loss: 0.904780
Train Epoch: 3 [38400/50000 (77%)]	Loss: 0.772286
Train Epoch: 3 [44800/50000 (90%)]	Loss: 0.593489
[3] Test Loss: 0.7578, accuracy: 73.14%

3. 유명한 모델 그대로 가져와 사용하는 방법

  • 기본적으로 Pytorch에 저장되어 있는 모델 사용하기.
  • 아래와 같이 굳이 모델을 위에 처럼 구현하지 않아도 아래처럼 쉽게, 학습시킬 수 있다.
import torchvision.models as models
model = models.resnet18().cuda()
optimizer = optim.Adam(model.parameters(), lr = 0.001)
EPOCHS = 3
for epoch in range(1, EPOCHS + 1):
    train(model, train_loader, optimizer, epoch)
    test_loss, test_accuracy = evaluate(model, test_loader)
    print("[{}] Test Loss: {:.4f}, accuracy: {:.2f}%\n".format(epoch, test_loss, test_accuracy))
Train Epoch: 3 [0/50000 (0%)]	Loss: 0.853458
Train Epoch: 3 [6400/50000 (13%)]	Loss: 0.816588
Train Epoch: 3 [12800/50000 (26%)]	Loss: 0.678977
Train Epoch: 3 [19200/50000 (38%)]	Loss: 0.873804
Train Epoch: 3 [25600/50000 (51%)]	Loss: 0.783468
Train Epoch: 3 [32000/50000 (64%)]	Loss: 1.123129
Train Epoch: 3 [38400/50000 (77%)]	Loss: 0.890110
Train Epoch: 3 [44800/50000 (90%)]	Loss: 0.780257
[3] Test Loss: 0.8566, accuracy: 70.31%

resnet18 = models.resnet18()
alexnet = models.alexnet()
vgg16 = models.vgg16()
squeezenet = models.squeezenet1_0()
densenet = models.densenet161()
inception = models.inception_v3()
googlenet = models.googlenet()
shufflenet = models.shufflenet_v2_x1_0()
mobilenet = models.mobilenet_v2()
resnext50_32x4d = models.resnext50_32x4d()
wide_resnet50_2 = models.wide_resnet50_2()
mnasnet = models.mnasnet1_0()

【Pytorch 실습】 CIFAR10 데이터셋. 학습 및 추론, Activation fucntion = relu, tanh

아래의 코드는 Kaggle 및 Git의 공개된 코드를 적극 활용한, 과거의 공부한 내용을 정리한 내용입니다.

  • 코드를 한줄한줄 치면서 공부해보기로 했다. CIRAR10 데이터를 사용해서 모델을 학습시키고 추론해보는 일렬의 과정들을 공부해보자. 그리고 Python과 모델 구현을 잘하는 방법은 눈으로 공부하는 것도 있지만, 한줄한줄 코드를 치면서 공부하고 깨닫는 것이 매우 중요하다고 하다.
  • 데이터셋 다운로드 : https://www.cs.toronto.edu/~kriz/cifar.html
  • 이번 Post의 목적은 코드를 한줄한줄 치면서 어떻게 공부하고 검색하는지에 대한 느낌을 가져가는 것이다.

1. Activation Function : Relu

1. 데이터 Load, 분할(train,valu), Pytorch.tensor.Load

def unpickle(file):
    import pickle
    with open(file, "rb") as fo:
        dict = pickle.load(fo, encoding = "bytes")
    return dict

다운 받은 파일에 1. data_batch1,2,3,4,5, 2. test 파일이 있다. 당연히 전자는 Train데이터 들이다.

tmp = unpickle("../data/CIFAR10/cifar-10-batches-py/data_batch_1")
# 이런식으로 변수를 계속 print해보고 확인해보면, 사실 다 별거아니다. 
print(tmp.keys())
tmp[b'data'].shape
(10000, 3072)
# 위의 일렬의 과정을 data_batch_1,2,3,4,5를 모두 해야하기 때문에 함수로 정의해 사용.
def pickle_to_images_and_labels(root):
    data = unpickle(root)
    data_images = data[b'data'] / 255
    data_images = data_images.reshape(-1, 3, 32, 32).astype("float32")
    data_labels = data[b'labels']
    return data_images, data_labels
images1, label1 = pickle_to_images_and_labels("../data/CIFAR10/cifar-10-batches-py/data_batch_1")
images2, label2 = pickle_to_images_and_labels("../data/CIFAR10/cifar-10-batches-py/data_batch_2")
images3, label3 = pickle_to_images_and_labels("../data/CIFAR10/cifar-10-batches-py/data_batch_3")
images4, label4 = pickle_to_images_and_labels("../data/CIFAR10/cifar-10-batches-py/data_batch_4")
images5, label5 = pickle_to_images_and_labels("../data/CIFAR10/cifar-10-batches-py/data_batch_5")
test_images, test_labels = pickle_to_images_and_labels("../data/CIFAR10/cifar-10-batches-py/test_batch")

아하.. 분할되어 다운받은 이미지 어떻게 할지 궁금했는데, 걍 Concatenation 해버리네…?? 이렇게 데이터가 분할되어 있으면 일단 가져오고, Concatenation해버리면 되는구나 라고 알아두자.

import numpy as np
train_images = np.concatenate([images1, images2, images3, images4, images5], axis = 0)
train_labels = np.concatenate([label1, label2, label3, label4, label5], axis = 0)
test_images = np.concatenate([test_images], axis = 0)
test_labels = np.concatenate([test_labels], axis = 0)
from sklearn.model_selection import train_test_split
train_images, valid_images, train_labels, valid_labels = train_test_split(train_images, train_labels, stratify = train_labels, random_state = 42, test_size = 0.2)
print("The Shape of Train Images: ", train_images.shape)
print("The Shape of Valid Images: ", valid_images.shape)
print("The Shape of Test Images: ", test_images.shape)
The Shape of Train Images:  (40000, 3, 32, 32)
The Shape of Valid Images:  (10000, 3, 32, 32)
The Shape of Test Images:  (10000, 3, 32, 32)
print("The number of Train Labels: ", train_labels.shape)
print("The number of Valid Labels: ", valid_labels.shape)
print("The number of Test Labels: ", test_labels.shape)
The number of Train Labels:  (40000,)
The number of Valid Labels:  (10000,)
The number of Test Labels:  (10000,)
import torch
from torch.utils.data import TensorDataset, DataLoader
train_images_tensor = torch.tensor(train_images)
train_labels_tensor = torch.tensor(train_labels)
train_tensor = TensorDataset(train_images_tensor, train_labels_tensor)
train_loader = DataLoader(train_tensor, batch_size = 64, num_workers = 0, shuffle = True)

valid_images_tensor = torch.tensor(valid_images)
valid_labels_tensor = torch.tensor(valid_labels)
valid_tensor = TensorDataset(valid_images_tensor, valid_labels_tensor)
valid_loader = DataLoader(valid_tensor, batch_size = 64, num_workers = 0, shuffle = True)

test_images_tensor = torch.tensor(test_images)

2. 모델 구현

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

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(in_channels = 3, out_channels = 8, kernel_size = 3, padding = 1)
        self.conv2 = nn.Conv2d(in_channels = 8, out_channels = 16, kernel_size = 3, padding = 1)
        self.pool = nn.MaxPool2d(kernel_size = 2, stride = 2)
        self.fc1 = nn.Linear(8 * 8 * 16, 64)
        self.fc2 = nn.Linear(64, 32)
        self.fc3 = nn.Linear(32, 10)
        
    def forward(self, x):
        x = self.conv1(x) # 32 * 32 * 8
        x = F.relu(x)     # 32 * 32 * 8
        x = self.pool(x)  # 16 * 16 * 8
        x = self.conv2(x) # 16 * 16 * 16
        x = F.relu(x)     # 16 * 16 * 16
        x = self.pool(x)  # 8 * 8 * 16
        
        x = x.view(-1, 8 * 8 * 16)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = F.relu(x)
        x = self.fc3(x)
        x = F.log_softmax(x)
        return x
USE_CUDA = torch.cuda.is_available()
DEVICE = torch.device("cuda" if USE_CUDA else "cpu")
model = CNN().to(DEVICE)
optimizer = optim.Adam(model.parameters(), lr = 0.001)
print("Model: ", model)
print("Device: ", DEVICE)
Model:  CNN(
  (conv1): Conv2d(3, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (conv2): Conv2d(8, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (fc1): Linear(in_features=1024, out_features=64, bias=True)
  (fc2): Linear(in_features=64, out_features=32, bias=True)
  (fc3): Linear(in_features=32, out_features=10, bias=True)
)
Device:  cuda

3. 학습 및 추론

def train(model, train_loader, optimizer):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(DEVICE), target.to(DEVICE, dtype = torch.int64)
        optimizer.zero_grad()
        output = model(data)
        loss = F.cross_entropy(output, target)
        loss.backward()
        optimizer.step()
        
        if batch_idx % 100 == 0:
            print("Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}".format(
            epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item()))
def evaluate(model, valid_loader):
    model.eval()
    
    valid_loss = 0
    correct = 0
    
    with torch.no_grad():
        for data, target in valid_loader:
            data, target= data.to(DEVICE), target.to(DEVICE, dtype = torch.int64)
            output = model(data)
            valid_loss += F.cross_entropy(output, target, reduction = "sum").item()
            prediction = output.max(1, keepdim = True)[1]  # 예측한 class score 중 가장 큰 index 어딘지? 즉 Class가 무엇인지. 
            correct += prediction.eq(target.view_as(prediction)).sum().item() # Ground True와 예측한 값이 몇개인지 계산해서 정확도를 파악한다. 
    
    valid_loss /= len(valid_loader.dataset)
    valid_accuracy = 100. * correct / len(valid_loader.dataset)
    return valid_loss, valid_accuracy
'''TRAINING'''
EPOCHS = 10
for epoch in range(1, EPOCHS + 1):
    train(model, train_loader, optimizer)
    valid_loss, valid_accuracy = evaluate(model, valid_loader)
    print("[EPOCH : {}], \tValidation Loss: {:.4f}, \tValidation Accuracy: {:.2f} % \n".format(
        epoch, valid_loss, valid_accuracy))
Train Epoch: 9 [0/40000 (0%)]	Loss: 1.180444
Train Epoch: 9 [6400/40000 (16%)]	Loss: 1.049773
Train Epoch: 9 [12800/40000 (32%)]	Loss: 0.980881
Train Epoch: 9 [19200/40000 (48%)]	Loss: 1.017157
Train Epoch: 9 [25600/40000 (64%)]	Loss: 0.960528
Train Epoch: 9 [32000/40000 (80%)]	Loss: 1.220239
Train Epoch: 9 [38400/40000 (96%)]	Loss: 0.947019
[EPOCH : 9], 	Validation Loss: 1.1328, 	Validation Accuracy: 60.19 % 

Train Epoch: 10 [0/40000 (0%)]	Loss: 0.898633
Train Epoch: 10 [6400/40000 (16%)]	Loss: 1.141634
Train Epoch: 10 [12800/40000 (32%)]	Loss: 0.852636
Train Epoch: 10 [19200/40000 (48%)]	Loss: 1.075439
Train Epoch: 10 [25600/40000 (64%)]	Loss: 1.237481
Train Epoch: 10 [32000/40000 (80%)]	Loss: 1.139879
Train Epoch: 10 [38400/40000 (96%)]	Loss: 0.973299
[EPOCH : 10], 	Validation Loss: 1.1565, 	Validation Accuracy: 58.96 % 

4. 추론 및 테스트 출력해보기

def testset_prediction(model, test_images_tensor):
    model.eval()
    result = []
    
    with torch.no_grad():
        for data in test_images_tensor:
            data = data.to(DEVICE)
            output = model(data.view(-1, 3, 32, 32))
            prediction = output.max(1, keepdim = True)[1]
            result.append(prediction.tolist())
    return result
from sklearn.metrics import accuracy_score
test_predict_result = testset_prediction(model, test_images_tensor)
accuracy_score(test_labels, np.squeeze(test_predict_result))
0.5898
test_images[30].shape
(3, 32, 32)
import matplotlib.pyplot as plt
plt.imshow(np.transpose(test_images[30], (1, 2, 0)))
plt.show()
test_labels[30]
6
test_predict_result[30]
[[6]]


2. Activation Function : tanh

코드 전계 과정은 위와 동일

import torch
USE_CUDA = torch.cuda.is_available()
DEVICE = torch.device("cuda" if USE_CUDA else "cpu")
from torchvision import transforms, datasets
train_loader = torch.utils.data.DataLoader(
    datasets.CIFAR10("../data/CIFAR_10/",
                     train = True,
                     download = True,
                     transform = transforms.Compose([
                         transforms.RandomHorizontalFlip(),
                         transforms.ToTensor(),
                         transforms.Normalize((0.5, 0.5, 0.5),
                                              (0.5, 0.5, 0.5))])), batch_size = 64, shuffle = True)

test_loader = torch.utils.data.DataLoader(
    datasets.CIFAR10("../data/CIFAR_10",
                     train = False,
                     transform = transforms.Compose([
                         transforms.RandomHorizontalFlip(),
                         transforms.ToTensor(),
                         transforms.Normalize((0.5, 0.5, 0.5),
                                              (0.5, 0.5, 0.5))])), batch_size = 64)
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(in_channels = 3, out_channels = 8, kernel_size = 3, padding = 1, stride = 2)
        self.conv2 = nn.Conv2d(in_channels = 8, out_channels = 16, kernel_size = 3, padding = 1)
        self.conv3 = nn.Conv2d(in_channels = 16, out_channels = 32, kernel_size = 3, padding = 1)
        self.conv4 = nn.Conv2d(in_channels = 32, out_channels = 64, kernel_size = 3, padding = 1)
        self.pool = nn.MaxPool2d(kernel_size = 2, stride = 2)
        self.fc1 = nn.Linear(1 * 1 * 64, 64)
        self.fc2 = nn.Linear(64, 32)
        self.fc3 = nn.Linear(32, 10)

    def forward(self, x):
        x = self.conv1(x) # 32 * 32 * 3 -> 16 * 16 * 8
        x = F.tanh(x)     # 16 * 16 * 8
        x = self.pool(x)  # 8 * 8 * 8

        x = self.conv2(x) # 16 * 16 * 8 -> 16 * 16 * 16
        x = F.tanh(x)     # 16 * 16 * 16
        x = self.pool(x)  # 8  *  8 * 16

        x = self.conv3(x) # 8 * 8 * 16 -> 8 * 8 * 32
        x = F.tanh(x)     # 8 * 8 * 32
        x = self.pool(x)  # 4 * 4 * 32

        x = self.conv4(x) # 4 * 4 * 32 -> 4 * 4 * 64
        x = F.tanh(x)     # 4 * 4 * 64
        x = self.pool(x)  # 2 * 2 * 64

        x = x.view(-1, 1 * 1 * 64)
        x = self.fc1(x)
        x = F.tanh(x)
        x = self.fc2(x)
        x = F.tanh(x)
        x = self.fc3(x)
        x = F.log_softmax(x, dim = 1)
        return x


model = CNN().to(DEVICE)
optimizer = optim.Adam(model.parameters(), lr = 0.001)
print("DEVICE: ", DEVICE)
print("MODEL: ", model)
DEVICE:  cuda
MODEL:  CNN(
  (conv1): Conv2d(3, 8, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))
  (conv2): Conv2d(8, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (conv3): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (conv4): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (fc1): Linear(in_features=64, out_features=64, bias=True)
  (fc2): Linear(in_features=64, out_features=32, bias=True)
  (fc3): Linear(in_features=32, out_features=10, bias=True)
)
def train(model, train_loader, optimizer):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(DEVICE), target.to(DEVICE)
        optimizer.zero_grad()
        output = model(data)
        loss = F.cross_entropy(output, target)
        loss.backward()
        optimizer.step()

        if batch_idx % 100 == 0:
            print("Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}".format(
                epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item()))
def evaluate(model, test_loader):
    model.eval()

    test_loss = 0
    correct = 0

    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(DEVICE), target.to(DEVICE)
            output = model(data)
            test_loss += F.cross_entropy(output, target, reduction = "sum").item()
            prediction = output.max(1, keepdim = True)[1]
            correct += prediction.eq(target.view_as(prediction)).sum().item()

    test_loss /= len(test_loader.dataset)
    test_accuracy = 100. * correct / len(test_loader.dataset)
    return test_loss, test_accuracy
EPOCHS = 3
for epoch in range(1, EPOCHS + 1):
    train(model, train_loader, optimizer)
    test_loss, test_accuracy = evaluate(model, test_loader)
    print("[{}] Test Loss: {:.4f}, accuracy: {:.2f}%\n".format(epoch, test_loss, test_accuracy))
Train Epoch: 3 [0/50000 (0%)]	Loss: 1.320623
Train Epoch: 3 [6400/50000 (13%)]	Loss: 1.344092
Train Epoch: 3 [12800/50000 (26%)]	Loss: 1.440148
Train Epoch: 3 [19200/50000 (38%)]	Loss: 1.254739
Train Epoch: 3 [25600/50000 (51%)]	Loss: 1.224567
Train Epoch: 3 [32000/50000 (64%)]	Loss: 1.368665
Train Epoch: 3 [38400/50000 (77%)]	Loss: 1.217434
Train Epoch: 3 [44800/50000 (90%)]	Loss: 1.176838
[3] Test Loss: 1.2608, accuracy: 55.20%

파라메터 수 확인하는 방법 :

print("CNN's number of Parameters: ", sum([p.numel() for p in model.parameters()]))
CNN's number of Parameters:  31098

【Pytorch 실습】 AutoEncoder를 사용한, Fashion Mnist data를 활용

아래의 코드는 Kaggle 및 Git의 공개된 코드를 적극 활용한, 과거의 공부한 내용을 정리한 내용입니다.

Fashion MNIST train, test 데이터셋을 미리 다운로드 할 필요 없음. PS.

  1. jupyter 실행결과도 코드 박스로 출력되어 있습니다.
  2. matplot을 이용해서 이미지를 출력하는 이미지는 첨부하지 않았습니다.

1. Data 다운 받고 torch에 Load 하기.

# torchvision 모듈을 이용해서 데이터 셋을 다운 받을 것이다. 
import torch
from torchvision import transforms, datasets  
BATCH_SIZE = 64

trainset = datasets.FashionMNIST(
    root      = './data/FASHIONMNIST/', 
    train     = True,
    download  = True,
    transform = transforms.ToTensor()
)
train_loader = torch.utils.data.DataLoader(
    dataset     = trainset,
    batch_size  = BATCH_SIZE,
    shuffle     = True,
    num_workers = 2
)

2. 모델 설계하기

from torch import nn, optim

class AE(nn.Module):
    def __init__(self):
        super(AE, self).__init__()

        # 데이터 Feature 뽑기
        self.encoder = nn.Sequential(
            nn.Linear(28*28, 128),
            nn.ReLU(),
            nn.Linear(128, 64),
        )
        
        # Feature를 이용해서 데이터 확장 해보기
        self.decoder = nn.Sequential(
            nn.Linear(64, 128),
            nn.ReLU(),
            nn.Linear(128, 28*28),
        )

    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return encoded, decoded

USE_CUDA = torch.cuda.is_available()
DEVICE = torch.device("cuda" if USE_CUDA else "cpu")

model = AE().to(DEVICE)
optimizer = optim.Adam(model.parameters(), lr = 0.005)
criterion = nn.MSELoss()

print("Model: ", model)
print("Device: ", DEVICE)
Model:  AE(
  (encoder): Sequential(
    (0): Linear(in_features=784, out_features=128, bias=True)
    (1): ReLU()
    (2): Linear(in_features=128, out_features=64, bias=True)
  )
  (decoder): Sequential(
    (0): Linear(in_features=64, out_features=128, bias=True)
    (1): ReLU()
    (2): Linear(in_features=128, out_features=784, bias=True)
  )
)
Device:  cuda
# encoder decoder를 모두 통과한 후의 데이터를 출력해보기 위해서 다음과 같이 데이터 후처리
view_data = trainset.data[:5].view(-1, 28*28)
view_data = view_data.type(torch.FloatTensor) / 255.
# Definite Train & Evaluate
def train(model, train_loader, optimizer):
    model.train()
    for step, (x, label) in enumerate(train_loader):
        x = x.view(-1, 28 * 28).to(DEVICE)
        y = x.view(-1, 28 * 28).to(DEVICE)
        label = label.to(DEVICE)
        
        encoded, decoded = model(x)
        # AutoEncoder를 지나서 자기자신이 되도록 학습된다. 
        # loss값을 y와 'decoded를 정규화한 후'의 값과의 차이로 구했다면 더 좋았을 것 같다. 
        loss = criterion(decoded, y)  
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        if step % 100 == 0:
            print("Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}".format(epoch, step * len(x), len(train_loader.dataset), 100. * step / len(train_loader), loss.item()))

4. Train 시키기. Train 하면서 중간결과도 출력해보기

''' Training'''
import numpy as np
import matplotlib.pyplot as plt

EPOCHS = 10
for epoch in range(1, EPOCHS + 1):
    train(model, train_loader, optimizer)
    test_x = view_data.to(DEVICE)
    encoded_data, decoded_data = model(test_x)
    f, a = plt.subplots(2, 5, figsize = (10, 4))
    print("[Epoch {}]".format(epoch))

    # 원래 이미지의 사진 출력
    for idx in range(5):
        img = np.reshape(view_data.data.numpy()[idx], (28, 28))
        a[0][idx].imshow(img, cmap = "gray")
        a[0][idx].set_xticks(())
        a[0][idx].set_yticks(())
        
    # Encoder와 Decoder를 모두 통화한 후 사진 출력
    for idx in range(5):
        img = np.reshape(decoded_data.to("cpu").data.numpy()[idx], (28, 28))
        a[1][idx].imshow(img, cmap = "gray")
        a[1][idx].set_xticks(())
        a[1][idx].set_yticks(())
    plt.show()

5. 위에서 압축한 Feature를 가지고 Classification해보자!

  • encodered 데이터를 사용함으로 feature수가 작아지고, Classification 속도가 빨라짐을 알 수 있다.
  • 위에서는 Input과 동일한 Output을 만드는 Autoencoder를 설계했다.
  • 여기서는 Supervised Learnging을 할것이다. Fashion 옷의 Class가 뭔지 예측한다.
# 굳이 모델을 설계하지 않고도, lightgbm이라는 모듈을 사용해서 모델을 학습시킬 수 있다. 이런게 있구나.. 정도로만 알아두기.
# 여기서는 학습이 오래 걸린다. 

import time
import lightgbm as lgb
from sklearn.metrics import accuracy_score
start = time.time() 
lgb_dtrain = lgb.Dataset(data = trainset.train_data.view(-1, 28 * 28).numpy(), label = list(trainset.train_labels.numpy()))
lgb_param = {'max_depth': 10,
            'learning_rate': 0.001,
            'n_estimators': 20,
            'objective': 'multiclass',
            'num_class': len(set(list(trainset.train_labels.numpy()))) + 1}

num_round = 10000
lgb_model = lgb.train(params = lgb_param, num_boost_round = num_round, train_set = lgb_dtrain)              # 여기서 학습을 진행한다. 모델의 파라메터를 학습 완료!
lgb_model_predict = np.argmax(lgb_model.predict(trainset.train_data.view(-1, 28 * 28).numpy()), axis = 1)   # TestDataset은 없고, 그냥 Traindata로 Inference!
print("Accuracy: %.2f" % (accuracy_score(list(trainset.train_labels.numpy()), lgb_model_predict) * 100), "%") 
print("Time: %.2f" % (time.time() - start), "seconds")
c:\users\justin\venv\lib\site-packages\torchvision\datasets\mnist.py:53: UserWarning: train_data has been renamed data
  warnings.warn("train_data has been renamed data")
c:\users\justin\venv\lib\site-packages\torchvision\datasets\mnist.py:43: UserWarning: train_labels has been renamed targets
  warnings.warn("train_labels has been renamed targets")
c:\users\justin\venv\lib\site-packages\lightgbm\engine.py:148: UserWarning: Found `n_estimators` in params. Will use it instead of argument
  warnings.warn("Found `{}` in params. Will use it instead of argument".format(alias))


Accuracy: 82.84 %
Time: 19.64 seconds
# 여기서는 학습이 빨리 이뤄지는 것을 확인할 수 있다.
# 왜냐면, Encoder한 값, 즉 작은 Feature Map Data(784 -> 64)를 사용하기 때문이다.  
# 하지만 낮은 차원의 Feature를 이용해서 학습을 시키므로, 정확도가 떨어지는 것을 확인할 수 있다. 
 
train_encoded_x = trainset.train_data.view(-1, 28 * 28).to(DEVICE)
train_encoded_x = train_encoded_x.type(torch.FloatTensor)
train_encoded_x = train_encoded_x.to(DEVICE)
encoded_data, decoded_data = model(train_encoded_x) # 위에서 만든 모델로 추론한 결과를 아래의 학습에 사용한다! 
encoded_data = encoded_data.to("cpu")

start = time.time() 
lgb_dtrain = lgb.Dataset(data = encoded_data.detach().numpy(), label = list(trainset.train_labels.numpy()))
lgb_param = {'max_depth': 10,
            'learning_rate': 0.001,
            'n_estimators': 20,
            'objective': 'multiclass',
            'num_class': len(set(list(trainset.train_labels.numpy()))) + 1}

num_round = 10000
lgb_model = lgb.train(params = lgb_param, num_boost_round = num_round, train_set = lgb_dtrain)   # 여기서 학습을 진행한다. 모델의 파라메터를 학습 완료!
lgb_model_predict = np.argmax(lgb_model.predict(encoded_data.detach().numpy()), axis = 1)        # TestDataset은 없고, 그냥 Traindata로 Inference!
print("Accuracy: %.2f" % (accuracy_score(list(trainset.train_labels.numpy()), lgb_model_predict) * 100), "%") 
print("Time: %.2f" % (time.time() - start), "seconds") 
Accuracy: 76.07 %
Time: 1.96 seconds

【Pytorch 실습】 Mnist 데이터셋 MLP, CNN으로 학습 및 추론

Mnist 데이터 셋을 다운받고 pytorch를 사용해서 학습 및 추론을 합니다. 아래의 코드는 Kaggle 및 Git의 공개된 코드를 적극 활용한, 과거의 공부한 내용을 정리한 내용입니다.

train, test 파일 다운받는 경로 :
https://www.kaggle.com/oddrationale/mnist-in-csv

PS.

  1. jupyter 실행결과도 코드 박스로 출력되어 있습니다.
  2. matplot을 이용해서 이미지를 출력하는 이미지는 첨부하지 않았습니다.

MLP 이용하기

1. 데이터 로드하기

# Load Dataset
import pandas as pd
train_dataset = pd.read_csv("./mnist_train.csv")
test_dataset = pd.read_csv("./mnist_test.csv")
# Check Train Set
train_dataset.head()
# Split to Image & Label
train_images = (train_dataset.iloc[:, 1:].values).astype("float32")
train_labels = train_dataset["label"].values
test_images = (test_dataset.iloc[:, 1:].values).astype("float32")
# Check Train Data's Image
print(train_images)
[[0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 ...
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]]
# Check Train Data's Label
print(train_labels)
[5 0 4 ... 5 6 8]
# Check Test Data's Image
test_images
array([[0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]], dtype=float32)
# Split into Train, Valid Dataset 분리 비율은 8:2
from sklearn.model_selection import train_test_split
train_images, valid_images, train_labels, valid_labels = train_test_split(train_images,
                                                                          train_labels,
                                                                          stratify = train_labels,
                                                                          random_state = 42,
                                                                          test_size = 0.2)
# Check Train, Valid, Test Image's Shape
print("The Shape of Train Images: ", train_images.shape)
print("The Shape of Valid Images: ", valid_images.shape)
print("The Shape of Test Images: ", test_images.shape)
The Shape of Train Images:  (48000, 784)
The Shape of Valid Images:  (12000, 784)
The Shape of Test Images:  (10000, 784)
# Check Train, Valid Label's Shape
print("The Shape of Train Labels: ", train_labels.shape)
print("The Shape of Valid Labels: ", valid_labels.shape)
The Shape of Train Labels:  (38400,)
The Shape of Valid Labels:  (9600,)
# Reshape image's size to check for ours
train_images = train_images.reshape(train_images.shape[0], 28, 28)
valid_images = valid_images.reshape(valid_images.shape[0], 28, 28)
test_images = test_images.reshape(test_images.shape[0], 28, 28)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-18-f37841568d28> in <module>
      2 train_images = train_images.reshape(train_images.shape[0], 28, 28)
      3 valid_images = valid_images.reshape(valid_images.shape[0], 28, 28)
----> 4 test_images = test_images.reshape(test_images.shape[0], 28, 28)


ValueError: cannot reshape array of size 7850000 into shape (10000,28,28)
# Check Train, Valid, Test Image's Shape after reshape
print("The Shape of Train Images: ", train_images.shape)
print("The Shape of Valid Images: ", valid_images.shape)
print("The Shape of Test Images: ", test_images.shape)
The Shape of Train Images:  (38400, 28, 28)
The Shape of Valid Images:  (9600, 28, 28)
The Shape of Test Images:  (10000, 785)
# Visualize Train, Valid, Test's Images
import matplotlib.pyplot as plt
for idx in range(0, 5):
    plt.imshow(train_images[idx], cmap = plt.get_cmap('gray'))
    plt.title(train_labels[idx])
    plt.show()
for idx in range(0, 5):
    plt.imshow(valid_images[idx], cmap = plt.get_cmap('gray'))
    plt.title(valid_labels[idx])
    plt.show()
for idx in range(0, 5):
    plt.imshow(test_images[idx], cmap = plt.get_cmap('gray'))
    plt.show()

2. Torch를 이용한 데이터 로드, 모델 생성

지금까지 로드한 데이터를 torch.tensor형태로 데이터를 변환해준다.

# Make Dataloader to feed on Multi Layer Perceptron Model
# train과 test 셋을 batch 단위로 데이터를 처리하기 위해서. _loader를 정의 해준다.
import torch
from torch.utils.data import TensorDataset, DataLoader
train_images_tensor = torch.tensor(train_images)
train_labels_tensor = torch.tensor(train_labels)
train_tensor = TensorDataset(train_images_tensor, train_labels_tensor)
train_loader = DataLoader(train_tensor, batch_size = 64, num_workers = 0, shuffle = True)

valid_images_tensor = torch.tensor(valid_images)
valid_labels_tensor = torch.tensor(valid_labels)
valid_tensor = TensorDataset(valid_images_tensor, valid_labels_tensor)
valid_loader = DataLoader(valid_tensor, batch_size = 64, num_workers = 0, shuffle = True)

test_images_tensor = torch.tensor(test_images)
# Create Multi Layer Perceptron Model
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()
        self.input_layer = nn.Linear(28 * 28, 128)
        self.hidden_layer = nn.Linear(128, 128)
        self.output_layer = nn.Linear(128, 10)

    def forward(self, x):
        x = x.view(-1, 28 * 28)
        x = F.relu(self.input_layer(x))
        x = F.relu(self.hidden_layer(x))
        x = self.output_layer(x)
        x = F.log_softmax(x, dim = 1)
        return x

USE_CUDA = torch.cuda.is_available()
DEVICE = torch.device("cuda" if USE_CUDA else "cpu")

model = MLP().to(DEVICE)
optimizer = optim.Adam(model.parameters(), lr = 0.001)  # optimization 함수 설정

print("Model: ", model)
print("Device: ", DEVICE)
Model:  MLP(
  (input_layer): Linear(in_features=784, out_features=128, bias=True)
  (hidden_layer): Linear(in_features=128, out_features=128, bias=True)
  (output_layer): Linear(in_features=128, out_features=10, bias=True)
)
Device:  cpu

3. 여기까지 모델 설계. 이제 학습 시작

# Definite Train & Evaluate
# 이제 학습키자!
def train(model, train_loader, optimizer):
    model.train()  # "나 모델을 이용해서 학습시킬게! 라는 의미"
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(DEVICE), target.to(DEVICE)
        optimizer.zero_grad()
        output = model(data)
        loss = F.cross_entropy(output, target)  # criterion
        loss.backward()
        optimizer.step()

        if batch_idx % 100 == 0:
            print("Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}".format(epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item()))

def evaluate(model, valid_loader):
    model.eval()  # "나 모델을 이용해서 학습시킬게! 라는 의미"
    valid_loss = 0  # just Loss를 확인하기 위해서.
    correct = 0

    with torch.no_grad():
        for data, target in valid_loader:
            data, target = data.to(DEVICE), target.to(DEVICE)
            output = model(data)
            valid_loss += F.cross_entropy(output, target, reduction = "sum").item()
            prediction = output.max(1, keepdim = True)[1]
            correct += prediction.eq(target.view_as(prediction)).sum().item()

    valid_loss /= len(valid_loader.dataset)
    valid_accuracy = 100. * correct / len(valid_loader.dataset)
    return valid_loss, valid_accuracy
''' Training'''
EPOCHS = 10
for epoch in range(1, EPOCHS + 1):
    train(model, train_loader, optimizer)
    valid_loss, valid_accuracy = evaluate(model, valid_loader)
    print("[EPOCH: {}], \tValidation Loss: {:.4f}, \tValidation Accuracy: {:.2f} %\n".format(epoch, valid_loss, valid_accuracy))
Train Epoch: 9 [0/38400 (0%)]	Loss: 0.005890
Train Epoch: 9 [6400/38400 (17%)]	Loss: 0.054453
Train Epoch: 9 [12800/38400 (33%)]	Loss: 0.017136
Train Epoch: 9 [19200/38400 (50%)]	Loss: 0.004437
Train Epoch: 9 [25600/38400 (67%)]	Loss: 0.150551
Train Epoch: 9 [32000/38400 (83%)]	Loss: 0.177758
[EPOCH: 9], 	Validation Loss: 0.2030, 	Validation Accuracy: 95.92 %

Train Epoch: 10 [0/38400 (0%)]	Loss: 0.075817
Train Epoch: 10 [6400/38400 (17%)]	Loss: 0.075776
Train Epoch: 10 [12800/38400 (33%)]	Loss: 0.010031
Train Epoch: 10 [19200/38400 (50%)]	Loss: 0.056201
Train Epoch: 10 [25600/38400 (67%)]	Loss: 0.056001
Train Epoch: 10 [32000/38400 (83%)]	Loss: 0.103519
[EPOCH: 10], 	Validation Loss: 0.2131, 	Validation Accuracy: 95.54 %

4. Test 하고 Test 결과를 출력해보자.

# Predict Test Dataset
# Validation 과 Test 같은 경우에 다음과 같이 torch.no_grad를 꼭 사용하니 참고하자.
def testset_prediction(model, test_images_tensor):
    model.eval()  # test모드 아니고, validation모드를 사용한다.
    result = []
    with torch.no_grad():
        for data in test_images_tensor:
            data = data.to(DEVICE)
            output = model(data)
            prediction = output.max(1, keepdim = True)[1]
            result.append(prediction.tolist())
    return result
test_predict_result = testset_prediction(model, test_images_tensor)
test_predict_result[:5]
[[[7]], [[2]], [[1]], [[0]], [[4]]]
import numpy as np
from collections import Counter
Counter(np.squeeze(test_predict_result)).most_common()
[(1, 1139),
 (3, 1115),
 (9, 1113),
 (7, 991),
 (0, 979),
 (8, 959),
 (6, 949),
 (4, 938),
 (2, 934),
 (5, 883)]
for idx in range(0, 10):
    plt.imshow(test_images[idx], cmap = plt.get_cmap('gray'))
    plt.title("Predict: " + str(test_predict_result[idx]))
    plt.show()

CNN 이용하기

1. Data Load 하기

# Load Dataset
import pandas as pd
train_dataset = pd.read_csv("./Mnist_train.csv")
test_dataset = pd.read_csv("./Mnist_test.csv")
# Check Train Set
train_dataset.head()
# Split to Image & Label
train_images = (train_dataset.iloc[:, 1:].values).astype("float32")
train_labels = train_dataset["label"].values
test_images = (test_dataset.values).astype("float32")
# Check Train Data's Image 
train_images
array([[0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]], dtype=float32)
# Check Train Data's Label
train_labels
array([1, 0, 1, ..., 7, 6, 9], dtype=int64)
# Check Test Data's Image
test_images
array([[0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]], dtype=float32)
# Split into Train, Valid Dataset
from sklearn.model_selection import train_test_split
train_images, valid_images, train_labels, valid_labels = train_test_split(train_images, 
                                                                          train_labels, 
                                                                          stratify = train_labels, 
                                                                          random_state = 42, 
                                                                          test_size = 0.2)
# Check Train, Valid, Test Image's Shape
print("The Shape of Train Images: ", train_images.shape)
print("The Shape of Valid Images: ", valid_images.shape)
print("The Shape of Test Images: ", test_images.shape)
The Shape of Train Images:  (33600, 784)
The Shape of Valid Images:  (8400, 784)
The Shape of Test Images:  (28000, 784)
# Check Train, Valid Label's Shape
print("The Shape of Train Labels: ", train_labels.shape)
print("The Shape of Valid Labels: ", valid_labels.shape)
The Shape of Train Labels:  (33600,)
The Shape of Valid Labels:  (8400,)
# Reshape image's size to check for ours
train_images = train_images.reshape(train_images.shape[0], 28, 28)
valid_images = valid_images.reshape(valid_images.shape[0], 28, 28)
test_images = test_images.reshape(test_images.shape[0], 28, 28)
# Check Train, Valid, Test Image's Shape after reshape
print("The Shape of Train Images: ", train_images.shape)
print("The Shape of Valid Images: ", valid_images.shape)
print("The Shape of Test Images: ", test_images.shape)
The Shape of Train Images:  (33600, 28, 28)
The Shape of Valid Images:  (8400, 28, 28)
The Shape of Test Images:  (28000, 28, 28)
# Visualize Train, Valid, Test's Images
import matplotlib.pyplot as plt
for idx in range(0, 5):
    plt.imshow(train_images[idx], cmap = plt.get_cmap('gray'))
    plt.title(train_labels[idx])
    plt.show()
for idx in range(0, 5):
    plt.imshow(valid_images[idx], cmap = plt.get_cmap('gray'))
    plt.title(valid_labels[idx])
    plt.show()
for idx in range(0, 5):
    plt.imshow(test_images[idx], cmap = plt.get_cmap('gray'))
    plt.show()
# Make Dataloader to feed on Multi Layer Perceptron Model
import torch
from torch.utils.data import TensorDataset, DataLoader
train_images_tensor = torch.tensor(train_images)
train_labels_tensor = torch.tensor(train_labels)
train_tensor = TensorDataset(train_images_tensor, train_labels_tensor)
train_loader = DataLoader(train_tensor, batch_size = 64, num_workers = 0, shuffle = True)

valid_images_tensor = torch.tensor(valid_images)
valid_labels_tensor = torch.tensor(valid_labels)
valid_tensor = TensorDataset(valid_images_tensor, valid_labels_tensor)
valid_loader = DataLoader(valid_tensor, batch_size = 64, num_workers = 0, shuffle = True)

test_images_tensor = torch.tensor(test_images)

2. 모델 생성

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

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size = 5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size = 5)
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)

    def forward(self, x):
        x = x.view(-1, 1, 28, 28)
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2(x), 2))
        x = x.view(-1, 320)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        x = F.log_softmax(x)
        return x

USE_CUDA = torch.cuda.is_available()
DEVICE = torch.device("cuda" if USE_CUDA else "cpu")

model = CNN().to(DEVICE)
optimizer = optim.Adam(model.parameters(), lr = 0.001)

print("Model: ", model)
print("Device: ", DEVICE)
Model:  CNN(
  (conv1): Conv2d(1, 10, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(10, 20, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=320, out_features=50, bias=True)
  (fc2): Linear(in_features=50, out_features=10, bias=True)
)
Device:  cuda

3. 학습

# Definite Train & Evaluate
def train(model, train_loader, optimizer):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(DEVICE), target.to(DEVICE)
        optimizer.zero_grad()
        output = model(data)
        loss = F.cross_entropy(output, target)
        loss.backward()
        optimizer.step()
        
        if batch_idx % 100 == 0:
            print("Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}".format(epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item()))

def evaluate(model, valid_loader):
    model.eval()
    valid_loss = 0
    correct = 0

    with torch.no_grad():
        for data, target in valid_loader:
            data, target = data.to(DEVICE), target.to(DEVICE)
            output = model(data)
            valid_loss += F.cross_entropy(output, target, reduction = "sum").item()
            prediction = output.max(1, keepdim = True)[1]
            correct += prediction.eq(target.view_as(prediction)).sum().item()

    valid_loss /= len(valid_loader.dataset)
    valid_accuracy = 100. * correct / len(valid_loader.dataset)
    return valid_loss, valid_accuracy
''' Training'''
EPOCHS = 10
for epoch in range(1, EPOCHS + 1):
    train(model, train_loader, optimizer)
    valid_loss, valid_accuracy = evaluate(model, valid_loader)
    print("[EPOCH: {}], \tValidation Loss: {:.4f}, \tValidation Accuracy: {:.2f} %\n".format(epoch, valid_loss, valid_accuracy))
Train Epoch: 9 [0/33600 (0%)]	Loss: 0.039682
Train Epoch: 9 [6400/33600 (19%)]	Loss: 0.002007
Train Epoch: 9 [12800/33600 (38%)]	Loss: 0.041496
Train Epoch: 9 [19200/33600 (57%)]	Loss: 0.047618
Train Epoch: 9 [25600/33600 (76%)]	Loss: 0.001618
Train Epoch: 9 [32000/33600 (95%)]	Loss: 0.191500
[EPOCH: 9], 	Validation Loss: 0.0745, 	Validation Accuracy: 98.02 %

Train Epoch: 10 [0/33600 (0%)]	Loss: 0.007429
Train Epoch: 10 [6400/33600 (19%)]	Loss: 0.077467
Train Epoch: 10 [12800/33600 (38%)]	Loss: 0.007383
Train Epoch: 10 [19200/33600 (57%)]	Loss: 0.009296
Train Epoch: 10 [25600/33600 (76%)]	Loss: 0.054614
Train Epoch: 10 [32000/33600 (95%)]	Loss: 0.032034
[EPOCH: 10], 	Validation Loss: 0.0807, 	Validation Accuracy: 98.23 %

4. 추론

# Predict Test Dataset
def testset_prediction(model, test_images_tensor):
    model.eval()
    result = []
    with torch.no_grad():
        for data in test_images_tensor:
            data = data.to(DEVICE)
            output = model(data)
            prediction = output.max(1, keepdim = True)[1]
            result.append(prediction.tolist())
    return result
test_predict_result = testset_prediction(model, test_images_tensor)
test_predict_result[:5]
c:\users\justin\venv\lib\site-packages\ipykernel_launcher.py:21: UserWarning: Implicit dimension choice for log_softmax has been deprecated. Change the call to include dim=X as an argument.





[[[2]], [[0]], [[9]], [[9]], [[3]]]
import numpy as np
from collections import Counter
Counter(np.squeeze(test_predict_result)).most_common()
[(1, 3176),
 (7, 2910),
 (3, 2872),
 (2, 2803),
 (9, 2801),
 (4, 2781),
 (0, 2725),
 (8, 2718),
 (6, 2716),
 (5, 2498)]
for idx in range(0, 10):
    plt.imshow(test_images[idx], cmap = plt.get_cmap('gray'))
    plt.title("Predict: " + str(test_predict_result[idx]))
    plt.show()

【캡스톤1】 자율주행 RC카 만들기

캡스톤 수업을 위한 rpLidar + 라즈베리파이 기본 설정하기

캡스톤 수업을 위한 rpLidar + 라즈베리파이 기본 설정하기 1

1. REFERENCE

  1. 로스 패키지 구동 네이버 블로그

  2. 로스란? 아두이노란? 아두이노에 Lidar데이터를 가져오는 코드는 여기에

  3. ROS 홈페이지에서 rplidar를 검색했을 때 나오는 코드 목록

    image-20200524194150672

  4. 라이더 드라이버 로스 패키지 목록 (위의 3개 하나하나)

    1. rplidar (distros = kinetic, melodic)
    2. rplidar driver in python (distros = indigo, jade)
    3. rplidar_ros - 2016년 버전이라 읽을 글 많이 없음
  5. RPLIDAR and ROS programming - 블로그 설명

  6. ROS and Hector SLAM - 블로그 설명

  7. RPLidar_Hector_SLAM - 깃 코드


2. 읽은 내용 정리하기

Reference 읽기 순서 : 4.1 -> 5 -> 6 -> 7

(1) Ref 4.1 : rplidar

차례
1. Overview
2. ROS Nodes
   - rplidarNode
      - Published Topics
      - Services
      - Parameters
3. Device Settings
4. Launch File Examples
5. About Slamtec/RoboPeak
6. Distributor Links
7. Related Links
  1. Overview

    rplidar에 대한 기본적 설명. sensor_msgs/LaserScan형식 구조체의 메세지를 publish

    SLAM based on RPLIDAR and ROS Hector Mapping 동영상 속 ROS Hector

  2. ROS Nodes

    • rplidarNode - RPLIDAR 스캔 결과를 로스 메세지 형태로 publish하는 노드

      • Published Topics

        • ‘scan’ : 스캔된 데이터의 메세지
      • Services

        • start_motor, stop_motor 모터의 시작과 중지를 관리하는 서비스
      • Parameters

        • ```sh
          1. Parameter이름 (자료형, default 값)
          2. serial_port (string, default: /dev/ttyUSB0) serial port name used in your system.
          3. serial_baudrate (int, default: 115200) serial port baud rate.
          4. frame_id (string, default: laser_frame) frame ID for the device.
          5. inverted (bool, default: false) indicated whether the LIDAR is mounted inverted.뒤집혔나
          6. angle_compensate (bool, default: false) indicated whether the driver needs do angle compensation. 각도 보상 필요?
          7. scan_mode (string, default: std::string()) the scan mode of lidar. ```
  3. Device Setting

    • rplidar tutorial - rplidar-ros/wiki
      • rplidar basic document
      • rplidar sdk - slamtec에서 재공해 줌 - SDK Git Code과 연결됨
      • 위의 Ref1에서 봤던 내용이 좀더 간략히 나와 있다. 코드 실행 순서.. image-20200524204312223
      • 이 사진과 같이 라이더를, 자동차에 해야한다. theta와 d가 publish되는 메세지값에 나타나는 듯 하다.
      • remap the USB serial port name 했을 때의 방법도 나온다. 이건 건들지 말자.
  4. Launch File Examples

    $ ls -l /dev |grep ttyUSB
    $ sudo chmod 666 /dev/ttyUSB0
    1.
    $ roslaunch rplidar_ros view_rplidar.launch    #for rplidar A1/A2
    2. 
    $ roslaunch rplidar_ros rplidar.launch
    $ rosrun rplidar_ros rplidarNodeClient
    

Ref 4.1.1 rplidar_ros 내용은 위의 rplidar tutorial 내용과 동일

(2) Ref 5 : RPLIDAR and ROS programming



3. 프로젝트 완수(중간과정 생략…)

안정적으로 프로젝트를 완수 했다.

  • 완성된 RC카 이미지.
    image

완성한 프로젝트의 소스코드는 깃에 Private로 저장해 두었다. (수업 과제이다 보니 공개적으로 오픈해두는 것은 좋지 않을 것 같아서…)

  • 나름 만족스러운 결과를 얻을 수 있어서 뿌듯하고 보람찼던 경험이었다.^^

【Python-Module】 argparse/yaml/logging python 모듈 공부 내용 정리

(위성Segment) argparse/yaml/logging python 모듈 공부 내용 정리 pytorch-semseg코드를 공부하면서 앞으로 계속 나오게 될 argparse/yaml 에 대해서 공부하고 정리한 내용을 기록해 놓는다.

참고 페이지 : https://github.com/meetshah1995/pytorch-semseg/issues/188

  1. http://host.robots.ox.ac.uk/pascal/VOC/voc2012/index.html#data
  2. http://home.bharathh.info/pubs/codes/SBD/download.html

1. Referece for argparse

  1. http://blog.naver.com/PostView.nhn?blogId=cjh226&logNo=220997049388&parentCategoryNo=&categoryNo=17&viewDate=&isShowPopularPosts=false&from=section
  2. https://greeksharifa.github.io/references/2019/02/12/argparse-usage/
  3. https://brownbears.tistory.com/413

첫번쩨 Reference 공부내용 정리

  • arg+parse = argument(parameter) + parsing
# 예제코드
from __future__ import print_function
import argparse

def main():
	parser = argparse.ArgumentParser(description='This code is written for practice about argparse')
	parser.add_argument('X', type=float,
			metavar='First_number',
			help='What is the first number?')
	parser.add_argument('Y', type=float,
			metavar='Second_number',
			help='What is the second number?')
	parser.add_argument('--op', type=str, default='add',
			choices=['add','sub','mul','div'],
			help='What operation?')
	args = parser.parse_args()
	
	X = args.X
	Y = args.Y
	op = args.op
	print(calc(X,Y,op))

def calc(x, y, op):
	if op == 'add':
		return x + y
	elif op == 'sub':
		return x - y
	elif op == 'mul':
		return x * y
	elif op == 'div':
		return x / y

if __name__=="__main__":
	main()
  1. 기초 코드
    • argparse.ArgumentParser함수를 통해 parser를 생성한다.
    • parser.add_argument를 이용하여 입력받고자 하는 인자의 조건을 설정한다
    • parser.parse_args 함수를 통해 인자들을 파싱하여 args에 저장한다. 각 인자는 add_argument의 type에 지정된 형식으로 저장된다
  2. parser.add_argument에 들어갈 수 있는 옵션
    • type/ default/ choices/ help 등등
    • 여기서 choices를 사용함으로써 help에서 어떤 옵션이 가능한지 보여준다.
    • metavar는 필수 인자를 입력하지 않았을 때, 그 자리 변수가 무엇인지에 대한 이름이다.
    • nargs=’+’를 사용함으로써, 여러개의 (제한 없음) 변수를 리스트로 받을 수 있다.
  3. parser.parse_args()로 정의된 객체 args 사용방법
    • X = args.X // Y = args.Y
    • op = args.op 에서 처럼 –[]라고 add_argument를 했다면, args.[]라고 사용가능하다.

두번쨰 Reference 공부내용 정리

  1. 위의 기초 코드 3개 중, ArgumentParseradd_argument에 사용가능한 메소드들이 잘 정리되어 있다.
  2. image

세번쨰 Reference 공부내용 정리

  • 지금까지 한 것보다 조금 더 심화된 내용이 설명되어 있다.
  • 이 정도는 필요할 때마다 찾아보기로 하자.

2. Referece for yaml

  1. https://itholic.github.io/python-yaml/
  2. https://teeeeeeemo.tistory.com/39
  3. https://junho85.pe.kr/1451

기본 사용방법은 매우 간단하다.

  1. 이와 같은 파일이 있다고 치자

    # /home/info/yaml
    language: python
    test: pytes
    
  2. 이렇게 py파일에서 쓰면 된다.

    import yaml
       
    with open('info.yaml') as f:
        cfg = yaml.load(f)
       
       
    language = conf['language']
    test = cfg['pytest']
    

    즉, yaml 모듈의 load함수를 통해서 conf를 dictionary 객체로 만들어 준다.

  3. 추가 사용법

    • 모르겠으면 우선 yaml파일을 가져오고, type과 같은 함수를 이용해서 내가 가지고 있는 yaml.load로 선언한 객체에 대한 분석을 해보자.

    • 코드 예제

      # yaml 파일
      yaml_str = """
      Date: 2017-08-08
      ChampionList:
      - champion_id: 1000
       name: Teemo
       position: top
       skill: ap
      - champion_id: 1001
       name: Vayne
       position: bottom
       skill: ad
      - champion_id: 1002
       name: Ahri
       position: mid
       skill: ap
      """
           
      # .py 파일 내부 코드
      import yaml
           
      cfg = yaml.load(yaml_str)
      for champion in cfg['ChampionList']:
      	print(champion["name"], champion["skill"])
           
      

3. Reference for logging

  1. https://ourcstory.tistory.com/97
  2. https://minimin2.tistory.com/41
  3. https://snowdeer.github.io/python/2017/11/17/python-logging-example/

<기본사용법>

  1. 로그 출력을 위한 logging 모듈을 제공합니다. 아주 간단히 사용할 수 있으며, print 함수 등을 통해 콘솔창에 지저분하게 출력하는 것보다 logging 모듈을 사용하는 것을 추천한다. 콘솔창과 파일에 동시에 로그 남기는 것이 가능하다.

  2. 로그를 콘솔에도 출력하고 싶고, 파일에도 동시에 남기고 싶다면 아래와 같이 fileHandler, streamHandler를 생성해서 logger에 Handler를 추가해주면 된다

  3. 로그 포매팅이라고 하면, 내가 로그를 남길때 앞에 쓰여지는 형식의 포맷을 정하는 것을 말한다 로그 포매팅 : %(log_name)s 를 사용하고 중간에 문자를 자유롭게 첨가

    import logging
    import logging.handlers
       
    # logger 인스턴스를 생성 및 로그 레벨 설정
    logger = logging.getLogger("crumbs")
    logger.setLevel(logging.DEBUG)
       
    # formmater 생성 <***adding***>
    formatter = logging.Formatter('[%(levelname)s|%(filename)s:%(lineno)s] %(asctime)s > %(message)s')
       
    # fileHandler와 StreamHandler를 생성
    fileHandler = logging.FileHandler('./log/my.log')
    streamHandler = logging.StreamHandler()
       
    # handler에 fommater 세팅 <***adding***>
    fileHandler.setFormatter(formatter)
    streamHandler.setFormatter(formatter)
       
    # Handler를 logging에 추가
    logger.addHandler(fileHandler)
    logger.addHandler(streamHandler)
       
    # logging
    logger.debug("debug")
    logger.info("info")
    logger.warning("warning")
    logger.error("error")
    logger.critical("critical")
       
    '''
    출력결과
    [DEBUG|input.py:24] 2016-05-20 10:37:06,656 > debug
    [INFO|input.py:25] 2016-05-20 10:37:06,657 > info
    [WARNING|input.py:26] 2016-05-20 10:37:06,657 > warning
    [ERROR|input.py:27] 2016-05-20 10:37:06,657 > error
    [CRITICAL|input.py:28] 2016-05-20 10:37:06,657 > critical
    
  4. 다른 코드를 통해 좀 더 알아보자. setLevel(logging.DEBUG) -> setLevel(logging.INFO)

    import logging
       
    # 로그 생성
    logger = logging.getLogger()
       
    # 로그의 출력 기준 설정
    logger.setLevel(logging.INFO)
       
    # log 출력 형식 기본 포맷 
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
       
    # log 출력
    stream_handler = logging.StreamHandler()
    stream_handler.setFormatter(formatter)
    logger.addHandler(stream_handler)
       
    # log를 파일에 출력
    file_handler = logging.FileHandler('my.log')
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)
       
    for i in range(10):
    logger.info(f'{i}번째 방문입니다.')
    

【위성Segment】 Segmentation 공부할 코드 사이트 정리

공부할 코드를 찾아보고, 안 내용을 기록해 놓았습니다.

(위성Segment) Segmentation 공부할 코드 사이트 정리

1. 전체 Segmentation Models 정리 GIT

  1. semantic-segmentation-pytorch

    (3.2 star) 난이도 4.5 / PPM PSP Uper HRNet 같은 최신 Segmentation 코드

  2. pytorch-semseg

    (2.6 star) 난이도 3 / FCN PSP U-Net 같은 기초+좋은 코드와 DataLoaders가 있다. Config 만드는 것이 필수

  3. segmentation_models.pytorch

    (1.6 star) 난이도 5 / pip install로 Segmentation을 수행할 수 있다. UNet PSP DeepLabv3

  4. awesome-semantic-segmentation-pytorch

    (1.1 star) 난이도 2 / Segmentation 모델들 정말 많다. But 대부분 중요한것 아님..

따라서 나는 2번의 코드를 공부해보기로 결정했다. 하는 김에 전체 코드를 잘근잘근 씹어먹자

2. Pytorch-semseg GIT 내부 내용 정리

segmentation_models.pytorch에 구현되어 있는 코드들을 간략히 설명해주는 이 사이트를 공부한 내용을 아래에 정리해 놓는다.

<전체 목차>
1. Segmentation, Pytorch란?
2. FCN
3. SegNet
4. U-Net
5. DenseNet
6. E-Net & Link-Net
7. Mask-RCNN
8. PSP-Net
9. RefineNet
10. G-FR-Net
11. DeCoupleNet
12. GAN-Approach
13. Dataset

1. Segmentation, Pytorch란?


3.pytorch-semseg 돌려보기

  1. pip install -r requirements.txt
  2. Pascal voc를 FCN8을 통해서 돌려보기

【Paper】 Semantic Segmentation for AutoDriving/ 공부 계획 및 모델 핵심 정리

Image Segmentation for Autonomous Driving 논문 리뷰 및 정리

(위성Segment) Segmentation for Autonomous Driving 논문 정리 논문 원본 : 2019 (cite:10) A Brief Survey and an Application of Semantic Image Segmentation for Autonomous Driving

1. 논문 필기 및 정리 자료 다운로드 링크

2. 논문 전체 요약

  • 이 논문에서는 deep learning이 무엇이고 CNN이 무엇인지에 대한 아주 기초적인 내용들이 들어가 있다. 이미 알고 있는 내용들이라면 매우 쉬운 논문이라고 할 수 있다.
  • FCN에 대한 소개를 해주고, a virtual city Image인 SYNTHIA-Rand-CVPR16 Dataset을 사용해, FCN-AlexNet, FCN-8s, FCN-16s and FCN-32s 이렇게 4가지 모델에 적용해 본다.
  • 결론 :
    1. Maximum validation accuracies of 92.4628%, 96.015%, 95.4111% and 94.2595% are achieved with FCN-AlexNet, FCN-8s, FCN-16 and FCN-32s models
    2. Training times는 FCN-AlexNet이 다른 모델들에 비해 1/4시간이 걸릴 만큼 학습시간이 매우 짧다. 하지만 우리에게 중요한 것은 inference시간이므로, the most suitable model for the application is FCN-8s.
    3. 각 모델들에 대한 inference 시간 비교는 논문에서 해주지 않는다.

3. 앞으로 추가 공부 계획

4. 면접 준비 - 딥러닝 모델 핵심 정리

각 모델별 핵심 용어 정리(논문 level2 정도로만 읽은 상태. 빠르게 Skip. 핵심만 파악)

  1. 코드는 직접만드는 것보다는, 이미 만들어진 코드들을 수정하고 참고
    • FPN : bottomup[bottleNet+resnet], topdown[ upsample, leteral connection(sum)]
    • ResNet : self.shortcut = nn.sequential(); out += self.shortcut(input)
    • vgg : 신경망은 매우 간단. data, criterion, optimizer. zero_grad -> loss -> backword -> opti.step
  2. DQN – Q learning, Fixed Target Network, Experience Replay memory
  3. FPN – Bottom-up, Top-down, lateral-connection, multi-scale-detection
  4. Fast-RCNN – Selective search, ROI pooling, Bounding Box Regression
  5. Faster-RCNN – RPN(anchor개념을 사용해서 각 grid마다 객체의 유무/ Box location 정보를 뽑아낸다. RPN의 Loss function도 따로 있다. 객체유무/ Box coordinate 차이), 9개 anchor.
  6. FCN – FCN32 ->(upsampling) FCN16
  7. Mask-RCNN – Align pooling(각 픽셀 4등분+weighted sum), Binary Cross Entropy, 마지막단 FCN, Multi training(keypoint Detection), 최초 Instacne Segmentation
  8. DeepLab – Dilated Con(global fearture/contexts), CRP(Posterior, Energy), ASPP(atrous spatial pyramid pooling)
  9. PSPNet – Pyramid Pooing layer, concatenate
  10. ParsNet – Global context information, Global pooling,
  11. SegNet – Encoder/Decoder, maxpooling index
  12. HRNet – high resolution, low resolution의 information Exchange. BackboneNetwork
  13. Panotic-Network (PA-Net) – FPN + mask+rcnn
  14. Dilated Conv – 추가 비용없이, receptive field 확장
  15. RNN, LSTM, Attention, GAN 개념 사용 가능
  16. CRF – Posterior를 최대화하고 Energy를 최소화한다.
    Energy는 위치가 비슷하고 RGB가 비슷한 노드사이에서 라벨이 서로 다른것이라고 하면 Panalty를 부과함으로써 객체의 Boundary를 더 정확하게 찾으려고 하는 노력입니다.
    Energy공식에 비용이 너무 많이 들어서 하는 작업이 mean field approximation이라고 합니다.
  17. Yolo – 1stage detector, cheaper grid, 7730(5+5+20), confidence낮음버림, NMS -> Class 통합
  18. SSD – Anchor, 다양한 크기 객체, 작은 -> 큰 물체, Detector&classifier(3개 Anchor, locallization(x,y,w,h), class-softMax결과(20+1(배경)) ), NMS

【Algorithm】 게임 맵 최단거리 - 카카오 문제

프로그래머스 게임 맵 최단거리 알고리즘 풀이

문제링크 : 게임 맵 최단거리
주석을 참고해서 코드 이해에 도움을 받으시길 바랍니다.

image

from collections import deque

def bfs(start, maps):
    dirs = [(0,1),(1,0),(0,-1),(-1,0)]
    queue = deque()                     # https://excelsior-cjh.tistory.com/96
    queue.append(start)
    while queue:                        # 빈 list, 빈 que는 False가 된다.
        y, x, cnt = queue.popleft()
        maps[y][x] = 0                  # Point! 이미 방문한 곳 처리는 벽으로 만들어 버린다!
        for dy, dx in dirs:
            ny, nx = y + dy, x + dx
            # BFS를 사용하므로, 가장 처음 발견하면, 그 cnt를 return하면 된다.
            if ny == len(maps)-1 and nx == len(maps[0])-1:
                return cnt + 1

            # 빈 공간을 만났다면,
            elif 0 <= ny < len(maps) and 0 <= nx < len(maps[0]) and maps[ny][nx] == 1: 
                maps[ny][nx] = 0
                queue.append((ny, nx, cnt+1))
    return -1

def solution(maps):
    # 첫 위치는, map[0][0]이며, count=1로 시작한다. 
    return bfs((0,0,1), maps) 

Pagination


© All rights reserved By Junha Song.