관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

딥러닝을 시작합니다 1 - 인공 신경망 1 : 패션 MINIST 데이터셋으로 딥러닝 실습해보기 본문

인공지능/딥러닝

딥러닝을 시작합니다 1 - 인공 신경망 1 : 패션 MINIST 데이터셋으로 딥러닝 실습해보기

huenuri 2024. 10. 4. 16:07

딥러닝을 하고 싶은 마음과 지난번에 마무리하지 못한 파이썬 교재의 마지막 장을 학습해야 할지 무척 고민이 된다. 우선 오늘은 딥러닝을 아침에 했으니 오후와 저녁에 남은 시간에 이 공부를 해보기로 했다.


 

학습 목표

딥러닝과 인공 신경망 알고리즘을 이해하고 텐서플로를 사용해 간단한 인공 신경망 모델을 만들어보기

 

시작하기 전에

마케팅 팀은 패션 상품의 주 고객층인 20대를 타깃으로 이전보다 럭키백의 정확도를 높여야 한다고 요구했다. 생선 럭키백에서 알고리즘으로 사용한 로지스틱 회귀 알고리즘으로 패션 럭키백의 정확도를 높이려고 한다.

 

지난 시간 복습


 

 

패션 MINIST

7장과 8장에서는 패션 MINIST 데이터셋을 사용하겠다. 이 데이터셋은 10종류의 패션 아이템으로 구성되어 있다. 머신러닝과 딥러닝을 처음 배울 때 많이 사용하는 데이터셋이 있다. 머신러닝에서는 붓꽃 데이터셋이, 딥러닝에서는 MINIST 데이터셋이 유명하다. 이 데이터는 손으로 쓴 0~9까지의 숫자로 이루어져 있다. MINIST와 크기, 개수가 동일하지만 숫자 대신 패션 아이템으로 이루어진 데이터가 바로 패션 MINIST이다.

 

MINIST 데이터는 워낙 유명하기 때문에 많은 딥러닝 라이브러리에서 이 데이터를 가져올 수 있는 도구를 제공한다. 여기서는 텐서플로를 사용해 이 데이터를 불러오겠다. 

 

 

전달받은 데이터 크기를 확인해 보면 훈련 데이터는 6만 개의 이미지로 이루어져 있고, 각 이미지는 28 x 28 크기이다. 타깃도 6만 개의 원소가 있는 1차원 배열이다.

테스트 세트의 크기는 10,000개의 이미지로 주어져 있다.


 

 

이 코드를 쓸 때 주의할 점은 /이 아니라 역슬레시라는 것이다. 이 기호는 원화로도 표시되기도 한다.

 

 

 

여기 mnist_test와 minist_train 데이터가 들어있음을 확인했다. 

 

 


 

 

 

훈련 데이터에서 몇 개의 샘플을 그림으로 출력해볼 것이다. 크기가 28 x 28이다 보니 작고 흐릿하다. 이 샘플들의 타깃값을 확인해 본다. 패션 MINIST의 타깃은 0~9까지 숫자 레이블로 구성된다. 진하게 표시된 부분이 높은 숫자이다.

이 값을 앞에서 출력한 결과와 비교해보았다. 0~9까지 레이블마다 정확히 6000개의 샘플이 들어 있는 것을 볼 수 있다.


 

 

 

 

 


 

 

 

 

로지스틱 회귀로 패션 아이템 분류하기

이 훈련 샘플을 6만 개나 되기 때문에 전체 데이터를 한꺼번에 사용하여 모델을 훈련하는 것보다 샘플을 하나씩 꺼내서 모델을 훈련하는 방법이 더 효율적으로 보인다. 이런 상황에 잘 맞는 방법이 확률적 경사 하강법이다.

확률적 경사 하강법은 여러 특성 중 기울기가 가장 가파른 방향을 따라 이동한다. 만약 특성마다 값의 범위가 많이 다르면 올바르게 손실 함수의 경사를 내려올 수 없다. 패션 MINIST의 경우 각 픽셀은 0~255 사이의 정수값을 가진다. 이런 이미지의 경우 보통 255로 나누어 0~1 사이의 값으로 정규화한다.

 

 

reshape() 메서드의 두 번째 매개변수를 28 x 28 이미지 크기에 맞게 지정하면 첫 번째 차원(샘플 개수)은 변하지 않고 원본 데이터의 두 번째, 세 번째 차원이 1차원으로 합쳐진다. 변환된 train_scaled의 크기를 확인해 본다.

784개의 픽셀로 이루어진 60000개의 샘플이 준비되었다. 이제 SGDClassifier 클래스와 cross_validate 함수를 이용해 이 데이터에서 교차 검증으로 성능을 확인했다.

 

여기서는 SGDClassifier의 반복 횟수(max_iter)를 5번으로 지정했다. 반복 횟수를 늘려도 성능이 크게 향상되지 않았다. 


 

 

 

 

반복 횟수를 9나 20 등의 여러 숫자를 넣어서 테스트해 보았다.

 

 


 

로지스틱 회귀 공식은 z = a x (weight) + b x (Length) + c x (Diagonal) + d x (Height) + e x (width) + f이다. 이 식을 패션 MINIST 데이터에 맞게 변형하면 다음과 같다.

z_티셔츠 = w1 x (픽셀1) + w2 x (픽셀2) +  ... + w784 x (픽셀784) + b

