반응형


+ Tensorflow로 XOR  학습을 구현하기


XOR 학습을 수동으로 계산하지 않고, tensorflow의 api를 사용하면 심플해진다.

복잡한 네트웍도 쉽게 구현이 가능하다.


노드의 개수 및 레이어를 2-4-1 로 구성.

입력층에 노드 2개(feature 개수. x1, x2)

은닉층에는 4개 

출력층은 1개의 노드. (Y)

back-propagation을 위한 골치 아픈 작업(미분)들을 할 필요없이 api 하나로 학습 가능! activation function도 원하는대로 쉽게 변경하고, 학습 알고리즘은 쉽게 바꿀 수 있다.


#!/usr/bin/env python3

# -*- coding: utf-8 -*-

"""

Created on Tue May 23 14:56:53 2017


@author: crazyj

"""



import numpy as np

import tensorflow as tf


# trainint set

X_train = np.array( [[0,0], [0,1], [1,0], [1,1]])

T_train = np.array( [[0], [1], [1], [0]] )



# placeholder

X = tf.placeholder(tf.float32, [None, 2])

T = tf.placeholder(tf.float32, [None, 1])


# variable

W1 = tf.Variable(tf.truncated_normal([2,4]))

b1 = tf.Variable(tf.zeros([4]))

W2 = tf.Variable(tf.truncated_normal([4,1]))

b2 = tf.Variable(tf.zeros([1]), dtype=tf.float32)


# model

A1 = tf.matmul(X, W1)+b1

Z1 = tf.sigmoid(A1)

A2 = tf.matmul(Z1, W2)+b2

Z2 = tf.sigmoid(A2)


learn_rate = 0.1

Cost = tf.reduce_mean(tf.reduce_sum(tf.square(Z2-T), 1))

train = tf.train.GradientDescentOptimizer(learn_rate).minimize(Cost)


predict = Z2


sess = tf.Session()

sess.run(tf.global_variables_initializer())

for i in range(5000):

    _train, _Cost = sess.run([train, Cost], feed_dict={X:X_train, T:T_train})

    print( "cost=", _Cost)

    

_predict = sess.run([predict], feed_dict={X:X_train})

print("predict=", _predict)

print("result=", np.array(np.array(_predict)>=0.5, np.int))




결과

cost= 0.021748

cost= 0.0217359

cost= 0.0217239

predict= [array([[ 0.10571096],

       [ 0.86153752],

       [ 0.84178925],

       [ 0.17739831]], dtype=float32)]

result= [[[0]

  [1]

  [1]

  [0]]]


+ 코드 설명

# trainint set

X_train = np.array( [[0,0], [0,1], [1,0], [1,1]])

T_train = np.array( [[0], [1], [1], [0]] )

훈련 데이터는 당연히 xor의 입력 조합에 따른 결과를 훈련시킨다. (0,0) -> 0 , (0,1) -> 1 , (1,0) -> 1 , (1,1)->1


# placeholder

X = tf.placeholder(tf.float32, [None, 2])

T = tf.placeholder(tf.float32, [None, 1])

플레이스 홀더는 텐서플로우내에서 돌아갈 입출력 변수들이라고 보면 된다. 노드에서 변수가 되는 것을 X 입력층은 (?,2) 매트릭스 크기(로우는 임의의 개수, 컬럼은 2개(x1,x2)), 출력층 T는 (n,1) 매트릭스 형태로 선언한다.


# variable

W1 = tf.Variable(tf.truncated_normal([2,4]))

b1 = tf.Variable(tf.zeros([4]))

W2 = tf.Variable(tf.truncated_normal([4,1]))

b2 = tf.Variable(tf.zeros([1]), dtype=tf.float32)

텐서 플로우 변수들을 정의한다. 이것은 그래프에 구성될 노드들의 변수의 형태를 정의한다.

네트웍을 2-4-1로 구성할 것이므로 여기에 따른 weight를 담을 변수와 bias 변수의 형태는 다음과 같다.

