Python에서 rpy2를 이용한 ROjbect 불러오기


rpy2 설치하기 (ubuntu)

R 구 버전 삭제
ubuntu 14.04는 기본적으로 3.0.1 버전을 설치한다.
rpy2는 guswo 3.2 버전 이상부터 동작하므로, 기본 보전인 2013년도 R을 설치하면 진행이 안된다.

우선 현재 구 버전 R이 설치되었다면 아래 방법으로 깨긋이 삭제 한다.

R을 실행해서 관련 package들이 어디에 설치 되어 있는지 확인 한다.

.libPaths() 

그리고 아래의 명령어로 삭제한다.

sudo apt-get remove r-base-core
sudo apt-get remove r-base
sudo apt-get autoremove

확인한 package 경로에 들어가서 남아있는 파일들이 없는지 확인 한다.

R 최신 버전 설치
Youtube 동영상: https://www.youtube.com/watch?v=Nxl7HDUyw0I
원본 방법: https://launchpad.net/~marutter/+archive/ubuntu/rrutter

필자는 동영상 처럼 Update방식으로 할 경우 충돌이나서 이전 버전을 완전히 지우고 새로 설치 하는 방법으로 진행 했다.

# Add PPA:
sudo add-apt-repository ppa:marutter/rrutter 

# Update ubuntu for upgrade:
sudo apt-get update

# install
sudo apt-get install r-base

rpy2 설치 하기
간단히 pip 명령어로 설치 할 수 있다.

pip install rpy2

아래와 같은 에러가 발생하면 R version이 구버전 이거나 중요 시스템 package들이 설치 안되서이다.
rpy2 error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

해결 방법은 아래의 package들을 모두 설치하는 것이다.

sudo apt-get install build-essential autoconf libtool pkg-config python-opengl python-imaging python-pyrex python-pyside.qtopengl idle-python2.7 qt4-dev-tools qt4-designer libqtgui4 libqtcore4 libqt4-xml libqt4-test libqt4-script libqt4-network libqt4-dbus python-qt4 python-qt4-gl libgle3 python-dev

통상 python-dev와 build-essential을 설치하지 않아서 발생 한다고 한다.
참고사이트: http://stackoverflow.com/questions/26053982/error-setup-script-exited-with-error-command-x86-64-linux-gnu-gcc-failed-wit

rpy2로 Rdata 불러오기

import rpy2.robjects as robjects
import pandas.rpy.common as com
import pandas as pd

# check the current working directory 
os.getcwd()

## load .RData and converts to pd.DataFrame
robj = robjects.r.load("seenPhoneStatus10FeaDfList.Rdata")

robjects.r('lapply(seenPhoneStatus10FeaDfList,dim)')

실행 결과

R object with classes: ('list',) mapped to:
<ListVector - Python:0x7f7b64129d40 / R:0x2e68950>
[IntVe..., IntVe..., IntVe..., ..., IntVe..., IntVe..., IntVe...]
  X: <class 'rpy2.robjects.vectors.IntVector'>
  R object with classes: ('integer',) mapped to:
<IntVector - Python:0x7f7b65bf67e8 / R:0x3f4ae18>
[    1038,       10]


Feature Selection with Caret (Auto)


자동 Feature Selection을 통해서 해당 Featrue가 Accurate Model을 생성하는데 필요한지 안한지를 결정할 수 있다.

기법들은 많이 있지만 인기있는 기술중 하나가Recursive Feature Elimination (RFE)방법 이다. 그리고 이 방법을 Caret R package에서 지원 한다.

Caret에서는 rfeInter와 rfe가 존재 한다.
하지만 재귀적 방법을 사용하는 rfe에 초점을 맞춘다.

rfe 함수의 필요 인자는 아래와 같다.

  • x, a matrix or data frame의 예측에 사용되는 feature들
  • y, 결과 백터값
  • sizes, subset의 크기를 결정하는 integer vector이다. 지정하지 않으면 ncol(x)로 설정 된다.
  • rfeControl, option을 포함 한다.

rfeControl 설정시 중요한것이 모델링에 사용할 function을 정하는 것이다.

control <- rfeControl(functions=nbFuncs, method="cv", number=10)

위경우 cross validation 방식으로 naive Baeys로 모델링 한다는 것이다.
그리고 cv는 10개로 쪼개서 수행 한다. 기본값이 10이다. 따로 설정안해도 number=10의 효과를 얻는다.

repeatedcv를 수행하기 위해서는 아래와 같다.

ctrl <- rfeControl(functions = lmFuncs,
                   method = "repeatedcv",
                   repeats = 5,
                   verbose = FALSE)

그 외에는 아래와 같다.

  • linear regression lmFuncs
  • random forests rfFuncs
  • naive Bayes nbFuncs

- bagged tress treebagFuncs

참고문헌

[1] Recursive Feature Elimination

[2] Feature Slection with the Caret R Package


'AI > Machine Learning with R' 카테고리의 다른 글

클래스 불균형을 다루는 방법 (Class Imbalance)  (1) 2017.07.20
Caret의 이해  (0) 2016.03.06
Cross Validation  (0) 2016.02.26
Ensemble method: Bagging (bootstrap aggregating)  (0) 2015.11.19
Bootstrapping  (0) 2015.11.19

R Notebook


Python의 Jupyter Notebook과 다르게 R의 경우 그동안 R Markdown만 있을뿐 Interative한 Document 타입이 없어서 불편 했었다.

하지만 이번 R Studio preview 업데이트로 막강한 Notebook기능이 업데이트 되었다.

Data Analysis시 좀 더 체계적인 문서와 관리가 가능해진 것 같다.

RStudio v1.0.44 Preview — Release Notes

  • Authoring tools for R Notebooks.
  • Integrated support for the sparklyr package (R interface to Spark).
  • Enhanced data import tools based on the readr, readxl and haven packages.
  • Performance profiling via integration with the profvis package.
  • Authoring tools for R Markdown websites and the bookdown package.
  • Many other miscellaneous enhancements and bug fixes.

동작 모습

아래와 같이 Notebook생성 기능이 새로 만들어 졌다.

그리고 아래와 같이 preview버튼으로 실행하고 옵션을 in panel로 하면 viewer 창에 결과가 보이고
interactive 하게 편집할 수 있도록 바뀐다.


R Markdown


R Studio가 1.0이상의 버전이 되면서 많은 부분들이 개선 되었다.
그것들에 대해서 하나씩 이야기해본다.

기본 R Markdown

아래처럼 HTML을 생성 할 때 Option으로 toc: truetoc_float: true를 설정하면 왼쪽에 제목에 따른 목차가 생성 되는 것을 알 수 있다. 추가 html옵션을 보려면 ?html_document를 실행 한다.

title: "Viridis Demo 2"
output: 
  html_document:
    toc: true
    toc_float: true

패널에 preview 표시

preview in viewer panel을 선택하면 안에서 표시 할 수 있게 된다.


Data를 그룹별로 요약 (Summarizing data)


특정 값에 따라서 그룹으로 나눈다음 특정 함수(평균, SD)를 적용하는 방법은 3가지가 있다.

  • ddply해당 함수는 plyr package를 통해서 쉽게 사용할 수 있다.
  • summarizeBy() 해당 함수는 doBy package를 이용해서 쉽게 사용할 수 있다.
  • aggregate() 해당 함수는 약간 어렵지만, 기본 R 함수이다.

주어진 데이터 형태

