댑덥딥 6주차 정리
Tags: ai, deeplearning, 스터디, 모두를위한딥러닝시즌2
Published: 2023-12-28 10:59:13

> '모두를 위한 딥러닝 시즌 2' 강의를 듣고 공부하는 스터디 입니다. https://deeplearningzerotoall.github.io/season2/lec_tensorflow.html
> 

---

***비대면 17 May, 2023***
# 10-2 mnist cnn

### [총정리]

1. 라이브러리 가져오기

```python
# Lab 11 MNIST and Convolutional Neural Network
import torch
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import torch.nn.init
```

2. gpu 사용 설정

```python
device = 'cuda' if torch.cuda.is_available() else 'cpu'

# for reproducibility
torch.manual_seed(777)
if device == 'cuda':
    torch.cuda.manual_seed_all(777)
```

3. 학습에 사용되는 parameter 설정

```python
# parameters
learning_rate = 0.001
training_epochs = 15
batch_size = 100
```

4. 데이터셋 가져오고 loader 만들기

```python
# MNIST dataset
mnist_train = dsets.MNIST(root='MNIST_data/',
                          train=True,
                          transform=transforms.ToTensor(),
                          download=True)

mnist_test = dsets.MNIST(root='MNIST_data/',
                         train=False,
                         transform=transforms.ToTensor(),
                         download=True)
```

```python
# dataset loader
data_loader = torch.utils.data.DataLoader(dataset=mnist_train,
                                          batch_size=batch_size,
                                          shuffle=True,
                                          drop_last=True)
```

5. 학습 모델 만들기(torch.nn.module)

```python
# CNN Model (2 conv layers)
class CNN(torch.nn.Module):

    def __init__(self):
        super(CNN, self).__init__()
        # L1 ImgIn shape=(?, 28, 28, 1)
        #    Conv     -> (?, 28, 28, 32)
        #    Pool     -> (?, 14, 14, 32)
        self.layer1 = torch.nn.Sequential(
            torch.nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2))
        # L2 ImgIn shape=(?, 14, 14, 32)
        #    Conv      ->(?, 14, 14, 64)
        #    Pool      ->(?, 7, 7, 64)
        self.layer2 = torch.nn.Sequential(
            torch.nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2))
        # Final FC 7x7x64 inputs -> 10 outputs(0~9)
        self.fc = torch.nn.Linear(7 * 7 * 64, 10, bias=True)    #fully connected layer
        torch.nn.init.xavier_uniform_(self.fc.weight)    #weight 초기화

    def forward(self, x):
        out = self.layer1(x)    #layer1 통과
				#print(out.shape)로 확인
        out = self.layer2(out)    #layer2 통과
        out = out.view(out.size(0), -1)   # Flatten them for FC
        out = self.fc(out)
        return out
```

```python
# instantiate CNN model
model = CNN().to(device)
```

6. loss function(criterion) 선택, 최적화 도구(optimizer) 선택

```python
# define cost/loss & optimizer
criterion = torch.nn.CrossEntropyLoss().to(device)    # Softmax is internally computed.
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
```

7. 모델 학습 및 loss check

```python
# train my model
total_batch = len(data_loader)
print('Learning started. It takes sometime.')
for epoch in range(training_epochs):
    avg_cost = 0

    for X, Y in data_loader:
        # image is already size of (28x28), no reshape
        # label is not one-hot encoded
        X = X.to(device)    #torch cuda 연산 진행
        Y = Y.to(device)

        optimizer.zero_grad()
        hypothesis = model(X)
        cost = criterion(hypothesis, Y)
        cost.backward()
        optimizer.step()

        avg_cost += cost / total_batch

    print('[Epoch: {:>4}] cost = {:>.9}'.format(epoch + 1, avg_cost))

print('Learning Finished!')
```

8. 학습된 모델 성능 확인

```python
# Test model and check accuracy
with torch.no_grad():
    X_test = mnist_test.test_data.view(len(mnist_test), 1, 28, 28).float().to(device)
    Y_test = mnist_test.test_labels.to(device)

    prediction = model(X_test)
    correct_prediction = torch.argmax(prediction, 1) == Y_test
    accuracy = correct_prediction.float().mean()
    print('Accuracy:', accuracy.item())
```

## 더 많은 layer의 CNN


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fl8ekpgvu951mvr2oifs.png)

5. 학습 모델 만들기(torch.nn.module)

