[Embedded System Lab] Chapter 4 - Introduction To Machine Learning
"Introduction To Machine Learning"
[Objective]
Python으로 Multi-Layer Perceptrons을 구현하여 이미지 분류를 통해 Machine Learning 이해하기
[Theory]
▣ Machine Learning
· 인공지능 : 사람의 지능과 연관된 인지 기능을 모방하는 System
· Machine Learning : 대규모 데이터, 통계로부터 학습한 정보에 기반하여 의사결정을 내리는 알고리즘
· Deep Learning : Machine Learning의 신경망 깊이에 해당하는 Layer를 여러 개 쌓아 만든 깊은 신경망을 이용한 학습
> Machine Learning Model
· Neural Networks & Multi-Layer Perceptrons (인공 신경망)
· Convolutional Neural Network (합성곱 신경망)
· Recurrent Neural Network (순환 신경망)
· Large Language Model (대규모 언어 모델)
· Large Language Model (대규모 언어 모델)
▣ Multi-Layer Perceptrons
> Single-Layer Perceptron
· Model의 입력 층과 출력 층만 있는 단순한 회귀식
· 각 Weight Node들은 입력 값에 따른 Weight를 보유 (Ex. W1-1, W1-2, W1-3, W1-4)
> Multi-Layer Perceptrons (= Neural Network)
→ 복잡한 비선형 관계를 학습하는데 유용
> Activation Function
· Activation Function 덕분에 Neural Network는 비선형적이고 복잡한 패턴을 학습 가능
· 목적에 따라 Sigmoid, ReLU, Softmax 등 다양한 Activation Function 사용 가능
· MLP의 각 Node들은 사전에 정의된 Weight를 이용해 출력을 계산
· "f"는 활성화 함수를 의미
· Forward Propagation을 통해 얻은 결과물(예측값)과 실제 입력에 따른 결과값을 비교
· 예측값과 실제값의 차이와 해당 Gradient를 이용하여 MLP Weight에 대한 Update 진행
· Chaine Rule에 따라 여러 층에 걸쳐 Forward Propagation의 반대방향으로 진행
> Training MLPs
· Forward Propagation을 이용해 입력값에 대한 출력값을 예측
· Backward Propagation을 통해 예측값과 실제값을 비교하며 각 층의 Weight를 Update
↑ 여러 차례 반복하는 것 = MLP Model을 Training
→ MLP Model을 훈련함으로써 Model은 입력값에 대해 실제값과 가까운 출력값을 갖게 됨
> Inference Using MLPs
<Ex. 신발 매장의 특징(입력값)에 대한 매출, 판매량(출력값)을 예측>
· 훈련이 완료되면, Neural Network는 학습 데이터를 기반으로 입력값에 대한 출력값을 잘 예측 가능
· 이후, Neural Network를 실제로 사용하여 결과물을 얻을 때에는 Forward Propagation만 사용
▣ Machine Learning Models
> Convolutional Neural Network
· 인간의 시신경 구조를 모방한 기술
· 이미지 안의 인접한 부분의 특징, 멀리 떨어진 부분에 대한 전반적인 인식을 하는데 있어 합성곱 사용
· 합성곱 연산의 경우 일반적인 행렬곱이 아닌 행렬의 원소끼리만 곱하여 결과를 출력 (Elementwise Product)
· 합성곱 연산에 사용되는 Weight는 Kernel 또는 Filter라고 지칭
· 이미지 분류나 영상 데이터 처리 등, 컴퓨터 비전 분야에서 많이 사용
· 합성곱 연산과 Pooling 연산을 통해 이미지의 특징을 추출
· Pooling 연산은 결과 행렬에서 최대값 또는 평균값을 추출하는 과정
· 합성곱, Pooling 층을 여러 개 쌓은 후, 마지막 몇 층을 MLP를 이용하여 구성
> Large Language Model
· 지금까지 사용한 단어들을 모아놓고 문법, 의미 등의 문맥을 Weight를 통해 얻어냄
· 지금까지 사용된 단어들에 대한 문법, 의미 등 다양한 문맥을 고려했을 때, 적절한 다음 단어를 출력
· 출력한 다음 단어를 포함하는 지금까지 사용된 단어들은 Model의 다음 입력 값으로 사용
· Transformer라는 Machine Learning Model 사용
[Code Description & Result]
▣ Library Setting
1 2 3 4 5 6 7 8 9 10 11 | # Model import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torchvision import datasets, transforms # Visualizing import matplotlib.pyplot as plt # etc from google.colab import drive drive.mount('/content/drive') | cs |
· Google Colab, PyTorch를 이용하여 MLP를 구현하기 위해 먼저 위 코드 실행
2 : PyTorch Library 전체를 "torch" 이름으로 불러오기 (x = torch.tensor([1.0, 2.0, 3.0]))
3 : PyTorch의 nn 모듈을 "nn" 이름으로 불러오기 (nn.Linear, nn.Conv2d, nn.ReLU, nn.CrossEntropyLoss)
4 : torch.nn.functional 모듈을 "F" 이름으로 불러오기 (F.relu(), F.softmax(), F.cross_entropy(), F.max_pool2d())
5 : torch.optim 모듈을 "optim" 이름으로 불러오기 (optim.SGD, optim.Adam, optim.RMSprop)
6 : torchvision Library에서 "datasets"와 "transforms"만 불러오기
(datasets : 자주 쓰는 이미지 데이터셋을 쉽게 불러오기 위한 기능)
→ MNIST, CIFAR-10, FashionMNIST
(transforms : 이미지 데이터를 모델에 넣기 전에 형태를 바꾸거나 전처리하는 기능)
→ transforms.ToTensor(), Transforms.Normalize(), transforms.Resize()
8 : matplotlib Library의 pyplot 모듈을 "plt" 이름으로 불러오기
10 : Google Colab 환경에서 Google Drive를 연결하기 위한 기능을 불러오기
11 : Google Drive를 Colab의 파일 System에 연결
▣ Device Setting
▣ Check Device
1 2 3 4 5 | # Check GPU is_cuda = torch.cuda.is_available() device = torch.device('cuda' if is_cuda else 'cpu') print('CUDA Device :', device) | cs |
· GPU(CUDA)를 사용할 수 있는지 확인하고, 사용 가능한 Device를 설정
2 : 현재 환경에서 GPU(CUDA)를 사용할 수 있는지 True/False로 확인
3 : 사용할 Device 설정 (GPU 가능 = True → device = GPU / GPU 불가능 = False → device = CPU)
▣ Load MNIST Dataset
1 2 3 4 5 6 | # load MNIST dataset train_data = datasets.MNIST(root = '/content/drive/MyDrive/MNIST', train = True, download = True, transform = transforms.ToTensor()) test_data = datasets.MNIST(root = '/content/drive/MyDrive/MNIST', train = False, download = True, transform = transforms.ToTensor()) print(len(train_data), len(test_data)) | cs |
· AI Model 학습에 필수적인 MNIST 손글씨 Dataset을 불러오고 준비하는 과정
2 : root 경로에서 학습용 데이터를 가져옴
3 : root 경로에서 평가용 데이터를 가져옴 → 학습에는 절대 보여주지 않고 오직 시험용으로만 쓸 이미지 데이터 1만장을 가져옴
6 : 데이터를 에러 없이 잘 불러왔는지 최종적으로 확인하기 위해 훈련 데이터 개수와 테스트 데이터 개수를 출력
· root : 데이터를 저장하거나 이미 다운로드 된 데이터를 찾을 폴더 경로 지정
· train : True = 학습용 데이터 / False = 평가용 데이터
· download : True = 만약 지정한 root 경로에 데이터 파일이 없다면, PyTorch가 알아서 인터넷에서 다운로드하여 폴더에 저장
· transforms.ToTensor( ) : Python의 기본 이미지 파일 형태를 PyTorch가 계산할 수 있는 숫자 행렬 형태인 Tensor로 변환
+ 0~255 볌위였던 Pixel 색상 값을 모델이 학습하기 좋은 0~1 사이의 소수점 범위로 압축(정규화)
▣ Check Size of Image
1 2 3 | # check size of image image, label = train_data[0] print(f'Shape of image: {image.squeeze().numpy().shape}') | cs |
2 : 훈련용 데이터의 첫 번째 Data Sample을 불러옴
3 : 이미지 구조 출력
· image, label : PyTorch의 이미지 Dataset은 기본적으로 (이미지 데이터, 정답 라벨) 2가지로 구성 → 분리해서 저장
· image : PyTorch에서 이미지를 [채널 수, 세로 Pixel, 가로 Pixel] 형태의 Tesnsor → [1, 28, 28]
· squeeze( ) : 차원의 크기가 '1'인 불필요한 차원을 제거 → [28, 28]
· numpy( ) : PyTorch 전용 데이터 형태인 Tensor를 수학/배열 계산에 사용하는 NumPy 배열로 변환
· shape : NumPy 배열의 형태(크기)를 알려주는 속성 → (28, 28)
▣ Fix Random Seed Number for Experiment Replication
1 2 | # fix random seed number for experiment replication torch.manual_seed(1) | cs |
2 : 난수 Seed 고정
· torch : PyTorch Library의 기능을 사용
· manual_seed(1) : 난수를 만들어낼 때 사용하는 시작점(Seed)을 수동으로 1로 지정
▣ Design MLP Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #################### fill the codes under annotation #################### # make mlp model class MLP(nn.Module): def __init__(self, input_dim=784, hidden1=256, hidden2=64, output_dim=10): super(MLP, self).__init__() # First hidden layer: Linear -> BatchNorm -> ReLU (fill this part!) self.layer1 = nn.Sequential( nn.Linear(input_dim, hidden1), nn.BatchNorm1d(hidden1), nn.ReLU() ) # Second hidden layer: Linear -> BatchNorm -> ReLU (fill this part!) self.layer2 = nn.Sequential( nn.Linear(hidden1, hidden2), nn.BatchNorm1d(hidden2), nn.ReLU() ) # Output layer: Linear mapping to classes (fill this part!) self.out = nn.Linear(hidden2, output_dim) def forward(self, x): # Flatten the input: [batch_size, 1, 28, 28] (fill this part!) x = x.view(x.size(0), -1) # Pass through two hidden layers (fill this part!) x = self.layer1(x) x = self.layer2(x) # Final output layer (fill this part!) x = self.out(x) return x | cs |
· PyTorch를 사용하여 MLP Model 설계
4 : "nn.Module" Class 상속
5 : 입력 데이터 크기 = 784, 은닉층1의 뉴런 개수 = 256, 은닉층2의 뉴런 개수 = 64, 최종 출력 값의 개수 = 10
6 : 상속받은 부모 Class인 nn.Module의 초기화 함수 실행
8 : 여러 개의 부품을 순서대로 묶는 역할
9 : 784개의 입력을 받아 256개로 변환
10 : 데이터의 Scale을 일정하게 맞춰 학습 속도를 높이고 안정적으로 만들기 위한 배치 정규화 실행
11 : 음수 값은 0, 양수는 그대로 통과시키는 비선형 함수 ReLU 적용
15 : 여러 개의 부품을 순서대로 묶는 역할
16 : 256개의 데이터를 받아 64개로 변환
17 : 데이터의 Scale을 일정하게 맞춰 학습 속도를 높이고 안정적으로 만들기 위한 배치 정규화 실행
18 : 음수 값은 0, 양수는 그대로 통과시키는 비선형 함수 ReLU 적용
22 : 64개의 데이터를 받아 10개로 변환
26 : [배치 크기, 1, 28, 28]인 2차원 이미지 데이터를 [배치 크기, 784] 형태의 1차원 데이터로 변환
29 : 1차원으로 펴진 데이터 x를 은닉층1 함수에 할당
30 : 은닉층1을 통과한 데이터를 은닉층2 함수에 할당
33 : 은닉층2를 통과한 데이터를 출력층 함수에 할당
35 : 최종 계산된 10개의 점수(예측값)를 반환
· (x.size(0), -1) : 배치 크기(한 번에 들어오는 이미지 256장)를 그대로 유지하며, 나머지 차원은 컴퓨터가 알아서 하나의 긴 줄로 계산
▣ Set Hyperparameter for Training
1 2 3 4 5 6 | # load MLP model to GPU # set hyperparameters for training model = MLP().to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) num_epochs = 50 | cs |
· 학습하기 전 Hyperparameter 설정
3 : 설계한 MLP를 CPU/GPU 중 위에서 설정한 장치에 올려 계산할 준비
4 : 오차 계산 공식
5 : 최적화 알고리즘 Adam을 사용하여 오차를 바탕으로 Model 안에 있는 Weight와 Bias 수정
6 : 전체 Dataset을 50번 반복해서 Weight를 Update(학습) → 너무 많이 반복 시 훈련 데이터만 달달 외우는 Overfitting 발생 가능
· lr : 학습율로, 한 번 틀렸을 때 Weight를 수정하는 '보폭 크기'를 의미 → 너무 크면 최적점을 지나치고, 너무 작으면 학습이 오래 걸림
▣ Use Data Loader for Training Data
1 2 3 | # use data loader for training data from torch.utils.data import DataLoader train_loader = DataLoader(dataset=train_data, batch_size=256, shuffle=True) | cs |
· 방대한 양의 데이터를 Model이 학습하기 좋게 적절한 크기로 나눠서 전달
2 : PyTorch에서 데이터를 다루는 데 유용한 도구들이 있는 Module에서 DataLoader Class를 가져옴
3 : DataLoader를 이용하여 실제로 훈련용 데이터를 관리할 변수 생성
· dataset : 어떤 데이터를 처리할 지 지정 → 훈련용 Dataset 지정
· batch_size : Model에게 데이터를 한 번에 몇 개씩 묶어서(Batch) 전달할지 결정 → 256장씩 1 묶음 (60,000 / 256 ≒ 235번 전달)
· shuffle : Model이 전체 Data를 한 번 다 볼 때마다 데이터의 순서를 무작위로 섞을지 결정 → 정확한 학습을 위해 반드시 True
▣ Training Data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #################### fill the codes under annotation #################### # run 50 iterations of training for epoch in range(num_epochs): # train model (fill this part!) model.train() # 모델을 학습 모드로 설정 running_loss = 0.0 for images, labels in train_loader: images, labels = images.to(device), labels.to(device) # 데이터를 GPU/CPU로 이동 optimizer.zero_grad() # 1. 이전 루프의 기울기 초기화 outputs = model(images) # 2. 순전파 (예측) loss = criterion(outputs, labels) # 3. 오차(Loss) 계산 loss.backward() # 4. 역전파 (기울기 계산) optimizer.step() # 5. 가중치 업데이트 running_loss += loss.item() # 손실 누적 # compute loss over epochs (fill this part!) epoch_loss = running_loss / len(train_loader) print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.4f}') | cs |
4 : 전체 Dataset을 50번 반복하여 훈련
6 : Model을 학습 Mode로 설정
7 : 전체를 1회 훈련하는 동안 발생한 오차(Loss)를 모두 더해서 기록할 변수를 0으로 초기화
9 : train_loader가 한 번에 256장씩 이미지와 정답 라벨을 묶어서 가져옴 → 6만 개의 데이터를 읽기 위해 235번 반복
10 : 가져온 256장의 이미지와 정답 라벨을 Model이 올라간 연산 장치로 전송 (모델과 데이터가 같은 장치 안에 있어야만 계산 가능)
12 : PyTorch는 기본적으로 기울기를 누적하는 특징이 있어 새로운 256장 문제를 풀기 전, 이전 문제에서 계산했던 기울기를 초기화
13 : 256장의 이미지를 Model에 통과(Forward Pass) → 각 이미지에 대해 예측 값 10개를 계산
14 : 예측 값과 정답 라벨을 채점 기준(CrossEntropyLoss)에 넣고 비교하여 Loss 계산
15 : 오차를 바탕으로 출력층부터 입력층까지 거꾸로 되돌아가며, 기울기 계산
16 : Backward로 계산된 기울기 정보와 학습율을 이용해 Weight Update
18 : Update 완료 시, 256장 묶음에서 발생한 오차(Loss)를 running_loss에 누적
21 : 235번 반복이 모두 끝나서 60,000장을 다 확인하면 1 Epoch 종료 후, 평균 오차 계산
22 : Epoch 번호와 계산된 평균 오차를 소수점 4자리까지 출력 → 학습이 잘 되고 있다면 뒤로 갈수록 Loss 값 감소
· item( ) : PyTorch Tensor로 감싸져 있는 숫자를 순수한 Python 숫자(float)로만 뽑아내는 함수 ∵ 불필요한 계산 기록 제거
▣ Test Data Using Original Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #################### fill the codes under annotation #################### # use data loader for test data test_loader = DataLoader(dataset=test_data, batch_size=256, shuffle=False) # check accuracy of the trained model (fill this part!) model.eval() # 모델을 평가 모드로 설정 model.to(device) # Ensure the model is on the correct device correct = 0 total = 0 with torch.no_grad(): # 평가 시에는 기울기 계산을 비활성화하여 메모리 절약 및 속도 향상 for images, labels in test_loader: images, labels = images.to(device), labels.to(device) # 데이터를 GPU/CPU로 이동 outputs = model(images) _, predicted = torch.max(outputs.data, 1) # 가장 높은 확률을 가진 클래스 추출 total += labels.size(0) correct += (predicted == labels).sum().item() # Calculate accuracy (fill this part!) accuracy = 100 * correct / total print(f"Original Model Test Accuracy: {accuracy:.2f}%") | cs |
4 : 학습할 때와 마찬가지로 Test Data를 256장씩 묶어서 가져오는 test_loader 생성
7 : Model을 평가 Mode로 설정
8 : Model이 연산을 수행할 장치에 올라가 있는지 확인
9 : Model이 정답을 맞춘 개수를 세기 위한 변수 초기화
10 : Model이 푼 전체 문제의 개수를 세기 위한 변수 초기화
11 : Test 할 때는 기울기 계산(Backward)을 비활성화하여 메모리 절약 및 속도 향상
12 : Test용 Data Loader에서 256장씩 이미지와 정답을 꺼내옴 → 10,000 / 256 ≒ 40번 전달
13 : Test 이미지와 정답 라벨을 Model이 올라간 장치로 전달
14 : 256장의 이미지를 Model에 통과시켜 각 이미지에 대한 10개의 예측 값 계산
15 : output에 담긴 10개의 점수 중 가장 점수가 높은 Index 찾기
16 : 현재 Batch에 들어있는 데이터의 개수(일반적으로 256)를 total에 누적하여 총 몇 문제를 풀었는지 기록
17 : 예측 값과 정답이 똑같은지 비교하여 256개의 문제 중 맞춘 것의 개수를 전부 누적
20 : 모든 Test 데이터를 다 확인한 후, 백분율로 정확도 계산
21 : 최종 계산된 정확도를 소수점 둘째 자리까지 출력
· dataset : 어떤 데이터를 처리할 지 지정 → Test용 Dataset 지정
· batch_size : Model에게 데이터를 한 번에 몇 개씩 묶어서(Batch) 전달할지 결정 → 256장씩 1 묶음 (10,000 / 256 ≒ 40번 전달)
· shuffle : Test 할 때는 굳이 순서를 섞을 필요가 없으므로 False로 설정
· torch.max : 1번째 차원을 기준으로 최댓값을 찾기
· _, : 몇 점인지 궁금하지 않고, Index만 필요하여 안 쓰는 값인 첫 번째 반환 값을 버리고 두 번째 반환값을 "predicted"에 저장
· item( ) : PyTorch Tensor로 감싸져 있는 숫자를 순수한 Python 숫자(float)로만 뽑아내는 함수 ∵ 불필요한 계산 기록 제거
▣ Setting for Quantization Model
1 2 3 4 5 6 7 8 9 10 11 12 | # 8bit quantization of the model model.to('cpu') import torch.quantization quantized_model = torch.quantization.quantize_dynamic( model, # the original model {nn.Linear}, # layers to quantize dtype=torch.qint8 # quantize to 8-bit integers ) quantized_model.eval() quantized_model.to('cpu') | cs |
· 학습이 완료된 크고 무거운 DL Model을, 성능은 최대한 유지하면서 크기는 줄이고 속도는 빠르게 만드는 Quantization 적용
2 : 학습을 마친 Original Model을 GPU에서 CPU 메모리로 이동 (∵ CPU 환경에서 추론 속도를 극대화하기 위해 설계)
4 : PyTorch 내부에 준비된 양자화 전용 함수 불러옴
5 : Model 압축을 실행하고, 해당 결과물을 새로운 변수에 저장
6 : CPU로 옮겨둔 학습된 Original Model 사용
7 : Linear 층들만 압축 (∵ MLP Model은 Weight가 꽉 들어찬 선형계층이 용량의 대부분을 차지)
8 : 32-bit Float 형태를 8-bit Integer 형태로 압축
11 : 양자화 Model을 추론 Mode로 설정 (양자화된 Model은 추가적인 학습을 할 수 없고 오직 추론만 하는 용도로 사용)
12 : 양자화된 Model이 CPU에 배치되었는지 확인
· quantize_dynamic : 동적 양자화를 수행하는 함수
→ Model의 Weight는 미리 압축하고, 데이터가 흐를 때 발생하는 Activation들은 계산할 때마다 실시간으로 압축하여 계산
▣ Test Data Using Quantized Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # check accuracy of the quantized model correct = 0 total = 0 with torch.no_grad(): for images, labels in test_loader: # Ensure images are on CPU since the quantized model works on CPU images = images.to('cpu') outputs = quantized_model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() accuracy = 100 * correct / total print(f"Quantized Model Test Accuracy: {accuracy:.2f}%") | cs |
· 8-bit로 압축한 Model의 정확도 평가
2 : Model이 정답을 맞춘 횟수를 기록할 변수 초기화
3 : Model이 푼 전체 문제 수를 기록할 변수 초기화
4 : 추론 Mode이므로 기울기 계산(Backward) 기능을 Off하여 메모리를 절약하고 속도를 높임
5 : test_loader에서 256장씩 이미지와 정답을 꺼내움
7 : 양자화 Model은 CPU에 있으므로 데이터도 반드시 CPU로 올라가야 에러 발생 X
8 : 256장의 이미지를 양자화된 모델에 통과시켜 각 이미지에 대한 10개의 예측 값 계산
9 : 10개의 예측 값 중 가장 점수가 큰 Index를 찾아 predicted 변수에 저장
10 : 묶음에 들어있는 데이터의 개수(일반적으로 256)를 total에 누적
11 : 예측 값과 정답 라벨이 일치하는 개수를 누적
13 : 10,000장의 데이터를 다 확인한 후, 정확도를 백분율로 정확도 계산
14 : 최종 계산된 정확도를 소수점 둘째 자리까지 출력
▣ Print Test Data Result Using Quantized Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import matplotlib.pyplot as plt # Select one test sample. image, label = test_data[1] plt.imshow(image.squeeze(), cmap='gray') plt.title(f"True Label: {label}") plt.axis('off') plt.show() # run single inference with torch.no_grad(): image = image.to('cpu') output = quantized_model(image.unsqueeze(0)) # convert probabilities to a NumPy array. probabilities = torch.softmax(output, dim=1) probabilities_np = probabilities.cpu().numpy()[0] # display the probability for each class as a percentage. for digit, prob in enumerate(probabilities_np): print(f"{prob*100:.2f}% that the number is {digit}") | cs |
1 : 이미지 출력을 위해 Library 선언
4 : 10,000장의 Test Dataset 중 1번째 Index(2번째 데이터)를 추론
5 : 2차원 숫자 배열을 이미지로 출력
6 : 이미지의 위에 정답 라벨을 텍스트로 출력
7 : 축 눈금 Off
8 : 설정한 옵션을 적용하여 화면에 출력
11 : Weight Update가 필요 없으므로, 기울기 계산(Backward) 기능을 꺼서 메모리와 속도를 최적화
12 : 이미지를 CPU 메모리로 이동
13 : 예측 값 계산
16 : Softmax 함수를 사용하여 전체의 합이 100%가 되도록 확률 값으로 변환
17 : PyTorch Tensor 형태인 결과를 Python에서 다루기 쉬운 NumPy 배열로 변환
20 : 각 숫자에 대한 정답 확률 표시
21 : 확률에 100을 곱해서 보기 편한 백분율로 표현 → 0 ~ 9 총 10줄
· unsqueeze(0) : PyTorch Model은 [배치 크기, 채널, 세로, 가로] 형태의 4차원 입력을 기대
→ 이미지는 [1, 28, 28] 형태의 3차원이므로 0번째 자리에 차원 하나 추가
· dim = 1 : 1번째 차원(Class 10개)을 기준으로 확률 계산
· [0] : 1장짜리 묶음([1, 10])으로 넣었으므로 결과도 묶음 형태
→ 유일한 결과물인 0번째 배열만 사용하여 10개의 확률 숫자 리스트([10]) 생성
· enumerate : List를 반복할 때, '순서 번호'와 '해당 값'을 동시에 가져옴
· digit : 0 ~ 9가 차례대로 할당
· prob : 각 숫자에 해당하는 확률 할당
[Discussion]
· 양자화된 Model이 아닌 Original Model로 추론 가능하며 마지막 이미지와 확률 출력 코드에서 약간의 수정이 필요
12 : image.to(device) → Original Model은 GPU에 있을 수 있으므로 이미지를 Model과 같은 장치에 위치시킴
13 : model(image.unsqueeze(0)) → quantized_model이 아닌 Original Model을 통과시킴
17 : probabilities.cpu( ).numpy( )[0] → NumPy로 바꾸려면 GPU에 있는 것을 CPU로 반드시 가져와야 하므로 .cpu( ) 필수
· MNIST의 데이터 중 다른 데이터를 추론하고 싶으면 마지막 이미지와 확률 출력 코드에서 test_data의 Index 수정
· 다른 이미지 데이터(CIFAR-10, FashionMNIST)를 사용하여 실험
→ train_data와 test_data를 Load 할 때 datasets.CIFAR-10, datasets.FashionMNIST으로 설정
· Original Model이 사용하는 데이터의 크기는 32-bit Float 형태로 GPU에서 계산하는 것이 압도적으로 빠름
· Quantized Model이 사용하는 데이터의 크기는 8-bit Integer 형태로 CPU에서 계산하는 것이 훨씬 빠름
· Quantized Model 사용 : 추론 정확도가 크게 감소하지 않지만, 메모리 사용량과 전력 소모가 감소하고 모델 크기(용량)이 작아져 추론(계산) 속도가 훨씬 빨라짐
→ 성능 하락 대비 얻는 가성비가 압도적으로 큼
[Reference]
· Intro_to_ML_4 (Embedded System Lab : Chapter4) - William J. Song
댓글
댓글 쓰기