data <- read.table(header=TRUE, text='
 subject sex condition before after change
       1   F   placebo   10.1   6.9   -3.2
       2   F   placebo    6.3   4.2   -2.1
       3   M   aspirin   12.4   6.3   -6.1
       4   F   placebo    8.1   6.1   -2.0
       5   M   aspirin   15.2   9.9   -5.3
       6   F   aspirin   10.9   7.0   -3.9
       7   F   aspirin   11.6   8.5   -3.1
       8   M   aspirin    9.5   3.0   -6.5
       9   F   placebo   11.5   9.0   -2.5
      10   M   placebo   11.9  11.0   -0.9
      11   F   aspirin   11.4   8.0   -3.4
      12   M   aspirin   10.0   4.4   -5.6
      13   M   aspirin   12.5   5.4   -7.1
      14   M   placebo   10.6  10.6    0.0
      15   M   aspirin    9.1   4.3   -4.8
      16   F   placebo   12.1  10.2   -1.9
      17   F   placebo   11.0   8.8   -2.2
      18   F   placebo   11.9  10.2   -1.7
      19   M   aspirin    9.1   3.6   -5.5
      20   M   placebo   13.5  12.4   -1.1
      21   M   aspirin   12.0   7.5   -4.5
      22   F   placebo    9.1   7.6   -1.5
      23   M   placebo    9.9   8.0   -1.9
      24   F   placebo    7.6   5.2   -2.4
      25   F   placebo   11.8   9.7   -2.1
      26   F   placebo   11.8  10.7   -1.1
      27   F   aspirin   10.1   7.9   -2.2
      28   M   aspirin   11.6   8.3   -3.3
      29   F   aspirin   11.3   6.8   -4.5
      30   F   placebo   10.3   8.3   -2.0
 ')

ddply 사용

library(plyr)

# Run the functions length, mean, and sd on the value of "change" for each group, 
# broken down by sex + condition
cdata <- ddply(data, c("sex", "condition"), summarise,
               N    = length(change),
               mean = mean(change),
               sd   = sd(change),
               se   = sd / sqrt(N)
)
cdata
#>   sex condition  N      mean        sd        se
#> 1   F   aspirin  5 -3.420000 0.8642916 0.3865230
#> 2   F   placebo 12 -2.058333 0.5247655 0.1514867
#> 3   M   aspirin  9 -5.411111 1.1307569 0.3769190
#> 4   M   placebo  4 -0.975000 0.7804913 0.3902456

참고자료

http://www.cookbook-r.com/Manipulating_data/Summarizing_data/


'AI > R Basic' 카테고리의 다른 글

R Notebook  (0) 2016.11.02
R Markdown  (0) 2016.11.02
리스트 데이터 프레임을 단일 큰 데이터 프레임으로 변환, identical  (0) 2016.10.10
Word Cloud from PDF using R  (1) 2016.08.25
빈도분석 표와 백분율 구하기  (0) 2016.08.21

표준오차 (Standard Error)


평균의 표준 오차(평균의 SE)는 같은 모집단에서 여러 표본을 추출하는 경우 얻게 될 표본 평균 간의 변동성을 추정합니다. 평균의 표준 오차는 표본 간의 변동성을 추정하는 반면, 표준 편차는 단일 표본 내의 변동성을 측정합니다.

예를 들어, 312개의 배송 시간 랜덤 표본을 근거로 1.43일의 표준 편차가 있는 평균 배송 시간이 3.80일입니다. 이 숫자로 0.08일의 평균에 대한 표준 오차가 산출됩니다(1.43을 312 제곱근으로 나눈 값). 동일한 크기의 여러 랜덤 표본을 동일한 모집단에서 추출한 경우 서로 다른 표본 평균의 표준 편차는 약 0.08일이 됩니다.

평균의 표준 오차를 사용하여 표본의 평균이 모평균을 얼마나 정확하게 추정하는지 확인할 수 있습니다. 평균의 표준 오차의 하한 값은 모집단 평균의 더 정확한 추정치를 나타냅니다. 일반적으로, 표준 편차가 클수록 평균의 표준 오차가 더 크고 추정치가 덜 정확합니다. 표본 크기가 클수록 평균의 표준 오차가 더 작고 추정치가 더 정확하게 됩니다.

se   = sd / sqrt(N)

수식 유도

참고자료

http://stats.stackexchange.com/questions/89154/general-method-for-deriving-the-standard-error


'AI > Probability & Statistics (R)' 카테고리의 다른 글

정규성 검정  (3) 2016.08.20
비교 분석  (0) 2016.08.03
가설 검증과 추정  (0) 2016.08.03
이상치 제거 (Box-plot 해석을 통한)  (0) 2015.01.03
통계학: F-검정  (0) 2013.08.29

리스트 데이터 프레임을 단일 큰 데이터 프레임으로 변환


do.call 방식

id가 따로 생성되지 않아서 나중에 식별이 어렵다.

df <- do.call("rbind", listOfDataFrames)

plyr pakcage의 ldply이용

.id로 index를 만들기 때문에 여러므로 편리하다.
ldply을 사용하는것이 좋다.
plyr package를 반드시 부착 한다.

df <- ldply(listOfDataFrames, data.frame)
system.time({ df <- do.call("rbind", listOfDataFrames) })
user  system elapsed 
0.25    0.00    0.25 


ldply(phoneStatusDf, function(x){
  x[,2]  
})
system.time({ df2 <- ldply(listOfDataFrames, data.frame) })
user  system elapsed 
0.30    0.00    0.29
identical(df, df2)
[1] TRUE

빠른 속도: rbindlist

library("data.table")
rbindlist(listOfDataFrames, idcol=TRUE)

idcol의 옵션에 따라서 .id 컬럼이 생성된다.


'AI > R Basic' 카테고리의 다른 글

R Markdown  (0) 2016.11.02
Data를 그룹별로 요약 (Summarizing data)  (0) 2016.10.27
Word Cloud from PDF using R  (1) 2016.08.25
빈도분석 표와 백분율 구하기  (0) 2016.08.21
Vector 분할  (0) 2016.08.21

TensorFlow 기본 개념 (2)


연산은 Graph로 이뤄 진다.
Graph는 Session Context에 들어가서 처리 된다.
Data는 Tensor로 표현된다.
상태 정보는 Variables로 관리 된다.

Session

반드시 그래프의 실행은 Session안에서 이뤄져야 한다.
Session은 Graph ops를 CPUsGPUs와 같은 장치에서 실행 시킨다.
그리고 실행 결과로 ndarray object를 반환 한다.

Simple Example

Building the graph

import tensorflow as tf

# Create a Constant op that produces a 1x2 matrix.  The op is
# added as a node to the default graph.
#
# The value returned by the constructor represents the output
# of the Constant op.
matrix1 = tf.constant([[3., 3.]])

# Create another Constant that produces a 2x1 matrix.
matrix2 = tf.constant([[2.],[2.]])

# Create a Matmul op that takes 'matrix1' and 'matrix2' as inputs.
# The returned value, 'product', represents the result of the matrix
# multiplication.
product = tf.matmul(matrix1, matrix2)

위 코드는 Graph를 생성하는 코드이다.
현재 Default Graph는 3개의 Node로 구성된다.
두 개의 constant() 그리고 하나의 matmul() op 함수이다.

  • Matrix1: 1x2
  • Matrix2: 2x1

하지만, 지금은 정의만 한것이다. 앞선 기본개념에서도 언급 했듯이 TensorFlow는 정의 부분과 실행 부분이 나눠진다.
실제 seesion에서 해당 Graph를 실행해야 비로소 연산이 실행 된다.

Launching the graph in a session

# Launch the default graph.
sess = tf.Session()


# To run the matmul op we call the session 'run()' method, passing 'product'
# which represents the output of the matmul op.  This indicates to the call
# that we want to get the output of the matmul op back.
#
# All inputs needed by the op are run automatically by the session.  They
# typically are run in parallel.
#
# The call 'run(product)' thus causes the execution of three ops in the
# graph: the two constants and matmul.
#
# The output of the op is returned in 'result' as a numpy `ndarray` object.
result = sess.run(product)
print(result)
# ==> [[ 12.]]

# Close the Session when we're done.
sess.close()

위 코드는 Graph를 Launch하는 코드이다. 이를 위해서 Session object를 생성 한다.
어떠한 Argument도 없이 session을 생성하면 default graph로 실행 된다.

최종적으로 matrix연산을 수행한 후에 ndarry object 형태로 실수 12.이 반환 된다.

Session은 반드시 close시켜서 resource해제 시켜줘야 한다.

With block
with를 이용하면 자동으로 with block이 끝나는 지점에서 리소스를 반환하게 된다.

with tf.Session() as sess:
  result = sess.run([product])
  print(result)

TensorFlow의 구현은 Graph정의를 실행가능한 operation으로 변환하는 것을 말한다. 
그리고 이러한 operation은 현재 가능한 컴퓨팅 리소스 (CPU, GPU card)등에 할당 된다.
이 작업은 추상화되어 프로그래머가 명시적으로 해줘야할 것은 없다.

장치가 여러개일 경우

with tf.Session() as sess:
  with tf.device("/gpu:1"):
    matrix1 = tf.constant([[3., 3.]])
    matrix2 = tf.constant([[2.],[2.]])
    product = tf.matmul(matrix1, matrix2)
    ...

위와 같이 직접 하드웨어를 선택해서 처리 한다.

"/cpu:0": The CPU of your machine.
"/gpu:0": The GPU of your machine, if you have one.
"/gpu:1": The second GPU of your machine, etc.

Interactive Usage

# Enter an interactive TensorFlow Session.
import tensorflow as tf
sess = tf.InteractiveSession()

x = tf.Variable([1.0, 2.0])
a = tf.constant([3.0, 3.0])

# Initialize 'x' using the run() method of its initializer op.
x.initializer.run()

# Add an op to subtract 'a' from 'x'.  Run it and print the result
sub = tf.sub(x, a)
print(sub.eval())
# ==> [-2. -1.]

# Close the Session when we're done.
sess.close()

Tensor

Tensor는 n-dimensional array 도는 list를 말한다.

Variables

import tensorflow as tf

# Create a Variable, that will be initialized to the scalar value 0.
state = tf.Variable(0, name="counter")

# Create an Op to add one to `state`.

one = tf.constant(1)
new_value = tf.add(state, one)
update = tf.assign(state, new_value)

# Variables must be initialized by running an `init` Op after having
# launched the graph.  We first have to add the `init` Op to the graph.
init_op = tf.initialize_all_variables()

# Launch the graph and run the ops.
with tf.Session() as sess:
  # Run the 'init' op
  sess.run(init_op)
  # Print the initial value of 'state'
  print(sess.run(state))
  # Run the op that updates 'state' and print 'state'.
  for _ in range(3):
    sess.run(update)
    print(sess.run(state))

# output:

# 0
# 1
# 2
# 3

Graph의 실행 상태를 저장하는 것이 Variables의 특징이다.
위 예제에서의 Variables는 간단한 counter의 역할을 하게 된다.

  • assign() operation은 add()와 같은 graph상의 하나의 operation이다. 당연히 session.run()을 하기 전까지는 실행 되지 않는다.
  • Neural network에서 tensor에 weight값으 저장할 때 Variables를 사용하게 된다.

Fetches

input1 = tf.constant([3.0])
input2 = tf.constant([2.0])
input3 = tf.constant([5.0])
intermed = tf.add(input2, input3)
mul = tf.mul(input1, intermed)

with tf.Session() as sess:
  result = sess.run([mul, intermed])
  print(result)

# output:
# [array([ 21.], dtype=float32), array([ 7.], dtype=float32)]

Graph의 실행은 결국 run을 이용해서 수행하게 된다.

Feeds

input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.mul(input1, input2)

with tf.Session() as sess:
  print(sess.run([output], feed_dict={input1:[7.], input2:[2.]}))

# output:
# [array([ 14.], dtype=float32)]

이전 까지 예제들은 Constants와 Variables에 저장된 값을 가지고 graph를 연산하는 것을 배웠다.

동적으로 값을 전달하는 방법을 알아보자.
run()을 할 때 Argument로 전달할 수 있는 매커니즘을 말한다.

placeholder라는 이름으로 선언하면 run()을 할 때 값을 정해주는 기능으로 동작하게 된다. 
주의할 것은 정의를 하지 않으면 error를 발생 시킨다는 점이다. 반드시 초기화를 해줘야 한다.

작성코드

본 내용에 작성된 코드들은 Github를 통해서 공유하겠습니다.
주소: https://github.com/leejaymin/TensorFlowLecture/tree/master/0.Basic


이 때 까지 출판한 논문들을 이용해서 Word Cloud를 생성해 보았다.

저전력 컴퓨팅을 주로 했지만 어느 순간 부터 모델링을 하다보니 기계학습 내용도 많이 공부하게 됬다.

스스로의 학문적 근간이 모호해지는 상황이다.

최종적으로 생성한 Word Cloud는 아래와 같다.


해당 코드는 아래의 필자의 Github에 업로드 했다.

https://github.com/leejaymin/WordCloud 


Word Cloud from PDF using R


This project is to create Wrold Cloud from PDF file.
My code shows how a word cloud can be generated using the Rprogramming language on the basis of a given PDF document.

Used packages are as bellow:

  • tm (text mining)
  • wordcloud
  • RColorBrewer (fancy colors in a word cloud)

Code strcture

  • Loading the required libraries and setting inital parameters
  • Reading the text in the PDF file
  • Creating the text corpus
  • Generating the word cloud. This result is the following:

  • Anlyzing word frequency is as follow.

Reference

[1] Using R to create a Wrod Cloud from a PDF Document
[2] Basic Text mining in R


빈도분석 표와 백분율 구하기


descr package

질적 자료의 빈도와 백분율을 구하고 싶을 때, 유용한 함수로는 descr 패키지에 있는 freq()가 있다.

# 사용법 : freq(질적 자료)
# 예제 데이터 : InsectSprays
> attach(InsectSprays)

>install.packages("descr")
>library(descr)...

# 빈도표 작성하기 : 빈도와 백분율을 한번에 구해 준다.
> freq(spray)

# 빈도표와 막대그래프 작성하기
> freq(spray, plot=TRUE)

plyr package

install.packages('plyr')

Then, call its library, and the count() function will be ready for use.
> library(plyr)
> count(mtcars, 'gear')
       gear      freq
1      3         15
2      4         12
3      5         5
> y = count(mtcars, 'gear')
> y
       gear      freq
1      3         15
2      4         12
3      5         5
> class(y)
[1] "data.frame"

정렬하기

plyr페키지의 arrange를 사용

> library(plyr)

> arrange(v123, v1, desc(v2), v3)

  v1   v2 v3

1 30 6500  B

2 40 5100  A

3 40 4500  A

4 50 3000  B

5 50 2000  A

6 50 2000  B

7 90 9000  A 


Vector 분할


한줄로 해결 가능하다.

split(d, ceiling(seq_along(d)/20))

seq_along()split()ceiling()을 좀 더 자세히 설명하면 아래와 같다.

> d <- rpois(73,5)
> d
 [1]  3  1 11  4  1  2  3  2  4 10 10  2  7  4  6  6  2  1  1  2  3  8  3 10  7  4
[27]  3  4  4  1  1  7  2  4  6  0  5  7  4  6  8  4  7 12  4  6  8  4  2  7  6  5
[53]  4  5  4  5  5  8  7  7  7  6  2  4  3  3  8 11  6  6  1  8  4
> max <- 20
> x <- seq_along(d)
> d1 <- split(d, ceiling(x/max))
> d1
$`1`
 [1]  3  1 11  4  1  2  3  2  4 10 10  2  7  4  6  6  2  1  1  2

$`2`
 [1]  3  8  3 10  7  4  3  4  4  1  1  7  2  4  6  0  5  7  4  6

$`3`
 [1]  8  4  7 12  4  6  8  4  2  7  6  5  4  5  4  5  5  8  7  7

$`4`
 [1]  7  6  2  4  3  3  8 11  6  6  1  8  4


정규성 검정


정규성을 판별해야지 통계학의 많은 개념들을 활용 할 수 있다.

평균값, 중앙값, 왜도, 첨도 등을 확인하는것이 필 수 적이다.

정규성 검증에 관한 고찰

정규성 가정이 상대적으로 덜 한 통계적 분석 방법

  • Sample t test
  • t test
  • ANOVA (비모수 Krukal-Wallis test)
  • Regression Analysis

위와 같은 경우 평균에 대해서 비교하기 때문에 정규성 가정의 중요도가 상대적으로 덜 하다.

이러한 이유에서 정규분포 하지 않는 데이터 분석에도 사용되어지고 있다.

정규성이 성립하지 않는 이유들로는 다음과 같다.

  • 배경에 사용된 분포가 정규분포를 하지 않는 경우
  • 이상치나 두개 이상의 분포가 섞여 있는 경우
  • 낮은 해상도의 Gage R&R을 사용한 경우
  • 데이터의 중심이 한쪽으로 치우쳐 있는 경우(Skewed data)
  • 표본의 갯수가 너무 많은 경우

통계학의 근간 이론

중심극한 정리 (Central Limit Theorem)

모집단의 실제 분포에 관계 없이 표본크기 n이 증가할수록 표본평균의 분포는 정규분포에 근사한다.

대수의 법칙 (Law of Large Number)

정규성 검증 Sapiro-Wilks Test

정규성을 판별하는 검증 방법은
Kolmogorov-Smirnov test(콜모고로프 스미르노프), Sapiro-Wilks test가 있다.
표본수가 30개 이하 일 때는 중심극한정리를 가정하기 어렵기 때문에 정규성 검정을 해야 한다.

귀무가설 $H_0$: 데이터가 정규분포를 따른다.
대립가설 $H_1$: 데이터가 정규분포를 따르지 않는다.

p-value가 .05 보다 커야 귀무가설을 채택할 수 있다.

> data <- sample(50:1000,replace=TRUE)
> shapiro.test(data)

    Shapiro-Wilk normality test

data:  data
W = 0.95422, p-value < 2.2e-16

p값이 너무 작기 때문에 귀무가설은 기각 된다.
히스토그램을 그려봐도 정규성을 만족하지 않음을 알 수 있다.

정규성을 따르지 않는다.

이제, rnorm으로 해보자. 당연히 parameter(모수)가 정규 분포이므로 정규분포를 따를 것이다.

> dataNorm <- rnorm(1000,0,1)
> hist(dataNorm)
> hist(dataNorm,las=1)
> shapiro.test(dataNorm)

    Shapiro-Wilk normality test

data:  dataNorm
W = 0.99882, p-value = 0.7661

p값이 0.05많이 크다. 귀무가설을 채택한다.
히스토그램도 정규성을 가진다는것을 눈으로 쉽게 확인 가능 하다.

그래프에 의한 정규성 검증, Kernel Density Plot, Q-Q plot

Normal Q-Q plot을 그려서 Linear화의 정도를 눈으로 보면서 확인 할 수 있다.

dataNorm <- rnorm(1000,0,1)
qqnorm(dataNorm)
qqline(dataNorm)

비정규성 일떄의 검증 방법, Kruskal-Wallis Test(비모수적인 방법)

갖고 계신 표본이 정규성 가정을 만족하지 못할 경우에 각 집단별 표본평균의 동질성을 비교하기 위해서는 비모수 검정 중 하나인 Kruskal-Wallis Test를 한다.

비모수 검정에서는 Bonferroni Correction이라는 방법을 이용해서 각 집단간 차이를 비교한다.

예를 들어 a,b,c,d 4개 집단을 비교하고 싶다면, a-b, a-c, a-d, b-c, b-d, c-d 에 대해 각각 Mann-Whitney test 를 한다.

총 6번의 분석을 다시 해야 되겠죠. 그 다음에 각각의 분석 결과에서 얻은 p-value 를 살펴보는데, 유의수준을 0.05로 설정했을 경우 0.05가 아닌 0.05/6 = .00833를 기준값으로 p-value를 해석한다.

즉, p-value 가 .00833 작으면 Bonferroni Correction 에 의한 사후분석 결과 그 집단들 사이에는 통계적으로 유의한 차이가 있다고 판단하면 된다.

참고자료

[1] 이론, http://dermabae.tistory.com/148
[2] 코드, http://acpi.tistory.com/30
[3] 단일 모집단 분포의 정규성 검정, http://rfriend.tistory.com/118
[4] 정규성 가정이 상대적으로 덜 중요한 통계적 분석 방법은?|작성자 평화롭게
[5] 깜신의 통계이야기, R을 이용해서 정규성 검증을 해보자!


'AI > Probability & Statistics (R)' 카테고리의 다른 글

표준오차 (Standard Error)  (0) 2016.10.27
비교 분석  (0) 2016.08.03
가설 검증과 추정  (0) 2016.08.03
이상치 제거 (Box-plot 해석을 통한)  (0) 2015.01.03
통계학: F-검정  (0) 2013.08.29

테스트 주도의 개발을 위한 Unit Test in R


유닛 테스트를 통한 Test Driven Development (TDD)를 생각해 보자.

RUnit 테스팅을 위해서는 RUnit와 testthat 두 개의 package가 존재 한다.

사용할 수 있는 함수

  • expect_true(x): x가 참인가

  • expect_false(x): x가 거짓인가

  • expect_equal(object, expected): object가 기대되는 값 expected와 동일한가. 값의 비교에는 all.equal()이 사용되며 all.equal()은 두 객체가 (거의) 같은지를 비교한다. 따라서 부동소수의 경우 epsilon 이하로 차이나는 두 값은 같은 값으로 취급한다.

  • expect_equivalent(x,y): x,y가 동등한가. expect_equal()과 달리 속성 (예를 들면, rownames)을 제거한 뒤 값만 비교 한다.

생성한 파일 구조는 아래와 같다.

tests/test_fibo.R #test case가 저장됨
run_tests.R #test 실행 명령어들의 집함
fibo.R # test할 함수가 저장됨

소스코드

fibo.R

fibo <- function(n){
  if(n==0 || n == 1){
    return(1)
  }
  return(fibo(n-1) + fibo(n-2))
}

run_tests.R

require(testthat)
source("fibo.R")

test_dir("tests", reporter="summary")

tests/test_fibo.R

context("fibonacci series")

test_that("base test",{
  expect_equal(1, fibo(0))
  expect_equal(1, fibo(1))
})

test_that("recursion test",{
  expect_equal(2, fibo(2))
  expect_equal(3, fibo(3))
  expect_equal(5, fibo(4))
})

실행 결과

정상적인경우

> source("run_tests.R")
fibonacci series: .....

DONE ============================================================================================================================================

의도적으로 오류를 발생 시키자

  expect_equal(0, fibo(4))

문제가 있는 경우

> source("run_tests.R")
fibonacci series: ....1

Failed ------------------------------------------------------------------------------------------------------------------------------------------
1. Failure: recursion test (@test_fibo.R#12) ----------------------------------------------------------------------------------------------------
0 not equal to fibo(4).
1/1 mismatches
[1] 0 - 5 == -5


DONE ============================================================================================================================================

참고문헌

[1] R을 이용한 데이터 처리 & 분석 실무, 서민구


비교 분석 (t-test)


분포

t-분포

정규 분포를 사용하기 위해선 샘플이 많아야 하는 문제를 개선 (30개 이상)
땜 빵으로 사용하게 되는게 t 분포이다. 정규분포처럼 좌우 대칭인 상황
자유도에 따라서 그래프의 모양이 변한다.

  • 자유도: 표본분포를 구성하기 위해 자유롭게 반복해서 추출할 수 있는 표본(repeated random sample)의 수를 의미함

ex> 예를 들어 1~30까지에 이르는 30개의 수 중 2개의 수를 임의로 선택해서 표본을 구성한다면 표본의 크기는 2(N=2)가
된다. 이 때의 자유도(df)는 표본구성에 아무런 제한이 없기애 2가 된다.
하지만 2개의 수를 뽑되, 그 합이 20이 되는 수 2개를 고르라고 한다면, 표본의 크기는 2로 동일하지만 합이 20이 되어야
한다는 제한이 2개 생겼으므로 이때의 자유도는 1(표본의 크기 - 제약조건의 수= 1)이 되는 것

일반적으로 t분포의 자유도는 크기가 N인 표본에서 모분산이 추정되어야 한다는 제한을 받기 때문에 각 표본에서는 N-1개의
자유도를 가지게 된다.

ex> 두 개의 표본간에 존재하는 평균의 차이를 검정하기 위해 t분포를 사용하는 경우 두 표본의 자유도를 합산
(N1 - 1)(N2 - 1) = N1+ N2 - 2의 자유도를 가진 t분포를 사용하여 가설을 검정

f-분포

두 정규 모집단의 분산 비교에 대한 추론에 사용하는 분포
두 모 분산의 비에 대한 통계적 추론, 분산분석 등에 유용하게 활용

비교 분석

단일 모집단 평균 t-test

귀무가설:
$H_0$: $mu_1$ - $mu_2$ = 0

세 가지 전략

  1. 두 집단의 데이터가 서로 연관: paired T-test
  2. 두 집단의 데이터가 서로 독립: T-test
    • 두 집단의 분산이 서로 같은지 여부에 따라 분석 방법이 달라짐
  3. 두 집단의 분산을 알고 있느냐? 모르냐?
    • 중심극한 정리를 사용할 수 있는가? 없는가?

참고자료

https://m.blog.naver.com/PostView.nhn?blogId=mykepzzang&logNo=220853827288&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F

http://blog.naver.com/PostView.nhn?blogId=victor3dh&logNo=220841293738&parentCategoryNo=&categoryNo=35&viewDate=&isShowPopularPosts=true&from=search


'AI > Probability & Statistics (R)' 카테고리의 다른 글

표준오차 (Standard Error)  (0) 2016.10.27
정규성 검정  (3) 2016.08.20
가설 검증과 추정  (0) 2016.08.03
이상치 제거 (Box-plot 해석을 통한)  (0) 2015.01.03
통계학: F-검정  (0) 2013.08.29

가설 검증과 추정


추정 (Estimation)

점 추정 (point estimation)
- 모 평균 값은 얼마 일 것이다.
- 모평균, 모분산, 모표준편차 등이 모집단의 모수중 중요한 하나의 값이 된다.

구간 추정 (interval estimation): 모평균 값은 최소 얼마내지 최대 얼마일 것이다.

모든 자료를 조사할 수 없는 경우 표본에서 얻은 결과를 이용하여 모집단을 추측.

중심 극한 정리

  • 통계학을 있게한 핵심 정리

가설 검정 (Hypothesis Testing)

귀무가설 (null hypothesis, $H_0$): 통계학에서 처음부터 버릴 것을 예상하는 가설이다.

연구자가 증며하고자 하는 실험가설과 반대되는 입장, 증명되기 전까지는 효과도 없고 차이도 없다는 영가설을 귀무가설이라 한다.

흡연여부는 뇌혈관 질환의 발생에 영향을 미치지 않는다

대립가설 (alternative hypothesis): 연구가설 또는 유지가설은 귀무가설에 대립하는 명제이다. 보통, 모집단에서 독립변수와 결과 변수 사이에 어떤 특정한 관련이 있다는 꼴이다.

연구자가 실험을 통해 규명하고자 하는 가설을 대립가설이라 한다.

가설 검정의 순서

검증(test)

귀무가설: $H_0$
대립가설: $H_1$

  1. 가설 설정

    • 귀무가설 설정

      • 핵심은 무조건 최대한 보수적으로 가정해야한다. 이게 틀려야 연구가설이 입증되기 떄문이다.

      예: 치료법은 효과가 없다.

    • 대립가설 설정

      • 주장하는 바를 설정 한다.

      예: 치료법은 효과가 있다.

  2. 유의 수준 결정 (5%, 1%)

    • 실험 결과 통계적으로 유의한 결과를 얻음 ( p < 0.05)
    • 유의수준 $\alpha$이 있다.
    • 유의 수준이란 귀무가설($H_0$)가 참인데도 불구하고 $H_0$를 기각할 확률의 최대 허용 한계를 의미한다.
    • 유의 확률은 P값이라 부른다. 주어진 데이터가 귀무가설을 기각 시키고자 할 때 필요한 최소의 유의 수준을 말한다.
    • 즉 P value < $\alpha$, 이면 귀무가설을 기각 한다. 그리고 대립 가설을 채택 한다.
  3. 결과해석 불가

    • 귀무가설 전제로 이런 결과가 도출될 가능성은 전체 5% 이하임.
  4. 귀무가설 기각

    • 그렇다면 처음에 전제로 가정했던 귀무가설이 틀린 것임.
  5. 대립가설 채택

    • 실제 효과가 있기 때문에 이 결과가 관찰 되었다.

$H_0$를 기각할 것인지 아닌지를 결정할 때, 2가지 의사결정 실수를 할 수 있다.

위와 같이 배심원이 재판을 하는 상황을 교차표(cross tabulation)를 그려서 확인해 본다.
2개의 과오가 존재하는데 여기서 알파위험이 죄 없는 사람을 감옥에 보내기 때문에 더 심각하다
이러한 이유는 $H_0$ 귀무 가설은 보수적인 결적인데 이것을 기각하게 되면 실험적인 주장 대립 가설을 채택하게 되고
이것이 잘못 될 경우 문제는 심각해 지게 된다.

  • 죄없는 사람을 감옥에 보냄
  • 잘못된 약 처방을 내려서 사람이 죽음


'AI > Probability & Statistics (R)' 카테고리의 다른 글

정규성 검정  (3) 2016.08.20
비교 분석  (0) 2016.08.03
이상치 제거 (Box-plot 해석을 통한)  (0) 2015.01.03
통계학: F-검정  (0) 2013.08.29
회귀 분석 (1)  (0) 2013.08.29

MNIST 데이터 셋을 이용한 손글씨 인식 Deep Nerual Network 구현


Deep Nerual net에 여러 기술을 적용해서 정확도를 점점 향상시켜보는 내용이다.

MNIST Database overview

머신러닝 최고 Guru중 한명인 Yann LeCun 뉴욕대 교수가 제공하는 데이터 셋이다.
교수 겸임과 함께 Facebook과 함께 일하고 있다.

숫자 0~9까지의 손글씨 이미지의 집합이다.

학습데이터 60,000개, 테스트데이터 10,000개로 구성 되어 있다.
이전과 다르게 모든 모델이 검증은 이 테스트 데이터로 수행하게 된다.
재치환 에러가 아니라, unseen data에 대한 평가이기 때문에 진짜 평가라고 할 수 있다.

이 손글씨는 size-normalized 되어 있고 centered 되어 있다.
사이즈는 28x28의 크기를 가진다. 이미지의 값은 0 또는 1이다 (흑,백)

결국 이 데이터 셋은 패턴인식이나 기계학습 기술을 적용하기 위해 사용할 수 있는 최적의 이미지 셋이다. 이미 preprocessing이나 formatting이 모두 완료 되었기 때문이다.

4개의 파일을 아래의 주소에서도 다운받을 수 있고, 아래의 input_data.py를 통해서도 자동으로 다운 받을 수 있다.
a Link of the MNIST Database of handwritten digits, Yann LeCun

train-images-idx3-ubyte.gz:  training set images (9912422 bytes) 
train-labels-idx1-ubyte.gz:  training set labels (28881 bytes) 
t10k-images-idx3-ubyte.gz:   test set images (1648877 bytes) 
t10k-labels-idx1-ubyte.gz:   test set labels (4542 bytes)

편리한 이미지 제어를 위해서 TensorFlow자체에서 제공하는 script인 input_data.py를 사용한다.
다운로드
기능은 크게 두 가지이다.

  • dataset downloading
  • Loading the entire dataset into numpy array

Softmax Logistic regression for MNIST

단일 layer의 logistic regression에다가 softmax를 붙여서 0~9 사이의 숫자로 classifier 해주는 code 이다.
이런 단순한 방법의 경우 정확도가 얼마나 나오는지를 확인해보자.

import tensorflow as tf
import input_data

learning_rate = 0.01
training_epochs = 25
batch_size = 100
display_step = 1

mnist = input_data.read_data_sets("./MNIST_DATA", one_hot=True)

# tensorflow graph input
X = tf.placeholder('float', [None, 784]) # mnist data image of shape 28 * 28 = 784
Y = tf.placeholder('float', [None, 10]) # 0-9 digits recognition = > 10 classes

# set model weights
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

# Our hypothesis
activation = tf.add(tf.matmul(X, W),b)  # Softmax

# Cost function: cross entropy
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(activation, Y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)  # Gradient Descen

# Before starting, initialize the variables. We will `run` this first.
init = tf.initialize_all_variables()

# Launch the graph,
with tf.Session() as sess:
    sess.run(init)

    # Training cycle
    for epoch in range(training_epochs):
        avg_cost = 0.
        total_batch = int(mnist.train.num_examples/batch_size)

        # Fit the line.
        for step in xrange(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            # Fit training using batch data

            sess.run(optimizer, feed_dict={X: batch_xs, Y: batch_ys})

            # Compute average loss
            avg_cost += sess.run(cost, feed_dict={X: batch_xs, Y: batch_ys})/total_batch
        # Display logs per epoch step
        if epoch % display_step == 0:
            print "Epoch:", '%04d' %(epoch+1), "cost=", "{:.9f}".format(avg_cost)

    print "Optimization Finished!"

    # Test model
    correct_prediction = tf.equal(tf.argmax(activation, 1), tf.argmax(Y, 1))
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print ("Accuracy:", accuracy.eval({X: mnist.test.images, Y: mnist.test.labels}))

동작을 할떄 수행 과정이 너무 많기 때문에 batch단위로 나눠서 보여주게 된다.

총 트레이닝에 사용되는 example은 55,000개이다.
batch size는 100이다. 즉 한번에 550개를 이용해서 training을 수행 하게 된다.

위와 같이 수행하면 아래와 같은 결과를 얻는다.
테스트 데이터 1만개에 대해서 91% 정확도로 숫자를 판별 할 수 있었다. 훌륭한 결과이다.
이제 이것을 계속 개선 시켜 나간다.

Epoch: 0001 cost= 0.358261517
Epoch: 0002 cost= 0.281931180
Epoch: 0003 cost= 0.271845694
Epoch: 0004 cost= 0.265042298
Epoch: 0005 cost= 0.261528213
Epoch: 0006 cost= 0.260637467
Epoch: 0007 cost= 0.259087178
Epoch: 0008 cost= 0.255747356
Epoch: 0009 cost= 0.256775191
Epoch: 0010 cost= 0.254862096
Epoch: 0011 cost= 0.253365451
Epoch: 0012 cost= 0.250304825
Epoch: 0013 cost= 0.250392489
Epoch: 0014 cost= 0.248266828
Epoch: 0015 cost= 0.252892739
Epoch: 0016 cost= 0.245914599
Epoch: 0017 cost= 0.246812203
Epoch: 0018 cost= 0.248447235
Epoch: 0019 cost= 0.245472498
Epoch: 0020 cost= 0.243310648
Epoch: 0021 cost= 0.244416240
Epoch: 0022 cost= 0.244889498
Epoch: 0023 cost= 0.242864834
Epoch: 0024 cost= 0.242400869
Epoch: 0025 cost= 0.244274715
Optimization Finished!
('Accuracy:', 0.91829997)

Deep Neural Nets (DNN) for MNIST

Hidden Layer를 하나 추가해서 multiple nerual network을 구성해보자.
학습을 위해서 activation function으로 ReLU를 사용 한다.

weight 초기는 아래와 같이 random_normal을 이용해서 랜덤으로 설정해 준다.
정규 분포에 의해서 0~1사이의 값으로 만들어 낸다.

W1 = tf.Variable(tf.random_normal([784, 256]))
W2 = tf.Variable(tf.random_normal([256, 256]))
W3 = tf.Variable(tf.random_normal([256, 10]))

B1 = tf.Variable(tf.random_normal([256]))
B2 = tf.Variable(tf.random_normal([256]))
B3 = tf.Variable(tf.random_normal([10]))

그냥 무작정 0으로 wegiht을 모두 초기화한 다음 수행하면 cost 값이 converge 되지 않는다.

import tensorflow as tf
import input_data


learning_rate = 0.01
training_epochs = 15
batch_size = 100
display_step = 1

mnist = input_data.read_data_sets("./MNIST_DATA", one_hot=True)
# tensorflow graph input
X = tf.placeholder('float', [None, 784]) # mnist data image of shape 28 * 28 = 784
Y = tf.placeholder('float', [None, 10]) # 0-9 digits recognition = > 10 classes

# set model weights
W1 = tf.Variable(tf.random_normal([784, 256]))
W2 = tf.Variable(tf.random_normal([256, 256]))
W3 = tf.Variable(tf.random_normal([256, 10]))

B1 = tf.Variable(tf.random_normal([256]))
B2 = tf.Variable(tf.random_normal([256]))
B3 = tf.Variable(tf.random_normal([10]))

# Construct model
L1 = tf.nn.relu(tf.add(tf.matmul(X,W1),B1))
L2 = tf.nn.relu(tf.add(tf.matmul(L1,W2),B2)) # Hidden layer with RELU activation
hypothesis = tf.add(tf.matmul(L2, W3), B3) # No need to use softmax here

# Define loss and optimizer
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(hypothesis, Y)) # Softmax loss
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost) # Adam Optimizer

# Initializing the variables
init = tf.initialize_all_variables()

# Launch the graph,
with tf.Session() as sess:
    sess.run(init)

    # Training cycle
    for epoch in range(training_epochs):
        avg_cost = 0.
        total_batch = int(mnist.train.num_examples/batch_size)

        # Fit the line.
        for step in xrange(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)

            # Fit training using batch data

            sess.run(optimizer, feed_dict={X: batch_xs, Y: batch_ys})

            # Compute average loss
            avg_cost += sess.run(cost, feed_dict={X: batch_xs, Y: batch_ys})/total_batch
        # Display logs per epoch step
        if epoch % display_step == 0:
            print "Epoch:", '%04d' %(epoch+1), "cost=", "{:.9f}".format(avg_cost)

    print "Optimization Finished!"

    # Test model
    correct_prediction = tf.equal(tf.argmax(hypothesis, 1), tf.argmax(Y, 1))
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print ("Accuracy:", accuracy.eval({X: mnist.test.images, Y: mnist.test.labels}))

activation function을 ReLU로 변경하고 1개의 hidden layer만 추가 했는데도 정확도가 많이 좋아졌다.
심지어 epoch를 더 적게 수행해서 트레닝 데이터 55,000개에 대해서 모두 bach processing을 다 하지도 않았다.
하지만, initial wegiht을 zero로 주거나 잘못 줄경우 아에 학습이 안될 수도 있는 불안 요소가 있고
초기에 cost값이 너무 크게 시작한다는 문제점이 있다. 자칫 layer가 다수가 된다면 정상적으로 동작 안할 수도 있다.

/root/tensorflow/bin/python /root/DataScience/TensorFlowLecture/DNNforMNIST.py
Extracting ./MNIST_DATA/train-images-idx3-ubyte.gz
/usr/lib/python2.7/gzip.py:268: VisibleDeprecationWarning: converting an array with ndim > 0 to an index will result in an error in the future
Extracting ./MNIST_DATA/train-labels-idx1-ubyte.gz
  chunk = self.extrabuf[offset: offset + size]
Extracting ./MNIST_DATA/t10k-images-idx3-ubyte.gz
/root/DataScience/TensorFlowLecture/input_data.py:47: VisibleDeprecationWarning: converting an array with ndim > 0 to an index will result in an error in the future
  data = data.reshape(num_images, rows, cols, 1)
Extracting ./MNIST_DATA/t10k-labels-idx1-ubyte.gz
Epoch: 0001 cost= 36.855221693
Epoch: 0002 cost= 6.358338172
Epoch: 0003 cost= 2.991123097
Epoch: 0004 cost= 1.751982349
Epoch: 0005 cost= 1.301591293
Epoch: 0006 cost= 1.072350917
Epoch: 0007 cost= 0.896756601
Epoch: 0008 cost= 0.748790441
Epoch: 0009 cost= 0.573228549
Epoch: 0010 cost= 0.474619466
Epoch: 0011 cost= 0.429405935
Epoch: 0012 cost= 0.421186241
Epoch: 0013 cost= 0.325840454
Epoch: 0014 cost= 0.297165287
Epoch: 0015 cost= 0.260923379
Optimization Finished!
('Accuracy:', 0.95840001)

Process finished with exit code 0

Weight initialization

지금 까지는 아래의 코드와 같이
초기 weight vector들을 그냥 0으로 초기화 했었다.
또는 그냥 정규분포를 이용해서 0~1사이의 값으로 대충 초기화 했었다.
이렇게하면 계층구조가 복잡해질 경우 학습이 이뤄지지 않는 문제가 있다.

W = tf.Variable(tf.zeros([784, 10]))
tf.random_normal([784, 256])

이렇게 무식하게 하지말고 weight 값을 좀 더 올바르게 주고 시작하자는 의미 이다.

Hinton 교수가 2006년에 발표한 논문 A Fast Learning Algorithm for Deep Belief Nets에서 제안한Restricted Boatman Machine (RBM)방법에 기초 한다.

해당 방법은 인접한 두개의 layer 들에 대해서만 pre-training step을 거쳐서 wegiht 값을 정하는 것을 말한다.

그렇게 한다고 쳐도 RBM 방식은 약간 복잡하다고 할 수 있다.

좋은 소식은 아래와 같이 더 쉽지만 비슷한 효과를 얻는 pre-training 방법들이 많이 고안 되었다.

  • Xavier initialization: X. Glorot and Y. Bengio,“Understanding the difficulty of training deep feedforward neural networks,” in International conference on artificial intelligence and statistics, 2010.
  • He’s initialization: K. He, X. Zhang, S. Ren, and J. Sun,“Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification,” 2015.

Xavier initialization은 URL에서 코드를 알 수 있다.

import tensorflow as tf
import input_data

def xavier_initializer(n_inputs, n_outputs, uniform = True):
    if uniform:
        init_range = tf.sqrt(6.0/ (n_inputs + n_outputs))
        return tf.random_uniform_initializer(-init_range, init_range)

    else:
        stddev = tf.sqrt(3.0 / (n_inputs + n_outputs))
        return tf.truncated_normal_initializer(stddev=stddev)

learning_rate = 0.01
training_epochs = 15
batch_size = 100
display_step = 1

mnist = input_data.read_data_sets("./MNIST_DATA", one_hot=True)
# tensorflow graph input
X = tf.placeholder('float', [None, 784]) # mnist data image of shape 28 * 28 = 784
Y = tf.placeholder('float', [None, 10]) # 0-9 digits recognition = > 10 classes

# set model weights
W1 = tf.get_variable("W1", shape=[784, 256], initializer=xavier_initializer(784, 256))
W2 = tf.get_variable("W2", shape=[256, 256], initializer=xavier_initializer(256, 256))
W3 = tf.get_variable("W3", shape=[256, 10], initializer=xavier_initializer(256, 10))


B1 = tf.Variable(tf.zeros([256]))
B2 = tf.Variable(tf.zeros([256]))
B3 = tf.Variable(tf.zeros([10]))

# Construct model
L1 = tf.nn.relu(tf.add(tf.matmul(X,W1),B1))
L2 = tf.nn.relu(tf.add(tf.matmul(L1,W2),B2)) # Hidden layer with RELU activation
hypothesis = tf.add(tf.matmul(L2, W3), B3) # No need to use softmax here

# Define loss and optimizer
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(hypothesis, Y)) # Softmax loss
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost) # Adam Optimizer