```python
# CNN Model
class CNN(torch.nn.Module):

    def __init__(self):
        super(CNN, self).__init__()
        self.keep_prob = 0.5
        # L1 ImgIn shape=(?, 28, 28, 1)
        #    Conv     -> (?, 28, 28, 32)
        #    Pool     -> (?, 14, 14, 32)
        self.layer1 = torch.nn.Sequential(
            torch.nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2))
        # L2 ImgIn shape=(?, 14, 14, 32)
        #    Conv      ->(?, 14, 14, 64)
        #    Pool      ->(?, 7, 7, 64)
        self.layer2 = torch.nn.Sequential(
            torch.nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2))
        # L3 ImgIn shape=(?, 7, 7, 64)
        #    Conv      ->(?, 7, 7, 128)
        #    Pool      ->(?, 4, 4, 128)
        self.layer3 = torch.nn.Sequential(
            torch.nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2, padding=1))

        # L4 FC 4x4x128 inputs -> 625 outputs
        self.fc1 = torch.nn.Linear(4 * 4 * 128, 625, bias=True)
        torch.nn.init.xavier_uniform_(self.fc1.weight)
        self.layer4 = torch.nn.Sequential(
            self.fc1,
            torch.nn.ReLU(),
            torch.nn.Dropout(p=1 - self.keep_prob))
        # L5 Final FC 625 inputs -> 10 outputs
        self.fc2 = torch.nn.Linear(625, 10, bias=True)
        torch.nn.init.xavier_uniform_(self.fc2.weight)

    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = self.layer3(out)
        out = out.view(out.size(0), -1)   # Flatten them for FC
        out = self.layer4(out)
        out = self.fc2(out)
```

```python
#모델에 임의의 값을 넣어 test
value = torch.Tensor[1,1,28,28]
print(model(value).shape)
```

⇒ 더 깊어져도 모델의 성능이 떨어질 수 있음

⇒ 효율적으로 만드는 것이 중요!

# 10-3 visdom

-visdom 설치

```python
pip install visdom
```

-visdom 서버 켜기

```python
python -m visdom.server
```

### visdom 사용법

```python
**import** torch
**import** torch.nn **as** nn

**import** torchvision
**import** torchvision.datasets **as** dsets
```

```python
#Jupyter Notebook > Terminal 를 새로 켜서 python -m visdom.server 를 입력
#import visdom
**import** visdom
vis **=** visdom**.**Visdom()
```

```python
#Text
vis.text("Hello, world!",env="main")

#image
a=torch.randn(3,200,200)
vis.image(a)

#images
vis.images(torch.Tensor(3,3,28,28))
```

```python
##example (using MNIST and CIFAR10)
# 시간이 좀 걸립니다.
MNIST = dsets.MNIST(root="./MNIST_data",train = True,transform=torchvision.transforms.ToTensor(), download=True)
cifar10 = dsets.CIFAR10(root="./cifar10",train = True, transform=torchvision.transforms.ToTensor(),download=True)
CIFAR10
data = cifar10.__getitem__(0)
print(data[0].shape)
vis.images(data[0],env="main")

##MNIST
data = MNIST.__getitem__(0)
print(data[0].shape)
vis.images(data[0],env="main")

##Check dataset
data_loader = torch.utils.data.DataLoader(dataset = MNIST,
                                          batch_size = 32,
                                          shuffle = False)
for num, value in enumerate(data_loader):
    value = value[0]
    print(value.shape)
    vis.images(value)
    break
vis.close(env="main")
```

```python
##Line Plot
Y_data = torch.randn(5)
plt = vis.line (Y=Y_data)
X_data = torch.Tensor([1,2,3,4,5])
plt = vis.line(Y=Y_data, X=X_data)

##Line update
Y_append = torch.randn(1)
X_append = torch.Tensor([6])

vis.line(Y=Y_append, X=X_append, win=plt, update='append')
multiple Line on single windows
num = torch.Tensor(list(range(0,10)))
num = num.view(-1,1)
num = torch.cat((num,num),dim=1)

plt = vis.line(Y=torch.randn(10,2), X = num)

##Line info
plt = vis.line(Y=Y_data, X=X_data, opts = dict(title='Test', showlegend=True))
plt = vis.line(Y=Y_data, X=X_data, opts = dict(title='Test', legend = ['1번'],showlegend=True))
plt = vis.line(Y=torch.randn(10,2), X = num, opts=dict(title='Test', legend=['1번','2번'],showlegend=True))
```

