15 분 소요

Image Outlier Detection using Artificial Neural Network

인공 신경망을 이용한 이미지 이상점 탐지

Introduction

인공지능은 프로세스를 자동화하고, 비즈니스에 대한 통찰력을 모으고, 프로세스 속도를 높이기 위해 다양한 산업에서 사용되고 있습니다. 인공지능이 실제로 산업에 어떤 영향을 미치는지 실제 시나리오에서 인공지능의 사용을 연구하기 위해 Python을 사용할 것입니다.

기계 학습에서 이상 탐지 작업은 매우 일반적입니다. 데이터 과학자들은 이상 징후를 보여주고 설명하고 예측해야 하는 문제에 자주 관여합니다. 이상 징후를 미리 감지하고 예측하면 많은 비용을 절감할 수 있습니다. 항상 그렇듯이 AI는 이 경우에 우리를 도울 수 있습니다.

이 노트북에서는 인공 신경망을 사용한 이미지 이상값 감지에 중점을 둘 것입니다.

Context

우리는 Kaggle에서 가져온 완벽한 벽과 금이 간 벽을 보여주는 데이터 세트로 작업할 것이다. 데이터 세트 이미지의 반은 새롭고 손상되지 않은 벽 조각을 보여줍니다; 나머지 부분은 다양한 치수와 유형의 균열을 가진 벽 조각을 보여줍니다.

Side note: VGG 란 무엇입니까??

VGG는 대규모 이미지 인식에 사용되는 신경망입니다. 우리는 이 노트북에서 VGG를 많이 사용할 것입니다. 이것은 1,400만 개가 넘는 수작업으로 라벨링된 이미지가 있는 ImageNet 데이터베이스에서 훈련되었습니다.

Use Python to open csv files

scikit-learn, pandas, TensorFlowKeras를 사용하여 데이터 세트를 작업합니다. Scikit-learn은 예측 데이터 분석을 위한 효율적인 도구를 제공하는 매우 유용한 기계 학습 라이브러리입니다. TensorFlow 및 Keras는 ML 모델을 개발하고 교육하는 데 도움이 되는 오픈 소스 라이브러리입니다. Pandas는 데이터 과학을 위한 인기 있는 Python 라이브러리입니다. 강력하고 유연한 데이터 구조를 제공하여 데이터 조작 및 분석을 더 쉽게 만듭니다.

Import Libraries

라이브러리가 설치되어 있지 않은 경우 터미널에서 다음 단계를 수행하십시오.

pip install tensorflow

pip install torch

pip install torchvision

pip install tqdm « 예도 설치해야 되더라;;;

아무튼 없다면 없는대로 설치;;

# 없을테니 설치...
%pip install tensorflow
%pip install torch
%pip install torchvision
Collecting tensorflow
  Downloading tensorflow-2.10.0-cp39-cp39-win_amd64.whl (455.9 MB)
     ------------------------------------- 455.9/455.9 MB 12.8 MB/s eta 0:00:00

......

     ---------------------------------------- 1.1/1.1 MB 6.3 MB/s eta 0:00:00
Requirement already satisfied: requests in c:\users\user\.conda\envs\myai\lib\site-packages (from torchvision) (2.28.1)
Requirement already satisfied: typing-extensions in c:\users\user\.conda\envs\myai\lib\site-packages (from torchvision) (4.4.0)
Requirement already satisfied: numpy in c:\users\user\.conda\envs\myai\lib\site-packages (from torchvision) (1.23.4)
Requirement already satisfied: torch==1.13.0 in c:\users\user\.conda\envs\myai\lib\site-packages (from torchvision) (1.13.0)
Requirement already satisfied: pillow!=8.3.*,>=5.3.0 in c:\users\user\.conda\envs\myai\lib\site-packages (from torchvision) (9.3.0)
Requirement already satisfied: certifi>=2017.4.17 in c:\users\user\.conda\envs\myai\lib\site-packages (from requests->torchvision) (2022.9.24)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in c:\users\user\.conda\envs\myai\lib\site-packages (from requests->torchvision) (1.26.12)
Requirement already satisfied: charset-normalizer<3,>=2 in c:\users\user\.conda\envs\myai\lib\site-packages (from requests->torchvision) (2.1.1)
Requirement already satisfied: idna<4,>=2.5 in c:\users\user\.conda\envs\myai\lib\site-packages (from requests->torchvision) (3.4)
Installing collected packages: torchvision
Successfully installed torchvision-0.14.0
Note: you may need to restart the kernel to use updated packages.
# 이것도 설치;;
%pip install tqdm
Collecting tqdm
  Using cached tqdm-4.64.1-py2.py3-none-any.whl (78 kB)