# Initializing the variables
init = tf.initialize_all_variables()

# Launch the graph,
with tf.Session() as sess:
    sess.run(init)

    # Training cycle
    for epoch in range(training_epochs):
        avg_cost = 0.
        total_batch = int(mnist.train.num_examples/batch_size)

        # Fit the line.
        for step in xrange(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)

            # Fit training using batch data

            sess.run(optimizer, feed_dict={X: batch_xs, Y: batch_ys})

            # Compute average loss
            avg_cost += sess.run(cost, feed_dict={X: batch_xs, Y: batch_ys})/total_batch
        # Display logs per epoch step
        if epoch % display_step == 0:
            print "Epoch:", '%04d' %(epoch+1), "cost=", "{:.9f}".format(avg_cost)

    print "Optimization Finished!"

    # Test model
    correct_prediction = tf.equal(tf.argmax(hypothesis, 1), tf.argmax(Y, 1))
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print ("Accuracy:", accuracy.eval({X: mnist.test.images, Y: mnist.test.labels}))

정확도 면에서는 크게 차이없지만, cost function이 converge하는 속도가 다르다.
처음 시작 할 때 cost 값이 0.2수준으로 이전과는 엄청난 차이가 있다.

/root/tensorflow/bin/python /root/DataScience/TensorFlowLecture/DNNforMNIST.py
Extracting ./MNIST_DATA/train-images-idx3-ubyte.gz
/usr/lib/python2.7/gzip.py:268: VisibleDeprecationWarning: converting an array with ndim > 0 to an index will result in an error in the future
  chunk = self.extrabuf[offset: offset + size]
/root/DataScience/TensorFlowLecture/input_data.py:47: VisibleDeprecationWarning: converting an array with ndim > 0 to an index will result in an error in the future
  data = data.reshape(num_images, rows, cols, 1)
Extracting ./MNIST_DATA/train-labels-idx1-ubyte.gz
Extracting ./MNIST_DATA/t10k-images-idx3-ubyte.gz
Extracting ./MNIST_DATA/t10k-labels-idx1-ubyte.gz
Epoch: 0001 cost= 0.237908776
Epoch: 0002 cost= 0.094579589
Epoch: 0003 cost= 0.076395853
Epoch: 0004 cost= 0.065301783
Epoch: 0005 cost= 0.061461856
Epoch: 0006 cost= 0.055610619
Epoch: 0007 cost= 0.055899355
Epoch: 0008 cost= 0.048690692
Epoch: 0009 cost= 0.044984061
Epoch: 0010 cost= 0.042311433
Epoch: 0011 cost= 0.046229366
Epoch: 0012 cost= 0.041400560
Epoch: 0013 cost= 0.037953107
Epoch: 0014 cost= 0.035833549
Epoch: 0015 cost= 0.034003958
Optimization Finished!
('Accuracy:', 0.96890002)

Process finished with exit code 0

Dropout을 이용한 5 layer nerual network

Layer 수를 증가 시킨다.
그리고 overffiting을 막기 위해서 training을 할 때 dropout을 적용해서 training을 수행 한다.

dropout은 모든 레이어의 perceptron을 연결 시키지않고 임의로 지정된 비율만큼 단절 시킨 상태에서 weight값을 계산하는 기법을 말한다. 이를 통해서 overffting을 어느정도 막을 수 있다.

그리고 prediction을 수행 할 때는 다시 dropout 비율을 1로 해서 모든 perceptron을 연결한 상태에서 모델예측을 수행 한다.

