본문 바로가기

Hello MLop/DL

MLop_DL_CNN 실습

20221118

31일차

 


 

처음으로 해보는 이미지 예측이다.

 

컴퓨터

어떻게 이미지를 예측할까?아니, 어떻게 이미지라고 인식할까?

 

 

인간은 컴퓨터에게 어떻게 이미지를 분별하게 했을까?란 고민으로 이 글을 읽어보면 좋다.

 

우리가 일상적으로 보는 사진 및 이미지컴퓨터가 인식시키기 위해서는

이미지를 숫자로 변환해주어야 한다.

 

인간은 이미지를 분별하기 위해 이미지를 특성에따라 로 배열했다.

이 말이 무슨말인지 기본적으로 흑백 이미지를 보자.

 

출처 : wikidoc

위의 이미지를 보면 인간은 육안으로 y라는 문자라는것을 인식하지만,

컴퓨터에게 입력하기 위해서는 위와같이 쪼개서 1줄로 만들어서

 

흰색이면 0, 검정이면 1의 형태로 넣어줘야한다.

 

그럼 만약 똑같은 사이즈의 이미지가 왔을때 01로 분별할 수 있게만 나타내 주면

우린 컴퓨터에게 다른 문자를 만들게 할 수 있는것이다.

 

💡 채널

 

컴퓨터는 글자나 이미지보다 숫자. 다시 말해, 텐서(tensor)를 더 잘 처리할 수 있다.

 

이미지는 (높이, 너비, 채널)이라는 3차원 텐서다.

 

높이는 이미지의 세로 방향 픽셀 수,

너비는 이미지의 가로 방향 픽셀 수,

채널색 성분을 의미합니다.

 

위의 흑백 이미지채널 수1이며,

각 픽셀은 0부터 255 사이의 값을 가진다.

 


컬러 이미지를 보자.

 

💡 도메인 지식으로 꼭 알아야 할점. ⭐⭐⭐

색은 삼원색으로 이루어져 있다.

빨강(R) 초록(G) 파랑(B)

 

위의 R, G, B 이용해 채널을 만든다면?

컬러 이미지 또한 3개의 차원에 높이, 너비, 채널로 각각 저장할 수 있다.

 


자 그럼 이미지를 컴퓨터, 즉 기계에 넣을 수 있게 되었다.

그럼 학습은 어떻게 시키는가?

 

즉, 딥러닝에서는 이미지를 구별하고 판단하고 추려주기까지 한다는데

과연 그런것들은 어떻게 하는걸까?

 

여기서 번뜩! 가중치라는 단어가 떠올라야 한다.

이전 실습에서 가중치는 무었을 의미하였는가

 

분류에서는 분류의 기준이 되었고

회귀 분석에서는 Feature # aka.컬럼명, 독립변수 의 중요도로 선택되었다.

 

그럼 채널별로 저장한 값들에 가중치를 주면?

기계는 이게 중요하다, 이걸 살리자로 인식하게 되는것이다.

 

그리고 다음 단계로 넘기고 넘기고 결과가 나오고 오차를 수정하고 다시 적용하면

딥러닝의 이미지 분석 및 러닝과정이 되는것이다.

 


⭐⭐⭐⭐⭐

 

이를 머신러닝 관점으로 보면 

 

이미지를 채널별로 tensor형태로 변환 해서

입력층에 들어가기 전 단계가 전처리 단계가 되고

 

입력층에  들어온 데이터에 가중치를 주는

모델을 만들고 적용시키고 오차를 줄이기 위해 오차역전파 써서

가중치 최적화 하는것을 모델링 단계

 

그럼 이제 학습된 모델훈련셋 테스트셋 만들어 넣고 결과 비교하고

정확도 비교하고 정확도 분석하는게 결과 도출 및 사후처리 비교 단계이다.

 


그럼 CNN이 무었인지 알아보자.

 

 

💡 CNN(Convolutional Neural Network)?

영어를 그대로 해석하면

 

Convolutional 합성곱

Neural Network 신경망

 

합성곱을 이용한 다층 신경망을 CNN이라 한다.

 

CNN은 크게 두가지로 구성되어 있다.


합성곱층(Convolution layer)

합성곱 연산의 결과가 활성화 함수 ReLU를 지난다.

이 두 과정을 합성곱층이라 한다.

 

즉, 합성곱층합성곱을 이용해

이미지의 부분부분의 가중치들을 획득해서

기계판단할 수 있게 기준(=가중치 연산 결과)을 만들어 주는 이다.

 

간단히 설명하면 가중치를 주는 방식이 합성곱 방식인것이다.

 