2개 노드는 placeholder로 X이고, 2-4연결되는 W(웨이트)는 2행(입력노드개수) 4열(출력노드개수) 매트릭스이다. bias는 4개(출력노드개수)이다.

4-1로 연결되는 파트의 W는 4x1 이렇게 b는 1개 이렇게 구성한다. 초기값들은 랜덤하게 채워준다. bias는 0으로 초기화해준다.


# model

A1 = tf.matmul(X, W1)+b1

Z1 = tf.sigmoid(A1)

A2 = tf.matmul(Z1, W2)+b2

Z2 = tf.sigmoid(A2)

이제 빠진 히든 노드들과 출력층 노드들을 구성한다.

2-4-1네트웍에서 2개는 X, 4개는 A1으로 정하고,

A1 = X x W1 + b1 으로 정의한다.

Z1=은 A1에 활성화함수 sigmoid를 적용한다.


A2=Z1 x W2 + b2로 정의한다. 앞 노드의 출력 결과에 weighted sum이다.

Z2 = A2에 sigmoid를 적용한 것으로 최종 output이다.


learn_rate = 0.1

Cost = tf.reduce_mean(tf.reduce_sum(tf.square(Z2-T), 1))

train = tf.train.GradientDescentOptimizer(learn_rate).minimize(Cost)

predict = Z2

이제 학습방식을 정한다.
cost function은 오차 제곱법을 쓰고, 학습방식은 gradient descent를 사용하여 훈련 그래프를 만든다.
예측값은 최종 노드 출력인 Z2가 된다.


sess = tf.Session()

sess.run(tf.global_variables_initializer())

for i in range(5000):

    _train, _Cost = sess.run([train, Cost], feed_dict={X:X_train, T:T_train})

    print( "cost=", _Cost)

텐서플로우로 학습을 돌린다. 세션을 만들고, 초기화하여 5000번 학습한다. 그래프의 꼭지인 train을 집어 넣고, feed_dict로 플레이스 홀더 X, T에 훈련 데이터를 넣는다.  학습1회마다 cost값을 출력해 본다. 


_predict = sess.run([predict], feed_dict={X:X_train})
학습 완료후, 학습이 잘 되었는지  입력값 X_train을 넣고 출력값을 생성한다.

print("result=", np.array(np.array(_predict)>=0.5, np.int))

최종 결과로 시그모이드 함수에서 0.5이상이면 1로 미만이면 0으로 출력하여 binary 분류를 한다.





반응형


XOR  학습

단층 퍼셉트론으로는 비선형이 학습이 안된다.

따라서 멀티 퍼셉트론을 사용. 입력 레이어를 제외하고 Two-Layer 구성.

Sigmoid를 사용. 0/1 binary구별로 함.



#!/usr/bin/env python3

# -*- coding: utf-8 -*-

"""

Created on Tue May 23 14:10:10 2017


@author: crazyj

"""


import numpy as np

import os


# xor simple network.

#   X(2) - 2 - Y(1)

# sigmoid activation function use.

# manual gradient

#

# if fail?, try again!

#   local minima problem exists... 

#   make deep and wide network.

#



X = np.array( [[0,0], [0,1], [1,0], [1,1]])

T = np.array( [[0], [1], [1], [0]] )


np.random.seed(int(os.times()[4]))


W1 = np.random.randn(2,2)

b1 = np.zeros([2])

W2 = np.random.randn(2,1)

b2 = np.zeros([1])



def Sigmoid(X):

    return 1/(1+np.exp(-X))


def Predict(X,  W1, b1, W2, b2):

    Z1 = np.dot(X, W1)+b1

    A1 = Sigmoid(Z1)

    Z2 = np.dot(A1, W2)+b2

    A2 = Sigmoid(Z2)

    Y = A2

    return Y


def Cost(X, W1, b1, W2, b2, T):

    epsil = 1e-5

    Z1 = np.dot(X, W1)+b1

    A1 = Sigmoid(Z1)

    Z2 = np.dot(A1, W2)+b2

    A2 = Sigmoid(Z2)

    Y = A2

    return np.mean(-T*np.log(Y+epsil)-(1-T)*np.log(1-Y+epsil))