import tensorflow as tf
import input_data

def xaver_init(n_inputs, n_outputs, uniform = True):
    if uniform:
        init_range = tf.sqrt(6.0/ (n_inputs + n_outputs))
        return tf.random_uniform_initializer(-init_range, init_range)

    else:
        stddev = tf.sqrt(3.0 / (n_inputs + n_outputs))
        return tf.truncated_normal_initializer(stddev=stddev)

learning_rate = 0.001
training_epochs = 25
batch_size = 100
display_step = 1

mnist = input_data.read_data_sets("./MNIST_DATA", one_hot=True)
# tensorflow graph input
X = tf.placeholder('float', [None, 784]) # mnist data image of shape 28 * 28 = 784
Y = tf.placeholder('float', [None, 10]) # 0-9 digits recognition = > 10 classes

# set dropout rate
dropout_rate = tf.placeholder("float")

# set model weights
W1 = tf.get_variable("W1", shape=[784, 256], initializer=xaver_init(784, 256))
W2 = tf.get_variable("W2", shape=[256, 256], initializer=xaver_init(256, 256))
W3 = tf.get_variable("W3", shape=[256, 256], initializer=xaver_init(256, 256))
W4 = tf.get_variable("W4", shape=[256, 256], initializer=xaver_init(256, 256))
W5 = tf.get_variable("W5", shape=[256, 10], initializer=xaver_init(256, 10))

B1 = tf.Variable(tf.random_normal([256]))
B2 = tf.Variable(tf.random_normal([256]))
B3 = tf.Variable(tf.random_normal([256]))
B4 = tf.Variable(tf.random_normal([256]))
B5 = tf.Variable(tf.random_normal([10]))

# Construct model
_L1 = tf.nn.relu(tf.add(tf.matmul(X,W1),B1))
L1 = tf.nn.dropout(_L1, dropout_rate)
_L2 = tf.nn.relu(tf.add(tf.matmul(L1, W2),B2)) # Hidden layer with ReLU activation
L2 = tf.nn.dropout(_L2, dropout_rate)
_L3 = tf.nn.relu(tf.add(tf.matmul(L2, W3),B3)) # Hidden layer with ReLU activation
L3 = tf.nn.dropout(_L3, dropout_rate)
_L4 = tf.nn.relu(tf.add(tf.matmul(L3, W4),B4)) # Hidden layer with ReLU activation
L4 = tf.nn.dropout(_L4, dropout_rate)

hypothesis = tf.add(tf.matmul(L4, W5), B5) # No need to use softmax here

# Define loss and optimizer
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(hypothesis, Y)) # Softmax loss
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost) # Adam Optimizer

# Initializing the variables
init = tf.initialize_all_variables()

# Launch the graph,
with tf.Session() as sess:
    sess.run(init)

    # Training cycle
    for epoch in range(training_epochs):
        avg_cost = 0.
        total_batch = int(mnist.train.num_examples/batch_size)

        # Fit the line.
        for step in xrange(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)

            # Fit training using batch data
            # set up 0.7 for training time
            sess.run(optimizer, feed_dict={X: batch_xs, Y: batch_ys, dropout_rate: 0.7})

            # Compute average loss
            avg_cost += sess.run(cost, feed_dict={X: batch_xs, Y: batch_ys, dropout_rate: 0.7})/total_batch
        # Display logs per epoch step
        if epoch % display_step == 0:
            print "Epoch:", '%04d' %(epoch+1), "cost=", "{:.9f}".format(avg_cost)

    print "Optimization Finished!"

    # Test model
    correct_prediction = tf.equal(tf.argmax(hypothesis, 1), tf.argmax(Y, 1))
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print ("Accuracy:", accuracy.eval({X: mnist.test.images, Y: mnist.test.labels, dropout_rate: 1}))

위코드에서 아래의 코드가 dropout을 나타낸다.
prediction을 할떄는 dropout_rate = 1로 설정한 다음 수행 한다.
learning_rate = 0.001으로 설정한것이 이전 코드와 차이점이다.
0.01로 할경우 오히려 정확도가 떨어진다.

L1 = tf.nn.dropout(_L1, dropout_rate)

최종 결과는 아래와 같다.
testing set 10000개에 대해서 98%의 정확도로 prediction을 하고 있다.
매우 훌륭한 결과를 얻었다.

/root/tensorflow/bin/python /root/DataScience/TensorFlowLecture/DNN_DropoutForMNIST.py
Extracting ./MNIST_DATA/train-images-idx3-ubyte.gz
/usr/lib/python2.7/gzip.py:268: VisibleDeprecationWarning: converting an array with ndim > 0 to an index will result in an error in the future
  chunk = self.extrabuf[offset: offset + size]
/root/DataScience/TensorFlowLecture/input_data.py:47: VisibleDeprecationWarning: converting an array with ndim > 0 to an index will result in an error in the future
  data = data.reshape(num_images, rows, cols, 1)
Extracting ./MNIST_DATA/train-labels-idx1-ubyte.gz
Extracting ./MNIST_DATA/t10k-images-idx3-ubyte.gz
Extracting ./MNIST_DATA/t10k-labels-idx1-ubyte.gz
Epoch: 0001 cost= 0.541453579
Epoch: 0002 cost= 0.206996800
Epoch: 0003 cost= 0.157958631
Epoch: 0004 cost= 0.131259738
Epoch: 0005 cost= 0.115274848
Epoch: 0006 cost= 0.098876665
Epoch: 0007 cost= 0.089464739
Epoch: 0008 cost= 0.088287840
Epoch: 0009 cost= 0.078404236
Epoch: 0010 cost= 0.072852779
Epoch: 0011 cost= 0.066189782
Epoch: 0012 cost= 0.066654595
Epoch: 0013 cost= 0.060475496
Epoch: 0014 cost= 0.057644885
Epoch: 0015 cost= 0.054782469
Epoch: 0016 cost= 0.052261842
Epoch: 0017 cost= 0.053377932
Epoch: 0018 cost= 0.049687267
Epoch: 0019 cost= 0.050434303
Epoch: 0020 cost= 0.049436003
Epoch: 0021 cost= 0.044065983
Epoch: 0022 cost= 0.043885315
Epoch: 0023 cost= 0.044500848
Epoch: 0024 cost= 0.044421383
Epoch: 0025 cost= 0.040629214
Optimization Finished!
('Accuracy:', 0.98079997)

Process finished with exit code 0

구현 코드는 GitHub에 올려 두었다.

참고자료

모두를 위한 머신 러닝 by 홍콩과기대 김성훈 교수


TensorFlow 기본 개념 (1)


머신러닝의 정의란 Andrew Ng교수님의 말을 인용하면 아래와 같다.

A computer program is said to learn from experience E with respect to some class of taks T and performance tasks in T, as measured by P, improves with experience E, Tom M. Mitchell

Tensor는 뭔가?

많은 데이터를 효과적으로 처리하는 자료구조이다.
다차원 array, list라고 생각하면 된다.
이래서 NumPy를 확장한것이 Tensor인 것이다.

# What is tensor?
tensor1 = 7          # 0-dimensional
tensor2 = [7]        # 1-dimensional
tensor3 = [[1,2,3],  # 2-dimensional
           [4,5,6]]  ...
           ...

Flow

Flow란 결국 Graph이다.
즉 모든 계산을 쉽게 하기 위해서 각각의 연산을 잘게 쪼개고 이것을 Graph로 연결 한 것이다.
미분 Chain Rule 같은것을 생각해보면 왜 연산이 간단해 지는지 알 수 있다.

Graph, Node, Edge

선언부와 실행부가 다르다

TensorFlow코드 상에서 a=1을 선언해도 추후에 이것이 반영되는 것이지 지금 당장 변수 a가 1로 assgin된것은 아니다.
이러한 부분이 기본적인 python 프로그래밍과는 다른점이다. 
이러한 동작 매커니즘을 생각해보면 결국 앞으로 어떻게 동작 할 것이다라는 계획을 Graph로 표현한것이 TensorFlow가 되는 것이다.

  • Operation: 동작을 정의한 것
  • Node: Operation 정의를 포함한 것
  • Edge: Node와 Node를 연결한 것

이러한 구조에서 Tensor데이터 구조가 이동하면서 Operation에 의해서 연산을 하는 방식이다.

import tensotflow as tf

위처럼 TensorFlow를 일단 Import 하면 내부적으로 default_graph_stack에 Default Graph가 생긴다.

tf.get_default_graph()명령어로 접근 가능
이 graph에 저장된 operation을 확인해 보면 []비어 있는 것을 알 수 있다.

상수를 하나 선언 하면 아래처럼 주소가 기록된다.
이러한 의미는 operation이 리스트 형태로 들어가 있는 것이다.

import tensorflow as tf
graph = tf.get_default_graph()
graph.get_operations()
input = tf.constant(1.0)
operations = graph.get_operations()
operations
[<tensorflow.python.framework.ops.Operation at 0x7f94695fbd90>,
 <tensorflow.python.framework.ops.Operation at 0x7f944788a990>]

operation을 감싸고 있는 node를 출력해보자.

>>> operations[0].node_def
## name: "Const"
## op: "Const"
## attr {
##   key: "dtype"
##   value {
##     type: DT_FLOAT
##   }
## }
## attr {
##   key: "value"
##   value {
##     tensor {
##       dtype: DT_FLOAT
##       tensor_shape {
##       }
##       float_val: 1.0
##     }
##   }
## }

TensorFlow는 내부적으로 protocol buffer를 이용한다.
어떤 google style의 JSON이라고 생각하면 쉽다. 위에 출력도 JSON 스럽기 때문이다.

왜 tensorflow는 이처럼 고유한 특징의 구조나 타입들을 가지는 것일까?

Numpy는 기본적으로 matrix을 연산을 위해서 C++로 개발 되었다. 하지만 여전히 많은 overhead를 발생 시킨다.
완전히 Python 영역 밖에서 동작 시킴으로 성능을 끌어 올린다.
이러한 방법은 Theano또는 Torch에서 수행하는 방식이다.

그냥 input을 출력해 보자

In [27]: input
Out[27]: <tf.Tensor 'Const_9:0' shape=() dtype=float32>

32비트 float tensor를 확인 할 수 있다. no dimension 이며 그냥 싱글 숫자이다.

이제 실제로 input값을 session으로 실행하자.
default에 의해서 default graph에서 값을 꺼내오는 방식이다.

>>> sess = tf.Session()
>>> sess.run(input_value)
## 1.0

초 간단 TensorFlow neuron

Hadley Wickham said Names have objects rather than the reverse이다.
표현 하면 아래의 그림과 같다.

여기서 말하는 초간단 neron은 non-identity activation function도 없고 bias도 없는 것을 말한다.

constant는 상수를 의미하고, variable은 계속 변화하는 값을 의미 한다.

weight = tf.Variable(0.8)
#지원하는 operation 이름 확인
for op in graph.get_operations(): print op.name

x에 w를 곱해서 y라는 출력값을 만들어냄
이때 참값은 0이다.

입력값은 1로 고정 시킨다면 당연히 참값 y_ = 0과 일치시키는 w는 0일것이다.

단순한 방정식이다.

$$ 1 \times w = 0 $$

위와 같을 때는 $w$는 0이 최적화된 값일 것이다.

하지만 이러한 해를 wieght값 w를 조정하면서 전체 cost를 줄이는 방법으로 차근 차근 찾아보자.

w의 시작값을 0.8로 설정 한다.
이때의 cost는 $1 \times 0.8 = 0.8$ 이다.
이 cost를 계산하는 것이 최소제곱법이 있다.

$$ cost = minimum(\hat { y }- y)^{2} $$
이것을 최소화로 만들어주는 방법은 y를 결정하는 함수 $f(x) = wx$ 입니다. 결국 w를 조정해서 해를 찾을 수 있게 됩니다.

우선, cost함수를 w에 대해서 편미분하면 chain rule에 의해서 아래와 같이 나옵니다.

$$ \frac{\partial cost}{\partial w} = 2 \times x$$

그리고 이러한 과정에 쓰이는 데이터를 트레이닝 데이터라고 하고 과정을 학습(learning)이라고 합니다.
TensorFlow에서느 사실 이러한 미분을 자동으로 해주게 됩니다. 구지 손으로 저렇게 해서 식으로 적을 필요 없습니다.

그리고 이러한 미분값을 최적화 시키기위해서 조금씩 값을 update하는 방법을 사용하게 됩니다. 
방법의 이름은 gradient descent algorihtm입니다. 알고리즘을 표현하면 아래와 같습니다.

$$ w = w - \alpha \frac{\partial cost}{\partial w} $$

위 알고리즘은 간단하게 TensorFlow에서는 아래와 같은 함수하나만 이용하면 딥니다.

optim = tf.train.GradientDescentOptimizer(learning_rate = 0.025)

learing rate을 0.025를 적용해서 손으로 1단계를 게산해보면 아래와 같습니다.
$1.6 \times 0.025 = 0.04$가 됩니다.

아래 코드는 이러한 과정을 적용한 전체 코드 입니다.

import tensorflow as tf
x = tf.constant(1.0, name='input')
w = tf.Variable(0.8, name='weight')
y = tf.mul(w, x, name='output')
y_ = tf.constant(0.0, name='correct_value')
loss = tf.pow(y - y_, 2, name='loss')

train_step = tf.train.GradientDescentOptimizer(0.025).minimize(loss)

for value in [x, w, y, y_, loss]:
    tf.scalar_summary(value.op.name, value)

summaries = tf.merge_all_summaries()

sess = tf.Session()
summary_writer = tf.train.SummaryWriter('log_simple_stats', sess.graph)

sess.run(tf.initialize_all_variables())
for i in range(100):
    if i % 10 ==0:
        print("epoch {}, output: {}".format(i, sess.run(y)))
    summary_writer.add_summary(sess.run(summaries), i)
    sess.run(train_step)

출력결과

epochs 0, output: 0.800000011921
epochs 10, output: 0.478989481926
epochs 20, output: 0.286788702011
epochs 30, output: 0.171710968018
epochs 40, output: 0.10280970484
epochs 50, output: 0.0615559667349
epochs 60, output: 0.0368558317423
epochs 70, output: 0.0220669470727
epochs 80, output: 0.0132122989744
epochs 90, output: 0.00791069027036

output은 weight 값 w를 의미하며 정답인 0에 거의 근접한것을 알 수 있다.

해당 결과를 Tensor Board를 통해서 시각적으로 확인 할 수도 있다.
프로젝트 디렉터리에서 log_simple_stats에 저장한다고 했으니 그곳에서 아래의 명령어를 수행 한다.

tensorboard --logdir=./log_simple_stats

그다음 크롬을 이용해서 http://192.168.188.129:6006/#graphs아래 주소로 접속 한다.
IP Address는 각자 맞춰서 한다. 
그냥 local에서 작업한다면 localhost:6006/#graphs라고 쓰면 된다.

작성코드

본 내용에 작성된 코드들은 Github를 통해서 공유하겠습니다.
주소: https://github.com/leejaymin/TensorFlowLecture/tree/master/0.Basic

참고자료

https://www.oreilly.com/learning/hello-tensorflow
https://jihobak.github.io/2016-06-26-deeplearning-ninja001/


TensorFlow 버전 업데이트 (Version Update)


현재 버전 확인

virtualenv 사용자는 활성화 시킴

source ./tensorflow/bin/activate

Tensor flow version 확인

(tensorflow)root@jemin-virtual-machine:~/tensorflow# pip show tensorflow
---
Name: tensorflow
Version: 0.5.0
Location: /root/tensorflow/lib/python2.7/site-packages
Requires: numpy, six

필자의 경우 설치를 예전에해서 r0.5버전이다.

업데이트 (r0.5 -> r0.9)

당연히 python에서 pacakge를 쉽게 설치하게 도와주는 pip유틸이 설치되어 있어야 한다.

# Ubuntu/Linux 64-bit
$ sudo apt-get install python-pip python-dev python-virtualenv

그 다음 Ubuntu 6bit이며 Python 2.7버전을 쓰는 사람은 아래의 r0.9 tensorflow를 다운 받자.
2016.6.15일 기준으로 필자는 r0.5에서 r0.9로 업데이트 했다.

# Ubuntu/Linux 64-bit, CPU only, Python 2.7
export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.9.0rc0-cp27-none-linux_x86_64.whl

# Python 2
(tensorflow)$ sudo pip install --upgrade $TF_BINARY_URL

실행하면 아래와 같이 설치가 된다.

    changing mode of /root/tensorflow/bin/f2py to 755
  Found existing installation: wheel 0.24.0
    Not uninstalling wheel at /usr/lib/python2.7/dist-packages, outside environment /root/tensorflow
  Found existing installation: setuptools 2.2
    Uninstalling setuptools:
      Successfully uninstalled setuptools
Successfully installed tensorflow numpy protobuf wheel setuptools
Cleaning up...

버전을 확인하면 r0.9로 변경된것을 알 수 있다.

(tensorflow)root@jemin-virtual-machine:~/tensorflow# pip show tensorflow
---
Name: tensorflow
Version: 0.9.0rc0
Location: /root/tensorflow/lib/python2.7/site-packages
Requires: numpy, protobuf, wheel, six

업데이트 (r0.9 -> r0.12)

Update 전

(tensorflow)root@jemin-virtual-machine:~# pip show tensorflow
---
Name: tensorflow
Version: 0.9.0rc0
Location: /root/tensorflow/lib/python2.7/site-packages
Requires: numpy, protobuf, wheel, six

자신에게 맞는 최신 TensorFlow 링크를 추가한다.

# Ubuntu/Linux 64-bit, CPU only, Python 2.7
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.0rc0-cp27-none-linux_x86_64.whl

# Ubuntu/Linux 64-bit, GPU enabled, Python 2.7
# Requires CUDA toolkit 8.0 and CuDNN v5. For other versions, see "Installing from sources" below.
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-0.12.0rc0-cp27-none-linux_x86_64.whl

# Mac OS X, CPU only, Python 2.7:
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-0.12.0rc0-py2-none-any.whl

# Mac OS X, GPU enabled, Python 2.7:
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/gpu/tensorflow_gpu-0.12.0rc0-py2-none-any.whl