바지에 대한 방정식도 이와 비슷하다. 다만 바지에 대한 출력을 계산하기 위해 가중치와 절편은 다른 값을 사용해야 한다. 티셔츠와 같은 가충치를 사용한다면 바지와 티셔츠를 구분할 수 있을 리가 없다.

 

 

이런 식으로 나머지 클래스에 대한 선형 방정식을 모두 생각해 볼 수 있다. 이 방정식을 그림으로 나타낸 것이다. 여기서 중요한 점은 티셔츠를 계산하기 위해 픽셜 784개와 곱하는 가중치 784개(w1~w784)와 절편(b)이 바지를 계산하기 위해 픽셀 784개와 곱하는 가중치 784개와 다르다는 것이다.

그럼 이제 인공 신경망을 만들어 패션 아이템 분류 문제의 성능을 높일 수 있는지 생각해 보자.


 

 

 

 

인공 신경망

가장 기본적인 인공 신경망은 확률적 경사 하강법을 사용하는 로지스틱 회귀와 같다. 딥러닝과 인공 신경망은 동일한 용어이다.

 

 

 

클래스가 총 10개이므로 z10까지 계산한다. 이를 바탕으로 클래스를 예측하기 때문에 신경망의 최종 값을 만든다는 의미에서 출력층이라고 부른다. 인공 신경망에서는 z값을 계산하는 단위를 뉴런이라고 부른다. 하지만 뉴런에서 일어나는 일은 선형 계산이 전부이다. 유닛이라고 부르기도 한다.

인공 신경망은 x1~x784까지를 입력층이라고 부른다. 입력층은 픽셀값 자체이고 특별한 계산을 수행하지 않는다.

 

인공 신경망은 생물학적 뉴런에서 영감을 받아 만들어졌다. 뉴런은 수상 돌기로부터 신호를 받아 세포체에 모은다. 신호가 어떤 임계값에 도달하면 축삭 돌기를 통해 다른 세포에 신호를 전달한다. 하지만 생물학적 뉴런이 가중치와 입력을 곱하여 출력을 만드는 것은 아니다. 

4장에서 보았던 시그모이드 함수나 소프트맥스 함수를 사용하는 것은 더욱 아니다. 인공 뉴턴은 생물학적 뉴런의 모양을 본뜬 수학 모델에 불과하다. 인공 신경망은 뇌 속에 있는 무언가를 만드는 일이 아니라는 것을 꼭 기억하자.

 

기존 머신러닝 알고리즘이 잘 해결하지 못했던 문제에서 높은 성능을 발휘하는 새로운 종류의 머신러닝 알고리즘일 뿐이다. 가장 인기가 높은 딥러닝 라이브러리인 텐서플로를 사용해 인공 신경망 모델을 만들어보겠다.


 

 

텐서플로와 테라스

텐서플로는 구글이 2015년 11월 오픈소스로 공개한 딥러닝 라이브러리이다. 이때를 기점으로 딥러닝에 대한 개발자의 관심이 늘어났고, 2016년 3월 알파고가 이세돌 9단을 이겨 대중에게 알려지면서 그야말로 폭발적으로 인기가 높아졌다. 

텐서플로에는 저수준 API와 고수준 API가 있다. 케라스는 텐서플로의 고수준 API이다. 

딥러닝 라이브러리가 다른 머신러닝 라이브러리와 다른 점 중 하나는 그래픽 처리 장치인 GPU를 사용하여 인공 신경망을 훈련한다는 것이다. GPU는 벡터와 행렬 연산에 매우 최적화되어 있기 때문에 곱셈과 덧셈이 많이 수행되는 인공 신경망에 큰 도움이 된다.

 

 

케라스 라이브러리는 직접 GPU 연산을 수행하지 않는다. 대신 GPU 연산을 수행하는 다른 라이브러리를 백엔드로 사용한다. 예를 들면 텐서플로가 케라스의 백엔드 중 하나이다. 이 외에도 씨아노, CNTK와 같은 여러 딥러닝 라이브러리를 케라스 백엑드로 사용할 수 있다. 이런 케라스를 멜티-백엔드 케라스라고 부른다.

케라스 API만 익히면 다양한 딥러닝 라이브러리를 입맛대로 골라서 쓸 수 있다. 이를 위해 케라스는 직관적이고 사용하기 편리한 고수준 API를 제공한다.

 

텐서플로 2.0부터는 케라스 API만 남기고 고수준 API를 모두 정리했고, 케라스는 텐서플로의 핵심 API가 되었다. 이제는 케라스와 텐서플로가 거의 동의어가 된 셈이다.

 


 

 

 

학습을 마치고

머신러닝을 공부할 때는 강의를 먼저 들은 것과 책 내용을 정리한 것을 하나의 포스트에 담았고 다른 포스트에 실습한 것을 올렸었다. 하지만 이렇게 하니 실습할 때는 글을 중복으로 쓰기도 그렇고 설명이 거의 없는 상태로 실행 화면만 보여주게 되었다. 

이번에 학습할 때는 이런 점을 보완해서 중간에 학습한 부분까지만 학습과 실습을 함께 한 부분을 발행하기로 했다. 훨씬 이해도 잘 되고 더 잘 들어오는 것 같았다.

 

오늘은 사실 공부하기가 정말 싫은 날이었다. 하루 종일 잠과 사투를 벌였지만 그래도 끝까지 공부하는 걸 놓지는 않았다. 곧 외출을 가야 할 시간이 되어 두 번째 내용은 정리하지 못할 것 같다.