def Gradient(learning_rate, X, W1, b1, W2, b2, T):

    Z1 = np.dot(X, W1)+b1

    A1 = Sigmoid(Z1)

    Z2 = np.dot(A1, W2)+b2

    A2 = Sigmoid(Z2)

    deltaY = A2-T

    deltaA1 = np.dot(deltaY, W2.T) * (A1*(1-A1))

    m = len(X)

    

    gradW2 = np.dot(A1.T, deltaY)

    gradW1 = np.dot(X.T, deltaA1)

    W2 = W2-(learning_rate/m)*gradW2

    b2 = b2-(learning_rate/m)*np.sum(deltaY)

    W1 = W1-(learning_rate/m)*gradW1

    b1 = b1-(learning_rate/m)*np.sum(deltaA1)

    return (W1, b1, W2, b2)



for i in range(3000):

    J= Cost(X,W1,b1,W2,b2,T)

    W1,b1,W2,b2 = Gradient(1.0, X, W1, b1, W2, b2, T)

    print ("Cost=",J)


Y = Predict(X, W1, b1, W2, b2)

print("predict=", Y)




결과


Cost= 0.351125685078

predict= [[ 0.50057071]

 [ 0.49643107]

 [ 0.99648031]

 [ 0.00640712]]



실패?

다시 실행을 반복하다 보니 성공할때도 있다??? local minima 문제가 있음.

이를 해결하기 위해서는 여러번 시도해서 코스트가 낮아질 때까지 처음부터 반복(initialize 가 중요).하던가 network을 deep & wide하게 설계한다.


Cost= 0.00403719259697

predict= [[ 0.00475473]

 [ 0.99634993]

 [ 0.99634975]

 [ 0.00409427]]

이건 성공 결과.


반응형

binary classification은 두 개로 분류하는 것이다.

이 binary classification을 하는 것을 여러개 붙이면 다중 분류도 가능하다.

즉,  isAclass() 로 A이냐 아니냐 판단,   isBclass()로 B이냐 아니냐 판단. isCclass()로 C이냐 아니냐 하는 판단 모듈들이 있으면, 조합하면 A, or B or C로 분류할 수 있다.


(x1, x2)의 특성을 같는 데이터 X를 세 가지(A,B,C)로 분류한 학습 데이터가 있다고 하자.   새로운 X가 올 경우 학습모델을 갖고 분류를 추정할 수 있다.

아래 그림에서 검은색은 훈련데이터로 이미 A, B, C 분류 결과도 있다. 이를 기반으로 학습을하여  다중 분류 모델을 만들고, 실습데이터(빨간색)로 분류하여 표시한 그래프이다.  

원하는대로 적절하게 잘 분류하였다.


훈련 데이터는 (x1,x2) 좌표와 클래스 구분결과를 one hot인코딩한 데이터이다.



아래는 sigmoid만 사용한 방식.

# deep learning test

# Multinomial Classification... Softmax

#         choose learning.... A,B,C

# A=left side, B=bottom side, C=right,up side


PLOTSHOW=TRUE


# training , X1=1 (bias)

X=rbind(  c(1,1,1), c(1,1,5), c(1,2,6), c(1,2,3), c(1,4,6), 

          c(1,2,1), c(1,3,2), c(1,4,2), c(1,6,3), c(1,8,1), 

          c(1,1,10), c(1,4,8), c(1,6,6), c(1,7,5), c(1,9,3) )


# training result Y

Y=rbind ( c(1,0,0), c(1,0,0), c(1,0,0), c(1,0,0), c(1,0,0),

          c(0,1,0), c(0,1,0), c(0,1,0), c(0,1,0), c(0,1,0),

          c(0,0,1), c(0,0,1), c(0,0,1), c(0,0,1), c(0,0,1))


# searching parameter, A's W column, B's, C's

W=cbind( c(1,2,3), c(2,3,2), c(3,4,1) )


