<목차>
• 분류(Classification)란?
분류는 주어진 입력 데이터를 미리 정의된 클래스 또는 범주로 구분하는 작업을 의미한다. 즉 비연속적인 값을 예측한다.
지도학습의 한 유형으로, 모델을 훈련시키기 위해 레이블(정답)이 지정된 훈련 데이터를 사용한다. 각 입력 데이터 포인트는 특징(feature)으로 구성되어 있고, 모델은 이러한 특징을 기반으로 해당 데이터가 어떤 크랠스에 속하는지 예측한다.
클래스 또는 범주의 수가 2개면 이진 분류라고 하며, 3개 이상이면 다중클래스 분류(Multiclass Classification)라고 한다.
이진 분류(Binary Classification)
두 개의 클래스 중 하나로 분류하는 문제다. 예를 들어, 이메일이 스팸인지 아닌지를 판별하는 문제가 있다.
다중 클래스 분류(Multiclass Classification)
세 개 이상의 클래스 중 하나로 분류하는 문제다. 손글씨 숫자를 인식하거나 동물 종을 분류하는 문제가 다중 클래스 분류에 해당한다.
분류가 사용되는 분야는 다음과 같다.
금융 : 고객의 신용 위험을 평가하는 데 사용
의료 : 질병을 진단하는 데 사용
보안 : 침입을 감지하는 데 사용
소비자 : 제품의 선호도를 예측하는 데 사용
NOTE : 앞으로 다룰 퍼셉트론, 로지스틱 회귀, SVM과 신경망은 두 클래스의 경계면에 대한 함수(경계면을 나타내는 수식)를 학습한다. |
• 퍼셉트론(Perceptron)
퍼셉트론은 인공 신경망의 기초를 이루는 간단한 형태의 인공 뉴런이다.
그렇기 때문에 다중 퍼셉트론은 신경망까지의 개념으로 확장될 수 있다.
프랑크 로젠블라트(Frank Rosenblatt)에 의해 1957년에 제안되었으며, 이는 선형 분류 문제를 위한 간단한 모델이다.
퍼셉트론의 구조
입력층 -> 가중치 -> 편향 -> 출력층 |
손글씨가 악필인 것은... 아쉽다.
동작 원리를 보면 입력층에서 입력값을 받은 후 가중치와 계산 후 합산하여 활성화 함수를 통해서 임계값을 구한다.
이를 수식으로 표현하면 다음과 같다.
z = w1*x1 + w2*x2 + ..., wn-1 * xn-1 + wn * xn y = step(z) |
각각의 요소를 좀 더 자세히 설명하면 다음과 같다.
퍼셉트론의 요소
입력(input) | 각각의 입력은 하나의 특성(feature)을 나타내며, 이 특성은 실제 데이터에서 추출된 값이다. 위 그림을 참고하면 'x1, x2, ..., xn-1, xn'까지의 값들이 입력층에 해당하는 입력값이다. |
가중치(Weight) | 가중치는 해당 입력값에 대한 중요도를 나타내며, 모델이 학습하는 파라미터다. 위 그림을 참고하면 'w0, w1, w2, ..., wn-1, wn' 값들이 가중치에 해당한다. |
활성화 함수 (Activation Function) |
가중치를 곱한 입력값들의 합에 활성화 함수를 적용하여 출력값을 생성한다. 활성화 함수는 일반적으로 계단 함수(Step Function)를 사용하며, 출력이 특정 임계값을 넘으면 1, 그렇지 않으면 0을 출력한다. 활성화 함수에는 'Sign, Sigmoid, Tanh, ReLU, Leaky ReLU' 함수 등이 있다. |
임계값(Threshold) | 활성화 함수의 출력이 결정되는 임계값이다. 임계값을 초과하면 1, 아니면 0을 출력한다. 이를 통해서 분류를 한다. |
편향(Bias Node) | 편향 또는 바이어스 노드라고 불리는 해당 값은 입력 데이터의 평균값을 조절하는 역할을 한다. 편향의 역할은 입력값이 모두 0일 때에도 퍼셉트론이 활성화 되도록 하는 것이다. 즉, 편향을 통해 원점을 지나도록 하여 더 다양한 패턴을 학습할 수 있다. 위 그림을 통해 보면 x0의 값에 해당한다. |
퍼셉트론의 특성
1. 선형 분류
퍼셉트론은 선형 분리 가능(Linearly Separable)한 문제만을 풀 수 있다.
즉, 입력 공간에서 클래스를 구분하는 초평면(Hyperplane)이 존재하는 경우에 효과적으로 작동할 수 있다.
NOTE 초평면(Hyperplane)이란?
초평면이란 결정 경계(Decision Boundary)를 나타내는 용어다.
예를 들어, 2차원 입력 공간에서는 직선이 초평면이 될 수 있다. 해당 직선은 두 클래스(카테고리, 범주)를 나누는 경계를 형성하여, 입력값이 해당 경계를 넘어가면 하나의 클래스로 분류되고 그렇지 않은 경우에는 다른 클래스로 분류하는 기준이 된다.
즉, 초평면은 학습 과정에서 가중치와 편향을 조절하여 분류를 결정하는 경계선이 되고, 퍼셉트론은 이러한 초평면을 학습하여 데이터를 분류한다.