아래 사진으로 합성곱 방식으로 가중치를 저장하는 법을 보자.

 

출처 : wikidocs

입력은 당연히 이미지를 채널을 기준으로 특성에 따라 수를 넣어논 상태이다.

이미지에 가중치를 넣는 방식은 위와 같이 커널을 이용하는게 대표적이다.


💡 커널(kernel) 또는 필터(filter)?

 

커널(kernel)은 n * m의 형태로 이미지의 높이(height) * 너비(width) 크기의

이미지처음부터 끝까지 겹치며 훑으면서

# 왼쪽 상단부터 오른쪽 하단 순서가 일반적이다.

 

커널원소값과  이미지겹치는 부분을 계산하여

가중치를 더해주는 도구

 

💡 스트라이드(stride)

 

사용자인 우리는 파라미터를 튜닝한것처럼,

커널이동방향거리의 단위를 변경할 수 있는데,

이때 커널의 이동 범위스트라이드라고 한다.

 


 

결과적으로 커널은 위와같이 가중치들을 얻게 되고

이렇게 만들어진 커널을 특성 맵(feature map)이라고 한다.

 


풀링층(Pooling layer)

 

간단하게 설명하면 풀링계산을 하는 층이다.

 

그럼 풀링 은 뭘까?

 

1차원에서 커널을 이용해

이미지의 특징에 가중치를 줘서 저장해줬다면

 

풀링은 2차원, 즉 이미지의 크기와 관련된 부분에서 

커널을 사용해 데이터의 

세로 및 가로 방향의 공간을 줄이는 연산이다


💡 풀링의 종류

 

최대 풀링(Max Pooling)

풀링에서 사용하는 커널에서 겹치는 부분의 최대값만 추출

▶ 풀링커널의 feature map에 저장

 

 평균 풀링(Average Pooling)

풀링에서 사용하는 커널에서 겹치는 부분의 평균값을 구해 추출

▶ 풀링커널의 feature map에 저장

 

출처 : www.edwith.org


출처 : wikidocs

지금까지의 내용들을 정리한 사진이다.

 

CNN(Convolutional Neural Network)

이제 무었을 의미하는지 이해 되길 바란다.

 


이제 위에서 본 내용들을 실습해보자.

 

실습 데이터는

from torchvision.datasets.cifar import CIFAR10

torchvision.datasets에서 CIFAR10을 가져왔다.

 


기본 임포트를 해준다.

plt(시각화), CIFAR10(데이터셋), ToTensor(Tensor로 변환)

 

 


train데이터와 test데이터로 받아주고

행렬의 형태를 tensor형태로 바꿔주기 위해

ToTensor해준다.

 


 

이제 이를 반복문을 이용해 데이터 확인 차 출력해준다.

 


데이터를 증강하는 경우는

이미지의 개수를 증가시켜 오버피팅을 방지하기 위함이다.

 

transforms을 이용해 이미지의 개수를 증가 시킬 수 있다.

 

크롭핑을 이용해 이미지 개수를 늘리기 위해

필요 임포트를 해준다.

 

💡 ToPILImage() : Pytorch Image Tensor 

---> PIL(Python Imaging Library)이미지, Numpy 배열

 

배열구조

"C x H x W"  →  "H x W x C"

 

# H : height 높이

# W : width 너비

# C : channel 채널 (RGB 컬러의 경우 3, grayscale의 경우 1또는 0)

 

Compose : 구성하다.

RandomHorizontalFlip : y축을 기준으로 대칭

RandomCrop  : 랜덤으로 이미지를 일부 제거 하고 패딩해준다.

 

💡 크롭핑 (Cropping)

사전적 의미는 자르다.

 

중요 포인트는 원래의 사진을  아예 다른 사진으로 바꿔준다는 것이다.

 


 

training_data, test_data를 다시 정해주는데,

위의 transform # Compose내의 조건으로 정의된 으로 바꿔준다.

 

그리고 출력하면?

 

위와 같이 크롭핑되고 패딩으로 채워진, 대칭, ToPILImage된 이미지가 출력된다.

 


💡 이미지 정규화

이미지는 대부분 R,G,B 데이터로 구성

 

왜 하는걸까?

색을 R,G,B로 나누더라도 특정 색의 경우 데이터가 치우쳐져 있기 때문에!

 

위의 사진은 색의 삼원소로 만들어진 색들을 보여준다.

만약 위의 색들만 있는 이미지를 R,G,B로 쪼갠다면

깔끔하게 데이터가 떨어지겠지만

 

위의 범주에서 좀 더 치우쳐지거나, 한쪽으로 몰린 색이라면,