Requirement already satisfied: colorama in c:\users\user\.conda\envs\myai\lib\site-packages (from tqdm) (0.4.6)
Installing collected packages: tqdm
Successfully installed tqdm-4.64.1
Note: you may need to restart the kernel to use updated packages.
import numpy as np 
import pandas as pd
import scipy as sp
import matplotlib.pyplot as plt

import tensorflow as tf
from tensorflow.keras.applications import vgg16
from tensorflow.keras.preprocessing.image import load_img, img_to_array, array_to_img, ImageDataGenerator
from tensorflow.keras.models import *
from tensorflow.keras.layers import *
from tensorflow.keras import optimizers
from tensorflow.keras.utils import *

from PIL import Image
import requests
from io import BytesIO
import os
import random
import pickle
import tqdm
import itertools

import torch
import torchvision
from torchvision import datasets, models, transforms
import matplotlib.pyplot as plt
import torch.nn as nn


from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, accuracy_score, confusion_matrix

Dataset 읽기

여기에서 훈련 및 테스트 디렉토리를 정의합니다. [Dataset]Module11TrainQualityAssuranceSystem 및 [Dataset]Module11TestQualityAssuranceSystem 폴더에는 훈련 및 테스트 데이터가 포함되어 있습니다.

축소된 훈련 데이터 세트: [Dataset]Module11TrainReducedQualityAssuranceSystem은 더 작은 훈련 세트를 로드하고 훈련 시간을 줄여야 하는 경우에도 사용할 수 있습니다. 계속하기 전에 폴더의 압축을 풀어줍니다.

훈련 디렉토리에는 2개의 하위 디렉토리가 있습니다:

  • cracked(폴더에 금이 간 벽 이미지가 포함되어 있습니다.)

  • uncracked(폴더에 금이 가지 않은 벽 이미지가 포함되어 있습니다.)

# 훈련 및 테스트 데이터 디렉토리 정의
#  [Dataset]Module11TrainReducedQualityAssuranceSystem을 사용하여 훈련 시간을 줄일 수도 있습니다.
train_dir = '[Dataset]Module11TrainReducedQualityAssuranceSystem'

# 클래스는 이러한 이름을 가진 각 디렉토리의 폴더입니다.
classes = ['cracked','uncracked']
#classes = ['blue','red', 'yellow']
# 우리의 인공 신경망은 특정 크기 224X224 이미지를 처리합니다.
# 따라서 우리는 먼저 이미지 크기를 변환합니다.
data_transform = transforms.Compose([transforms.RandomResizedCrop(244), transforms.ToTensor()])

train_data = datasets.ImageFolder(train_dir, transform=data_transform)
#test_data = datasets.ImageFolder(test_dir, transform=data_transform)

Task 1: 훈련 데이터의 길이 출력

# your code here
print("Num training images: ", len(train_data))
Num training images:  240
train_c_dir = '[Dataset]Module11TrainReducedQualityAssuranceSystem/cracked'
train_uc_dir = '[Dataset]Module11TrainReducedQualityAssuranceSystem/uncracked'

#train_c_dir = 'signal/red'
#train_uc_dir = 'signal/blue'


def get_files_count(folder_path):
    dirListing = os.listdir('./' + folder_path)
    return len(dirListing)

print("Cracked image 개수:", get_files_count(train_c_dir))
print("Uncraked image 개수:", get_files_count(train_uc_dir))

#print("빨간 신호등 개수:", get_files_count(train_c_dir))
#print("파란 신호등 개수:", get_files_count(train_uc_dir))
Cracked image 개수: 120
Uncraked image 개수: 120
# 매개변수 정의
batch_size = 50

