튜토리얼: 다층 퍼셉트론
이 초보자용 튜토리얼에서는 이미지 분류를 위해 더 복잡한 신경망을 구축하고, 신경망이 실제로 어떻게 작동하는지에 대한 몇 가지 핵심 내용을 다룹니다. 이 글은 AI 번역본입니다. 오역이 있을 경우 댓글로 알려 주세요.
Created on September 15|Last edited on September 15
Comment
이 영상에서는 이미지 분류를 위한 더 복잡한 신경망을 구축하고, 신경망이 어떻게 작동하는지에 관한 몇 가지 세부 내용을 다룹니다.
프로젝트
주제
- 원-핫 인코딩
- 새로운 손실 함수: 범주형 교차 엔트로피
- 새로운 활성화 함수: ReLU
- 데이터 정규화
- 드롭아웃으로 과적합 줄이기
다층 퍼셉트론
출력이 0인지 1인지에 따라 숫자 5를 분류하는 퍼셉트론을 만드는 법을 알게 되었으니, 이제 0부터 9까지 모든 숫자를 인식하도록 모델을 어떻게 확장해야 할까요?
놀랍게도 정답은 숫자마다 하나씩, 총 10개의 퍼셉트론을 병렬로 두는 것입니다. 각 퍼셉트론은 특정 숫자에 대한 분류를 담당합니다. 예를 들어 0을 분류하는 퍼셉트론, 1을 분류하는 퍼셉트론, 2를 분류하는 퍼셉트론 … 이런 식입니다. 어떤 이미지에 대해, 가장 높은 값을 출력한 퍼셉트론에 따라 해당 숫자를 예측합니다. 예를 들어 손글씨 7의 이미지를 입력하면, ‘퍼셉트론 7’이 1에 매우 가까운 값을 출력하고, 나머지 퍼셉트론들은 0을 출력하길 기대합니다.

다중 클래스 퍼셉트론에서의 손실 함수는 각 퍼셉트론에 대해 우리가 기대하는 이상적인 출력(타깃)과 실제 출력 사이의 차이입니다.

원-핫 인코딩
숫자 3이 주어졌을 때 우리가 기대하는 이상적인 출력은 ‘001000000’입니다. 3을 인식하는 퍼셉트론이 1을 출력하고, 나머지 퍼셉트론들은 모두 0을 출력하는 것이죠. 라벨(3)을 이런 형식(001000000)으로 변환하기 위해 원-핫 인코딩을 사용합니다.

원-핫 인코딩은 매우 일반적인 방식으로, 숫자를 이진 배열로 변환합니다. 코드에서는 20–23번째 줄에서 이를 확인할 수 있습니다. perceptron-linear.py학습 데이터 라벨과 테스트 데이터 라벨을 모두 원-핫 인코딩으로 변환해, 모델 출력과 비교할 수 있도록 합니다.
numpy 라이브러리를 확인하여 ‘to_categorical’ 함수가 어떻게 동작하는지 더 알아보세요.
활성화 함수
모델을 실행해 보면 정확도가 대략 16% 정도 나옵니다(결정적이지 않으므로 값은 달라질 수 있습니다). 머신러닝에서는 먼저 무작위 추측으로 어느 정도의 정확도를 얻을 수 있는지 고려해야 합니다. 숫자는 10개이고 데이터가 고르게 분포되어 ��으므로, 무작위로 맞히면 약 10%의 정확도가 나옵니다.
좋은 출발이지만, 이 모델은 더 개선할 수 있습니다. 가장 먼저 할 일은 활성화 함수를 바로잡는 것입니다. 우리의 타깃 값은 0과 1이지만, 가중합은 어떤 값이든 될 수 있다는 점을 기억하세요. 따라서 그 가중합을 0과 1 사이의 숫자로 변환하는 방법이 필요합니다.
이를 위해 활성화 함수를 사용할 수 있습니다. 시그모이드나 소프트맥스 활성화 함수는 가중합을 받아 출력 값을 0과 1 사이로 압축합니다. 분류 문제를 다룰 때는 마지막 층에 항상 소프트맥스 활성화 함수를 사용해 출력이 0과 1 사이가 되도록 제한해야 합니다. 활성화 함수를 포함한 코드는 다음에 있습니다 perceptron-logistic.py.
이렇게 하면 모델의 성능이 크게 향상되지만, 여전히 개선할 수 있는 부분이 남아 있습니다.
범주형 교차 엔트로피
첫 번째 영상에서 우리는 손실 함수의 개념을 소개했습니다. 절대 오차와 평균 제곱 오차의 차이, 그리고 각각을 어떤 상황에서 사용해야 하는지도 살펴보았습니다. 하지만 분류 문제를 다룰 때는 손실 함수로 범주형 교차 엔트로피를 사용하는 것이 좋습니다.