R,G,B로 쪼개지긴하나, 각각의 값들은 모두 다를 것이다.

 

이런 경우 가중치를 가중곱으로 연산할때

이미 시작부터 데이터가 다르게 연산이 되기 때문에

이미지의 값들을 3차원으로 쪼개고 정규화를 시키고 시작한다.


 

정규화가 포함된 transforms를 정의해보자.

 

구성(Compose)은 아래와  같다.

 

RandomCrop, padding=4 로 잘라주고

RandomHorizontalFlip y축 대칭으로 뒤집어주고

T.ToTensor() Tensor배열로 바꿔주고

# 컬러이미지이니 이 순간 3채널(R,G,B)의 Tensor배열이 됨

 

Normalize 각각의 채널을 정규화 해준다.

mean(평균)과, std(표준편차)로

# 값이 3개있는 이유는 3채널(R,G,B)이기 때문

 

이제 이를 다시 training_data와 test_data에 적용시켜주고

9개만 출력 시켜보면?

 

위와 같은 정규화된 이미지 결과물이 나온다.

 


이미지의 전처리 과정을 종류별로 보았다.

이제 본론으로 돌아와 시작해보자.

 

넣을 데이터 training_data를 정의해주자.

 

트레인  셋(training_data)정의의 포인트는

trasform은 ToTensor()로 해주었다는것이다.

 

현재 이미지는 우리가 원하는 데이터 구조로 되어있지 않다.

따라서 앞서 봤던 높이너비채널 구조의 형태로 만들어야 한다.

 