# drawing 

if ( PLOTSHOW ) {

  plot(1:10,1:10,type="n")

  pchs = vector(length = nrow(X))

  pchs[which(Y[,1]==1)]="A"

  pchs[which(Y[,2]==1)]="B"

  pchs[which(Y[,3]==1)]="C"

  points(X[,2], X[,3], pch=pchs)

}



# most high probablity select

Onehot = function(T) {

  OH=matrix(0, nrow=nrow(T), ncol=ncol(T))

  ohw=apply(T,1,function(x) return(which.max(x)))

  for (i in seq(ohw))

    OH[i,ohw[i]]=1

  return (OH)

}


# logistic function: sigmoid

# 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)

  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) %*% (((Y-1)*exp(X%*%W)+Y) / (exp(X%*%W)+1)) ) 

  return (W)

}


print( Cost(X, W, Y) )


#learning

alpha=0.1

for ( i in 1 : 600 ) {

  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] ))

  }

}


# test

# classify

xmat = matrix( c(1,1,1, 1,2,4, 1,4,1, 1,9,2, 1,6,8, 1,3,4,

                 1,8,8, 1,6,6, 1,2,8, 1,9,5), byrow = T, ncol=3 ) 

qy = G( xmat, W )

print (xmat)

print (qy)

qy2=Onehot(qy)

print(qy2)



# drawing 

if ( PLOTSHOW ) {

  pchs = vector(length = nrow(xmat))

  pchs[which(qy2[,1]==1)]="A"

  pchs[which(qy2[,2]==1)]="B"

  pchs[which(qy2[,3]==1)]="C"

  points(xmat[,2], xmat[,3], pch=pchs, col="red")

}

#dev.off()



아래는 softmax의 확률 함수와 cost를 계산하는 함수는 다음과 같다.

# softmax ; make probablity ; S(yi)=e^yi / Sigma(e^yi)

# cross entropy cost function

# D(S,L) = Sigma Li.* -log(y^)


softmax와 cross entropy로 학습한 방식

# deep learning test
# Multinomial Classification... Softmax
#         choose learning.... A,B,C
# A=left side, B=bottom side, C=right,up side

PLOTSHOW=TRUE

# training , X1=1 (bias)
X=rbind(  c(1,1,1), c(1,1,5), c(1,2,6), c(1,2,3), c(1,4,6), 
          c(1,2,1), c(1,3,2), c(1,4,2), c(1,6,3), c(1,8,1), 
          c(1,1,10), c(1,4,8), c(1,6,6), c(1,7,5), c(1,9,3) )

# training result Y
Y=rbind ( c(1,0,0), c(1,0,0), c(1,0,0), c(1,0,0), c(1,0,0),
          c(0,1,0), c(0,1,0), c(0,1,0), c(0,1,0), c(0,1,0),
          c(0,0,1), c(0,0,1), c(0,0,1), c(0,0,1), c(0,0,1))

# searching parameter, A's W column, B's, C's
W=cbind( c(1,2,3), c(2,3,2), c(3,4,1) )

# drawing 
if ( PLOTSHOW ) {
  plot(1:10,1:10,type="n")
  pchs = vector(length = nrow(X))
  pchs[which(Y[,1]==1)]="A"
  pchs[which(Y[,2]==1)]="B"
  pchs[which(Y[,3]==1)]="C"
  points(X[,2], X[,3], pch=pchs)
}


# softmax ; make probablity ; S(yi)=e^yi / Sigma(e^yi)
# yi = xw
Softmax = function(X, W) {
  T=exp(X%*%W)
  sume=apply(T, 1, sum)
  return (T/sume)
}

# most high probablity select
Onehot = function(T) {
  OH=matrix(0, nrow=nrow(T), ncol=ncol(T))
  ohw=apply(T,1,function(x) return(which.max(x)))
  for (i in seq(ohw))
    OH[i,ohw[i]]=1
  return (OH)
}