# Ubuntu/Linux 64-bit, CPU only, Python 3.4
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.0rc0-cp34-cp34m-linux_x86_64.whl

# Ubuntu/Linux 64-bit, GPU enabled, Python 3.4
# Requires CUDA toolkit 8.0 and CuDNN v5. For other versions, see "Installing from sources" below.
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-0.12.0rc0-cp34-cp34m-linux_x86_64.whl

# Ubuntu/Linux 64-bit, CPU only, Python 3.5
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.0rc0-cp35-cp35m-linux_x86_64.whl

# Ubuntu/Linux 64-bit, GPU enabled, Python 3.5
# Requires CUDA toolkit 8.0 and CuDNN v5. For other versions, see "Installing from sources" below.
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-0.12.0rc0-cp35-cp35m-linux_x86_64.whl

# Mac OS X, CPU only, Python 3.4 or 3.5:
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-0.12.0rc0-py3-none-any.whl

# Mac OS X, GPU enabled, Python 3.4 or 3.5:
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/gpu/tensorflow_gpu-0.12.0rc0-py3-none-any.whl

업그레이드

필자는 Ubuntu 64bit, python 2.7, CPU 버전을 쓰므로 아래 링크를 추가 했다.

# Ubuntu/Linux 64-bit, CPU only, Python 2.7
export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.0rc0-cp27-none-linux_x86_64.whl

pip install --upgrade $TF_BINARY_URL

성공 메시지

Successfully installed tensorflow protobuf mock numpy setuptools funcsigs pbr
Cleaning up..

버전업데이트 확인
무슨 문제인건지 pip show로 이전처럼 버전 확인이 잘 안된다. 계속 예전버전으로 표시된다.
직접 파이썬에서 Tensorflow를 실행해서 확인하자.

(tensorflow)root@jemin-virtual-machine:~# python -c 'import tensorflow as tf; print(tf.__version__)'

0.12.0-rc0


Naive Baeys vs Neural network


Naive Bayes와 Deep Neural Networks에서 어느 알고리즘이 더 우수한지 평가한다.

한 사용자의 응답성을 나타내는 데이터이다.
1276개의 응답성 지표를 가지고 분석 했다.
1276

응답 비율은 아래와 같다.
(FALSE): 922
(TRUE): 354

해당 데이터를 70%는 트레이닝 30%는 테스팅으로 분할 한다.
임의로 분할 하기 때문에 모든 요일과 시간이 적절히 섞인다.

요청이 있어서 데이터의 일부분을 Google Drive로 공유합니다.
단순히 형태만 참고 하시면 됩니다.
앞의 8개는 입력 Feature 이고 마지막 class가 출력값 입니다.
응답성은 True와 False값을 가지므로 Binary classification문제가 됩니다.

Naive Bayes Classifier in R##

데이터 구조

> head(training)
1        1    74          18               4                  2         2        1                 1
2        2    10          18               4                  2         2        3                 2
4        1    56          19               4                  2         2        1                 1
6        1    84          19               4                  1         1        1                 4
8        1    39          19               4                  1         2        1                 4
9        1    56          19               4                  1         2        1                 4
library(caret)
set.seed(12358)
inTrain <- createDataPartition(y=factorClassList[['ikhee']], p=0.70, list =FALSE)
training <- data.frame(dfList[['ikhee']][inTrain,])
testing <-  data.frame(dfList[['ikhee']][-inTrain,])

classTraining <- factorClassList[['ikhee']][inTrain]
classtesting <-  factorClassList[['ikhee']][-inTrain]

sms_model1 <- train(training,classTraining, method="nb", trControl = ctrl, tuneGrid = 
                        data.frame(.fL=c(0,0,1,1,10,10), .usekernel=c(FALSE,TRUE,FALSE,TRUE,FALSE,TRUE)))
sms_model1

sms_predict1 <- predict(sms_model1, testing)
cm1 <- confusionMatrix(sms_predict1, classtesting, positive="TRUE")
cm1

결과

> cm1
Confusion Matrix and Statistics

          Reference
Prediction FALSE TRUE
     FALSE   273  102
     TRUE      3    4
                                          
               Accuracy : 0.7251          
                 95% CI : (0.6774, 0.7693)
    No Information Rate : 0.7225          
    P-Value [Acc > NIR] : 0.4806          
                                          
                  Kappa : 0.0377          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.03774         
            Specificity : 0.98913         
         Pos Pred Value : 0.57143         
         Neg Pred Value : 0.72800         
             Prevalence : 0.27749         
         Detection Rate : 0.01047         
   Detection Prevalence : 0.01832         
      Balanced Accuracy : 0.51343         
                                          
       'Positive' Class : TRUE  

실제값

> table(classtesting)
classtesting
FALSE  TRUE 
  276   106 

Deep Neural Networks with TensorFlow in Python##

three layers neural networks. Activation function is Sigmoid (logistic)

데이터구조
Neural network의 경우 학습을 위해서
모든 Feature와 Class를 0~1 사이로 normalization 해야 cost function이 convergence 된다.
그렇지 않으면 발산 한다.

> head(ikheeTrainingDf_norm)
1   0.0000 0.56153846   0.7391304             0.5                  1         1        0               0.0  1
2   0.0625 0.06923077   0.7391304             0.5                  1         1        1               0.2  1
3   0.0000 0.42307692   0.7826087             0.5                  1         1        0               0.0  1
4   0.0000 0.63846154   0.7826087             0.5                  0         0        0               0.6  1
5   0.0000 0.29230769   0.7826087             0.5                  0         1        0               0.6  0
6   0.0000 0.42307692   0.7826087             0.5                  0         1        0               0.6  1

이러한 데이터를 txt로 export해서
python으로 다시 처리한다.

import tensorflow as tf
import numpy as np
from sklearn.metrics import precision_score, confusion_matrix
from sklearn.metrics import classification_report
import pandas as pd

# three layers neural networks. Activation function is Sigmoid (logistic)

xyTraining = np.loadtxt('ikheeTrainingNorm.txt', unpack=True)
xyTesting = np.loadtxt('ikheeTestingNorm.txt', unpack=True)

x_data_training = np.transpose(xyTraining[0:-1])
y_data_training = np.reshape(xyTraining[-1], (len(x_data_training), 1))

x_data_testing = np.transpose(xyTesting[0:-1])
y_data_testing = np.reshape(xyTesting[-1], (len(x_data_testing), 1))

X = tf.placeholder(tf.float32, name='X-input')
Y = tf.placeholder(tf.float32, name='Y-input')

W1 = tf.Variable(tf.random_uniform([8, 16], -1.0, 1.0), name='Weight1')
W2 = tf.Variable(tf.random_uniform([16, 8], -1.0, 1.0), name='Weight2')
W3 = tf.Variable(tf.random_uniform([8, 1], -1.0, 1.0), name='Weight3')

b1 = tf.Variable(tf.zeros([16]), name="Bias1")
b2 = tf.Variable(tf.zeros([8]), name="Bias2")
b3 = tf.Variable(tf.zeros([1]), name="Bias3")


# Our hypothesis
with tf.name_scope("layer2") as scope:
    L2 = tf.sigmoid(tf.matmul(X, W1) + b1)

with tf.name_scope("layer3") as scope:
    L3 = tf.sigmoid(tf.matmul(L2, W2) + b2)

with tf.name_scope("layer4") as scope:
    hypothesis = tf.sigmoid(tf.matmul(L3, W3) + b3)

# Cost function
with tf.name_scope("cost") as scope:
    cost = -tf.reduce_mean(Y*tf.log(hypothesis) + (1-Y)*tf.log(1-hypothesis))
    cost_summ = tf.scalar_summary("cost", cost)

# Minimize
with tf.name_scope("train") as scope:
    a = tf.Variable(0.01) # Learning rate, alpha
    optimizer = tf.train.GradientDescentOptimizer(a)
    train = optimizer.minimize(cost)

# Add histogram
w1_hist = tf.histogram_summary("weights1", W1)
w2_hist = tf.histogram_summary("weights2", W2)

b1_hist = tf.histogram_summary("biases1", b1)
b2_hist = tf.histogram_summary("biases2", b2)

y_hist = tf.histogram_summary("y", Y)


# Before starting, initialize the variables.
# We will `run` this first.
init = tf.initialize_all_variables()


# Launch the graph,
with tf.Session() as sess:
    # tensorboard --logdir=./logs/xor_logs
    merged = tf.merge_all_summaries()
    writer = tf.train.SummaryWriter("./logs/xor_logs", sess.graph_def)

    sess.run(init)
    # Fit the line.
    for step in xrange(2000):
        sess.run(train, feed_dict={X:x_data_training, Y:y_data_training})
        if step % 200 == 0:
            summary = sess.run(merged, feed_dict={X:x_data_training, Y:y_data_training})
            writer.add_summary(summary, step)
            #print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W1), sess.run(W2)
            print step, sess.run(cost, feed_dict={X:x_data_training, Y:y_data_training})

    # Test model
    correct_prediction = tf.equal(tf.floor(hypothesis+0.5), Y)
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

    y_data_pred = sess.run(tf.floor(hypothesis + 0.5),
                           feed_dict={X: x_data_testing, Y: y_data_testing})

    print sess.run([hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], feed_dict={X:x_data_testing, Y:y_data_testing})
    print "Accuracy:", accuracy.eval({X:x_data_testing, Y:y_data_testing})

#   print confusion_matrix(y_data_testing[:,0], y_data_pred[:,0], labels=[0, 1])
    pd_y_true = pd.Series(y_data_testing[:, 0])
    pd_x_pred = pd.Series(y_data_pred[:, 0])
    print pd.crosstab(pd_y_true, pd_x_pred, rownames=['True'], colnames=['Predicted'], margins=True)

    target_names = ['false', 'true']
    print(classification_report(y_data_testing[:, 0], y_data_pred[:, 0], target_names=target_names))
    print 'Precision', precision_score(y_data_testing[:, 0], y_data_pred[:, 0], average='binary',pos_label=1)

결과

# Iteration & Cost
0 0.594439
200 0.59129
400 0.591194
600 0.591135
800 0.591078
1000 0.59102
1200 0.590963
1400 0.590907
1600 0.590852
1800 0.590796

Accuracy: 0.722513

# Confusion Matrix
Predicted  0.0  All
0.0        276  276
1.0        106  106
All        382  382


# Precision & Recall
             precision    recall  f1-score   support
      false       0.72      1.00      0.84       276
       true       0.00      0.00      0.00       106

avg / total       0.52      0.72      0.61       382

11 layers neural networks.
Activation functions are LeRu and Sigmoid (logistic)

코드

import tensorflow as tf
import numpy as np
from sklearn.metrics import precision_score, confusion_matrix
from sklearn.metrics import classification_report
import pandas as pd

# three layers neural networks. Activation function is Sigmoid (logistic)

xyTraining = np.loadtxt('ikheeTrainingNorm.txt', unpack=True)
xyTesting = np.loadtxt('ikheeTestingNorm.txt', unpack=True)

x_data_training = np.transpose(xyTraining[0:-1])
y_data_training = np.reshape(xyTraining[-1], (len(x_data_training), 1))

x_data_testing = np.transpose(xyTesting[0:-1])
y_data_testing = np.reshape(xyTesting[-1], (len(x_data_testing), 1))

X = tf.placeholder(tf.float32, name='X-input')
Y = tf.placeholder(tf.float32, name='Y-input')

W1 = tf.Variable(tf.random_uniform([8, 8], -1.0, 1.0), name='Weight1')
# 9 hidden layers
W2 = tf.Variable(tf.random_uniform([8, 8], -1.0, 1.0), name='Weight2')
W3 = tf.Variable(tf.random_uniform([8, 8], -1.0, 1.0), name='Weight3')
W4 = tf.Variable(tf.random_uniform([8, 8], -1.0, 1.0), name='Weight4')
W5 = tf.Variable(tf.random_uniform([8, 8], -1.0, 1.0), name='Weight5')
W6 = tf.Variable(tf.random_uniform([8, 8], -1.0, 1.0), name='Weight6')
W7 = tf.Variable(tf.random_uniform([8, 8], -1.0, 1.0), name='Weight7')
W8 = tf.Variable(tf.random_uniform([8, 8], -1.0, 1.0), name='Weight8')
W9 = tf.Variable(tf.random_uniform([8, 8], -1.0, 1.0), name='Weight9')
W10 = tf.Variable(tf.random_uniform([8, 8], -1.0, 1.0), name='Weight10')

W11 = tf.Variable(tf.random_uniform([8, 1], -1.0, 1.0), name='Weight11')

b1 = tf.Variable(tf.zeros([8]), name="Bias1")
b2 = tf.Variable(tf.zeros([8]), name="Bias2")
b3 = tf.Variable(tf.zeros([8]), name="Bias3")
b4 = tf.Variable(tf.zeros([8]), name="Bias4")
b5 = tf.Variable(tf.zeros([8]), name="Bias5")
b6 = tf.Variable(tf.zeros([8]), name="Bias6")
b7 = tf.Variable(tf.zeros([8]), name="Bias7")
b8 = tf.Variable(tf.zeros([8]), name="Bias8")
b9 = tf.Variable(tf.zeros([8]), name="Bias9")
b10 = tf.Variable(tf.zeros([8]), name="Bias10")

b11 = tf.Variable(tf.zeros([1]), name="Bias11")


# Our hypothesis
with tf.name_scope("layer1") as scope:
    L1 = tf.nn.relu(tf.matmul(X, W1) + b1)
with tf.name_scope("layer2") as scope:
    L2 = tf.nn.relu(tf.matmul(L1, W2) + b2)
with tf.name_scope("layer3") as scope:
    L3 = tf.nn.relu(tf.matmul(L2, W3) + b3)
with tf.name_scope("layer4") as scope:
    L4 = tf.nn.relu(tf.matmul(L3, W4) + b4)
with tf.name_scope("layer5") as scope:
    L5 = tf.nn.relu(tf.matmul(L4, W5) + b5)
with tf.name_scope("layer6") as scope:
    L6 = tf.nn.relu(tf.matmul(L5, W6) + b6)
with tf.name_scope("layer7") as scope:
    L7 = tf.nn.relu(tf.matmul(L6, W7) + b7)
with tf.name_scope("layer8") as scope:
    L8 = tf.nn.relu(tf.matmul(L7, W8) + b8)
with tf.name_scope("layer9") as scope:
    L9 = tf.nn.relu(tf.matmul(L8, W9) + b9)
with tf.name_scope("layer10") as scope:
    L10 = tf.nn.relu(tf.matmul(L9, W10) + b10)
with tf.name_scope("last") as scope:
    hypothesis = tf.sigmoid(tf.matmul(L10, W11) + b11)


# Cost function
with tf.name_scope("cost") as scope:
    cost = -tf.reduce_mean(Y*tf.log(hypothesis) + (1-Y)*tf.log(1-hypothesis))
    cost_summ = tf.scalar_summary("cost", cost)

# Minimize
with tf.name_scope("train") as scope:
    a = tf.Variable(0.001) # Learning rate, alpha
    optimizer = tf.train.GradientDescentOptimizer(a)
    train = optimizer.minimize(cost)



# Before starting, initialize the variables.
# We will `run` this first.
init = tf.initialize_all_variables()


# Launch the graph,
with tf.Session() as sess:
    # tensorboard --logdir=./logs/xor_logs
    merged = tf.merge_all_summaries()
    writer = tf.train.SummaryWriter("./logs/xor_logs", sess.graph_def)

    sess.run(init)
    # Fit the line.
    for step in xrange(50000):
        sess.run(train, feed_dict={X:x_data_training, Y:y_data_training})
        if step % 2000 == 0:
            summary = sess.run(merged, feed_dict={X:x_data_training, Y:y_data_training})
            writer.add_summary(summary, step)
            #print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W1), sess.run(W2)
            print step, sess.run(cost, feed_dict={X:x_data_training, Y:y_data_training})

    # Test model
    correct_prediction = tf.equal(tf.floor(hypothesis+0.5), Y)
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

    y_data_pred = sess.run(tf.floor(hypothesis + 0.5),
                           feed_dict={X: x_data_testing, Y: y_data_testing})

    print sess.run([hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], feed_dict={X:x_data_testing, Y:y_data_testing})
    print "Accuracy:", accuracy.eval({X:x_data_testing, Y:y_data_testing})

#   print confusion_matrix(y_data_testing[:,0], y_data_pred[:,0], labels=[0, 1])
    pd_y_true = pd.Series(y_data_testing[:, 0])
    pd_x_pred = pd.Series(y_data_pred[:, 0])
    print pd.crosstab(pd_y_true, pd_x_pred, rownames=['True'], colnames=['Predicted'], margins=True)

    target_names = ['false', 'true']
    print(classification_report(y_data_testing[:, 0], y_data_pred[:, 0], target_names=target_names))
    print 'Precision', precision_score(y_data_testing[:, 0], y_data_pred[:, 0], average='binary',pos_label=1)

결과

/root/tensorflow/bin/python /root/PycharmProjects/TensorFlowTest/PASSwithDNNLeRu9Hidden.py
I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 8
I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 8
0 0.770699
2000 0.589376
4000 0.580235
6000 0.578699
8000 0.577574
10000 0.576372
12000 0.575388
14000 0.574309
16000 0.572363
18000 0.570983
20000 0.569931
22000 0.568943
24000 0.567569
26000 0.565458
28000 0.564114
30000 0.562682
32000 0.561554
34000 0.56046
36000 0.559264
38000 0.558028
40000 0.556391
42000 0.555027
44000 0.553637
46000 0.55207
48000 0.550296


Accuracy: 0.727749
Predicted  0.0  1.0  All
True                    
0.0        276    0  276
1.0        104    2  106
All        380    2  382
             precision    recall  f1-score   support

      false       0.73      1.00      0.84       276
       true       1.00      0.02      0.04       106

avg / total       0.80      0.73      0.62       382

Precision 1.0

Conclusion

데이터 자체의 Label즉 truefalse가 부정확하기 때문에

Garbage in Garbage out의 명제대로 그다지 차이가 없다.
하지만 precision 정확도가 Deep Neural Network의 경우 매우 우수하기 때문에
False Prediction이 치명적인 시스템에서는 유효하다고 볼 수있다.