<R - 결정 경계>
# 필요한 라이브러리 로드
library(ggplot2)
# 데이터 생성을 위한 시드 설정
set.seed(123)
# 무작위로 2차원 데이터 생성
data <- data.frame(
x1 = runif(100, 0, 10), # 0에서 10까지의 무작위 x1 값
x2 = runif(100, 0, 10) # 0에서 10까지의 무작위 x2 값
)
# 퍼셉트론의 초평면을 기준으로 클래스 레이블 생성
data$label = factor(ifelse(2 * data$x1 - 1.5 * data$x2 + 5 + rnorm(100) > 0, 1, 0))
# 초평면을 나타내는 함수 정의
perceptron_hyperplane <- function(x1) {
return(1.5 * x1 - 5) / 2
}
# 산점도와 퍼셉트론 초평면 시각화
ggplot(data, aes(x = x1, y = x2, color = label)) +
geom_point() +
geom_abline(slope = 1.5, intercept = 5/2, linetype = "dashed", color = "blue") +
labs(title = "Perceptron Hyperplane Example",
x = "X1",
y = "X2",
color = "Label") +
theme_minimal()
2. 단일 뉴런
퍼셉트론은 하나의 뉴런으로 이루어져 있다. 이는 입력과 가중치의 선형 조합을 계산하고 그 결과를 활성화 함수에 통과시켜 출력을 생성한다. 다만 여러 퍼셉트론을 결합하여 다중 퍼셉트론(MLP)과 같은 복잡한 신경망을 생성할 수 있다.
3. AND, OR, NOT 연산
퍼셉트론은 선형 분리가 가능한 문제에만 적용이 가능하기 때문에 XOR 같은 비선형 문제를 해결하기에는 한계가 있다.
그렇기 때문에 AND, OR, NOT 연산만을 지원하며 XOR 연산을 해결하기 위해 다중 퍼셉트론이 등장했다.
<퍼셉트론의 AND, OR, NOT 연산 자세한 내용 + XOR 연산>
<AND 연산 : 논리곱>
입력된 값이 모두 참일 경우에만 참이 출력되는 논리 연산을 수행한다.

import numpy as np
# AND 연산자
def AND_gate(x1, x2):
inputs = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.7
result = np.sum(inputs * w) + b
# return 1 if result > 0 else 0
if result > 0:
print(1)
return 1
else:
print(0)
return 0
print("and 연산자")
AND_gate(0, 0) # 0
AND_gate(1, 0) # 0
AND_gate(0, 1) # 0
AND_gate(1, 1) # 1
<OR 연산자 : 논리합>
입력 중 하나 이상이 참이면 참이 출력되는 논리 연산이다.