# cross entropy cost function
Cost =function (X, W, Y) {
  # D(S,L) = Sigma Li.* -log(y^)
  m = nrow(X)
  return ( (-1)/m * sum(Y*log(Softmax(X,W)) ) )
}


Gradient = function (X, W, Y, alpha) {
  m = nrow(X)
  W = W - alpha/m * ( t(X) %*% (Softmax(X,W)-Y) )
  return (W)
}

print( Cost(X, W, Y) )

#learning
alpha=0.1
for ( i in 1 : 2000 ) {
  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] ))
  }
}

# test
# classify
xmat = matrix( c(1,1,1, 1,2,4, 1,4,1, 1,9,2, 1,6,8, 1,3,4,
                 1,8,8, 1,6,6, 1,2,8, 1,9,5), byrow = T, ncol=3 ) 
qy = Softmax( xmat, W )
print (xmat)
print (qy)
qy2=Onehot(qy)
print(qy2)


# drawing 
if ( PLOTSHOW ) {
  pchs = vector(length = nrow(xmat))
  pchs[which(qy2[,1]==1)]="A"
  pchs[which(qy2[,2]==1)]="B"
  pchs[which(qy2[,3]==1)]="C"
  points(xmat[,2], xmat[,3], pch=pchs, col="red")
}
#dev.off()



'AI(DeepLearning)' 카테고리의 다른 글

[tf] XOR tensorflow로 학습구현  (0) 2017.05.23
[tf] XOR manual solve  (0) 2017.05.23
[R] binary classification  (0) 2017.05.19
[R] linear regression Normal Equation  (0) 2017.05.19
[R] linear regression (multi variable) 더하기 학습  (0) 2017.05.11
반응형

바이너리 분류 문제를 풀어보자.

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

반응형

linear regression을 학습하는데, Normal Equation 방정식으로 풀기.

+Computing parameters analytically

Gradient descent 말고 다른 방법은 많다. 그 중에 하나가  Normal Equation

Alpha (학습률 learning rate)가 필요없다. 반복(iteratoin)도 필요없다.

단,    구하는 비용이 크다.  N x N 매트릭스가 필요.

n이 크면 느림. 100정도? 10000을 초과하면 gradient descent 방식이 낫다.


example)
m=4 (training data count)
n=4 (attributes/features)

=house price=
house size, # rooms , # floor, age of home , price
 x1,            x2,           x3,         x4,                y
data1..
data2.
data3..
data4..
가장 좌측에 x0 컬럼을 추가하여 모두 1로 설정. (x0=1)  (for bias)

X=matrix [ x0, x1, ... x4] ; 4x5 dim ; m x (n+1)
Y=[y] ; 4x1 dim  ; m x 1

Y = X S
X^-1 Y = S
S = (X^-1) Y
그러나 X의 inverse 벡터(X^-1)를 구하려면... 정사각행렬이어야 한다.
그래서 정사각 행렬로 먼저 변환해줘야 한다.

Y = X S
X^t Y = X^t X S     ; 왼쪽에 X^t(X의 transpose)를 곱함

(X^t X )^-1 X^t Y = (X^t X )^-1 (X^t X )  S    ; 왼쪽에 (X^t X)^-1 를 곱한다.
(X^t X )^-1 X^t Y = S

따라서 아래와 같이된다.