```python
##make function for update line
def loss_tracker(loss_plot, loss_value, num):
    '''num, loss_value, are Tensor'''
    vis.line(X=num,
             Y=loss_value,
             win = loss_plot,
             update='append'
             )
plt = vis.line(Y=torch.Tensor(1).zero_())

for i in range(500):
    loss = torch.randn(1) + i
    loss_tracker(plt, loss, torch.Tensor([i]))
```

```python
##close the window
vis**.**close(env**=**"main")
```

⇒ visdom 왜 씀? → 모델 학습을 시각적으로 확인할 수 있도록 돕는 tool

cf) tensorboardx도 visualization tool로 많이 쓰임

### minist-cnn with visdom

```python
##make plot
loss_plt = vis.line(Y=torch.Tensor(1).zero_(),opts=dict(title='loss_tracker', legend=['loss'], showlegend=True))
```

```python
##train with loss_tracker
total_batch = len(data_loader)

for epoch in range(training_epochs):
    avg_cost = 0
    
    for X, Y in data_loader:
        X = X.to(device)
        Y = Y.to(device)
        
        optimizer.zero_grad()
        hypothesis = model(X)
        
        cost = criterion(hypothesis, Y)
        cost.backward()
        optimizer.step()
        
        avg_cost += cost / total_batch
    
    print('[Epoch:{}] cost = {}'.format(epoch+1, avg_cost))
    **loss_tracker(loss_plt, torch.Tensor([avg_cost]), torch.Tensor([epoch]))**
print('Learning Finished!')
```

# 10-4 ImageFolder

? 내가 가진 사진 활용해서 딥러닝 모델 학습하기

1. 나만의 데이터 셋 준비하기

-class마다 다르게 폴더를 만들어 이미지들 넣어놓기

-사진 크기 줄이기

```python
#이미지 보이게 할 때 활용
from matplotlib.pyplot import imshow
%matplotlib inline
```

2. torchvision.datasets.ImageFolder으로 불러오기

```python
trans = transforms.Compose([
    transforms.Resize((64,128))
])

train_data = torchvision.datasets.ImageFolder(root='custom_data/origin_data', transform=trans)
```

3. transforms 적용하여 저장 하기 origin_data -> train_data

```python
for num, value in enumerate(train_data):
    data, label = value
    print(num, data, label)
    
    if(label == 0):
        data.save('custom_data/train_data/gray/%d_%d.jpeg'%(num, label))    #경로대로 폴더 만들어져 있어야 함
    else:
        data.save('custom_data/train_data/red/%d_%d.jpeg'%(num, label)
```

4. CNN모델 생성 및 학습


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zrdlbhhp70ucgutztmgv.png)

```python
#모델 저장하고 불러오기
torch.save(net.state_dict(), "./model/model.pth")
new_net = CNN().to(device)
new_net.load_state_dict(torch.load('./model/model.pth'))
```

Q. 왜 저장해놔야 함? 어디에 저장되는 거임?

```python
#test
trans=torchvision.transforms.Compose([
    transforms.Resize((64,128)),
    transforms.ToTensor()
])
test_data = torchvision.datasets.ImageFolder(root='./custom_data/test_data', transform=trans)
test_set = DataLoader(dataset = test_data, batch_size = len(test_data))
with torch.no_grad():
    for num, data in enumerate(test_set):
        imgs, label = data
        imgs = imgs.to(device)
        label = label.to(device)
        
        prediction = net(imgs)
        
        correct_prediction = torch.argmax(prediction, 1) == label
        
        accuracy = correct_prediction.float().mean()
        print('Accuracy:', accuracy.item())
```

---

***대면 20 May, 2023***

###(sum up)mnist cnn
CIFAR-10 이미지 크기에 맞춰 CNN2 다시 설계

3x32x32

```
self.layer1 = torch.nn.Sequential(
            nn.Conv2d(3,x,kernel_size=3, stride=1, padding=0),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
    self.layer2 = nn.Sequential(
            nn.Conv2d(x,y,kernel_size=3, stride=1, padding=0),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
    self.layer3 = nn.Sequential(
            nn.Linear(inputsize_height->(outputsize 식/maxpool1/maxpool2)*inputsize_width->(outputsize 식/maxpool1/maxpool2)*y, 120),
            nn.ReLU(),
            nn.Linear(120,10)
        )
```
{% embed https://colab.research.google.com/drive/1e7SmLuENHNk9wxaRs39syrln0CCQzf4e?usp=sharing %}