# OR 연산자
def OR_gate(x1, x2):
inputs = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.2
result = np.sum(inputs * w) + b
if result > 0:
print(1); return 1
else:
print(0); return 0
print("OR 연산자")
OR_gate(0, 0) # 0
OR_gate(1, 0) # 1
OR_gate(0, 1) # 1
OR_gate(1, 1) # 1
<NOT 연산자 : 부정>
def NOT_gate(x):
w = -0.5
b = 0.5
result = x * w + b
if result > 0:
print(1); return 1
else:
print(0); return 0
# AND, OR 함수에서 if문의 print 결과를 주석처리한 후 출력하면 깔끔하다.
print("NOT AND 연산자")
NOT_gate(AND_gate(0, 0)) # 1
NOT_gate(AND_gate(1, 0)) # 1
NOT_gate(AND_gate(0, 1)) # 1
NOT_gate(AND_gate(1, 1)) # 0
print("NOT OR 연산자")
NOT_gate(OR_gate(0, 0)) # 1
NOT_gate(OR_gate(1, 0)) # 0
NOT_gate(OR_gate(0, 1)) # 0
NOT_gate(OR_gate(1, 1)) # 0
<XOR 연산자 : 배타적 논리합>
두 입력 값이 서로 다를 때만 결과가 참이 되고, 두 입력 값이 같으면 결과가 거짓이 되는 연산이다.
일반적으로 퍼셉트론으로는 구현이 불가능하며 다중 퍼셉트론을 이용하여 구현할 수 있다.
두 개의 은닉층을 사용하며 활성화 함수로는 시그모이드 함수를 사용한다.
아래 코드는 위에서 사용한 AND, OR, NOT 연산자들을 이용하여 구현하였다.