Octave에서는 :   pinv(X' * X)* X' * Y

R에서는 : W = solve( t(X) %*% X ) %*% t(X) %*% Y


example을 만들어 보자


# deep learning test

# linear regression ; test.. y=2x+1 learning 

#


# training , X1=1 (bias)

X=matrix( c(1,1,1 , 1,2,3), nrow=3 ) 


# training result Y

Y=matrix( c(3,5,7) ) 


# searching parameter, w1=bias 

W=c(2,2)



# H(X,W)=w1+ w2*x2

H = function (X, W) {

  H = X %*% W

  return (H)

}


Cost =function (X, W, Y) {

  m = nrow(X)

  return (sum((H(X,W)-Y)^2) / m)

}


NormalEquation = function (X, W, Y) {

  # no need alpha

  # no iteration

  # S =  inv( t(X) X ) t(X) Y

  W = solve( t(X) %*% X ) %*% t(X) %*% Y

  return (W)

}


print( Cost(X, W, Y) )


#learning

W = NormalEquation(X, W, Y)

print(paste(" Cost=", Cost(X,W,Y), " W1(b)=", W[1,1], " W2=", W[2,1]) )


# predict

qx = c(7,8,9)

xmat = cbind( rep(1, length(qx)), qx)

qy = H( xmat, W )

print (qx)

print (qy)



[1] 1

[1] " Cost= 3.15544362088405e-30  W1(b)= 1  W2= 2"

[1] 7 8 9

     [,1]

[1,]   15

[2,]   17

[3,]   19



'AI(DeepLearning)' 카테고리의 다른 글

[tf] XOR manual solve  (0) 2017.05.23
[R] multinomial classification. 다중분류  (0) 2017.05.19
[R] binary classification  (0) 2017.05.19
[R] linear regression (multi variable) 더하기 학습  (0) 2017.05.11
[R] linear regression  (0) 2017.05.11
반응형


더하기를 학습시키는 Model을 만들어보자.

구현은 R을 사용하여 간략히 작성.

전에 것과 큰 차이는 없고, x의 feature가 하나 늘어났음.


(X) -W-> (Y)


샘플 데이터는 

input X     Y

 x1 x2  x3 y

 1

 1 

 1

 2

 1

 2

 5

 1

 4

 2 6

 1

 2

 4

 1 3 3 6
 1 3

5

 1 4 4 8

 1

 5 1 6
 1 1 3 4
 1 1 4 5

X의 첫번째 컬럼에 1을 모두 준 것은 Matrix 연산시에 bias를 한 번에 계산하기 위해 x1를 1로 두었다. 이렇게 되면 w1을 bias로 볼 수 있다.

y값은 x2+x3이다. 더하기를 학습시키기로 한다.


X = (10, 3) shape     (1열에 모두 1을 추가. for bias)

Y = (10, 1) shape


W = (3, 1) shape    ( W1이 bias 역할을 수행한다.)   

훈련데이터 하나로 봤을 때, 입력이 3개(그중 하나는 bias를 위해 무조건 1로 고정)이고 출력은 1개 이다.



* linear 모델 디자인

H(x) = w*x+b 


b는 필요없고, matrix를 맞추면.

Hypothesis(Y~) = X * W   ; 10x3 * 3x1 = 10x1


* cost function

m = training set 개수; 10개

Cost = (1/m)  * Sigma ( (Y~-Y)^2 )


* learning

W:=W-alpha*Cost'

Cost 미분 = d Cost / d W

Cost' = 1/(2m) * Sigma ( (Y~-Y)*x )

alpha가 상수이기 때문에 2m이나 m이나 상관없다.


W = W-alpha * 1/m  * Sigma ( (Y~-Y)*x )

Sigma( (Y~-Y)*x ) 이 부분을 풀면

예측값(Y~)은 H(X,W)이고, Y(실측값)을 빼고, X를 곱한다.

shape은 왼쪽이 Y형태이니 (10,1), X는 (10,3)인데, matrix 곱을 해야 한다.

Y의 행과 X의 행은  훈련데이터 레코드를 구분하는 것이다. Y의 가로와 X의 가로가 곱해야 한다. 즉, 어느 한 쪽을 transpose해 주어야 함.

결과가 W의 shape모양이 나와야 한다. (3,1)

따라서

(3,10)*(10,1) = (3,1) 을 만들 수 있다.


W = W-alpha * 1/m  *  t(X) %*% (H(X,W)-Y) )



# deep learning test

# linear regression, multi vars. ADD learning.... y = x2+x3

#


# training , X1=1 (bias)

X=matrix( c(1,1,1, 1,2,3, 1,4,2, 1,2,2, 1,3,3, 1,3,2, 1,4,4, 1,5,1, 1,1,3, 1,1,4), byrow = T, ncol=3 ) 


# training result Y