train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, shuffle=True)
#test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, shuffle=True)
# 일부 이미지를 표시해 보겠습니다.
dataiter = iter(train_loader)
images, labels = next(dataiter)
images = images.numpy() # 표시를 위해 이미지를 numpy로 변환

# 해당 라벨과 함께 배치 이미지를 보여줍니다.
fig = plt.figure(figsize=(25, 4))
for idx in np.arange(20):
    ax = fig.add_subplot(2, 10, idx+1, xticks=[], yticks=[])
    plt.imshow(np.transpose(images[idx], (1, 2, 0)))
    ax.set_title(classes[labels[idx]])

훈련 시작하기 먼저!!!!

만일! CPU보다 GPU 쿠다등 성능이 더 좋고 빠르다!

라고 한다면.. CUDA로 쓰라는 코드 유무를 확인하고, 없을 경우 변경해둘것!!!!!

만약.. gpu가 멀쩡히 있는데도 작동을 안한다면…

cuda 전용 소프트웨어 설치가 시급..

https://normal-engineer.tistory.com/163 - 참고1

쿠다가 정상적으로 되어있어도 만일 안된다면 pytorch 재설치를 해야함…

cuda version에 맞게;;;

https://pytorch.org/get-started/locally/

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)
cuda:0
# GPU 사용가능인지 확인 
torch.cuda.is_available()
True
# 모델을 초기화 합니다.
vgg16 = models.vgg16(weights=True)
vgg16 = vgg16.to(device)   # 쿠다로 가능하도록..

# 모델 구조 출력
print(vgg16)
C:\Users\User\.conda\envs\myai\lib\site-packages\torchvision\models\_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and may be removed in the future. The current behavior is equivalent to passing `weights=VGG16_Weights.IMAGENET1K_V1`. You can also use `weights=VGG16_Weights.DEFAULT` to get the most up-to-date weights.
  warnings.warn(msg)