좀더 Deep Neural Network을
DroupoutAda Optimizer초기 Weight설정 등을 통해서 향상 시킬 수 있을것 같다.


'AI > TensorFlow, PyTorch, Keras, Scikit' 카테고리의 다른 글

TensorFlow 기본 개념 (1)  (0) 2016.07.01
TensorFlow 버전 업데이트 (Version Update)  (4) 2016.06.15
Softmax Function  (0) 2016.04.19
Neural Networks in XOR problem  (0) 2016.04.18
Logistic Regression  (0) 2016.04.17

Softmax Function


Logistic regression이란 아래의 식 처럼 0~1사이의 값을 출력해 준다.

$$ Z=H(X), g(z)$$
$$ g(z) = \frac{1}{1+e^{-z}}$$

이것을 그림으로 간소화 시켜보면 아래와 같다.

결국, Logistic Regression이라고 하는 것은 아래와 같은 두개의 데이터 분포에서
하나의 선을 그어서 데이터를 분할 하는 것을 말한다.

Activation Function으로 Sigmoid를 사용한다면 Logistic Regression과 Perceptron은 같은 개념 같기도 하다.

Multinomial Classification

여러개의 class로 확장을 해보자.

데이터 셋은 아래와 같다.

x1(hours)x2(attendance)y(grade)
105A
95A
32B
24B
111C

A, B, C 세 개가 있을 때

  • A or B, C
  • B or A, C
  • C or A, C 이렇게 세개의 Classifier가 있으면 가능 하다. 

그리고 이것을 각각 Matrix 연산을 하게 된다.

계산이 복잡하므로 이것을 합치면 아래와 같다.

그리고 세개의 값 중에서 가장 큰 값을 선택해서 그것으로 class label을 prediction 해도 괜찮다.

결국 20, 10, 0.1 이런식으로 나올 것이다.
하지만 이것은 우리가 원하는 것이 아니다.

0~1의 값을 가지며, 모든 class를 합치면 1이 되는 그러한 형태로 만들고 싶다.

그래서 사용하는것이 아래와 같은 Softmax함수이다.
그러면 0~1값과 모두 확률 값이므로 더하면 1이된다.

마지막으로 이중에서 가장 큰 확률을 가지는것만 1로 설정하고 나머지들은 모두 0으로 하기 위해서 아래와 같이
one hot encoding방식을 이용하게 된다.

이렇게해서 hypothesis는 완성이 되었다.

Cost Function 생성
예측값과 실제값 간의 차이를 나타내는 함수를 이제 설계 한다.
이것을 최소화 함으로써 학습을 완성하게 된다.

아래의 그림과 같이 예측값 $\hat{y}$과 실제값 $L=y$에대한 모습을 나타낸다.
그리고 이것의 차이를 나타내는 cost function을 cross entropy로 설정하게 된다.
즉 이전에 logistic regression의 cost function과 같은 형태인 것이다.

로그를 한것과 element wise multiplicatoin을 수행하는 형태이다.

수식으로 좀 더 자세히 표현하면 아래와 같다.

$$-\sum_{i}{L_{i}\log(S_{i})} = -\sum_{i}{L_{i} \log{(\hat{y}_{i})}}$$

여기서 곱은 내적 즉 element wise multiplication 이다.

결국 이것은 Logistic regression에서 다루었던 cost function
$$ C(H(x),y) = -y\log{(H(x))}+(1-y)\log{(1-H(x))}$$
과 같은 형태를 가진다.

각각을 예제에 따라서 계산해보면 아래와 같이 일치하면 cost가 0이고
불일치 하면 cost가 무한대로 계산 되는 것을 알 수 있다.

그리고 이것을 일반화 하면 아래와 같이 나오고 똑같이 미분해서 gradient descent알고리즘을 수행 시키면 된다.

Multinomial Classification 구현

구현 코드

import tensorflow as tf
import numpy as np

xy = np.loadtxt('softmaxTrain.txt', unpack=True, dtype='float')

x_data = np.transpose(xy[0:3])
y_data = np.transpose(xy[3:])
# tensorflow graph input
X = tf.placeholder('float', [None, 3]) # x1, x2, and 1 (for bias)
Y = tf.placeholder('float', [None, 3]) # A, B, C = > three classes
# set model weights
W = tf.Variable(tf.random_uniform([3,3],-1.0, 1.0))

# Our hypothesis
hypothesis = tf.nn.softmax(tf.matmul(X, W)) # softmax

# Cost function: cross entropy
cost = tf.reduce_mean(-tf.reduce_sum(Y*tf.log(hypothesis), reduction_indices=1))

# Minimize
a = tf.Variable(0.2) # Learning rate, alpha
optimizer = tf.train.GradientDescentOptimizer(a)
train = optimizer.minimize(cost)

# Before starting, initialize the variables. We will `run` this first.
init = tf.initialize_all_variables()

# Launch the graph,
with tf.Session() as sess:
    sess.run(init)

    # Fit the line.
    for step in xrange(10000):
        sess.run(train, feed_dict={X:x_data, Y:y_data})
        if step % 200 == 0:
            print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W)

    # Test model
    correct_prediction = tf.equal(tf.floor(hypothesis+0.5), Y)
    # Calculate accuracy (re-substitution error)
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print sess.run([hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], feed_dict={X:x_data, Y:y_data})
    print "Accuracy:", accuracy.eval({X:x_data, Y:y_data})

    # Test & one-hot encoding
    a = sess.run(hypothesis, feed_dict={X:[[1, 11, 7]]})
    print a, sess.run(tf.arg_max(a,1))

    b = sess.run(hypothesis, feed_dict={X: [[1, 3, 4]]})
    print b, sess.run(tf.arg_max(b, 1))

    c = sess.run(hypothesis, feed_dict={X: [[1, 1, 0]]})
    print b, sess.run(tf.arg_max(c, 1))

    all = sess.run(hypothesis, feed_dict={X:[[1, 11, 7], [1, 3, 4], [1, 1, 0]]})
    print all, sess.run(tf.arg_max(all, 1))

재치환 에러 (re-substitution)은 0이다. 결국 정확도는 1이 나온다.

두 번째는 샘플을 주고 각각의 argmax를 실행하는 것이다.
참값은 모르기 때문에 그냥 생성된 모델이 저렇게 예측한다는 것을 보기 위함이다.

실행결과

9800 0.0927773 [[-21.29355621   2.04889441  21.23555946]
 [  0.84294367   0.75854331   0.5262934 ]
 [  4.56429529   0.49110752  -3.74019885]]

[array([[  1.98164840e-15,   4.48229486e-07,   9.99999523e-01],
       [  1.17479602e-11,   4.03313388e-05,   9.99959707e-01],
       [  1.81849638e-04,   1.70287594e-01,   8.29530597e-01],
       [  6.83906451e-02,   8.93268943e-01,   3.83404866e-02],
       [  8.11137408e-02,   8.94745708e-01,   2.41405368e-02],
       [  5.18718772e-02,   8.72947454e-01,   7.51806125e-02],
       [  8.34491730e-01,   1.65429384e-01,   7.89094338e-05],
       [  9.97000158e-01,   2.99978442e-03,   1.59018363e-08]], dtype=float32), array([[ 0.,  0.,  1.],
       [ 0.,  0.,  1.],
       [ 0.,  0.,  1.],
       [ 0.,  1.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  1.,  0.],
       [ 1.,  0.,  0.],
       [ 1.,  0.,  0.]], dtype=float32), array([[ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True]], dtype=bool), 1.0]

재치환 에러는 0이고

Accuracy: 1.0
[[  9.97858584e-01   2.14142259e-03   4.48543203e-09]] [0]
[[  1.81849638e-04   1.70287609e-01   8.29530597e-01]] [2]
[[  1.81849638e-04   1.70287609e-01   8.29530597e-01]] [2]
[[  9.97858584e-01   2.14142259e-03   4.48543203e-09]
 [  1.81849638e-04   1.70287594e-01   8.29530597e-01]
 [  3.34250399e-19   4.98129182e-09   1.00000000e+00]] [0 2 2]

각각에 대한 출력값은 0,2,2 이다.
즉 학점으로 보면 A,C,C 인것이다.

출처

모두를 위한 머신러닝/딥러닝 강의, 김성훈 교수 (홍콩과기대)
http://hunkim.github.io/ml/


Neural Networks in XOR problem


본 장에서는 Neural network을 약 20년간 암흑기에 빠지게한 
XOR문제에 대해서 다뤄 보겠다.

우선 직관적으로 Hiddlen Layer를 통해서 XOR 문제를 해결 하는 방법을 알아보고
두 번째로 Backpropagation Algorithm을 이용해서 기계적으로 학습을 통해서 Weight 값을 알아내는 방법을 알아본다.
마지막으로 TensorFlow를 통해서 이를 각각 구현해 보도록 한다.

XOR using NN

아래와 같은 문제가 있다고 하자.

아래와 같은 weight들로 구성 되어져 있다고 가정 하자. 

이것을 각각 계산하면 아래와 같다.

좀 더 정리하면 아래와 같은 모습이 된다.

생각해 볼것은 여기서 주어진 wegiht들 이외에 XOR 문제를 풀수 있는 새로운 W와 b를 찾을 수 있을까?

그리고 Vectorazation을 이용해서 좀 더 간소화 시킬 수 도 있다.

이것을 TensorFlow로 구현 하면 아래와 같다.

# Our hypothesis
K = tf.sigmoid(tf.matmul(X, W1) + b1)
hypothesis = tf.sigmoid(tf.matmul(K, W2) + b2)

Backpropagation

MIT AI Lab의 창시자 Marvin Minsky가 말했던

No one on earth had found a viable way to train MLPs good enough to learn such simple functions.

Forwarding 방식으로는 Derivation을 계산하기가 너무 어렵다.
따라서 제안된 방식이 Backpropagation이다.

기본적으로 Back propagation은 미분학의 chain rule을 사용하는 방식이다.
여기서 chain rule이란 아래의 미분 공식을 말한다.
함수 $f(g(x))$의 미분값은 아래의 방식으로 계산 할 수 있다.
$$\frac{\partial f}{\partial x}=\frac{\partial f}{\partial g}\frac{\partial g}{\partial x}$$

이제 아래와 같은 간단한 함수를 생각해 보자.
$$f=Wx+b, g=Wx, f=g+b$$
그리고 이것을 chain rule을 통해서 모두 계산 할 수 있게 된다. 즉 결과 f에 미치는 각각의 term들의 영향을 계산할 수 있는 것이다.

  • forward (w=-2, x=5, b=3)
  • backward

이제 각각의 계산하면
w = -2
x = 5
b = 3
g = -10
f = -7

그리고 계산의 편의를 위해서 각각의 partial derivative를 모두 계산해 보자.

$$\frac{\partial g}{\partial w}=x$$
$$\frac{\partial g}{\partial x}=w$$
$$\frac{\partial f}{\partial g}=1$$
$$\frac{\partial f}{\partial b}=1$$

이제 편미분 값을 이용해서 f에 미치는 영향을 각각 계산하면 아래와 같다.

위 값을 해석해보면 결국 1이라는 것은 1:1 영향 관계를 나타내고
5는 5배 만큼 영향을 미친다는 것이다.
즉 b=3에서 b=4로 증가시킬 경우 f의 값은 -6이 된다. 즉 1만큼 차이가 생긴다.
반대로 w를 -3으로 변경 시키면 f는 -12되므로 -5만큼 값이 증가하게 된다. 5배의 영향을 미치는 것을 알 수 있다.

이러한 방법을 이용해서 아무리 복잡해서 모두 계산 할 수 있다.

Neural network implementation

How can we learn W1, W2, B1, B2 from training data ?

구현 방법에 대해서 알아 보겠다.
지난번 logistic regression code에서 약간만 더 수정하면 된다.

아래의 코드는 아래의 그림을 표현한 것이다.

W1 = tf.Variable(tf.random_uniform([2, 2], -1.0, 1.0))
W2 = tf.Variable(tf.random_uniform([2, 1], -1.0, 1.0))

b1 = tf.Variable(tf.zeros([2]), name="Bias1")
b2 = tf.Variable(tf.zeros([1]), name="Bias1")


# Our hypothesis
L2 = tf.sigmoid(tf.matmul(X, W1) + b1)
hypothesis = tf.sigmoid(tf.matmul(L2, W2) + b2)

위와 같이 구현하면 쉽게 두개의 layer가 존재하는 neural network을 구성한 것이 된다.

전체소스코드는 아래와 같다.
기본적으로 변경된 것은 아래와 같다.

1) hypothesis를 위와 같이 변경 했다.

2) 입력 데이터 형테를 변경 했다.
변경전 
[[ 0, 0, 1, 1],
[ 0, 1, 0, 1]]
변경후
[[0, 0],
[0, 1],
[1, 0],
[1, 1]]

3) Learning rate과 interation을 조정했다. converge하는데 시간이 너무 오래 걸린다.

import tensorflow as tf
import numpy as np

xy = np.loadtxt('train.txt', unpack=True)

#x_data = xy[0:-1]
x_data = np.transpose(xy[0:-1])
#y_data = xy[-1]
y_data = np.reshape(xy[-1], (4, 1))

X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)

W1 = tf.Variable(tf.random_uniform([2, 2], -1.0, 1.0))
W2 = tf.Variable(tf.random_uniform([2, 1], -1.0, 1.0))

b1 = tf.Variable(tf.zeros([2]), name="Bias1")
b2 = tf.Variable(tf.zeros([1]), name="Bias1")


# Our hypothesis
L2 = tf.sigmoid(tf.matmul(X, W1) + b1)
hypothesis = tf.sigmoid(tf.matmul(L2, W2) + b2)

# Cost function
cost = -tf.reduce_mean(Y*tf.log(hypothesis) + (1-Y)*tf.log(1-hypothesis))

# Minimize
a = tf.Variable(0.1) # Learning rate, alpha
optimizer = tf.train.GradientDescentOptimizer(a)
train = optimizer.minimize(cost)

# Before starting, initialize the variables. We will `run` this first.
init = tf.initialize_all_variables()

# Launch the graph,
with tf.Session() as sess:
    sess.run(init)

    # Fit the line.
    for step in xrange(10000):
        sess.run(train, feed_dict={X:x_data, Y:y_data})
        if step % 200 == 0:
            print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W1), sess.run(W2)

    # Test model
    correct_prediction = tf.equal(tf.floor(hypothesis+0.5), Y)
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print sess.run([hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], feed_dict={X:x_data, Y:y_data})
    print "Accuracy:", accuracy.eval({X:x_data, Y:y_data})

재치환 오류 계산 코드 설명

# Test model
correct_prediction = tf.equal(tf.floor(hypothesis+0.5), Y)
# Calculate accuracy
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print sess.run([hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], feed_dict={X:x_data, Y:y_data})
print "Accuracy:", accuracy.eval({X:x_data, Y:y_data})

tf.floor(hypothesis+0.5)는 0~1 사이의 값을 나오게 한다.
그리고 Y의 실제 값과 비교를 한다.
이러한 기능을 하는 함수 correct_prediction를 디자인 한것이다.

accuracy는 평균을 구하는 것이다.

[hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], 
feed_dict={X:x_data_testing, Y:y_data_testing}

print "Accuracy:", accuracy.eval({X:x_data_testing, Y:y_data_testing})

실행결과

9800 0.0402879 [[-6.13605404 -4.11170053]
 [-6.11376047 -4.1088109 ]] [[-8.83549595]
 [ 8.12334061]]
[array([[ 0.02604489],
       [ 0.96690428],
       [ 0.96695912],
       [ 0.05478531]], dtype=float32), array([[ 0.],
       [ 1.],
       [ 1.],
       [ 0.]], dtype=float32), array([[ True],
       [ True],
       [ True],
       [ True]], dtype=bool), 1.0]
Accuracy: 1.0

cost가 0.04로 0에 근접하는 것을 알 수 있다.


'AI > TensorFlow, PyTorch, Keras, Scikit' 카테고리의 다른 글

Naive Bayes vs Neural network  (2) 2016.04.25
Softmax Function  (0) 2016.04.19
Logistic Regression  (0) 2016.04.17
Linear regression with TensorFlow  (0) 2016.04.17
TensorFlow 개발환경 ( Eclipse + PyDev, Pycharm, Jupyter)  (0) 2015.11.17

Logistic Regression


Logistic Regression의 기본 개념

Linear regression 방식은 0.5를 기점으로 1과 0을 만들기가 어렵다.
즉 학습 데이터에 너무 기울기가 민감하다는 점이다.

그래서 나온것이 logistic 함수이다.

Logistic Hypothesis
$$H(X) = \frac{1}{1+e^{-W^{T}X}} $$

Cost function을 
위의 Hoypothesis를 바로 이용해서 구하게 되면
구불 구불한 graph가 형셩되어 local minimum에 도달하는 문제가 발생 한다.

New cost function for logistic

그래서 새로 나온 cost 함수는 아래와 같다.

갑자기 log를 하는 이유는 exponential이 결국 cost 함수를 구불구불 하게 만들기 때문에 이러한 특성을 제거해 주기 위해서
log를 취하게 된다.

Logistic은 0~1 사이의 값이므로
g(z) = -log(z)를 생각해보면 결국 z가 1이면 0인 그래프가 생성된다.

cost함수의 정의는 결국 예측값이랑 실제값이랑 같으면 cost가 0이고
틀리면 패널티를 주는 것이 철학이다.

위함수 대로 cost를 계산해보면
H(x) = 1 -> cost(1) = 0 
H(x) = 0 -> cost(0) = infinite

반대로 y=0일때를 계산해 보면
H(x) = 0, cost = 0
H(x) = 1, cost = infinite

결국 우리가 목표로하는 cost 함수가 잘 만들어진것을 알 수 있다.
그리고 아래의 그래프를 보면 bowl 모양으로 local minimum이 없는 gradient decesent하기 좋은 graph shape인 것을 알 수 있다.
이러한 것을 convexity가 아주 좋다고 한다.

이것을 If조건 없이 간소화하면 아래와 같은 수식이 된다.
$$ C(H(x),y) = -y\log{(H(x))}+(1-y)\log{(1-H(x))}$$