def XOR_gate(x1, x2):
result = OR_gate(AND_gate(x1, NOT_gate(x2)), AND_gate(NOT_gate(x1), x2))
print(result)
return result
print("XOR 연산자")
XOR_gate(0, 0) # 0
XOR_gate(1, 0) # 1
XOR_gate(0, 1) # 1
XOR_gate(1, 1) # 0
4. 빠른 학습
퍼셉트론은 단일 뉴런으로 간단하면서도 학습이 빠르다. 결정경계를 통해서 선형 분리 가능한 문제를 처리하기 때문에 보통의 성능으로 빠른 학습이 가능하다.
5. 과적합(Overfitting)에 취약
과적합이란 간단히 말해서 학습 데이터(Traning Data)에서는 높은 성능을 보이지만 처음 보는 데이터에는 낮은 성능을 보이는 현상이다.
과적합은 머신러닝에서 자주 발생하는 현상으로 특징의 수를 줄이거나 여러 제한 사항을 넣거나, 간단한 알고리즘을 사용하여 해결하는 등 여러 방법을 사용할 수 있다. 전통적인 단일 퍼셉트론에는 과적합을 억제하는 기능이 없다.
과적합의 원인으로는 학습 데이터 양 부족, 모델이 너무 복잡하거나, 특성의 과다 활용, 지나친 학습 시간과 반복, 드롭아웃(정규화), 데이터 불균형 등이 있다.
<TIP : 과소적합(Underfitting)이란?>
과소적합은 학습 데이터에 대해 너무 과하게 학습하여 생기는 과적합과는 반대되는 현상으로 학습 데이터에 대해 너무 단순하게 학습되어, 학습 데이터와 테스트 데이터 모두 성능이 낮게 나타나는 현상이다.
모델이 너무 단순하거나, (다양한)학습 데이터의 양이 적거나 훈련 방법에 문제(너무 과도한 정규화, 잘못된 특징 선택, 클래스 불균형 등)가 있을 경우 발생한다.
6. 온라인 학습 방식(Online Learning)
퍼셉트론은 온라인 학습 방식이다. 온라인 학습은 데이터를 한 번에 하나씩 순차적으로 학습하며, 새로운 데이터가 도착할 때마다 실시간으로 모델을 업데이트 한다.
특징을 나열하면 모델은 즉시 데이터를 사용하여 가중치를 업데이트하고 적응한다.
메모리 효율이 좋고, 실시간으로 변하는 데이터에 대해 유용하다.
빠른 학습이 가능하지만 노이즈나 이상치에 민감할 수 있다.
데이터가 끝없이 생성되는 스트리밍 데이터와 같은 경우 유용하다.
<TIP : 배치 학습(Batch Learning)이란?>
배치 학습은 온라인 학습과는 상반되는 개념으로 전체 데이터 세트를 한 번에 모델에 제공하고, 모델은 전체 데이터에 대한 학습을 수행한다.
특징으로는 전체 데이터 세트에 대한 핵습을 한 번에 진행하므로 높은 계산 비용을 필요로 한다.
더 안정적이고 일관된 학습 결과를 제공한다.
대량의 데이터를 모아 한 번에 처리하는 데 유리하며, 학습이 완료된 후에만 모델을 업데이트한다.
• 가중치 결정(1) - 경사하강법과 손실함수, 힌지 손실
퍼셉트론에 대해 공부를 하면서 의문이 생기기 시작했다. 가중치는 어떤 원리로 부여하는 건가?
이는 경사 하강법(Gradient Descent)에 대해 숙지해야 한다. 경사 하강법은 비용 함수(손실 함수, Loss Function) 또는 오차 함수(Error Function)를 최소화하는 방향으로 가중치를 조정하는 최적의 알고리즘 중 하나이다.
비용 함수는 실제 출력과 기대 출력 간의 차이를 측정하는 함수로 이 차이를 최소화하기 위해 가중치를 조정하면 된다.
즉 같은 용어인 세 개의 함수는 이렇게 구성되어 있다.
[비용함수 = 손실함수 = 오차 함수] = (실제값 - 예측값)
여기서 가중치 벡터를 w, 입력된 값의 벡터를 x, 정답 레이블(분류될 범주)을 t(1 OR -1)이라고 표현하면 퍼셉트론에서 사용하는 손실 함수인 힌지 손실(Hinge Loss)를 다음과 같이 표현할 수 있다.
[TIP : 손실 함수(Loss Function)의 종류]
해당 게시글에서 설명하고 있는 힌지 함수는 퍼셉트론과 SVM(서포트 벡터 머신)에서 주로 사용하는 손실 함수다.
각각의 손실 함수에 대해 설명하면 다음과 같다.
1. 힌지 손실(Hinge Loss)
분류 모델에서 사용되며, 마진을 최대화하도록 하는 데 중점을 둔다. 여기서 마진이란 결정 경계와 가장 가까운 데이터의 위치 사이의 거리를 가르키며, 마진이 클수록 결정 경계가 더 안정적이며, 새로운 데이터에 대한 일반화 성능이 좋다.
2. 평균 제곱 오차(Means Squared Error, MSE)
회귀 문제에서 사용된다. 회귀 분석에 대한 게시글에도 잘 정리되어 있으므로 참고하면 좋다.
실제 값과 예측 값 간의 제곱 오차의 평균을 계산한 값이다.
3. 교차 엔트로피 손실(Corss-Entropy Loss)
분류 문제에서 사용되며, 예측된 확률 분포와 실제 분포 간의 차이를 측정한다.
4. 로그 손실(Log Loss 또는 Binary Cross-Entropy Loss)
이진 분류에서 사용되며, 예측된 확률과 실제 레이블 간의 로그 변환을 사용하여 손실을 계산한다.
여기서 'y'는 't', 'w * x = f(x)'이다.
그러면 위의 식 중 퍼셉트론의 힌지 함수를 기준으로 해석하면 아래와 같다.
-t * w * x > 1 인 경우
값의 결과가 1을 초과한 경우 0을 반환한다. 이는 곧 손실이 없다는 뜻이다.
-t * w * x <= 1 인 경우
1 - t * w * x 이므로 여유가 부족하거나 오분류된 경우로 1과 같거나 작다면 손실이 발생했다는 뜻이다.
만약 이해가 안된다면 일반식의 y 또는 퍼셉트론 식의 t에 분류가 되는 1 또는 -1의 값을 대입해서 계산해보면 된다.
[TIP : 힌지 손실 그래프]