Y=matrix( c(2, 5, 6, 4, 6, 5, 8, 6, 4, 5) ) 


# searching parameter, w1=bias 

#W=c(0, 0, 0)

W=rnorm(3)



# H(X,W)=w1+ w2*x2

H = function (X, W) {

  H = X %*% W

  return (H)

}


Cost =function (X, W, Y) {

  m = nrow(X)

  return (sum((H(X,W)-Y)^2) / m)

}


Gradient = function (X, W, Y, alpha) {

  m = nrow(X)

  W = W - alpha/m * ( t(X) %*% (H(X,W)-Y) )

  return (W)

}


print( Cost(X, W, Y) )


#learning

alpha=0.1

for ( i in 1 : 1000 ) {

  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( c(1,1,1, 1,2,4, 1,4,1, 1,2,2, 1,6,8, 1,30,45), byrow = T, ncol=3 ) 

qy = H( xmat, W )

print (xmat)

print (qy)



======================

[결과]

[1] 17.21935        => 처음에 에러가 높음

[1] "cnt= 100  Cost= 0.00734778231698152  W1(b)= 0.311519194482933  W2= 0.955780333009714  W3= 0.930195352334659"    => Cost가 감소함

[1] "cnt= 200  Cost= 0.00177641680389291  W1(b)= 0.153171902333706  W2= 0.978257487961482  W3= 0.965677519676141"

[1] "cnt= 300  Cost= 0.000429470624607385  W1(b)= 0.0753135990106769  W2= 0.989309352379876  W3= 0.983123866187081"

[1] "cnt= 400  Cost= 0.000103829808970766  W1(b)= 0.0370311924675553  W2= 0.99474348013076  W3= 0.991702117976784"

[1] "cnt= 500  Cost= 2.51021341465692e-05  W1(b)= 0.0182079894412524  W2= 0.997415404368608  W3= 0.995919986957054"

[1] "cnt= 600  Cost= 6.06874986055061e-06  W1(b)= 0.00895274651992987  W2= 0.998729171629903  W3= 0.997993884899299"

[1] "cnt= 700  Cost= 1.46719496656704e-06  W1(b)= 0.0044020055321717  W2= 0.999375142197631  W3= 0.999013606634366"

[1] "cnt= 800  Cost= 3.54712439857382e-07  W1(b)= 0.00216443665216407  W2= 0.999692761601513  W3= 0.999514996985255"

[1] "cnt= 900  Cost= 8.57560977625059e-08  W1(b)= 0.00106423901264822  W2= 0.999848932936186  W3= 0.999761527264368"

[1] "cnt= 1000  Cost= 2.07325920297307e-08  W1(b)= 0.000523279198266241  W2= 0.999925721335999  W3= 0.999882744552279"        => Cost가 거의 0이되었음. 학습 잘 됨.


     [,1] [,2] [,3]

[1,]    1    1    1

[2,]    1    2    4

[3,]    1    4    1

[4,]    1    2    2

[5,]    1    6    8

[6,]    1   30   45

          [,1]

[1,]  2.000332        ; 1+1

[2,]  5.999906        ; 2+4

[3,]  5.000109        ; 4+1

[4,]  4.000140        ; 2+2

[5,] 13.999140        ; 6+8

[6,] 74.993018        ; 30+45


완료



'AI(DeepLearning)' 카테고리의 다른 글

[tf] XOR manual solve  (0) 2017.05.23
[R] multinomial classification. 다중분류  (0) 2017.05.19
[R] binary classification  (0) 2017.05.19
[R] linear regression Normal Equation  (0) 2017.05.19
[R] linear regression  (0) 2017.05.11
반응형

R로 만들어본 linear regression


입력 x 1개에 대해 출력 y 1개를 만드는 추정 모델.


대략 y=2x+1 에 해당되는 학습데이터들이 있을 때 이를 학습해 보고, 테스트 데이터로 추정해 본다.


아래 그래프에서 검은 o은 학습 데이터, 빨간 o는 테스트 데이터로 추정해본 결과이다. 대략 비슷하게 잘 추정하였다. 



(X) -W-> (Y)


샘플 데이터는 

input X     Y

 x1 x2  y

 1

 1 

 2

 1

 2

 6

 1

 4

 10

 1

 6

 11

X의 첫번째 컬럼에 1을 모두 준 것은 Matrix 연산시에 bias를 한 번에 계산하기 위해 x1를 1로 두었다. 이렇게 되면 w1을 bias로 볼 수 있다.

y값이 대략 x의 2배  조금 큰 정도이다.


원래 input인 X의 크기는 아래와 같다.

X = (4, 1) shape

Y = (4, 1) shape

W = (1, 1) shape

b = (1,1) shape

여기서 b를 따로 계산하기 싫다면 아래와 같이 변경할 수 있다.


X = (4, 2) shape     (1열에 모두 1을 추가. for bias)

Y = (4, 1) shape

W = (2, 1) shape    ( W1이 bias 역할을 수행한다.)

b는 이제 생각할 필요없이 자동으로 계산된다.


* linear 모델 디자인

H(x) = w*x+b 


b는 필요없고, matrix를 맞추면.

Hypothesis(Y~) = X * W   ; 4x2 * 2x1 = 4x1


* cost function

m = training set 개수; 4개

Cost = (1/m)  * Sigma ( (Y~-Y)^2 )


* learning

W:=W-alpha*Cost'

Cost 미분 = d Cost / d W

Cost' = 1/(2m) * Sigma ( (Y~-Y)*x )

alpha가 상수이기 때문에 2m이나 m이나 상관없다.


W = W-alpha * 1/m  * Sigma ( (Y~-Y)*x )

Sigma( (Y~-Y)*x ) 이 부분을 풀면

예측값(Y~)은 H(X,W)이고, Y(실측값)을 빼고, X를 곱한다.

shape은 왼쪽이 Y형태이니 (4,1), X는 (4,2)인데, matrix 곱을 해야 한다.

Y의 행과 X의 행은  훈련데이터 레코드를 구분하는 것이다. Y의 가로와 X의 가로가 곱해야 한다. 즉, 어느 한 쪽을 transpose해 주어야 함.

결과가 W의 shape모양이 나와야 한다. (2,1)

따라서

(2,4)*(4,1) = (2,1) 을 만들 수 있다.

W = W-alpha * 1/m  *  t(X) %*% (H(X,W)-Y) )