범주형 교차 엔트로피 손실은 신경망이 결과의 실제 확률을 출력하도록 유도합니다. 우리가 원하는 정답이 1일 때, 예측이 0이면 손실이 무한대로 커지고, 1에 가까워질수록 손실이 점점 줄어듭니다(손실 함수는 값이 낮을수록 더 좋다는 점을 기억하세요). 이는 모델이 정답이 아님을 100% 확신하지 않는 한, 확률을 0으로 출력하지 않음을 의미합니다.
이렇게 하면 성능이 꽤 많이 좋아집니다. 이제 정확도를 더 높이려면 데이터 쪽을 개선해 볼 수 있습니다.
데이터 정규화
신경망은 스케일 불변이 아닙니다. 대부분의 신경망 라이브러리는 입력 범위를 매우 중요하게 다루며, 데이터를 0에서 1 사이로 정규화하면 훨씬 더 좋은 결과를 얻을 수 있습니다. 우리의 경우 입력은 픽셀 값으로, 범위가 0부터 255까지입니다. 모든 픽셀 값을 0과 1 사이의 숫자로 변환(데이터 정규화)하려면 각 값을 255로 나눕니다. 전체 코드는 perceptron-normalize.py에 있습니다.
이 변경만으로도 큰 도움이 됩니다. 정확도가 15%에서 90%로 올라갑니다!!
디버깅 요약
여기서는 머신러닝 모델을 디버깅하는 일반적인 기법들을 살펴보았습니다. 첫째, 가중치 합을 0과 1 사이의 값으로 변환하기 위해 소프트맥스 활성화 함수를 추가합니다. 둘째, 각 범주의 실제 확률을 출력하도록 손실 함수를 범주형 교차 엔트로피로 변경합니다. 셋째, 학습 데이터를 정제하고 정규화합니다.
다층 퍼셉트론
이제 퍼셉트론 한 층이 잘 작동하고 있지만, 모델을 더 최적화하려면 어떻게 해야 할까요? 현재 모델은 개별 픽셀과 레이블 간의 관계만 포착합니다. 픽셀들 사이의 상호작용을 인식하도록 만들려면 퍼셉트론에 몇 개의 레이어를 추가해야 합니다.
다층 퍼셉트론은 한 층의 퍼셉트론 출력값을 받아 다른 퍼셉트론 층의 입력으로 사용합니다. 이렇게 하면 입력층과 출력층 사이에 퍼셉트론으로 이루어진 “은닉층”이 생깁니다. 이 은닉층은 동작 방식은 출력층과 같지만, 분류를 수행하는 대신 단순히 숫자 값을 출력합니다.
일반적으로 은닉층에서는 ReLU라는 활성화 함수를 사용합니다. 정류 선형 유닛(ReLU) 활성화 함수는 음수 값을 간단히 잘라내는 방식입니다. 이 선형 함수는 매우 빠르기 때문에 은닉층에 특히 적합합��다.

열어 주세요 mlp.py이 코드는 40번째 줄에 한 줄만 추가된 점을 제외하면 우리의 퍼셉트론 모델과 매우 유사합니다. 이제 숨은 노드가 여러 개 있는 두 번째 밀집층이 추가되었습니다. config.hidden_nodes 기본값은 100으로 설정되어 있지만, 다른 값으로도 시도해 볼 수 있습니다.
Config.hidden_nodes = 100//line 40model.add(Dense(config.hidden_nodes, activation=’relu’)
이제 모델을 실행해 보면, 학습 정확도가 검증 정확도보다 높아지는 것을 발견할 수 있습니다. 시간이 지남에 따라 학습 정확도는 계속 향상되지만, 검증 정확도는 그대로 머무를 것입니다. 이러한 현상을 과적합이라고 합니다.
과적합과 드롭아웃

과적합은 모델이 학습 데이터를 지나치게 구체적으로 학습하여 새로운 입력에 일반화하지 못할 때 발생합니다. 학습 데이터의 정확도가 검증 정확도보다 높다면 모델이 과적합되었다고 판단할 수 있습니다. 검증 정확도는 모델이 이전에 보지 못한 데이터에서의 성능을 평가하므로, 단순한 정확도보다 모델 성능을 더 잘 보여 주는 지표입니다.
과적합은 머신러닝에서 매우 큰 문제입니다. 모델을 개선하기 위해 복잡도를 높이면, 오히려 과적합이 더 심해질 수 있기 때문입니다. 일반적인 경험칙으로, 모델이 과적합 상태라면 모델을 더 화려하게 만드는 어떤 시도도 성능을 떨어뜨릴 뿐입니다. 먼저 과적합을 해결해야 합니다. 다행히 과적합을 줄이는 데 정말 효과적이면서 사용하기 쉬운 알고리즘이 있습니다. 바로 드롭아웃입니다.

해결책은 입력값의 일부(이 경우 픽셀 값)를 0으로 설정하는 것입니다. 왜 이것이 도움이 될까요? 드롭아웃은 네트워크가 각 분류에 대해 한 가지 이상의 근거를 학습하도록 강제합니다. 오른쪽 위의 어떤 픽셀이 숫자가 7일 때에만 항상 켜진다고 상상해 보세요. 그러면 우리의 네트워크는 학습 데이터의 손실을 최소화하기 위해, 손글씨 숫자가 7인지 판단하려면 오른쪽 위 픽셀만 보면 된다고 기꺼이 학습할 것입니다. 드롭아웃은 일정 비율의 값이 가려지기 때문에, 숫자가 7인지 결정하기 위한 여러 경로를 네트워크가 학습하도록 만듭니다.
우리는 다층·다중 클래스 퍼셉트론을 디버깅하면서 데이터 정규화와 과적합 같은 흔한 문제를 해결해 정확도를 크게 끌어올렸습니다. 하지만 여전히 이 고전적인 데이터셋에서 낼 수 있는 최고 정확도까지는 도달하지 못했습니다. 다음 튜토리얼에서는 합성곱 신경망을 살펴보겠습니다.
Add a comment