[R] binary classification
바이너리 분류 문제를 풀어보자.
logistic regression을 하면 된다.
linear regression은 출력이 실수범위로 주어진 샘플들을 거의 만족하는 수식을 찾아내는 거고, 그 수식을 기반으로 새로운 임의의 입력에 대해서 출력을 하여 그 값이 추측값이다.
logistic regression은 분류의 문제로 출력은 0 또는 1이다. 따라서 출력 범위가 실수 전체가 아니라 0/1 바이너리이다.
이를 위해서 모델의 방식이 logistic function을 사용하게 된다. 0~1범위의 출력값을 갖는 함수를 이용하여 0에 가까운지 1에 가까운지로 0/1을 분류한다. sigmoid 함수를 사용할 경우 보통 0.5를 기준으로 분류.
여기서는 sigmoid 함수를 사용.
(x1,x2) -> O 또는 X로 구분하는 학습
아래의 검은 색은 학습 데이터로 이미 O, X가 지정되어 있는 데이터이다.
이를 학습하여, 빨간색의 점들을 O, X로 분류해 봤다.
왼쪽, 아래 부분들이 X, 오른쪽 상단 부분들이 O로 분류되는 모습이다. 테스트 데이터(빨간색)도 잘 분류하였다.
#
# deep learning test
#
# logistic regression( Binary classfication) multi vars.
# ADD learning.... y=x2+x3 and
# Decide big or low than 10
PLOTSHOW=TRUE
# training , X1=1 (bias)
X=matrix( c(1,1,1, 1,2,3, 1,4,2, 1,2,2, 1,5,4,
1,7,4, 1,2,9, 1,7,7, 1,10,3, 1,9,4), byrow = T, ncol=3 )
# training result Y
Y=matrix( c(0, 0, 0, 0, 0,
1, 1, 1, 1, 1) )
# searching parameter, w1=bias
W=c(0, 0, 0)
# drawing
if ( PLOTSHOW ) {
plot(1:10,1:10,type="n")
pchs = vector(length = nrow(X))
pchs[which(Y==0)]="X"
pchs[which(Y==1)]="O"
points(X[,2], X[,3], pch=pchs)
}
# G(X,W)=1/(1+e^-z) , z=WX
G = function (X, W) {
Z=X %*% W
G = 1/(1+exp(-Z))
return (G)
}
Cost =function (X, W, Y) {
m = nrow(X)
# Cost(W) = -1/m Sigma( y log(H(x))+(1-y)log(1-H(x)) )
return ( (-1)/m * sum(Y*log(G(X,W)) + (1-Y)*log(1-G(X,W))) )
}
Gradient = function (X, W, Y, alpha) {
m = nrow(X)
W = W - alpha/m * ( t(X) %*% (G(X,W)-Y) )
# w=w-alpha*cost'
# cost' = -1/m Sigma ( X( (y-1)e^wx + Y) /(e^wx+1) )
#W = W + alpha/m * ( t(X) %*% (((Y-1)*exp(X%*%W)+Y) / (exp(X%*%W)+1)) )
return (W)
}
print( Cost(X, W, Y) )
#learning
alpha=0.05
for ( i in 1 : 6000 ) {
W = Gradient(X,W,Y,alpha)
if ( i %% 100==0 ) {
print(paste("cnt=", i, " Cost=", Cost(X,W,Y), " W1(b)=", W[1,1], " W2=", W[2,1], " W3=", W[3,1] ))
}
}
# predict
xmat = matrix(runif(10*3, 0, 11), nrow=10, ncol=3)
xmat[,1]=1
#xmat = matrix( c(1,1,1, 1,2,4, 1,4,1, 1,9,2, 1,6,8, 1,3,4,
# 1,6,6, 1,4,6, 1,6,2), byrow = T, ncol=3 )
qy = G( xmat, W )
print (xmat)
print (qy)
threshold=0.5
qy2=ifelse(qy>threshold, 1, 0)
print(qy2)
# drawing
if ( PLOTSHOW ) {
pchs = vector(length = nrow(xmat))
pchs[which(qy2==0)]="X"
pchs[which(qy2==1)]="O"
points(xmat[,2], xmat[,3], pch=pchs, col="red")
# abline
m=- ( W[2]/W[3])
x1y0= (threshold-W[1])/W[2]
abline(x1y0, m)
}
출력결과
1] 0.6931472
[1] "cnt= 100 Cost= 0.506130153063577 W1(b)= -0.742347709743049 W2= 0.166960447480382 W3= 0.13719656124762"
[1] "cnt= 200 Cost= 0.426904719548934 W1(b)= -1.36454376946518 W2= 0.21941982410039 W3= 0.211042797611876"
[1] "cnt= 300 Cost= 0.371538453508252 W1(b)= -1.88474084142892 W2= 0.263640326808228 W3= 0.27307497177045"
... 학습
[1] "cnt= 5900 Cost= 0.0989403091216031 W1(b)= -9.1090676929688 W2= 0.894710399352723 W3= 1.08049771083572"
[1] "cnt= 6000 Cost= 0.0982119304342858 W1(b)= -9.16885104353332 W2= 0.900021687190386 W3= 1.08680663800592"
[,1] [,2] [,3]
[1,] 1 6.5452887 8.024256
[2,] 1 9.5209285 9.637048
[3,] 1 6.8177543 1.780934
[4,] 1 3.6139041 2.678026
[5,] 1 0.6012657 7.200270
[6,] 1 9.5897683 6.282960
[7,] 1 7.7645759 4.530263
[8,] 1 7.2534271 7.010700
[9,] 1 9.8989604 2.489668
[10,] 1 1.0309055 10.951213
[,1]
[1,] 0.9956916
[2,] 0.9999485
[3,] 0.2502662
[4,] 0.0471662
[5,] 0.3095129
[6,] 0.9981496
[7,] 0.9395143
[8,] 0.9931638
[9,] 0.9202843
[10,] 0.9749335
[,1]
[1,] 1
[2,] 1
[3,] 0
[4,] 0
[5,] 0
[6,] 1
[7,] 1
[8,] 1
[9,] 1
[10,] 1