1. 분류 알고리즘
머신러닝에서 데이터 분류 알고리즘은 트레이닝 데이터의 특성과 상관관계 등을 분석한 후에
임의의 입력 데이터에 대해서 그 결과를 어떤 종류의 값으로 나눌 수 있는지 ,
즉 분류할 수 있는지를 예측합니다
아래 이미지는 분류 알고리즘의 도식화입니다.
위 이미지처럼 데이터를 2개 집단 이상으로 나누어 분류하는 알고리즘을
분류 알고리즘이라 합니다.
2. 로지스틱 회귀
데이터의 특성과 분포를 가장 잘 나타내는 직선을 먼저 찾고 , 이직선을 기준으로 데이터를 위아래 또는
왼쪽이나 오른쪽 등으로 분류하는 방법을 로지스틱회귀라고 합니다
이러한 로지스틱 회귀는 분류 알고리즘 중에서도 정확도가 상당히 높은 것으로 알려져 있어서 신경망 ,
즉 딥러닝에서도 기본적인 컴포넌트로 사용됩니다.
컴포넌트는 기존의 코딩 방식에 의한 개발에서 벗어나 소프트웨어 구성단위 (module) 를 미리 만든 뒤
필요한 응용기술을 개발할 때 이 모듈을 조립하는 기술을 의미합니다
로지스틱 회귀 알고리즘을 정리해보면 아래의 그림과 같이 트레이닝 데이터를 입력으로 받아서
회귀 부분에서는 최적의 직선을 찾고 , 그 직선을 마탕으로 분류 부분에서는 위 아래 등으로 나누어서
최종 출력값으로 True (1) 또는 False(0) 등을 갖도록 분류해 줍니다
예를 들어 성적에 따른 Pass, Fail여부를 예측하는 등의 경우에서 사용할 수 있습니다.
3. 시그모이드 함수
시그모이드 함수에 대한 정의입니다.
아래의 그림과 같이 입력값 z=0 에서 함수값은 0.5, 입력 값 z>0 인 경우 함수값은 1 에 가까워지며 ,
입력값 z<0 인 경우에는 함수값이 0 에 수렴합니다. 즉, 모든 입력값에 대한 함수의 출력이
0 과 1 사이의 값이 되는 함수를 시그모이드 함수라고하며 y = sigmoid(z) = 1/1+e^-z(z=Wx+b) 형태로 나타납니다
시그모이드 함수에 대한 해석입니다.
시그모이드 함수는 0 과 1 사이 값으로 계산되기 때문에 시그모이드 함수의 결과를 확률로해석하기도 합니다 .
예를 들어 시그모이드 함수값을 0.75 라고 할 때 , True 상태로 정의할 수도 있지만 상황에 따라서
결과가 나올 확률이 75% 라고 해석하기도 합니다
분류에서의 손실함수에 대한 대수적 표현입니다.
최종 출력값은 시그모이드 함수에 의해서 0 과 1 사이의 값으로 표시되며 ,
이러한 출력값은 확률로 해석할 수 있기 때문에 분류 시스템의 오차값을 나타내는 손실함수는
아래의 식과 같은 로그를 포함한 대수식으로 표현되며 , 크로스 엔트로피라고 부릅니다
$$y=\dfrac{1}{1+e^{-\left( wx+b\right) }},t_{i}=0or1$$
$$\begin{aligned}l \left( W,b\right) =-\sum ^{n}_{i=1}\{ t_{i}\log y_{i}+\left( 1-t_{i}\right) \ log\left( 1-y_{i}\right) \} \end{aligned}$$
$$W=W-\alpha \dfrac{\partial l(W,b)}{\partial W},b=b-\alpha \dfrac{\partial l( W,b) }{\partial b}$$
여기서 알파 값은 학습률을 뜻합니다.
이 손실함수의 유도를 알아보겠습니다.
분류의 최종 출력값 y 는 sigmoid 함수에 의해 0~1 사이의 값을 가지는 확률적인 분류 모델이므로 ,
다음과 같이 확률변수 C 를 이용해 출력값을 나타낼 수 있습니다
p(c=1|x) = y = sigmoid(Wx+b)이고, (c=0|x)=1-p(c=1|x)=1-y라고 가정하겠습니다.
여기서 p(c=1|x)는 x가 1로 분리될 확률을 의미하고 given이라 부릅니다.
아래 식은 손실함수의 유도 식입니다.
$$p( c= t|x) =y^{t}\left( 1-y\right) ^{1-t}$$
↓
$$\begin{aligned}L\left( W,b\right) =\prod ^{n}_{i=1}p\left( c=t_{i}| x\right) =\ \prod ^{n}_{i=1}yt_i\left( 1-y_{i}\right) ^{1-t_{i}}\end{aligned}$$
↓
$$\begin{aligned}-\ln L\left( W,b\right) =-\Sigma _{i=1}^{n}\{ t_{i}\log y_{i}+\left( 1-t_{i}\right) \ \log \left( 1-y_{i}\right) \} \end{aligned}$$
4. 로지스틱 회귀 파이썬 구현
import numpy as np
# 학습데이터 준비
x_data = np.array([2,4,6,8,10,12,14,16,18,20]).reshape(10,1)
t_data = np.array([0,0,0,0,0,0,1,1,1,1]).reshape(10,1)
학습 데이터 입니다.
reshape를 사용해 10행 1열의 행렬로 변경합니다.
# 임의의 직선 z= Wx+b 정의
W = np.random.rand(1,1)
b = np.random.rand(1)
print(x_data.shape,t_data.shape)
print(W,W.shape,b,b.shape)
임의의 직선인 z = Wx+b를 정의합니다.
W와 b는 랜덤 값을 가지며 W는 1행1열의 행렬, b는 스칼라입니다.
# 크로스 엔트로피 정의
def sigmoid(z):
return 1/(1+np.exp(-z))
def loss_func(x,t):
delta = 1e-7 # log 무한대 발산 방지 log0이 되면 안되기 때문임
z = np.dot(x,W)+b
y = sigmoid(z)
return -np.sum(t*np.log(y+delta)+(1-t)*np.log((1-y)+delta))
크로스 엔트로피를 정의하고 손실률 함수를 정의합니다.
임의의 직선 z를 입력받으면 1/(1+e^-z)를 리턴합니다.
손실률 함수는 log0가 되는것을 방지하기 위해 delta 변수를 생성하고
z는 W와x의 행렬 곱을 한것과 스칼라 b를 더한 값입니다.
y는 크로스 엔트로피 함수에 z를 넣은 값입니다.
# 수치미분 numerical_derivative 및 utility 함수 정의
def numerical_derivative(f,x): # f는 미분하고자 하는 다변수 함수, x는 모든 변수를 포함하고 있는 numpy 객체(배열, 행렬)등
delta_x = 1e-5 #lim에 해당되는 작은 값
grad = np.zeros_like(x) # 계산된 수치미분 값 저장 변수
it = np.nditer(x, flags =['multi_index'],op_flags=['readwrite'])# 모든 입력변수에 대해 편미분하기 위해 사용
while not it.finished:
idx = it.multi_index # x에대한 편미분 후 y에 대한 편미분 실행 [1.0,2.0]이라면 1.0 편미분 후 2.0 편미분
tmp_val = x[idx] # numpy 타입은 mutable이므로 원래 값 보관
x[idx] = float(tmp_val)+delta_x #하나의 변수에 대해 수치미분 계산
fx1 = f(x) # f(x+delta_x) 전체에 대해 계산해야 하기 때문에 x[idx]가 아닌 x를 넣어줌
x[idx] = tmp_val - delta_x
fx2=f(x) # f(x-delta_x)
grad[idx] = (fx1-fx2)/(2*delta_x)
x[idx] = tmp_val
it.iternext()
return grad
def loss_val(x,t):
delta = 1e-7 # log 무한대 발산 방지 log0이 되면 안되기 때문임
z = np.dot(x,W)+b
y = sigmoid(z)
return -np.sum(t*np.log(y+delta)+(1-t)*np.log((1-y)+delta))
def predict(test_data):
z = np.dot(test_data,W)+b
y = sigmoid(z)
if y>=0.5:
result = 1
else:
result = 0
return y,result
수치미분에 대한 함수를 불러오고
값이 바뀔 수 있으므로 다시 손실 함수를 재정의합니다.
다음 예측 함수를 정의합니다.
만약 예측률이 0.5이상이면 1을 반환하고
0.5 미만이면 0을 반환합니다.
# 학습률 초기화 및 손실함수가 최소가 될 때까지 W,b 업데이트
learning_rate = 1e-2
f = lambda x: loss_func(x_data,t_data) # loss_func에 x_data,t_data가 들어감
print("Initial loss value = ",loss_val(x_data,t_data))
for step in range(50001):
W-= learning_rate * numerical_derivative(f,W) # w에 대한 수치미분
b-= learning_rate * numerical_derivative(f,b) # b에 대한 수치미분
if(step % 5000==0):
print("step = ",step,"loss value = ",loss_val(x_data,t_data))
학습률을 변수로 설정하고
f변수에 lambda를 이용해 loss_func함수에 데이터를 전달합니다.
반복문에서 W값과 b값을 구한 후 step에 따른 손실률을 출력합니다.
step이 반복될 수록 손실률이 떨어지는 모습을 볼 수 있습니다.
# 3과 17에 대한 미래 값 예측
test_data = np.array([3.0])
(real_val_1,logical_val_1) = predict(test_data)
print(real_val_1,logical_val_1)
test_data = np.array([17.0])
(real_val_1,logical_val_1) = predict(test_data)
print(real_val_1,logical_val_1)
3과 17에 대한 예측 값입니다.
0과 1로 잘 예측한 모습을 볼 수 있습니다.
1.416...e-09는 지수표현식으로 0의 근사치입니다.
'머신러닝' 카테고리의 다른 글
[파이썬] scikit-learn 기초 사용법 (0) | 2023.09.04 |
---|---|
[파이썬] 로지스틱 회귀 알고리즘 활용 (0) | 2023.06.01 |
[파이썬] 다변수 함수의 수치미분, 선형 회귀와 경사하강법 (0) | 2023.05.22 |
[파이썬] 합성함수, 체인 룰 , 수치 미분 (0) | 2023.05.18 |
[파이썬] boston 집 값 예측 ( 결정트리 회귀, 랜덤 포레스트 회귀 ) (0) | 2023.05.16 |