Minimum cost, Gradient decent algorithm

이제 간소화된 hypothesis를 이용해서 cost function을 아래와 같이 생성한다.
$$ cost(W) = -\frac{1}{m}\sum{y\log{(H(x))}+(1-y)\log{(1-H(x))}}$$

그리고 이것을 partial derivative해서 gradient descent algorithm을 수행 한다.
derivative를 하는 것은 복잡하므로 그냥 그렇게 한다고만 생각하자.
컴퓨터가 자동으로 계산해 줄 것이다.

$$ W:=W-\alpha\frac{\partial}{\partial W}cost(W)$$

Logistic regression의 Cost function을 최적화 하는 코드는 아래와 같다.
아래의 GradientDescentOPtimizer함수가 tensorflow에 구현되어 있으니 이것을 그냥 사용하면 된다.

# Cost function
cost = -tf.reduce_mean(Y*tf.log(hypothesis) + (1-Y)*tf.log(1-hypothesis))

# Minimize
a = tf.Variable(0.1) # Learning rate, alpha
optimizer = tf.train.GradientDescentOptimizer(a)
train = optimizer.minimize(cost)

Logistic Regression Basic Implementation

간단한 Logistic Regression을 이용한 코드는 아래와 같다.

Training Data

#x0 x1 x2 y
1 2 1 0
1 3 2 0
1 3 4 0
1 5 5 1
1 7 5 1
1 2 5 1

Code

import tensorflow as tf
import numpy as np

xy = np.loadtxt('logisticTrain.txt', unpack=True, dtype='float32')

x_data = xy[0:-1]
y_data = xy[-1]

X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)

W = tf.Variable(tf.random_uniform([1,len(x_data)],-1.0, 1.0))

# Our hypothesis
h = tf.matmul(W, X)
hypothesis = tf.div(1., 1+tf.exp(-h))

# Cost function
cost = -tf.reduce_mean(Y*tf.log(hypothesis) + (1-Y)*tf.log(1-hypothesis))

# Minimize
a = tf.Variable(0.1) # Learning rate, alpha
optimizer = tf.train.GradientDescentOptimizer(a)
train = optimizer.minimize(cost)

# Before starting, initialize the variables. We will `run` this first.
init = tf.initialize_all_variables()

# Launch the graph.
with tf.Session() as sess:
    sess.run(init)

    # Fit the line.
    for step in xrange(2000):
        sess.run(train, feed_dict={X:x_data, Y:y_data})
        if step % 200 == 0:
            print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W)

    # Test model: re-substitution error
    correct_prediction = tf.equal(tf.floor(hypothesis+0.5), Y)
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print sess.run([hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], feed_dict={X:x_data, Y:y_data})
    print "Accuracy:", accuracy.eval({X:x_data, Y:y_data})

    print '----------------------------------------'
    # study hour attendance
    # unseen data, but we don't know exact answer
    print sess.run(hypothesis, feed_dict={X:[[1], [2], [2]]}) > 0.5
    print sess.run(hypothesis, feed_dict={X:[[1], [5], [5]]}) > 0.5

    print sess.run(hypothesis, feed_dict={X:[[1, 1], [4, 3], [3, 5]]}) > 0.5

Result

1200 0.217096 [[-6.07444096  0.19686432  1.39010859]]
1400 0.205831 [[-6.5395813   0.2086037   1.48329437]]
1600 0.196362 [[-6.96585989  0.21742623  1.57006204]]
1800 0.188185 [[-7.36184502  0.22416407  1.65168989]]
[array([[ 0.00389449,  0.02695587,  0.46784386,  0.88681448,  0.92534608,
         0.79747105]], dtype=float32), array([[ 0.,  0.,  0.,  1.,  1.,  1.]], dtype=float32), array([[ True,  True,  True,  True,  True,  True]], dtype=bool), 1.0]
Accuracy: 1.0
----------------------------------------
[[False]]
[[ True]]
[[False  True]]

재치환 오류의 경우 0로 정확도가 1이 나온다.
그리고 2,2 5,5에 대해서는 False와 True가 나온다.
이것은 test data set을 임의로 만든 것이기 때문에 딱히 의미는 없다.
대략 생성된 모델로 저렇게 예측한 다는것을 보여주기 위함이다.

XOR with Logistic Regression

train.txt 데이터는 아래와 같다.
아무 편집기로나 하나 만들어 주면 된다.

import tensorflow as tf
import numpy as np

xy = np.loadtxt('train.txt', unpack=True)

x_data = xy[0:-1]
y_data = xy[-1]

X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)

W = tf.Variable(tf.random_uniform([1,len(x_data)],-1.0, 1.0))

# Our hypothesis
h = tf.matmul(W, X)
hypothesis = tf.div(1., 1+tf.exp(-h))

# Cost function
cost = -tf.reduce_mean(Y*tf.log(hypothesis) + (1-Y)*tf.log(1-hypothesis))

# Minimize
a = tf.Variable(0.01) # Learning rate, alpha
optimizer = tf.train.GradientDescentOptimizer(a)
train = optimizer.minimize(cost)

# Before starting, initialize the variables. We will `run` this first.
init = tf.initialize_all_variables()

# Launch the graph,
with tf.Session() as sess:
    sess.run(init)

    # Fit the line.
    for step in xrange(1000):
        sess.run(train, feed_dict={X:x_data, Y:y_data})
        if step % 200 == 0:
            print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W)

    # Test model
    correct_prediction = tf.equal(tf.floor(hypothesis+0.5), Y)
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print sess.run([hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], feed_dict={X:x_data, Y:y_data})
    print "Accuracy:", accuracy.eval({X:x_data, Y:y_data})

1) 200번 마다 print를 통해서 값을 출력하게 된다.
step, cost, W(wegiht) 이 세개의 값이다.

2) test model에서
hypothesis는 0~1사이의 값을 가진다. 
이것에 floor를 취하게 되면, element wise the largest value가 리턴 되어 지므로 0.5를 기준으로 0~1이 잘 반환 된다.
이것과 실제 Y값을 비교함으로써 accuracy를 측정 하게 된다.
마지막으로는 최종적으로 평균을 구하게 된다.

결과

/root/tensorflow/bin/python /root/PycharmProjects/TensorFlowTest/XORwithLogisticRegression.py
I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 8
I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 8
0 0.74015 [[ 0.71727103 -0.98306912]]
200 0.729532 [[ 0.66214472 -0.84831709]]
400 0.721451 [[ 0.60500312 -0.73486906]]
600 0.715226 [[ 0.54846114 -0.63875955]]
800 0.710393 [[ 0.49420556 -0.55683309]]
[array([[ 0.5       ,  0.38061982,  0.60909009,  0.48914438]], dtype=float32), array([[ 1.,  0.,  1.,  0.]], dtype=float32), array([[False, False,  True,  True]], dtype=bool), 0.5]
Accuracy: 0.5

Process finished with exit code 0

위와 같이 Logistic Regression 방법으로는 0.5의 정확도 밖에 얻을 수 없는것을 알 수 있다.

제대로 동작 하지 않는다.


Linear regression with TensorFlow

Placeholder

foo(a,b){ .. }

실행하는 시점에서 아래와 같이 값을 결정하게 할 수 있다.

a = tf.placeholder(tf.int16)
b = tf.placeholder(tf.int16)

# Define some operations
add = tf.add(a, b)
mul = tf.mul(a, b)

with tf.Session() as sess:
    print "Addition with variables: %i" % sess.run(add, feed_dict={a:2, b:3})
    print "Multiplication with variables: %d" % sess.run(mul, feed_dict={a:2, b:3})
Addition with variables: 5
Multiplication with variables: 6

Linear regression

H(x) = Wx +b

$$cost(H(x)) = \frac{1}{m} \sum_{i=1}^{m}{(H(x^{(i)})-y^{(i)})^2}$$

Variable로 지정해야 tensorflow가 update를 할 수 있게 된다.

import tensorflow as tf

x_data = [1,2,3]
y_data = [1,2,3]

# Try to find values for W and b taht compute y_data = W * x_data + b
# (We know that W should be 1 and b 0, but Tensorflow will figure that out for us.)

W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.random_uniform([1], -1.0, 1.0))

# Our hypothesis
hypothesis = W * x_data + b

# Simplified cost function
cost = tf.reduce_mean(tf.square(hypothesis-y_data))

# Minimize
a = tf.Variable(0.1) # Learning rate, alpha
optimizer = tf.train.GradientDescentOptimizer(a)
train = optimizer.minimize(cost)

# Before starting, initialize the variables.
# We are going to run this first.
init = tf.initialize_all_variables()

# Launch the graph
sess = tf.Session()
sess.run(init)

# Fit the line.
for step in xrange(2001):
    sess.run(train)
    if step % 100 == 0 :
        print step, sess.run(cost), sess.run(W), sess.run(b)

result

0 0.0695987 [ 1.0891968] [ 0.07517025]
100 1.00123e-06 [ 0.99883789] [ 0.00264173]
200 7.70968e-09 [ 0.99989802] [ 0.0002318]
300 5.84587e-11 [ 0.99999106] [  2.03111595e-05]
400 4.73695e-13 [ 0.99999917] [  1.74629804e-06]
500 4.73695e-15 [ 0.99999994] [  1.88630892e-07]
600 0.0 [ 1.] [  5.35269820e-08]
700 0.0 [ 1.] [  5.35269820e-08]
800 0.0 [ 1.] [  5.35269820e-08]
900 0.0 [ 1.] [  5.35269820e-08]
1000 0.0 [ 1.] [  5.35269820e-08]
1100 0.0 [ 1.] [  5.35269820e-08]
1200 0.0 [ 1.] [  5.35269820e-08]
1300 0.0 [ 1.] [  5.35269820e-08]
1400 0.0 [ 1.] [  5.35269820e-08]
1500 0.0 [ 1.] [  5.35269820e-08]
1600 0.0 [ 1.] [  5.35269820e-08]
1700 0.0 [ 1.] [  5.35269820e-08]
1800 0.0 [ 1.] [  5.35269820e-08]
1900 0.0 [ 1.] [  5.35269820e-08]
2000 0.0 [ 1.] [  5.35269820e-08]

with placeholder.
reuse가 가능하다.

import tensorflow as tf

x_data = [1,2,3]
y_data = [1,2,3]

# Try to find values for W and b taht compute y_data = W * x_data + b
# (We know that W should be 1 and b 0, but Tensorflow will figure that out for us.)

W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.random_uniform([1], -1.0, 1.0))

# with placeholder
X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)


# Our hypothesis
hypothesis = W * X + b

# Simplified cost function
cost = tf.reduce_mean(tf.square(hypothesis-Y))

# Minimize
a = tf.Variable(0.1) # Learning rate, alpha
optimizer = tf.train.GradientDescentOptimizer(a)
train = optimizer.minimize(cost)

# Before starting, initialize the variables.
# We are going to run this first.
init = tf.initialize_all_variables()

# Launch the graph
sess = tf.Session()
sess.run(init)

# Fit the line.
for step in xrange(2001):
    sess.run(train, feed_dict={X:x_data, Y:y_data})
    if step % 100 == 0 :
        print step, sess.run(cost,feed_dict={X:x_data, Y:y_data}), sess.run(W), sess.run(b)

result

0 0.0671113 [ 1.31180656] [-0.57569945]
100 0.000394039 [ 1.02305508] [-0.05240955]
200 3.03385e-06 [ 1.00202298] [-0.00459877]
300 2.33703e-08 [ 1.0001775] [-0.00040349]
400 1.7819e-10 [ 1.00001562] [ -3.54349249e-05]
500 1.51227e-12 [ 1.00000143] [ -3.18881439e-06]
600 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
700 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
800 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
900 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
1000 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
1100 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
1200 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
1300 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
1400 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
1500 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
1600 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
1700 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
1800 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
1900 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]
2000 3.78956e-14 [ 1.00000036] [ -6.25814607e-07]

이렇게 한번 model을 생성 했다면,
생성된 hypothesis를 이용해서 특정 X에 대한 모델을 출력할 수 있게 된다.

# learns best fit is W: [1], b: [0]

# Learns best fit is W: [1], b[0]
print sess.run(hypothesis, feed_dict={X:5})
print sess.run(hypothesis, feed_dict={X:2.5})

결과

[ 5.00000143]
[ 2.50000024]


Missing Value

How do I replace NA values with zeros in R

> m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10)
> d <- as.data.frame(m)
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1   4  3 NA  3  7  6  6 10  6   5
2   9  8  9  5 10 NA  2  1  7   2
3   1  1  6  3  6 NA  1  4  1   6
4  NA  4 NA  7 10  2 NA  4  1   8
5   1  2  4 NA  2  6  2  6  7   4
6  NA  3 NA NA 10  2  1 10  8   4
7   4  4  9 10  9  8  9  4 10  NA
8   5  8  3  2  1  4  5  9  4   7
9   3  9 10  1  9  9 10  5  3   3
10  4  2  2  5 NA  9  7  2  5   5

> d[is.na(d)] <- 0

> d
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1   4  3  0  3  7  6  6 10  6   5
2   9  8  9  5 10  0  2  1  7   2
3   1  1  6  3  6  0  1  4  1   6
4   0  4  0  7 10  2  0  4  1   8
5   1  2  4  0  2  6  2  6  7   4
6   0  3  0  0 10  2  1 10  8   4
7   4  4  9 10  9  8  9  4 10   0
8   5  8  3  2  1  4  5  9  4   7
9   3  9 10  1  9  9 10  5  3   3
10  4  2  2  5  0  9  7  2  5   5

listwise deletion of missing values

# create new dataset without missing data 
newdata <- na.omit(mydata)

na.locf 함수 사용

zoo package에 구현되어 있는 함수이다.

Last Observation Carried Forward

Generic function for replacing each NA with the most recent non-NA prior to it.

x <- c(NA,NA, "A","A", "B","B","B", NA,NA, "C", NA,NA,NA, "A","A","B", NA,NA)
na.locf(x)
x

출력 결과

 [1] "A" "A" "B" "B" "B" "B" "B" "C" "C" "C" "C" "A" "A" "B" "B" "B"

참고 사이트: http://www.cookbook-r.com/Manipulating_data/Filling_in_NAs_with_last_non-NA_value/


ggplot2: 그래픽 라이브러리

RStudio의 리더 Hadley Wickham이 ggplot2도 이끌고 있다.
개인홈페이지
Github 페이지

ggplot2

ggplot2의 Github 주소: https://github.com/hadley/ggplot2

버전에 따른 변경 이력

axis.line.x and axis.line.y work, but not axis.line #1567

2.1.0에서는 axis.line은 동작하지 않는다.

이전 버전에서 axis.line만 사용할 경우 
theme(panel.border = element_blank(), axis.line = element_line(colour="black"))
를 하면 x,y축에만 검정색 선이 생겼었다.

하지만 문제는 border를 공백처리하고 새로 선을 긋는것이기 때문에 새롭게 긋는 element_line이 너무 굵다면 
일부부만 겹치는 문제가 존재 했다.
theme(panel.border = element_blank(), axis.line = element_line(colour="black", size=4))
이러한 문제를 해결하기 위해서 추가적으로 lineend="square"옵션을 사용 했었다.
theme(panel.border = element_blank(), axis.line = element_line(colour="black", size=4, lineend="square"))

새로운 버전에서는 아래와 같이 하나 하나 설정 해줘야 한다.

mytheme <- theme_bw() + 
    theme(panel.border = element_blank(), axis.line.x = element_line(size = 1),
          axis.line.y = element_line(size = 1)) +







'AI > R ggplot2' 카테고리의 다른 글

CDF stat_ecdf  (0) 2016.12.21
R에서 EPS 이미지 생성  (0) 2015.06.16
ggplot2 package를 이용한 Graph 그리기  (0) 2015.02.16
R 그래프 페키지 종류  (0) 2014.11.05

Caret의 이해

Caret pakcage에 대해서 좀 더 알아 본다.

이전 포스
공식 사이트

Ch.11 Improving Model Performance

트레이닝 조건의 셋의 최적화 지점을 체계적으로 찾아서 모델의 성능을 튜닝하는 방법을 어떻게하면 자동으로 하는지를 배운다.

모델을 하나의 그룹으로 연합시키는 방법이다.

결정 트리의 variant

Tuning Stock Models for Better Performance

Machine Learning 알고리즘을 선택하는 만큼이나,
Parameter를 선택하는 것도 중요하고 어려운 문제이다.
Caret pakcage는 이러한 parameter 튜닝을 쉽게 하기위해서 grid search를 제공 한다.

Parameter tuning
This process of adjusting the model options to identify the best fit is called parameter tuning.

각 모델에서 필요한 파라메터를 바꿔 가면서 모델링을 수행 할 수 있다.

지원하는 모든 모델의 리스트는 아래 URL에서 확인 가능하다.
https://topepo.github.io/caret/modelList.html

특정 모델의 지원 파라메터를 잊었을 경우 아래 명령어로 확인 할 수 있다.

> modelLookup("nb")
  model parameter              label forReg forClass probModel
1    nb        fL Laplace Correction  FALSE     TRUE      TRUE
2    nb usekernel  Distribution Type  FALSE     TRUE      TRUE

Searching a set of cndidate models comprasing a matrix, or gride, of paremter combinations is impractical.
So, only a subset of possibilities is used to construc the grid.
By default, caret searches at most three values for each of the p parameters.
This means that at most $3^p$ cnadidate models will be tested.

하지만 이렇게 default tuning matrix을 쓰는것은 그다지 scientific하지 않다.

튜닝 파라메터를 주고 그중에서 최적의 모델을 선택 할수도 있다.

아래와 같은 코드에서 grid 방식으로 $ 4 \times 4$의 경우의 수가 존재하게 된다.
이것들을 하나하나 적용하면서 가장 정확도가 높은 model을 자동으로 선택하게 된다.
모델의 평가 방식은 10-folds cross validation 방식을 따른다.

set.seed(12358)
library(foreach)
library(caret)
ctrl <- trainControl(method="cv", 10)
grid <- data.frame(.fL=c(0,0,1,1), .usekernel=c(FALSE,TRUE,FALSE,TRUE))
sms_model1 <- train(dfList, factorClassList, method="nb",trControl = ctrl, tuneGrid = grid)