힌지 손실은 그래프를 보면 경첩(힌지)처럼 생겼기 때문에 이름이 붙여졌다.
값이 0보다 작을 때 즉, 잘못 분류하였을 때 y축 loss(손실) 값은 증가하는 것을 알 수 있다.
반면 제대로 분류한 경우에는 0이 된다. 예측값이 크게 틀릴수록 손실값은 선형으로 증가하는 특성이 있다.
import numpy as np
import matplotlib.pyplot as plt
def hinge_function(t, w, x_values):
return np.maximum(0, -t * w * x_values)
# 가중치와 편향을 설정
t = 1
w = 1 # 가중치
b = -0.5 # 임의로 정한 편향, 계산식에는 추가하지 않았다.
# 입력 데이터 생성
x_values = np.linspace(-3, 3, 300) # 라인 범위 -3 ~ 3까지 300개의 값을 지정.
# 힌지 함수 값 계산
hinge_values = hinge_function(t, w, x_values) # 편의상 편향값(b)을 제외했다
# 그래프 그리기
plt.plot(x_values, hinge_values, label='Hinge Function')
plt.axhline(0, color='black', linewidth=0.5, linestyle='--', label='y=0')
plt.axvline(0, color='black', linewidth=0.5, linestyle='--', label='x=0')
plt.xlabel('x_value')
plt.ylabel('max(0, -t * w * x)')
plt.title('Perceptron Hinge Function')
plt.legend()
plt.grid(False)
plt.show()
잘못 분류된 데이터의 수가 되도록 작아지는 loss값을 찾아 가중치를 적용하면 이 전체 데이터에 대한 손실값의 합도 최소가 된다.
• 가중치 결정(2) - 확률적 경사하강법
가중치 결정(1) 마지막 결론에서도 언급하였지만 손실 함수 loss 즉, 손실값이 최소가 될 때 가장 좋다고 했다.
이를 평가하기 위해 일반화 되어 모델이 데이터에 부합한지를 나타내는 것이 목적 함수(Objective Function)이다.
목적 함수 = 모든 데이터에 대한 손실 함수값의 합
정리하면 목적 함수가 최소라면 가장 최적의 상태라고 할 수 있다.
이런 상태를 만들어 주는 가중치 w값을 구하는 것이 '모델 학습'이다.
최적의 파라미터(w) 최적화에는 확률적 경사하강법(Stochastic Gradient Descent)을 많이 사용한다.
SGD는 최적의 목적 함수 값을 구하기 위해 경사가 심한 부분(골짜기)을 조금씩 내려가면서 최적의 파라미터 값을 구한다.
현실 문제에서는 해당 골짜기가 어디에 있는지 모르기 때문에 경사가 가장 심한 곳에서부터 파라미터를 수정해 나간다.
이 과정에서 목적 함수의 값이 가장 작은 지점에 도달하면 해당 지점의 파라미터 값을 최적값으로 지정한다.
이때 파라미터를 한 번에 어느 정도 수정할지를 결정하는 것이 학습률(Learning Rate)이라고 한다.
파라미터 수정 폭을 '학습률 * 경사'로 표현하는 데 학습률을 높게 주면 골짜기를 지나쳐 버릴 수 있다. 반대로 너무 적게 지정하면 계산하는 횟수가 증가하므로 학습 속도가 느리다는 단점이 있다.
보통 간단한 방법에서는 학습률은 고정되어 있지만 신경망에서는 해당 값의 선택을 동적으로 수정하는 다양한 방법이 있다.
[TIP : 확률적 경사하강법은 양의 기울기를 가진 2차함수의 기울기를 하나하나 계산한다고 생각하면 된다.]
이렇게 최적의 값으로 구해진 가중치 값은 퍼셉트론의 예상값을 계산하는데 사용된다.
핵심 내용을 요약하면
퍼셉트론 예상값은 가중치 벡터(w)와 입력 벡터(x)의 곱셈합의 부호에 따라 결정된다.
따라서 해당 곱셈합을 계단 함수(Step Function)에 통과시킨 것과 같다.
왜냐하면 계단 함수는 입력값을 +1 또는 -1로 바꿔준다.
계단 함수 같은 활성화 함수는 출력값을 비선형 변환해준다.
단, 일반적으로 계단 함수는 0과 1을 출력하지만 퍼셉트론 이진 분류에서는 편의를 위해 1과 -1로 표현한다.
'파이썬(Python) > 머신러닝 공부' 카테고리의 다른 글
머신 러닝(Machine Learning) 알고리즘의 선택 (0) | 2023.12.26 |
---|---|
머신러닝(Machine Learning) - 개요 / 시작 (0) | 2023.12.14 |