VGG(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU(inplace=True)
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU(inplace=True)
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (6): ReLU(inplace=True)
    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): ReLU(inplace=True)
    (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (13): ReLU(inplace=True)
    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): ReLU(inplace=True)
    (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): ReLU(inplace=True)
    (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (20): ReLU(inplace=True)
    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (22): ReLU(inplace=True)
    (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (25): ReLU(inplace=True)
    (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (27): ReLU(inplace=True)
    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (29): ReLU(inplace=True)
    (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)
# 입력 및 출력 feature 수를 출력해 보겠습니다.
print(vgg16.classifier[6].in_features) 
print(vgg16.classifier[6].out_features)
4096
1000

훈련

테스트 데이터에서 이상을 식별할 수 있도록 VGG 모델을 사용하여 데이터 세트를 훈련합니다. 이를 위해 softmax 함수와 categorical_crossentropy 손실 함수를 사용할 것입니다.

softmax 함수는 지수 함수이며 분류 및 회귀 방법에 사용됩니다. Softmax 함수는 잠재적 결과 목록의 확률 분포를 나타내는 벡터를 출력합니다. 자세한 내용은 Softmax를 참조하십시오.

범주형 교차엔트로피(Categorical crossentropy)는 분류 작업에 사용되는 손실 함수입니다. 손실 함수는 분류가 얼마나 좋은지를 나타내는 척도입니다. 손실이 낮을수록 분류가 잘된 것입니다. 자세한 내용은 loss에서 확인하세요.

하나의 Epoch는 전체 데이터 세트가 신경망을 통해 한 번 앞뒤로 전달되는 경우입니다. 배치 크기는 단일 배치에 있는 훈련 예제의 총 수입니다.

# VGG 모델에는 컨볼루션 레이어, 최대 풀링 레이어 및 고밀도 레이어와 같은 다양한 레이어가 있습니다.
# 우리는 계산을 위해 모든 레이어를 사용할 필요는 없습니다.

# 모든 "특징" 레이어에 대한 훈련 동결
for param in vgg16.features.parameters():
    param.requires_grad = False

n_inputs = vgg16.classifier[6].in_features
last_layer = nn.Linear(n_inputs, len(classes)).to(device)
vgg16.classifier[6] = last_layer
import torch.optim as optim

# 손실 함수 지정(범주형 교차 엔트로피)
criterion = nn.CrossEntropyLoss().to(device)

# optimizer는 stochastic gradient descent로 지정
# 학습률(learning rate) = 0.001
optimizer = optim.SGD(vgg16.classifier.parameters(), lr=0.001)

Training

n_epochs = 60
larr = []

for epoch in range(1, n_epochs+1):

    # 훈련 및 검증 손실 추적
    train_loss = 0.0
    
    ###################
    # train the model #
    ###################
    # 기본적으로 모델은 훈련으로 설정되어 있습니다.
    for batch_i, (data, target) in enumerate(train_loader):
        data = data.to(device)
        target = target.to(device)
        
        # CUDA를 사용할 수 있는 경우 텐서를 GPU로 이동
        optimizer.zero_grad()
        # 순방향 전달: 입력을 모델에 전달하여 예측된 출력을 계산합니다.
        output = vgg16(data)
        # 배치 손실을 계산
        loss = criterion(output, target)
        # 역방향 패스: 모델 매개변수에 대한 손실 기울기 계산
        loss.backward()
        # 단일 최적화 단계 수행(매개변수 업데이트)
        optimizer.step()
        # 훈련 손실 업데이트 
        train_loss += loss.item()
        
        if epoch % 1 == 0:    # 지정된 수의 미니 배치마다 훈련 손실 출력
            print('Epoch %d, Batch %d loss: %.16f' %
                  (epoch, batch_i + 1, train_loss / 32))
            larr.append(train_loss / 32)
            train_loss = 0.0
Epoch 1, Batch 1 loss: 0.0223015006631613
Epoch 1, Batch 2 loss: 0.0225327182561159
Epoch 1, Batch 3 loss: 0.0221402570605278
Epoch 1, Batch 4 loss: 0.0213284045457840
Epoch 1, Batch 5 loss: 0.0238252207636833
Epoch 2, Batch 1 loss: 0.0228128693997860
Epoch 2, Batch 2 loss: 0.0217789486050606
Epoch 2, Batch 3 loss: 0.0211439821869135
Epoch 2, Batch 4 loss: 0.0221301298588514
Epoch 2, Batch 5 loss: 0.0220028869807720
Epoch 3, Batch 1 loss: 0.0216766241937876
Epoch 3, Batch 2 loss: 0.0216344818472862
Epoch 3, Batch 3 loss: 0.0217473953962326
Epoch 3, Batch 4 loss: 0.0217833500355482
Epoch 3, Batch 5 loss: 0.0211814008653164

......

Epoch 59, Batch 1 loss: 0.0202604718506336
Epoch 59, Batch 2 loss: 0.0209795162081718
Epoch 59, Batch 3 loss: 0.0210705287754536
Epoch 59, Batch 4 loss: 0.0203020982444286
Epoch 59, Batch 5 loss: 0.0206648670136929
Epoch 60, Batch 1 loss: 0.0216166395694017
Epoch 60, Batch 2 loss: 0.0212676469236612
Epoch 60, Batch 3 loss: 0.0198379606008530
Epoch 60, Batch 4 loss: 0.0214051157236099
Epoch 60, Batch 5 loss: 0.0211311690509319
# 손실 그래프
plt.plot(larr)
[<matplotlib.lines.Line2D at 0x1ad550d1c40>]

Task 2: 학습률을 0.1, 0.0001로 변경하고 네트워크를 다시 훈련시키십시오.

시간이 더 걸리나요?

이전엔..

loss: 0.0212165545672178 (최종)

gpu cuda 기준으로 30초 정도..

학습률 변경 후.. : 0.1

loss: 0.0191897824406624 (최종)

gpu cuda 기준으로 30초 정도..

학습률 변경 후.. : 0.0001

loss: 0.0210543293505907 (최종)

gpu cuda 기준으로 30초 정도..

시간은 별 차이가 없을… cpu로 하면 차이가 날려나….

Task 3: Epoch 수를 60, 10 으로 변경하여 네트워크를 다시 훈련시키십시오.

손실이 어떻게 변화하나요?

학습율은 0.001 그대로에서 epoch를 60 이나 10으로 변경.

60으로…

Epoch 60, Batch 5 loss: 0.0149131594225764

10으로..

Epoch 10, Batch 5 loss: 0.0219363141804934

결론..

살짝은 줄지만.. 데이터 양을 생각하면.. 그렇게.. 차이는..

만일.. 원래 데이터 양으로 한다면…

이때까지는 축소된 데이터양으로 진행. 그렇다보니.. 시간차이도 오류율도 그대로 일 수도있다.

그렇다면 원래 훈련 데이터로 하게된다면..

step1

# 훈련 및 테스트 데이터 디렉토리 정의
#  [Dataset]Module11TrainReducedQualityAssuranceSystem을 사용하여 훈련 시간을 줄일 수도 있습니다.
train_dir = '[Dataset]Module11TrainReducedQualityAssuranceSystem'

# 클래스는 이러한 이름을 가진 각 디렉토리의 폴더입니다.
classes = ['cracked','uncracked']
#classes = ['blue','red', 'yellow']

# 우리의 인공 신경망은 특정 크기 224X224 이미지를 처리합니다.
# 따라서 우리는 먼저 이미지 크기를 변환합니다.
data_transform = transforms.Compose([transforms.RandomResizedCrop(244), transforms.ToTensor()])

train_data = datasets.ImageFolder(train_dir, transform=data_transform)
#test_data = datasets.ImageFolder(test_dir, transform=data_transform)
# your code here
print("Num training images: ", len(train_data))

train_c_dir = '[Dataset]Module11TrainQualityAssuranceSystem/cracked'
train_uc_dir = '[Dataset]Module11TrainQualityAssuranceSystem/uncracked'

#train_c_dir = 'signal/red'
#train_uc_dir = 'signal/blue'

print("Cracked image 개수:", get_files_count(train_c_dir))
print("Uncraked image 개수:", get_files_count(train_uc_dir))

#print("빨간 신호등 개수:", get_files_count(train_c_dir))
#print("파란 신호등 개수:", get_files_count(train_uc_dir))
Num training images:  240
Cracked image 개수: 7501
Uncraked image 개수: 7449
# 매개변수 정의
batch_size = 50

train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, shuffle=True)
#test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, shuffle=True)
# 일부 이미지를 표시해 보겠습니다.
dataiter = iter(train_loader)
images, labels = next(dataiter)
images = images.numpy() # 표시를 위해 이미지를 numpy로 변환

# 해당 라벨과 함께 배치 이미지를 보여줍니다.
fig = plt.figure(figsize=(25, 4))
for idx in np.arange(20):
    ax = fig.add_subplot(2, 10, idx+1, xticks=[], yticks=[])
    plt.imshow(np.transpose(images[idx], (1, 2, 0)))
    ax.set_title(classes[labels[idx]])

step2

여기서는 모델 생성은 패스, 바로 훈련준비

# VGG 모델에는 컨볼루션 레이어, 최대 풀링 레이어 및 고밀도 레이어와 같은 다양한 레이어가 있습니다.
# 우리는 계산을 위해 모든 레이어를 사용할 필요는 없습니다.

# 모든 "특징" 레이어에 대한 훈련 동결
for param in vgg16.features.parameters():
    param.requires_grad = False

n_inputs = vgg16.classifier[6].in_features
last_layer = nn.Linear(n_inputs, len(classes)).to(device)
vgg16.classifier[6] = last_layer
# 손실 함수 지정(범주형 교차 엔트로피)
criterion = nn.CrossEntropyLoss().to(device)

# optimizer는 stochastic gradient descent로 지정
# 학습률(learning rate) = 0.001
optimizer = optim.SGD(vgg16.classifier.parameters(), lr=0.001)

step3 훈련

n_epochs = 60
larr = []

for epoch in range(1, n_epochs+1):

    # 훈련 및 검증 손실 추적
    train_loss = 0.0
    
    ###################
    # train the model #
    ###################
    # 기본적으로 모델은 훈련으로 설정되어 있습니다.
    for batch_i, (data, target) in enumerate(train_loader):
        data = data.to(device)
        target = target.to(device)
        
        # CUDA를 사용할 수 있는 경우 텐서를 GPU로 이동
        optimizer.zero_grad()
        # 순방향 전달: 입력을 모델에 전달하여 예측된 출력을 계산합니다.
        output = vgg16(data)
        # 배치 손실을 계산
        loss = criterion(output, target)
        # 역방향 패스: 모델 매개변수에 대한 손실 기울기 계산
        loss.backward()
        # 단일 최적화 단계 수행(매개변수 업데이트)
        optimizer.step()
        # 훈련 손실 업데이트 
        train_loss += loss.item()
        
        if epoch % 1 == 0:    # 지정된 수의 미니 배치마다 훈련 손실 출력
            print('Epoch %d, Batch %d loss: %.16f' %
                  (epoch, batch_i + 1, train_loss / 32))
            larr.append(train_loss / 32)
            train_loss = 0.0
Epoch 1, Batch 1 loss: 0.0220786780118942
Epoch 1, Batch 2 loss: 0.0213427897542715
Epoch 1, Batch 3 loss: 0.0214892216026783
Epoch 1, Batch 4 loss: 0.0223208907991648
Epoch 1, Batch 5 loss: 0.0228392165154219
Epoch 2, Batch 1 loss: 0.0213486142456532
Epoch 2, Batch 2 loss: 0.0223400648683310
Epoch 2, Batch 3 loss: 0.0210086181759834
Epoch 2, Batch 4 loss: 0.0210963506251574
Epoch 2, Batch 5 loss: 0.0221033729612827
Epoch 3, Batch 1 loss: 0.0223134066909552
Epoch 3, Batch 2 loss: 0.0205910205841064
Epoch 3, Batch 3 loss: 0.0216252747923136
Epoch 3, Batch 4 loss: 0.0231794379651546
Epoch 3, Batch 5 loss: 0.0217113532125950
Epoch 4, Batch 1 loss: 0.0221475269645452
Epoch 4, Batch 2 loss: 0.0217335876077414
Epoch 4, Batch 3 loss: 0.0214411299675703
Epoch 4, Batch 4 loss: 0.0228641703724861
Epoch 4, Batch 5 loss: 0.0212537497282028

......

Epoch 59, Batch 1 loss: 0.0194798819720745
Epoch 59, Batch 2 loss: 0.0212294012308121
Epoch 59, Batch 3 loss: 0.0206220932304859
Epoch 59, Batch 4 loss: 0.0210658423602581
Epoch 59, Batch 5 loss: 0.0217369534075260
Epoch 60, Batch 1 loss: 0.0215414837002754
Epoch 60, Batch 2 loss: 0.0190316364169121
Epoch 60, Batch 3 loss: 0.0195462927222252
Epoch 60, Batch 4 loss: 0.0218246001750231
Epoch 60, Batch 5 loss: 0.0197362415492535

step4 훈련그래프 결과

# 손실 그래프
plt.plot(larr)
[<matplotlib.lines.Line2D at 0x1ad54f07cd0>]

결론

epoch = 60, learning rate = 0.001, batch를 줄여서 시도…

마지막 로그 : Epoch 60, Batch 5 loss: 0.0214790515601635

걸린 시간 : 대략 1분..

별 차이는 없어보임…

신호등으로 해보자

이번엔 신호등 파란불, 빨간불 구분으로 학습을…

step1

# 훈련 및 테스트 데이터 디렉토리 정의
#  [Dataset]Module11TrainReducedQualityAssuranceSystem을 사용하여 훈련 시간을 줄일 수도 있습니다.
train_dir = 'signal'

# 클래스는 이러한 이름을 가진 각 디렉토리의 폴더입니다.
# classes = ['cracked','uncracked']
#classes = ['blue','red', 'yellow']
classes = ['blue', 'red']

# 우리의 인공 신경망은 특정 크기 224X224 이미지를 처리합니다.
# 따라서 우리는 먼저 이미지 크기를 변환합니다.
data_transform = transforms.Compose([transforms.RandomResizedCrop(244), transforms.ToTensor()])

train_data = datasets.ImageFolder(train_dir, transform=data_transform)
#test_data = datasets.ImageFolder(test_dir, transform=data_transform)
# your code here
print("Num training images: ", len(train_data))

#train_c_dir = '[Dataset]Module11TrainQualityAssuranceSystem/cracked'
#train_uc_dir = '[Dataset]Module11TrainQualityAssuranceSystem/uncracked'

train_c_dir = 'signal/red'
train_uc_dir = 'signal/blue'

#print("Cracked image 개수:", get_files_count(train_c_dir))
#print("Uncraked image 개수:", get_files_count(train_uc_dir))

print("빨간 신호등 개수:", get_files_count(train_c_dir))
print("파란 신호등 개수:", get_files_count(train_uc_dir))
Num training images:  200
빨간 신호등 개수: 99
파란 신호등 개수: 101
# 매개변수 정의
batch_size = 50

train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, shuffle=True)
#test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, shuffle=True)
# 일부 이미지를 표시해 보겠습니다.
dataiter = iter(train_loader)
images, labels = next(dataiter)
images = images.numpy() # 표시를 위해 이미지를 numpy로 변환

# 해당 라벨과 함께 배치 이미지를 보여줍니다.
fig = plt.figure(figsize=(25, 4))
for idx in np.arange(20):
    ax = fig.add_subplot(2, 10, idx+1, xticks=[], yticks=[])
    plt.imshow(np.transpose(images[idx], (1, 2, 0)))
    ax.set_title(classes[labels[idx]])

step2

여기서는 모델 생성은 패스, 바로 훈련준비

# VGG 모델에는 컨볼루션 레이어, 최대 풀링 레이어 및 고밀도 레이어와 같은 다양한 레이어가 있습니다.
# 우리는 계산을 위해 모든 레이어를 사용할 필요는 없습니다.

# 모든 "특징" 레이어에 대한 훈련 동결
for param in vgg16.features.parameters():
    param.requires_grad = False

n_inputs = vgg16.classifier[6].in_features
last_layer = nn.Linear(n_inputs, len(classes)).to(device)
vgg16.classifier[6] = last_layer
# 손실 함수 지정(범주형 교차 엔트로피)
criterion = nn.CrossEntropyLoss().to(device)

# optimizer는 stochastic gradient descent로 지정
# 학습률(learning rate) = 0.001
optimizer = optim.SGD(vgg16.classifier.parameters(), lr=0.001)

step3 훈련

n_epochs = 60
larr = []

for epoch in range(1, n_epochs+1):

    # 훈련 및 검증 손실 추적
    train_loss = 0.0
    
    ###################
    # train the model #
    ###################
    # 기본적으로 모델은 훈련으로 설정되어 있습니다.
    for batch_i, (data, target) in enumerate(train_loader):
        data = data.to(device)
        target = target.to(device)
        
        # CUDA를 사용할 수 있는 경우 텐서를 GPU로 이동
        optimizer.zero_grad()
        # 순방향 전달: 입력을 모델에 전달하여 예측된 출력을 계산합니다.
        output = vgg16(data)
        # 배치 손실을 계산
        loss = criterion(output, target)
        # 역방향 패스: 모델 매개변수에 대한 손실 기울기 계산
        loss.backward()
        # 단일 최적화 단계 수행(매개변수 업데이트)
        optimizer.step()
        # 훈련 손실 업데이트 
        train_loss += loss.item()
        
        if epoch % 1 == 0:    # 지정된 수의 미니 배치마다 훈련 손실 출력
            print('Epoch %d, Batch %d loss: %.16f' %
                  (epoch, batch_i + 1, train_loss / 32))
            larr.append(train_loss / 32)
            train_loss = 0.0
Epoch 1, Batch 1 loss: 0.0210936516523361
Epoch 1, Batch 2 loss: 0.0229267030954361
Epoch 1, Batch 3 loss: 0.0230638626962900
Epoch 1, Batch 4 loss: 0.0216429680585861
Epoch 2, Batch 1 loss: 0.0223056431859732
Epoch 2, Batch 2 loss: 0.0218394976109266
Epoch 2, Batch 3 loss: 0.0207645148038864
Epoch 2, Batch 4 loss: 0.0240599196404219
Epoch 3, Batch 1 loss: 0.0218602158129215
Epoch 3, Batch 2 loss: 0.0228070020675659
Epoch 3, Batch 3 loss: 0.0222926754504442
Epoch 3, Batch 4 loss: 0.0212500169873238
Epoch 4, Batch 1 loss: 0.0237588230520487
Epoch 4, Batch 2 loss: 0.0225628595799208
Epoch 4, Batch 3 loss: 0.0215207394212484
Epoch 4, Batch 4 loss: 0.0201022438704967

.......

Epoch 58, Batch 1 loss: 0.0156913977116346
Epoch 58, Batch 2 loss: 0.0115372277796268
Epoch 58, Batch 3 loss: 0.0145329367369413
Epoch 58, Batch 4 loss: 0.0145702371373773
Epoch 59, Batch 1 loss: 0.0159023050218821
Epoch 59, Batch 2 loss: 0.0160456486046314
Epoch 59, Batch 3 loss: 0.0157261490821838
Epoch 59, Batch 4 loss: 0.0127053381875157
Epoch 60, Batch 1 loss: 0.0168359708040953
Epoch 60, Batch 2 loss: 0.0131517192348838
Epoch 60, Batch 3 loss: 0.0156200854107738
Epoch 60, Batch 4 loss: 0.0160929299890995

step4 훈련그래프 결과

# 손실 그래프
plt.plot(larr)
[<matplotlib.lines.Line2D at 0x1ad5367d160>]

결론

epoch = 60, learning rate = 0.001

이정도 설정으로 배치4까지 반복으로 진행.

걸린시간은 1분

Epoch 60, Batch 4 loss: 0.0139679992571473

그래프 까지 참조해본 결과 학습이 잘 됨을 볼 수 있음.

최종결론

데이터가 중요하다.

그 외로…

10, 50, 100원 동전 구별하는 데이터셋 준비중…

정제 후, 들어가야 결과가 나오니…

이 파트는 추후 여유되는대로 다시 업로드..

Conclusion

이 노트북에서는 AI가 이상 탐지에 어떻게 사용되는지 살펴보았습니다. 우리는 벽 이미지의 균열을 식별하기 위해 신경망을 훈련시켰습니다. 우리는 이상 징후를 감지하고 이상치를 거부할 수 있도록 기계 학습 시스템을 훈련할 수 있습니다.

마무리…

  • 이미지처리로 어떠한 모델로 쓰이며, 어떠한 프레임워크로 하는지 익히는 계기가 됨.

  • cpu보다 gpu가 더 빠른건 말 안해도 진리일듯하다.

단, gpu로 할거라면 모델, 데이터 처리할때 일원화 되도록 해야 돌아감!

  • pytorch가 왜 자주 쓰이는지 알 것 같기도…

  • 그 외 데이터 추가해서 크랙유무, 신호등으로 해보았는데 아래와 같은 사항들이 중요할 것 같다.

  • 데이터를 잘 분별해서 수집, 구별이 중요하다. 첫 단추가 시작의 반이다고 하듯..
  • 반복(에포크), 학습률(lr)등 적당한 수치가 가장 중요하다.

그 외 참조한 사이트들.

https://stackoverflow.com/questions/62549990/what-does-next-and-iter-do-in-pytorchs-dataloader

만일.. iter next라는 함수를 못찾는 경우….

버전이 바뀌면 써야되는 함수형태도..


https://wandb.ai/wandb_fc/korean/reports/PyTorch-GPU—VmlldzoxNTEwNjg5

pytorch를 gpu cuda로 돌리는 방법1


주의사항

본 포트폴리오는 인텔 AI 저작권에 따라 그대로 사용하기에 상업적으로 사용하기 어려움을 말씀드립니다.

댓글남기기