imgs = [item[0for item in training_data]

 

위의 코드는 이러한 복잡하게 구성되어있는 이미지를

0번째만 반복문으로 뽑아 낸것을 imgs에 저장하고

 

imgs = torch.stack(imgs, dim=0).numpy()

torch.stack를 이용해 dim=0 # 새로운 차원 으로 하여 따로 저장한다.


💡 갑자기 numpy()?

 

.numpy() 가 나와 당황했을것이다.

 

하지만 조금만 생각해보면 이해가 된다.

이미지는 데이터가 어떻게 구성되어있는지

현재 지식수준으로 파악하기 어렵지만

출처 : wikidoc

이 사진을 보면 감이 잡힌다.

이미지는 색의 구성을 의미하는 채널, 크기를 나타내는 높이, 너비 구성된다.

 

아직 tensor 배열로 변환이 안됬다면,

현재 각각의 이미지는 numpy배열, 즉 행렬의 형태로 이루어져 있다.

 

그리고 torch로 써야하니 .stack을 이용해

잠시 numpy()형태로 만들어서 변환해 준것이다.

 


현재 imgs에 shape를 찍어보면

우리가 원한 채널, 높이, 너비구성된다.

 

총 50000개의 이미지가 들어간 트레인 셋3채널32개의 높이, 너비로 모양이 잡혀있다.

4차원의 데이터인 것이다.

 


만약 현재 imgs의 구성이 파악이 되었다면

위의 코드에서 인덱싱한 부분이 어느 차원을 인덱싱 한것인지 알것이다.

 

4차원 데이터에서

2번째 차원(3채널= 담당)의 0번째 = R, 1번째 = G, 2번째 = B

데이터를 인덱싱한 것이다.

 

평균은 왜 구했을까?

바로 정규화가 떠올라야 한다.

 

정규화를 위한 데이터 저장 과정이다.

 

표준편차 또한 저장해준다.

이제 정규화를 위한 조각은 다 모였다.


이제 준비물은 모였으니 실습을 하기전에...

모델을 정의하는 방식도 나뉘는데

 

nn.Sequential 같은 경우는 어떤 베이직한 모델링 도구이다.

차곡차곡 정석대로 모델링하는 느낌이라면,

 

nn.Module은 복잡한 신경망이라는 말이 맞다.

목적을 위해 여러 사람의 계획이 있듯 아마 러닝의 결과를 위한 도화지가 아닐까 생각된다.

 

학습 루프(계획)합성곱3x3 kernal을 이용해 가중치를 연산하고 그 과정을 두 번 반복한다.

그때의 활성화 함수ReLU를 이용하며

마지막에 Max_pulling을 이용해 이미지의 사이즈 또한 특징을 추출할것이며

결과 값을 받겠다.


위의 학습 루프를 실행하기 위한 코드를 보자.

 

BasicBlock라는 class각 층(layer)에 들어갈 블록을 정의한 다음

 

전체 신경망들은 어떻게 작동할지 두 번째로 정의해 준다.

 


이제 베이직한 클래스를 만들었다면

CNN을 제대로 학습시키기 위해

 

위의 BasicBlock상속받는 새로운 class CNN을 만들어 주자.

# BasicBlock은 layer 안에 들어가는 블록을 정의하고 CNN은 layer안의 블록의 역할을 정의한다.


💡상속  ⭐⭐⭐⭐⭐

https://astrum93.tistory.com/18

 

상속은 현실의 단어 뜻 처럼 부모의 것을 물려받는 의미이다.

부모 클래스에 있던 요소들을 자식 클래스에서 쓸 수 있다.

또한 자식 클래스에서 리모델링 또한 가능하다.

 

위의 상속 포스팅을 읽고 오길 바란다.

 


 

자 이제 무었을 상속받았는지 함께 보자.

 

우선 BasicBlock의 입력 채널 수를 정의했다.

# 시작은 R,G,B 3채널로 시작하기 때문에 입력 채널 수3으로 시작.

 

그리고 out_channels 수에 변화를 주어 데이터를 좀 더 세분화 하였고

hidden_dim의 개수를 설정하여 좀더 합성곱 연산이 효율적이게 만들어 줬다.

 


💡 분류기

말 그대로 분류되지 않은 데이터를 분류해주는 모델이다.

nn.Flaten, nn.ReLU, nn.softmax, nn.Linear, nn.Sequential 등등 


nn.Linear (선형 계층)

= 저장된 가중치(weight)와 편향(bias)을 사용하여 입력에

선형 변환(linear transformation)을 적용하는 모듈입니다.

즉, Linear : 선형, 일차형!

벡터는 길이를 변경해주고 스칼라는 차원을 변경해준다.

 

❗ Linear의 경우 선형 함수를 적용했기 때문에 y = wx + b의 형태로 변환된다.

# 오차 역전파를 하면 w값과 b값이 최적화 되는것이다.

 

 

CNN class의 마지막 단락. 순전파를 실행하게 하는 forward 함수를 보자.

 

block1(x) ~ block3(x)

행렬의 형태인 이미지에 커널을 이용해 합성곱 연산을 통해 가중치를 뽑는다.

 

torch.flatten(x, start_dim=1)

차원 1을 시작으로 .flatten(# numpy에서 제공하는 다차원 배열 공간을 1차원으로 평탄화해주는 함수이다.)

행렬 ▶ (0차원, 1차원) = (이미지 넘버, 각 이미지 데이터)

 

.fc1(x)▶.relu(x) ~ .fc3(x)▶.relu(x)

nn.Liner() # 선형계층을 이용해 가중치 학습.

nn.ReLU()를 이용해 학습된 가중치 다음으로 넘김

 

위와 같이 이미지가 학습되는 아주 베이직한 러닝모델을 구성해보았다.


그럼 이 모든 내용을 종합해 학습 및 가중치 학습까지 해보자.

 

이미지의 오버피팅을 방지하기 위해 Compose에등록한 기능들을 적용한다.

 

자르고 패딩y축 대칭 반전텐서 변환정규화 R,G,B

 


 

임포트한 dataloader를 이용해트레인 데이터,

테스트 데이터 저장모델 구동시 이용할 자원 CPU? or GPU?

model은 CNN

 


💡 Adam (Adaptive Moment Estimation)= 가중치 최적화 알고리즘

 

optimizer를 의미하는 optim에 저장!lr = learning rate = 학습률 = 보폭

 

for문을 통해 100번의 epoch를 실행하는데

 

기울기 초기화하고 # 반복될때마다 깔끔하게 실행하기 위해

모델을 저장

loss=nn.CrossEntropyLoss()를 이용해

예측값과 실제값 오차 저장lossbackward() # 오차역전파 실행

optim.step()을 이용해 최적화 ▶ Adam을 이용

 

위를 실행하면?

 

epoch가 100에 가까워질수록 loss가 줄어드는것을 확인할 수 있다.

 


그럼 이제 학습된 모델에테스트셋을 불러와 예측된것과 정답이 eq하면 corr이라 하고

 

이렇게 나온 corr을 num_corr에 누적합한다.그럼 Accuracy는 num_corr/len(test_data)가 된다.

 

 

'Hello MLop > DL' 카테고리의 다른 글

MLop_DL_U-Net 실습  (0) 2022.12.05
MLop_DL_ResNet 실습  (0) 2022.12.04
MLop_DL_손글씨 판단 예측  (0) 2022.11.24
MLop_DL_보스톤 집값 예측  (0) 2022.11.23
MLop_DL_사인함수 예측하기  (0) 2022.11.22