# deep learning test

# linear regression ; test.. y=2x+1 near learning 

#


PLOTSHOW=TRUE


# training , X1=1 (bias)

X=matrix( c(1,1,1,1 ,

            1,2,4,6), ncol=2 ) 


# training result Y

Y=matrix( c(2,6,10, 11) ) 


# searching parameter, w1=bias 

W=c(2,2)



# drawing 

if ( PLOTSHOW ) {

  plot(1:20,1:20,type="n")

  points(X[,2], Y)

}




# H(X,W)=w1+ w2*x2

H = function (X, W) {

  H = X %*% W

  return (H)

}


Cost =function (X, W, Y) {

  m = nrow(X)

  return (sum((H(X,W)-Y)^2) / m)

}


Gradient = function (X, W, Y, alpha) {

  m = nrow(X)

  W = W - alpha/m * ( t(X) %*% (H(X,W)-Y) )

  return (W)

}


print( Cost(X, W, Y) )


#learning

alpha=0.1

for ( i in 1 : 500 ) {

  W = Gradient(X,W,Y,alpha)

  if ( i %% 50==0 ) {

    print(paste("cnt=", i, " Cost=", Cost(X,W,Y), " W1(b)=", W[1,1], " W2=", W[2,1]) )

  }

}


# predict

qx = c(3,5)

xmat = cbind( rep(1, length(qx)), qx)

qy = H( xmat, W )

print (qx)

print (qy)


# drawing 

if ( PLOTSHOW ) {

  

  abline(W[1,1], W[2,1]) # y axis bias, slope

  points(qx, qy, col="red")

}





+ Recent posts