Variable Importance

Variable Importance

two class problems
만약 Model에서 제공해주는 importance 측정 방법이 존재 하지 않는다면
각 predictor의 importance는 filter를 적용해서 평가 되어 질 수 있다.

ROC Curve분석을 각각의 predictor에 적용하게 된다.

trapezoidal rule을 이용해서 ROC curve의 면적을 계산 한다. 그리고 이 면적의 값이variable importance가 된다.

Multi-class problems
각각의 클래스를 분리한다.
그렇게해서 class들간의 쌍을 만든다.

class1 vs class2
class2 vs claass3
이런 형식이다.

이러한 각 class들에 대해서 최대 curve 면적 값을 가지는 것을 variable importance로 규정 한다.

regression

t-value의 기울기 절대치를 이용하거나
R^2를 이용 한다.

Example

sacle=FALSE 이면 정규화를 하지 않는다.
scale=TRUE로 설정하면 0~100 사이의 score로만 표현된다.

varImp(sms_model1, scale=FALSE)

                    Importance
df.title                0.7292
df.hours                0.6968
df.app_name             0.5589
df.recentPhoneUsage     0.5360

filterVarImp

the area under the ROC curve를 각각의 predictor에 대해서 구하고 싶을 경우, filterVarImp를 사용하게 된다.

RocImp <- filterVarImp(x = training[, -ncol(training)], y = training$Class)
RocImp
          M         R
V1 0.6273646 0.6273646
V2 0.5765656 0.5765656
V3 0.5999674 0.5999674
V4 0.6614481 0.6614481
V5 0.6520711 0.6520711
V6 0.5923842 0.5923842

위와 같이 각 feature들을 1개씩 적용 했을 때의 각각의 class에 대한 ROC 면적을 알 수 있다.

Bayes Classifier의 경우 scale을 FALSE로 설정할 경우 varImp와 filterVarImp의 결과는 같게 된다.

VI <- varImp(sms_model1, scale=FALSE)
VI["importance"][[1]][[1]]

RocImp <- filterVarImp(x = dfList[[1]], y = factorClassList[[1]])
RocImp

실행 결과

> RocImp
      FALSE.     TRUE.
X1 0.9085812 0.9085812
X2 0.5491523 0.5491523
X3 0.6975939 0.6975939
X4 0.4907589 0.4907589
X5 0.4425584 0.4425584
X6 0.5000964 0.5000964
X7 0.4230355 0.4230355
X8 0.5114213 0.5114213

> VI["importance"][[1]]
      FALSE.     TRUE.
X1 0.9085812 0.9085812
X2 0.5491523 0.5491523
X3 0.6975939 0.6975939
X4 0.4907589 0.4907589
X5 0.4425584 0.4425584
X6 0.5000964 0.5000964
X7 0.4230355 0.4230355
X8 0.5114213 0.5114213

이전 POST: ROC 정의

그래프 그리기

plot(varImp(sms_model1, scale=FALSE))


병렬화를 통한 연산 성능 향상


성능 측정 방법: system.time과 R profiler

특정함수에 대한 시간만 보고싶으면 간단하게 system.time함수를 이용한다.

아래와 같이 do.call ldply의 성능을 비교한 것이다.
user, sys, elapsed이 세가지 관점으로 시간을 나타내주게 된다.

> ptList <- list(1:100000)
> system.time(do.call(rbind,ptList))
 사용자  시스템 elapsed 
      0       0       0 
> system.time(ldply(ptList,rbind))
 사용자  시스템 elapsed 
   0.17    0.00    0.17

사용자(user): 시간의 경우 프로그램 코드 자체를 R에서 수행한 시간이다.

시스템(sys): 시간의 경우 운영체제(OS)가 대신 작업을 처리하는데 걸린 시간이다. 예를 들면 save()또는 load()함수의 경우 sys 시간이 더 길게 된다. 이는 OS 작업을 통해서 파일 입출력을 수행하기 때문이다.
sys 시간이 크다면 메모리 부족도 의심해 봐야한다. R은 기본적으로 메모리에 모든 오브젝트를 로드하고 처리하므로 만약 메모리가 부족할경우 페이지 폴트가 지속적으로 발생해서 성능저하의 원인이 된다.

경과(elapsed): 시간는 가장 이해하기 쉬운 개념으로 프로그램 시작할 때 시간을 측정해서 끝날 때 종료한 시간 차이이다.

병렬 프로세싱 (doParallel, Window도 가능)

doMC는 내부적으로 fork()를 이용하기 때문에 linux에서 동작 하게 된다.
doParallel는 윈도우에서 사용 할 수 있는 package를 의미한다.

상세 관련 문서 vignette(“gettingstartedParallel”)

doParallel은 내부적으로 multicore, foreach, snow를 사용하기 때문에snow의 기능인 다수의 머신에 클러스터를 구현하는 기능을 제공하므로 doMC보다 더 막강하다고 할 수 있다.

install.packages("doParallel")
library(doParallel)

프로세스의 수 설정

코어의 수를 설정 한다.

registerDoParallel(cores=4)

작업관리자를 보면, Rscript.exe가 존재 하는 것을 알 수 있다.

plyr의 병렬화

{adl}{adl_}ply

형태의 함수들의 도움말을 살펴보면 .parallel 옵션이 있다. 이 옵션 값이 TRUE로 설정 되면
registerDoParallel()을 사용해 설정한 만큼의 프로세스가 동시에 실행되어 데이터를 병렬적으로 처리한다.

foreach의 병렬화

이미 for보다는 apply 계열의 함수가 더 빠르다는 것을 알고 있다.
foreach는 이러한 apply보다 더 빠른 loop연산 함수 이다.
그 이유가 바로 간단한 병렬화를 지원하기 때문이다.

foreach()는 기본적으로 %do를 사용해 실행할 명령의 블록을 지정해야 한다.
만약 foreach()에서 블록 내 명령을 병렬로 수행하고자 한다면registerDoParallel()을 한 뒤 foreach() %do% 대신 %dopar%를 지정하면 된다.

registerDoParallel로 core 수를 결정하면 실행 중인 프로세스 목록에 Rscript.exe라는 프로세스들이 설정한 코어 갯수 만큼 생성된것을 알 수 있다. 반복적으로registerDoParallel을 실행하면 해당 프로세스가 계속해서 늘어나기 때문에 이를 막기 위해서 명시적으로 stopImplicitCluster()를 해주는 것이 좋다.R-session을 종료하면 자동으로 정리해 주긴 하지만 말이다.

foreach는 apply()계열의 함수와 for()를 대체할 수 있는 루프문을 위한 함수 이다.
for문과의 가장 큰 차이는 반환 값이 있다는 점이다. 또한 {}가 아닌 %do%문을 사용해 블록을 지정한다는 점이다.

foreach::foreach(
    ... # 표현식 ex에 넘겨줄 인자
    # .combine은 ex에서의 반환 값을 어떻게 합칠지 지정한다. cbind(컬럼 방향으로 합친 데이터 프레임 반환),
    # rbind(행 방향으로 합친 데이터 프레임 반환), c(벡터로 반환) 등이 그예다. 기본값은 결과를 리스트로 합친다.
    .combine
    %do% ex # ex는 평가할 표현식
)

단순히 foreach만 사용할 경우

system.time(l1 <- rnorm(10000000))

library(foreach)
system.time(l2 <- foreach(i=1:4, .combine = 'c')
            %do% rnorm(2500000))

> system.time(l1 <- rnorm(10000000))
 사용자  시스템 elapsed 
   0.75    0.00    0.75 
> 
> library(foreach)
> system.time(l2 <- foreach(i=1:4, .combine = 'c')
+             %do% rnorm(2500000))
 사용자  시스템 elapsed 
   0.78    0.00    0.78

오히려 속도가 느려지는 것을 알 수 있다.

doParallel과 같이 이용
좀더 차이를 주기위해서 이전 예제보다 10대 갯수를 증가 시켰다.

> system.time(l1 <- rnorm(100000000))
 사용자  시스템 elapsed 
   7.38    0.14    7.55 
> 
> library(foreach)
> system.time(l2 <- foreach(i=1:4, .combine = 'c')
+             %do% rnorm(25000000))
 사용자  시스템 elapsed 
   8.28    0.28    8.58 

> library(doParallel)
> registerDoParallel(cores = 8)
> system.time(l3p <- foreach(i=1:10, .combine = 'c')
+             %dopar% rnorm(10000000))
 사용자  시스템 elapsed 
   1.54    2.25    5.15 
> stopImplicitCluster()

> length(l1)
[1] 100000000
> length(l2)
[1] 100000000
> length(l3p)
[1] 100000000

코어를 8개로 병렬화 했지만 8배까지는 아니고 2배정도 향상된것 같다.
데이터 분할 및 병합 overhead 때문에 발생하는 통상의 문제이다.
또한 i7-processor 특징상 물리적으로는 4-cores 지만 HT기술을 고려해서 논리적으론 8개로 잡았다.

작업이 끝나면 stopImplicitCluster()를 실행해서 closing doParallel cluster를 수행 시켜 주자.

하지만, stopImplicitCluster()을 수행할경우 apply()계열의 함수들이 connection error가 발생 하므로
모든 작업이 끝난 다음에 한번만 호출해 주자.

foreach 기타 옵션들

foreach값이 return하는 list/data.frame에 이름을 부여하고 싶을 경우
.final = function(x) setName(x, names(foo))를 이용한다.
.final은 마지막에 한번만 호출되게 된다.

foo <- list(a = 1, b = 2)
bar <- foreach (x = foo, .final = function(x) setNames(x, names(foo))) %do% {
    x * 2
    }

병렬 프로세싱 (Parallel package, Linux 전용)

set up worker processes that can complete tasks simultaneously.

It does this by including components of the multicore and snow packages, each taking a different approach towards multitasking.

To determine the number of cores your machine has, use the detectCores()function as follows.

An easy way to get started with the multicore functionality is to use themclappy() function, which is a parallel version of lapply().

mclapply {parallel}

mclapply(X, FUN, ..., mc.preschedule = TRUE, mc.set.seed = TRUE,
         mc.silent = FALSE, mc.cores = 1L,
         mc.cleanup = TRUE, mc.allow.recursive = TRUE)

참고자료

http://www.exegetic.biz/blog/2013/08/the-wonders-of-foreach/


위도,경도를 주소로 변환 ggmap package를 이용한 (geocoding and revgeocode in R)


GGMAP package

geocode

geocode함수는 latitude와 longitude를 가지고 location으로 변환 하는것을 말한다.
이것은 Google Map을 이용하게 된다.

Usage

geocode(location, output = c("latlon", "latlona", "more", "all"),
source = c("google", "dsk"), messaging = FALSE, force = ifelse(source ==
"dsk", FALSE, TRUE), sensor = FALSE, override_limit = FALSE,
client = "", signature = "", nameType = c("long", "short"), data)
geocodeQueryCheck(userType = "free")

예제

library(ggmap)

gc <- as.numeric(geocode('Baylor University'))
revgeocode(gc, output = 'more')
revgeocode(gc, output = 'all')

as.numeric(dfLocation[3,])
revgeocode(as.numeric(dfLocation[2:3,]),output = 'more')
revgeocode(latlng,output = 'more')
revgeocode(latlng, ics = 'WGS-84', api = 'google', output = 'address')

data.frame에 기록된 longitude와 latitude를 이용해서 Place로 변환하는 코드이다.

place <- adply(dfLocation, 1,function(x){
    revgeocode(as.numeric(x),output = 'more')
    }
)

test code

Using Google Maps API and R

library(RCurl)
library(RJSONIO)
library(plyr)

url <- function(address, return.call = "json", sensor = "false") {
    root <- "http://maps.google.com/maps/api/geocode/"
    u <- paste(root, return.call, "?address=", address, "&sensor=", sensor, sep = "")
    return(URLencode(u))
}

geoCode <- function(address,verbose=FALSE) {
    if(verbose) cat(address,"\n")
    u <- url(address)
    doc <- getURL(u)
    x <- fromJSON(doc,simplify = FALSE)
    if(x$status=="OK") {
        lat <- x$results[[1]]$geometry$location$lat
        lng <- x$results[[1]]$geometry$location$lng
        location_type  <- x$results[[1]]$geometry$location_type
        formatted_address  <- x$results[[1]]$formatted_address
        return(c(lat, lng, location_type, formatted_address))
        Sys.sleep(0.5)
    } else {
        return(c(NA,NA,NA, NA))
    }
}
address <- geoCode("The White House, Washington, DC")


'AI > R Basic' 카테고리의 다른 글

Missing Value  (0) 2016.03.20
병렬화를 통한 연산 성능 향상 및 성능 측정 방법  (0) 2016.03.06
Do.call()  (0) 2016.02.05
날짜 시간 변환 (Date-Time Conversion Function in R)  (0) 2015.12.14
JSON in R using jsonlite  (0) 2015.12.12

Cross Validation


Ch.10 Evaluating Model Performance
k-fold cross-validation에 대해서 다룬다.

K는 통상 10을 선택 한다.
After the process of training and evaluating the model has occured for 10 times (with 10 different training/testing combinations), the average performance across all the folds is reported.

k가 너무 크면, leave-one-out method 방법이다. 이 방법은 training에 사용할 데이터가 너무 적을 때 사용하는 방법이다.

createFolds

아래의 함수를 이용해서 k-fold를 수행 할 수 있다.

createFolds(y, k = 10, list = TRUE, returnTrain = FALSE)

createFolds를 사용하기 위해서는 입력 y의 타입이 vector type이어야 한다.
그리고 chronological order야만 한다.

# 10-fold cross validation with implementation
set.seed(12358)
folds <- createFolds(dfList_jemin[[2]]$app_name, k = 10, returnTrain = TRUE)

cv_results <- lapply(folds, function(x) {
    training <- data.frame(df[x, ])
    testing <- data.frame(df[-x, ])

    classTraining <- class[x]
    classtesting <-  class[-x]


    sms_model1 <- train(training, classTraining, method="nb")

    credit_pred <- predict(sms_model1, testing)

    cm1 <- confusionMatrix(credit_pred, classtesting, positive="TRUE")

    return(cm1$overall[[1]])
})

str(cv_results)
mean(unlist(cv_results))

실행 결과

> str(cv_results)
List of 10
 $ Fold01: num 0.886
 $ Fold02: num 0.793
 $ Fold03: num 0.788
 $ Fold04: num 0.676
 $ Fold05: num 0.5
 $ Fold06: num 0.719
 $ Fold07: num 0.688
 $ Fold08: num 0.719
 $ Fold09: num 0.788
 $ Fold10: num 0.788
> mean(unlist(cv_results))
[1] 0.7343925

Caret control option을 이용한 방법: trControl=ctrl

caret package의 control 함수를 이용해서도 위의 cross-validation 방법을 수행 할 수 있다.

# 10-fold cross validation  with caret
ctrl <- trainControl(method="cv", 10, verbose = TRUE)

set.seed(12358)
sms_model1 <- train(df,class, method="nb", trControl=ctrl)
sms_model1

실행 결과

Naive Bayes 

325 samples
  1 predictor
  2 classes: 'FALSE', 'TRUE' 

No pre-processing
Resampling: Cross-Validated (10 fold) 
Summary of sample sizes: 292, 293, 293, 292, 292, 292, ... 
Resampling results across tuning parameters:

  usekernel  Accuracy   Kappa      Accuracy SD  Kappa SD 
  FALSE      0.7321481  0.4587484  0.07483437   0.1433968
   TRUE      0.7321481  0.4587484  0.07483437   0.1433968

Tuning parameter 'fL' was held constant at a value of 0
Accuracy was used to select the optimal model using  the largest value.
The final values used for the model were fL = 0 and usekernel = FALSE. 


'AI > Machine Learning with R' 카테고리의 다른 글

Feature Selection with Caret (Auto)  (0) 2016.11.20
Caret의 이해  (0) 2016.03.06
Ensemble method: Bagging (bootstrap aggregating)  (0) 2015.11.19
Bootstrapping  (0) 2015.11.19
Principal Component Analysis (PCA)  (0) 2015.11.18

Do.call()


데이터는 리스트 구조에 담겨져 있다.
이 데이터를 어떤 함수로 전달하고 싶지만 그 함수는 리스트를 인자로 받을 수 없는 구조이다.

해결책
1. 리스트를 벡터로 변환한다.
2. do.call함수로 리스트를 개별 인자들로 분해한 쓰려고 하는 함수에 적용 한다.

do.call(function, list)

예제 아래와 같이 중첩 리스트(nested list)일 경우에 데이터행렬로 변경하기가 골치아프게 된다.

> list <- list(col1 = list (1,2,3), col2 = list(3,4,5), col3 = list(6,7,8))
> list
$col1
$col1[[1]]
[1] 1

$col1[[2]]
[1] 2

$col1[[3]]
[1] 3


$col2
$col2[[1]]
[1] 3

$col2[[2]]
[1] 4

$col2[[3]]
[1] 5


$col3
$col3[[1]]
[1] 6

$col3[[2]]
[1] 7

$col3[[3]]
[1] 8

# cbind를 수행해도 원하는 않는 코드가 생성 된다.
> cbind(list)
     list  
col1 List,3
col2 List,3
col3 List,3


# data.frame()을 수행해도 이상한 결과이다.
> as.data.frame(list)
  col1.1 col1.2 col1.3 col2.3 col2.4 col2.5 col3.6 col3.7 col3.8
1      1      2      3      3      4      5      6      7      8

> unlist(list)
col11 col12 col13 col21 col22 col23 col31 col32 col33 
    1     2     3     3     4     5     6     7     8 

> cbind(unlist(list))
      [,1]
col11    1
col12    2
col13    3
col21    3
col22    4
col23    5
col31    6
col32    7
col33    8

#비로써 적절히 행과 열이 나뉘어서 합쳐지는 것을 볼 수 있다.
> do.call(cbind,list)
     col1 col2 col3
[1,] 1    3    6   
[2,] 2    4    7   
[3,] 3    5    8 


+ Recent posts