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

Autonomous Driving Example


자동 드라이빙의 경우 Dean Pomerleau가 만든것이다.
CMU의 Robotics Institute의 Adjunct Faculty이다.

같은 길에 대해서는 몇분만 트레이닝을 하면 사람과 같이 정확하게 동작하게 된다.

지금 사례를 찾아보면 테슬라 등등에서 훨씬 더 좋은 Auto Driving이 존재 한다.


'MOOC > Machine Learning (python)' 카테고리의 다른 글

Week 05: 1. Neural Network Cost Function  (0) 2017.01.28
Programming Exercise 4: Neural Networks Learning  (0) 2017.01.02
Putting it together  (0) 2016.10.12
Random Initialization  (0) 2016.09.19
Gradient Checking  (0) 2016.08.04

Putting it together


When training a neural network, the first thing you need to do is pick some network architecture.

Architectures mean connectivity pattern between the neurons

히든 레이어를 1개만 쓰는것이 일반 적이다.

많은 히든 레이러를 쓰고 싶으면 같은 수의 neuron으로 구성하는 것이 일반 적이다.

Hidden Layer가 많을 수록 잘 동작 할 수도 있지만 Computation Cost가 높기 때문에 신중히 선택해야 한다.

구현을 위한 과정은 아래와 같다.

위코드는 For-loop를 사용했지만 Advanced를 하게 되면 vectorization을 통해서 for-loop을 쓰지 않고
Backpropagation을 수행 할 수 있다.

그 다음 partial derivative가 정상적으로 동작하는지 알기 위해서 gradient checking 코드를 이용해서 확인 해야 한다.
$J(\theta)$가 non-convex function이라서 global minimum이 아닌 local minimum에 머물 지라도 practical problem에서는 그렇게 문제는 되지 않는다고 한다.

수업 초기에 보여주었던 그래프를 통해서 Gradient Descent Alogirhtm이 어떻게 $\theta$값을 최소화하는지 알아 보도록 하겠다.
해당 그래프는 아래와 같다.

Quiz

Backpropagation은 non-linear function을 classification하기 위한 하나의 좋은 algorithm이다.


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


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

Git config 설정 (계정설정)


기본 개념

Git을 설치하고 나면 Git의 사용 환경을 적절하게 설정해 주어야 한다. 한 번만 설정하면 된다. 설정한 내용은 Git을 업그레이드해도 유지된다. 언제든지 다시 바꿀 수 있는 명령어가 있다.

  • git config라는 도구로 설정 내용을 확인하고 변경할 수 있다. Git은 이 설정에 따라 동작한다. 이때 사용하는 설정 파일은 세 가지나 된다.
  • /etc/gitconfig 파일: 시스템의 모든 사용자와 모든 저장소에 적용되는 설정이다. git config --system 옵션으로 이 파일을 읽고 쓸 수 있다.
  • ~/.gitconfig 파일: 특정 사용자에게만 적용되는 설정이다. git config --global 옵션으로 이 파일을 읽고 쓸 수 있다. .git/config: 이 파일은 Git 디렉토리에 있고 특정 저장소(혹은 현재 작업 중인 프로젝트)에만 적용된다. 각 설정은 역순으로 우선시 된다. 그래서 .git/config가 /etc/gitconfig보다 우선한다.

윈도용 Git은 $HOME 디렉토리(%USERPROFILE% 환경변수)에 있는 .gitconfig 파일을 찾는다. 보통 C:\Documents and Settings\$USER 또는 C:\Users\$USER 이다(윈도우에서는 $USER 대신 %USERNAME%를 사용한다). 그리고 msysGit도 /etc/gitconfig를 가지고 있다. 경로는 MSys 루트에 따른 상대 경로다. 인스톨러로 msysGit을 설치할 때 설치 경로를 선택할 수 있다.

계정 설정

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

프로젝트 마다 다른 Email을 사용하고 싶으면 --global 옵션을 제거하면 된다.

설정 확인

$ git config --list
user.name=Scott Chacon
user.email=schacon@gmail.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto


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


Random Initialization


Neural Netwrok을 구현하기 위해서는
맨 처음에는 $\theta$를 초기화 하는 코드를 자성해야 한다.

보통 취하는 방법은 아래처럼 random initialTheta를 취하는 것이다.

optTheta = fminunc(@costFunction, initialTheta, options)

의문점은 Zero initialization에 관한 의문이 생긴다.
Logistic regression을 작성할 때는 별 다른 문제가 되지 않는다. 하지만 Nueral Netwrok이라면 그것은 문제가 된다.

위와 같이 0으로 초기화후 Gradient Descent 알고리즘을 수행하면 모든 Hidden Layer들이 정확히 같이 값이 변화기 때문에
그저 중복적인 Hidden Layer에 지나지 않게 된다.

Quiz


세관 신고 정리

  1. 총합 미화 600불을 기준으로 한다.
  2. 인천공항, 다른공항, 다른 나라 모든 물품의 구매 합이 600불을 넘으면 세관신고 해야한다.
  3. 외국에서 산 물품을 텍스 리펀받는다고 해서 그걸 텍스 리펀금액을 기준으로 과세 하지 않는다. 과세는 무조건 영수증 기준이고 더 엄격하게는 Tag를 기준으로 한다.
  4. 인천공항에서 산 물품은 모두 전산처리되어서 이미 알고 있다. 산걸 다시 입국 할 때 가지고 들어온다면 Tag를 땐다고 해도 소용 없다. 600불 넘으면 과세 대상이다.
  5. 자진신고 하면 앵간하면 총합이 700~1천불 사이면 걍 봐준다. 우리나라 정으로다가 (꼭 그런건 아님)
  6. 단일 물품이 600불 초과가 있지 않으면 자잘한거 합쳐서 초과하는건 앵간하면 봐준다. (꼭 그런건 아님)
  7. 과세는 700불 짜리가 있다고하면 600불을 제외하고 100불에 대해서만 과세 한다.
  8. 2명이 각각 600불 면제금액을 가지고 2개의 물품에 대해서 나눠서 과세 받을 수 있다.
  9. 1개의 물품은 쪼개서 과세 받지 못한다.
  10. 신용카드로 1명이 4개를 구입해도 4명의 것이라면 입국 할 때 각각 나눠서 과세 받을 수 있다.
  11. 예상 세액 조회: Link


This startup uses batteyr life to determine credit scores


폰의 사용량 예를들면 배터리 소모 같은것들을 이용해서 사용자의 신용도를 평가하는 방식이다.

Singapore에 있는 Lenddo회사이다.
Chairman은 Jeff Stewart 이다.

분석 데이터의 종류

  • smartphone user's messaging
  • browsing activity
  • Wi-Fi network activity

Lenddo puts the data points into a complex proprietary algorithm, which computes how likely someone will default on a loan. Lenders then decide the default rate they want to accept.

While certain mobile behavior could impact the outcome of a credit score (like always running out of battery power), Stewart said extremely well-maintained smartphones raise a red flag in the system, too.

보험 업계에서도 쓰이고 있다.
Your smartphone knows if you're good driver
Even though Lenddo isn't used in the U.S., insurance firms like Liberty Mutual and State Farm have started to adopt similar methodology to help determine car insurance discounts.
For example, the companies have asked customers to submit information collected from their smartphones' GPS, accelerometer and gyroscope to learn how people drive, brake and make turns.

참고문헌

Original Article


이 때 까지 출판한 논문들을 이용해서 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

몬슨(MONSOON) 파워모니터(Power Monitor)를 이용한 안드로이드 앱 전력 소모 측정 (스마트폰 전력 소모 분석)


본 포스트에서는 학위과정 동안 진행했던 스마트폰 전력 소모 측정을 하는 방법을 다룬다.
스마트폰 전력소모를 측정하는 방법은 여러가지다.
이번에는Monsoon Power Monitor 장비를 이용한 방법으로
가장 쉬운 형태인 분리형 배터리 (removable battery)에 대해서 측정 하는것을 다룬다.

Monsoon Power Monitor의 경우 미국에서 사면 800달러 미만이지만 한국으로 수입해오는 업체를 통해서 구입하면,
120~130만원 정도한다. 나름 개인이 구입하기에는 싼 가격은 아니다.
멀티미터기를 이용한 방법도 이어서 다루도록 하겠다.

준비물

사용된 스마트폰: Galaxy 3
측정 장비: Monsoon Power Monitor, FTA22D
 
테이프: 구리(Copper) tape, 캡톤(Kapton) Tape

측정 실험 환경

간단히 개념화하면 아래와 같은 그림으로 배터리와 폰은 직접적으로 연결 되지 않은 상태이다.
Ground만 연결한 상태에서 Vcc는 Monsoon을 통해서 공급하게 된다.

컴퓨터랑은 USB를 이용해서 연결하므로 그다지 특별한 것은 없다.

실행 화면

단순히 화면을킨 상태에서 외부로부터 카카오톡 메시지를 전송 받을 때의 전력 소모 그래프이다.

해당 그래프는 Galaxy 3는 아니고 Nexus 5로 실험한 것이다.
2011년에 Single core인 Nexus-one으로 연구 진행 했었을 때는 많이 써야 1000mW내외로 소모하던 전력이 Quard-cores로 개발된 Nexus 5의 경우 단순히 Processor와 Wi-Fi 그리고 Display 조금 썻다고 순간적으로 4000mW까지 치솟는걸 보면
현재 스마트폰이 얼마나 배터리를 소모하는 괴물인지 알 수 있다.

이에 맞추어서 Monsoon Power tool v5.0부터는 High Voltage를 허용한다.
원래 Monsoon은 허용 전압이 4.55v였다. 하지만 요즘은 동작 전압이 너무 높기 때문에 이러한 제한을 풀어주는 새로운 버전의Power Tool이 제조사로부터 공급된다.

몬슨의 장점은 전력 소모 측정과 데이터 전송을 동시에 할 수 있다는 점이다.
아래와 같이 USB를 연결한 상태에서 Main channel로 전력을 공급 할 수도 있다.
데이터 전송을 위해서 USB를 활성화 시키면 자동으로 Main channel을 off된다. 
역전류 현상을 방지하기 위함이다.

보통 Multi-meter나 Power supply로 실험 환경을 구성할 경우 데이터 전송을 위해서 USB를 연결하기 어려운 단점이 존재한다.
USB 또한 전류를 공급하기 때문이다.
자동으로 이러한 ON OFF기능이 몬슨의 또하나의 장점이라 할 수 있다.


테스트 주도의 개발을 위한 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을 이용한 데이터 처리 & 분석 실무, 서민구


Github에 100Mb이상 파일 올리는 방법 (오류 해결)


필자의경우 Bitbucket에서 사용하던 Project를 Github로 옴기려고 하다보니 이와 같은 에러가 발생 했다. Github의 경우 개당 파일은 100MB제한이고 있지만 전체 용량 제한은 없다.
Bitbucket은 개당 파일의 제한은 없지만 전체용량이 2GB이상이 안되는 제한사항이 존재 한다.

Github의 경우 50Mb는 Warning을 표시하며, 100Mb부터는 Error를 나타낸다.
따라서 이 이상의 파일을 Push하려하면 아래와 같은 에러를 발생 시킨다.
Github Policy

에러

root@ubuntu:~/python_source/AutoTestingModule# git push github --all
Username: 
Password: 
Counting objects: 40223, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (26581/26581), done.
Writing objects: 100% (40223/40223), 582.06 MiB | 7.94 MiB/s, done.
Total 40223 (delta 12516), reused 40162 (delta 12503)
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
remote: error: Trace: b052327128727acb5dc9e1fed5cdbb8f
remote: error: See http://git.io/iEPt8g for more information.
remote: error: File TestingResult.tar.gz is 111.47 MB; this exceeds GitHub's file size limit of 100.00 MB
root@ubuntu:~/python_source/AutoTestingModule# git log b05232
fatal: ambiguous argument 'b05232': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

위 에러 메시지는 HEAD에는 100MB 이상의 파일은 없다.
즉 최근 commit이나 현재 Directory에는 100MB 이상의 파일이 존재하지 않는다. 
하지만 이전 Commit에서라도 100MB이상의 파일이 존재한다면 이러한 에어를 발생 시킨다.
필자의 경우도 TestingResult.tar.gz의 경우 이전에 만들어 두었던 BackUp 파일 하나가 변경이력에 들어가서 문제가된 것이다.

해결방법

경고 메시지에도 나와 있듯이 몇가지 해주면 쉽게 해결이 가능하다.

1.git-lfs 이용

https://git-lfs.github.com/

2. BFG Repo-Cleaner 적용

https://rtyley.github.io/bfg-repo-cleaner/

필자의 경우 그냥 필요없는 파일이라 이전 이력을 뒤져서 제거하는 방법을 선택 했다.
위 공식 사이트에 가서 bfg-x.x.x.jar파일을 다운받고 아래처럼 실행하자.

실행 결과

root@ubuntu:~/python_source/AutoTestingModule# java -jar bfg-1.12.12.jar --strip-blobs-bigger-than 100M

Using repo : /root/python_source/AutoTestingModule/.git

Scanning packfile for large blobs: 40169
Scanning packfile for large blobs completed in 1,435 ms.
Found 1 blob ids for large blobs - biggest=116880364 smallest=116880364
Total size (unpacked)=116880364
Found 36035 objects to protect
Found 7 commit-pointing refs : HEAD, refs/heads/GUI, refs/heads/MultiRun, ...

Protected commits
-----------------

These are your protected commits, and so their contents will NOT be altered:

 * commit 034d2b0b (protected by 'HEAD')

Cleaning
--------

Found 52 commits
Cleaning commits:       100% (52/52)
Cleaning commits completed in 406 ms.

Updating 6 Refs
---------------

    Ref                            Before     After   
    --------------------------------------------------
    refs/heads/GUI               | bfec4c11 | ebffb517
    refs/heads/MultiRun          | 968de654 | d0fd0d5f
    refs/heads/master            | 034d2b0b | abe6ecc0
    refs/remotes/origin/GUI      | bfec4c11 | ebffb517
    refs/remotes/origin/MultiRun | 968de654 | d0fd0d5f
    refs/remotes/origin/master   | 034d2b0b | abe6ecc0

Updating references:    100% (6/6)
...Ref update completed in 262 ms.

Commit Tree-Dirt History
------------------------

    Earliest                                      Latest
    |                                                  |
    ......................DDDDDDDDmmmmmm.mmmmmmmmmmmmmmm

    D = dirty commits (file tree fixed)
    m = modified commits (commit message or parents changed)
    . = clean commits (no changes to file tree)

                            Before     After   
    -------------------------------------------
    First modified commit | 7a6c355c | c9286236
    Last dirty commit     | cb054c2b | 25d98799

Deleted files
-------------

    Filename               Git id             
    ------------------------------------------
    TestingResult.tar.gz | 4153149d (111.5 MB)


In total, 37 object ids were changed. Full details are logged here:

    /root/python_source/AutoTestingModule.bfg-report/2016-08-09/00-21-29

BFG run is complete! When ready, run: git reflog expire --expire=now --all && git gc --prune=now --aggressive


Has the BFG saved you time?  Support the BFG on BountySource:  https://j.mp/fund-bfg

위와 같이 이전 commit에서 빠르게 해당 파일을 찾아서 제거하고 commit메시지를 자동으로 바꾼것을 알 수 있다. 정말 편리한 유틸리티인것 같다.

이제 다시 Github repository에 PUSH를 시도해 보자.

root@ubuntu:~/python_source/AutoTestingModule# git push github --all
Username: 
Password: 
Counting objects: 40223, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (26589/26589), done.
Writing objects: 100% (40223/40223), 471.01 MiB | 8.80 MiB/s, done.
Total 40223 (delta 12516), reused 40126 (delta 12494)
To https://github.com/leejaymin/QDroid.git
 * [new branch]      GUI -> GUI
 * [new branch]      MultiRun -> MultiRun
 * [new branch]      master -> master
root@ubuntu:~/python_source/AutoTestingModule# 

참고문헌


Gradient Checking


Backprogation Algorithm은 구현이 다소 복잡하고 여러 방법으로 구현 할 수 있기 때문에
subtle bug를 찾기가 어렵다.

이것을 디버그하기 위한 아이디어가
Gradient Checking이다.

모든 복잡한 Nueral Network Algorithm을 개발할 때 사용 할 수 있다.


위 그림에서 파란색은 실제 미분 했을 때 구해지는 접선의 기울기이다.
해당 값은 epsilon을 이용해서 approximation할 수 있다.
빨간색과 같이 slope를 approximation하면 꽤 근사하게 구해지는 것을 알 수 있다.

추가로 위 그림에서 파란색 수식은 epsilon을 한번만 사용한 one sided difference이다.
이것 보다 빨간색 수식으로 epsilon을 두번 사용한 것이 더 정확하게 estimation할 수 있다.

Quize

So these equations give you a way to numerically approximate the partial derivative of $J$ with respect to any one of your parameters $\theta_i$.

구현해야 할것은 아래의 For loop이다.

결국 back-propagation을 통해서 DVec을 구하게 된다.
그리고 우리가 대략적으로 구한 gradApprox랑 비교하게 된다.

Backpropagation is a relatively efficient way to compute a derivative or a partial derivative of a cost function wrt to all our parameters.

이것을 통해서 구현이 정상적으로 이뤄 졌는지를 알 수 있다.

마지막으로 요점을 정리하면 아래와 같다.

  • Implementation Notes

    • Implement backpropagation to compute DVec (unrolled $D^{(1)}$, $D^{(2)}$, $D^{(3)}$).
    • Implement numerical gradient check to compute gradApprox.
    • Make sure they give similar values.
    • Turn off gradient checking. Using backpropacation code for learning.

    이 부분이 가장 중요한데, gradient checking은 computationally 굉장히 expensive 하기 때문에 학습할 때는 반드시 꺼야 한다. 당연한 말이지만 그래서 1960년대 nueral network 자체가 죽은것이다.
    이것을 해결한 알고리즘이 Backpropagation이기 때문이다. 딱 한번 구현 확인 용도로만 쓰자.

Quize


비교 분석 (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

Neural Networks Learning: Implementation note unrolling


Octave programming

아래 방법 처럼 초기 Weight vector를 생성하고
이것을 긴 하나의 vector로 언롤링 한다.
그리고 reshape을 이용해서 다시 복구 할 수 있다.

octave:1> Theta1 = ones(10,11)
Theta1 =

   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1

octave:2> Theta2 = 2 *ones(10,11)
Theta2 =

   2   2   2   2   2   2   2   2   2   2   2
   2   2   2   2   2   2   2   2   2   2   2
   2   2   2   2   2   2   2   2   2   2   2
   2   2   2   2   2   2   2   2   2   2   2
   2   2   2   2   2   2   2   2   2   2   2
   2   2   2   2   2   2   2   2   2   2   2
   2   2   2   2   2   2   2   2   2   2   2
   2   2   2   2   2   2   2   2   2   2   2
   2   2   2   2   2   2   2   2   2   2   2
   2   2   2   2   2   2   2   2   2   2   2

octave:3> Theta3 = 3*ones(1,11)
Theta3 =

   3   3   3   3   3   3   3   3   3   3   3

octave:8> thetaVec = [ Theta1(:); Theta2(:); Theta3(:)];
octave:9> size(thetaVec)
ans =

   231     1

octave:10> reshape(thetaVec(1:110), 10,11)
ans =

   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1
   1   1   1   1   1   1   1   1   1   1   1

위와 같이 긴 vector를 만듬으로써 fminunc의 성능을 끌어 올릴 수 있다.
Cost function을 계산 할때에는 reshape을 통해서 각각의 다시 계산하게 된다.


Neural Networks_Learning_3


Backpropagation Intuition

Backpropagation은 수학적으로 클린한 알고리즘은 아니다.
이것은 linear regression이나 Logistic regression와 비교하면 복잡한 알고리즘에 속한다.

먼저 Forward Propagation을 설명해 보자.

위 Neural Network의 구조는 [2 2 2 1]의 구조를 가진다.
$\theta$에서 $i$는 다음 layer에서 영향을 미칠 node의 위치를 나타낸다.
$j$는 특정 layer에서의 node위치를 의미한다.
$l$은 layer의 위치를 의미한다.

$z$에서 $a$로 변경 될때는 activation function을 거친다는 것을 알아두자.

What is backpropagation doing?


일단 output이 1개 뿐이라고 생각해보자. 그럼 Cost function이 위와 같이 간단해 진다.
그리고 regularization term을 무시하기 위해서 $\lambda$는 0으로 설정 한다.
cross entropy형태의 cost function은 결국 Square Error를 근사시키기 위한 변형 함수이다.
직관을 위해서 그냥 Square Error라고 생각하자.
그럼 좀 더 쉽게 생각 할 수 있다.

Forward propagation을 꺼구로 수행한것 처럼 계산하면
아래와 같이 식을 구할 수 있다.

결국 $\delta$라는 것은 실제 y와 예측한값 a간의 error를 나타낸다.
좀더 수학적으로 표현하면, 아래와 같다.
$$ \delta^{(l)}_{j} = \frac{\partial cost(i)}{\partial z_j^{(l)}} $$
여기서 $j$는 $\ge 0$를 만족 한다.
cost(i)는 cross entropy 값이다.


Programming Exercise 3: Multi-class classification and Neural Networks


Introduction

one-vs-all logistic regression과 neural networks를 구현하고 이를 통해서 hand-written digits를 인식해 볼 것이다.

Files included in this exercise

ex3.m - Octave/MATLAB script that steps you through part 1
ex3 nn.m - Octave/MATLAB script that steps you through part 2
ex3data1.mat - Training set of hand-written digits
ex3weights.mat - Initial weights for the neural network exercise
submit.m - Submission script that sends your solutions to our servers
displayData.m - Function to help visualize the dataset
fmincg.m - Function minimization routine (similar to fminunc)
sigmoid.m - Sigmoid function
[] lrCostFunction.m - Logistic regression cost function
[
] oneVsAll.m - Train a one-vs-all multi-class classifier
[] predictOneVsAll.m - Predict using a one-vs-all multi-class classifier
[
] predict.m - Neural network prediction function

전반적으로 ex3.m과 ex3_nn.m파일을 가지고 작업을 하게 된다.

1. Multi-class Classification

우선, 이전에 개발한 Logistic regression을 확장해서 one-vs-all classification을 구현 하게 된다.

1.1 Dataset

ex3data1.mat에 저장되어 있다.
이 파일에는 5000개의 handwritten digit들이 training example로써 5000개 저장되어 있다.
.mat format은 native Ooctave/MATLAB matrixv 포멧을 의미한다.

정확히 저장 되었다면 결과 값이 matrix에 저장 되게 된다.

% Load saved matrices from file
load('ex3data1.mat');
% The matrices X and y will now be in your Octave environment

20 by 20 grid of pixels is "unrolled" into a 400-dimensional vector.
결국 Eample 하나는 single row가 되고 matrix는
5000 by 400 matrix가 된다.

호환성을 위해서 0을 10으로 mapping 하고 나머지는 그대로 mapping 한다.

1.2 Visualizing the data

displayData 코드는 랜덤으로 100개의 image들을 선택해서 보여주게 된다.

1.3 Vectorizing Logistic Regression

Training 시간을 줄이기 위해서 vectorization을 반드시 수행 해야 한다.

1.3.1 Vectorizing the cost function

vectorization을 이용해서 unregularized cost function을 lrCostFunction.m에 다가 구현을 한다.
반드시 fully vectorized version을 만들어야 한다.
이것의 의미는 loop가 없어야 함을 의미한다.

1.3.2 Vectorizing the gradient

gradient descent algorithm도 vectorization을 통해서 적용을 하게 된다.

Cost Function과 Gradient를 모두 적용한 matlab 코드는 아래와 같다.

1.3.3 Vectorizing regularized logistic regression

Regularzation 까지 적용한 Vectorization을 생성 한다.
최종 코드는 아래와 같다.

lrCostFunction.m

function [J, grad] = lrCostFunction(theta, X, y, lambda)
%LRCOSTFUNCTION Compute cost and gradient for logistic regression with
%regularization
%   J = LRCOSTFUNCTION(theta, X, y, lambda) computes the cost of using
%   theta as the parameter for regularized logistic regression and the
%   gradient of the cost w.r.t. to the parameters.

% Initialize some useful values
m = length(y); % number of training examples

% You need to return the following variables correctly
J = 0;
grad = zeros(size(theta));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta.
%               You should set J to the cost.
%               Compute the partial derivatives and set grad to the partial
%               derivatives of the cost w.r.t. each parameter in theta
%
% Hint: The computation of the cost function and gradients can be
%       efficiently vectorized. For example, consider the computation
%
%           sigmoid(X * theta)
%
%       Each row of the resulting matrix will contain the value of the
%       prediction for that example. You can make use of this to vectorize
%       the cost function and gradient computations.
%
% Hint: When computing the gradient of the regularized cost function,
%       there're many possible vectorized solutions, but one solution
%       looks like:
%           grad = (unregularized gradient for logistic regression)
%           temp = theta;
%           temp(1) = 0;   % because we don't add anything for j = 0
%           grad = grad + YOUR_CODE_HERE (using the temp variable)
%

H_theta = sigmoid(X * theta);

% Cost
J =(1/m) * sum(-y .* log(H_theta) - (1 - y) .* log(1 - H_theta)) + ...
   (lambda/(2*m)) * norm(theta([2:end]))^2;

G = (lambda/m) .* theta;
G(1) = 0; % extra term for gradient

% Gradient
grad = ((1/m) .* X' * (H_theta - y)) + G;


% =============================================================

grad = grad(:);

end

1.4 One-vs-all Classification

one-vs-all classification을 multiple regularized logistic regression 이용한 방법이다.

작성해야할 코드는 oneVsAll.m이다.

oneVsAll.m

function [all_theta] = oneVsAll(X, y, num_labels, lambda)
%ONEVSALL trains multiple logistic regression classifiers and returns all
%the classifiers in a matrix all_theta, where the i-th row of all_theta
%corresponds to the classifier for label i
%   [all_theta] = ONEVSALL(X, y, num_labels, lambda) trains num_labels
%   logisitc regression classifiers and returns each of these classifiers
%   in a matrix all_theta, where the i-th row of all_theta corresponds
%   to the classifier for label i

% Some useful variables
m = size(X, 1);
n = size(X, 2);

% You need to return the following variables correctly
all_theta = zeros(num_labels, n + 1);

% Add ones to the X data matrix
X = [ones(m, 1) X];

% ====================== YOUR CODE HERE ======================
% Instructions: You should complete the following code to train num_labels
%               logistic regression classifiers with regularization
%               parameter lambda.
%
% Hint: theta(:) will return a column vector.
%
% Hint: You can use y == c to obtain a vector of 1's and 0's that tell use
%       whether the ground truth is true/false for this class.
%
% Note: For this assignment, we recommend using fmincg to optimize the cost
%       function. It is okay to use a for-loop (for c = 1:num_labels) to
%       loop over the different classes.
%
%       fmincg works similarly to fminunc, but is more efficient when we
%       are dealing with large number of parameters.
%
% Example Code for fmincg:
%
%     % Set Initial theta
%     initial_theta = zeros(n + 1, 1);
%
%     % Set options for fminunc
%     options = optimset('GradObj', 'on', 'MaxIter', 50);
%
%     % Run fmincg to obtain the optimal theta
%     % This function will return theta and the cost
%     [theta] = ...
%         fmincg (@(t)(lrCostFunction(t, X, (y == c), lambda)), ...
%                 initial_theta, options);
%

for k = 1:num_labels

    initial_theta = zeros(n + 1, 1);
    options = optimset('GradObj', 'on', 'MaxIter', 500); % iteration could be bigger, e.g. 500

    [theta] = ...
         fmincg (@(t)(lrCostFunction(t, X, (y == k), lambda)), ...
                 initial_theta, options);

    all_theta(k,:) = theta';
end
% =========================================================================
end

1.4.1 One-vs-all Prediction

주어진 image를 prediction 해보자.
10개의 classifier가 존재하고 이중에서 가장 높은 probability를 가지는 것으로 prediction 하게 된다.

작성해야할 코드는 predictOneVsAll 함수 이다.
이전에 학습된 #\theta$를 이용해서 prediction을 수행하게 된다.
정확도는 94.9%를 기록하게 된다.

predictOneVsAll.m

function p = predictOneVsAll(all_theta, X)
%PREDICT Predict the label for a trained one-vs-all classifier. The labels
%are in the range 1..K, where K = size(all_theta, 1).
%  p = PREDICTONEVSALL(all_theta, X) will return a vector of predictions
%  for each example in the matrix X. Note that X contains the examples in
%  rows. all_theta is a matrix where the i-th row is a trained logistic
%  regression theta vector for the i-th class. You should set p to a vector
%  of values from 1..K (e.g., p = [1; 3; 1; 2] predicts classes 1, 3, 1, 2
%  for 4 examples)

m = size(X, 1);
num_labels = size(all_theta, 1);

% You need to return the following variables correctly
p = zeros(size(X, 1), 1);

% Add ones to the X data matrix
X = [ones(m, 1) X];

% ====================== YOUR CODE HERE ======================
% Instructions: Complete the following code to make predictions using
%               your learned logistic regression parameters (one-vs-all).
%               You should set p to a vector of predictions (from 1 to
%               num_labels).
%
% Hint: This code can be done all vectorized using the max function.
%       In particular, the max function can also return the index of the
%       max element, for more information see 'help max'. If your examples
%       are in rows, then, you can use max(A, [], 2) to obtain the max
%       for each row.
%

[x, ix] = max(sigmoid(X * all_theta'), [], 2);

p = ix;

% =========================================================================
end

단순 logistic regression으로도 아래와 같이 훌륭한 결과를 얻을 수 있다.

Loading and Visualizing Data ...
Program paused. Press enter to continue.

Training One-vs-All Logistic Regression...
Iteration   457 | Cost: 1.311466e-02
Iteration   500 | Cost: 5.080189e-02
Iteration   500 | Cost: 5.760187e-02
Iteration   500 | Cost: 3.306492e-02
Iteration   500 | Cost: 5.445615e-02
Iteration   500 | Cost: 1.825591e-02
Iteration   500 | Cost: 3.064138e-02
Iteration   500 | Cost: 7.845164e-02
Iteration   500 | Cost: 7.118580e-02
Iteration   500 | Cost: 8.567845e-03
Program paused. Press enter to continue.

Training Set Accuracy: 96.460000
octave:38> 

2. Neural Networks

이전까지는 Logistic regression을 다중으로 사용해서 이미지 숫자를 구별하는 방법을 했었다.

여기서는 handwritten digits을 인식하기 위해서 neural network을 이용하게 된다.

하지만 parameter trained은 직접 하지 않고 이미 학습한 $\theta$값을 이용한다.

여기서는 이미 정의된 $\theta$를 이용해서 feedforward propagation algorithm을 구현 하는데 의미가 있다.

2.1 Model representation

입력, 히든, 출력 이렇게 3개의 레이어로 구성된 neural network 이다.

입력은 20x20 이미지 이기때문에 400이라고 할 수 있다.
이것에 bias unit 값으로 +1이 추가 된다.

neural network에서 쓰이는 parameter들은 이미 학습 되어져서 ex3weights.mat에 저장되어 있다.
히든 레이어는 25개의 unit으로 구성되어 있고 output 레이어는 10개의 unit으로 구성되어 있다.

이전에 강의 자료에서 설명되었듯이 $\theta^{j}$의 dimension은 $s_{j+1} \times s_{j}+1$로 정의 된다.
따라서 아래와 같은 matrix를 구성하게 된다.

% Load saved matrices from file
load('ex3weights.mat');
% The matrices Theta1 and Theta2 will now be in your Octave
% environment
% Theta1 has size 25 x 401
% Theta2 has size 10 x 26

2.2 Feedforward Propagation and Prediction

predict.m을 구현 함으로써 feedforward propagaction을 구현하게 된다.

어떤 example $i$에 대해서 $h_{\theta}(x^{(i)})$를 이용해서 digit을 prediction 하게 된다.
one-vs-all classification과 같이 가장큰 확률을 가지는 i class로 prediction 된다.

predict.m

function p = predict(Theta1, Theta2, X)
%PREDICT Predict the label of an input given a trained neural network
%   p = PREDICT(Theta1, Theta2, X) outputs the predicted label of X given the
%   trained weights of a neural network (Theta1, Theta2)

% Useful values
m = size(X, 1);
num_labels = size(Theta2, 1);

% You need to return the following variables correctly
p = zeros(size(X, 1), 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Complete the following code to make predictions using
%               your learned neural network. You should set p to a
%               vector containing labels between 1 to num_labels.
%
% Hint: The max function might come in useful. In particular, the max
%       function can also return the index of the max element, for more
%       information see 'help max'. If your examples are in rows, then, you
%       can use max(A, [], 2) to obtain the max for each row.
%

a1 = [ones(m, 1) X]; % add 1

z2 = a1 * Theta1';

a2 = [ones(size(sigmoid(z2), 1), 1) sigmoid(z2)]; % add 1

z3 = a2 * Theta2';
a3 = sigmoid(z3); % H_theta(x)

[x, ix] = max(a3, [], 2);

p = ix;

% =========================================================================
end

결과를 확인해보면,
우선 ex3_nn.m은 미리 학습에 의해서 정해진 Theta1과 Theta2를 불러온다.
그런다음 예제 5000개가 저장된 X를 입력해서 prediction 하게 된다.

최종 결과를 참값 y를 통해서 비교하게된다.
정확도는 97.5%가 나오게 된다.

그다음에는 하나하나 이미지를 보여주면서 생성한 모델이 어떻게 prediction 하는지 확인 할 수 있다.

실행결과

Loading and Visualizing Data ...
Program paused. Press enter to continue.

Loading Saved Neural Network Parameters ...

Training Set Accuracy: 97.520000
Program paused. Press enter to continue.

Displaying Example Image

Neural Network Prediction: 8 (digit 8)
Program paused. Press enter to continue.


Week 04: Neural Networks

Non-linear Hypotheses

Model representation 1

$\theta$를 weight라고도 하고 parameter라고도 한다.

activiation fucntion을 sigmoid (logistic)이라고도 한다.

Neural networks -notation

  • $a_i^{(j)}$, activiation of unit i in layer j

    • 해석하면 만약, $a_1^{2}$라고 하면 두번째 레이어에 있는 첫번째 유닉이라는 의미 이다.
  • $\theta_i^{(j)}$ 이란 결국 layer j에서 layer j+1로 연결 시켜주는 mapping function을 의미한다.

    • Prameters for controlling mapping from one layer to the next
    • $s_j$란 layer j에 있는 유닛을 말한다.
    • $s_{j+1}$ unit은 layer j+1에 있는 유을 말한다.
    • 결국 $\theta^j$의 dimension은 $s_{j+1}$ by $s_{j}+1$로 결정 된다.
      • 왜냐하면, $s_{j+1}$은 layer (j+1)의 유닉수와 같기 때문이다
      • is equal to the number of units in layer j, plus an additional unit
    • Looking at the Ɵ matrix
      • Column length is the number of units in the following layer
      • Row length is the number of units in the current layer + 1 (because we have to map the bias unit)

Model representation 2

Forward propagation: Vectorized implementation

이전에 설계한 구조를 아래와 같다.

이것을 formula로 좀더 정리해 보면

a^(2)는 R^3로 삼차원 vector를 의미한다.
x와 a^(1)은 같기 때문에 동일하다는 판단하에 지울 수 있다.

추가로 bias에 대해서 입력으로 넣어준다.
4차원 vector로 정의되고 R^4가 된다.

이러한 과정을 forward propagation이라고 한다.

Neural Network Learning its own features

아래의 그림과 같이 Neural netwrok이 하는 일은 그저 logistic regression이 하는 일과 같다.

단지, original features, $x_1$, $x_2$, $x_3$를 사용하는 것이 아닌
새로운 features, $a_1^2$, $a_2^2$, $a_3^2$를 사용하게 된다.

결국 이것을 이용해서 Hypothesis를 구현하게 되면 아래와 같다.

$$ h_{\theta}^{(x)} = g(\theta_{10}^{(2)} a_0^2 + \theta_{11}^{(2)} a_1^2 + \theta_{12}^{(2)} a_2^2 + \theta_{13}^{(2)} a_3^2 ) $$

위 equation은 완벽히 Logistic regression과 일치 한다.

Applications: Examples and Intuitions 1

Neural network이 어떻게 non-linear function을 간단히 해결 하는지 다루겠다.

AND의 경우

OR의 경우

Applications: Examples and Intuitions 2

Yann LeCun 교수의 handwritten digit classification에 관한 비디오이다.
Video

7.Multi-class classification

In this section, I want to tell you about how to use nerual entworks to do multiclass classification where we may have more than one category that we're trying to distinguish amongst.

이것은 an extention of the one versus all method 이다.

즉, 결과가 0이나 1이 아니라면 그것은 multiclass classification 이라고 할 수 있다.

하나의 예제로 pedestrian, car, motobike or truck 이 4가지중 하나를 추출하는 classification이 있다고 생각해 보자.
이것을 위해서는 output vector가 4개의 숫자를 가져야 한다.

  • 1 is 0/1 pedestrian
  • 2 is 0/1 car
  • 3 is 0/1 motocycle
  • 4 is 0/1 truck

만약 이미지가 pedestrian 이라면 [1,0,0,0]의 값을 얻게 된다.

결국 아래와 같이

$$ h_{\theta}^{(i)} = y^{(i)} $$
로 결정 된다.


Programming Exercise 2: Regularized Logistic Regression


Microchip 제작에 관한 Quality Assureance (QA)를 예측하는 작업을 수행 한다.

QA동안에 microchip은 많은 test를 겪게 된다.

chips manager라고 가정하고 이제 2개의 test 결과를가지고 해당 chips을 통과 시킬지 말지를 결정하는 것을 생각해 보자.

이번에는 결국 아래의 파일만 구현하면 된다.

  • [*] costFunctionReg.m - Regularized Logistic Regression Cost

2.1 Visualizing the data

이전과 같이 일단 visualization 부터 수행 한다.
ex2_reg를 실행하면 기본적으로 아래와 같이 그래프를 그려 준다.

해당 분포를 보면 linear dicision boundary로는 결정을 할 수 없는 것을 알 수 있다.

2.2 Feature mapping

mapFeature.m에 의해서 featrue의 수를 증가 시킨다.

6 제곱 까지 증가시킨 다항식을 통해서 정확도 높은 dicision boundary를 생성 할 수 있다.

mapping 함수를 통해서 two features vector는 28-dimensional vector로 변경 된다.

이러한 feature mapping은 좀더 설명 가능한 classifier를 생성하게 도와 준다. 하지만 overfitting에 대해서는 민감하게 반응하게 된다.

2.3 Cost Function and Gradient

regularized logistic regression을 완성하기 위해서 cost function과 gradient function을 costFunctionReg.m에다가 구현 한다.

Regularized Cost Function
$$ J(\theta) = \frac{1}{m}\sum_{i=1}^{m}\big[-y^{(i)}\, log\,( h_\theta\,(x^{(i)}))-(1-y^{(i)})\,log\,(1-h_\theta(x^{(i)}))\big] + \frac{\lambda}{2m}\sum_{j=1}^{n}\theta_{j}^{2} $$

Vectorized Cost Function
$$ J(\theta) = \frac{1}{m}\big((\,log\,(g(X\theta))^Ty+(\,log\,(1-g(X\theta))^T(1-y)\big) + \frac{\lambda}{2m}\sum_{j=1}^{n}\theta_{j}^{2} $$

Partial derivative
$$ \frac{\delta J(\theta)}{\delta\theta_{j}} = \frac{1}{m}\sum_{i=1}^{m} ( h_\theta (x^{(i)})-y^{(i)})x^{(i)}{j} + \frac{\lambda}{m}\theta{j} $$

Vectorized
$$ \frac{\delta J(\theta)}{\delta\theta_{j}} = \frac{1}{m} X^T(g(X\theta)-y) + \frac{\lambda}{m}\theta_{j} $$

$\theta_0$는 regularization 하지 않는다. $j$는 1부터 시작하게 된다.

모든 $\theta$가 0으로 초기화 되었을 때의 cost 값은 0.693이다.

costFunctionReg.m

function [J, grad] = costFunctionReg(theta, X, y, lambda)
%COSTFUNCTIONREG Compute cost and gradient for logistic regression with regularization
%   J = COSTFUNCTIONREG(theta, X, y, lambda) computes the cost of using
%   theta as the parameter for regularized logistic regression and the
%   gradient of the cost w.r.t. to the parameters.

% Initialize some useful values
m = length(y); % number of training examples

% You need to return the following variables correctly
J = 0;
grad = zeros(size(theta));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta.
%               You should set J to the cost.
%               Compute the partial derivatives and set grad to the partial
%               derivatives of the cost w.r.t. each parameter in theta

H_theta = sigmoid(X * theta);

% Cost
J =(1/m) * sum(-y .* log(H_theta) - (1 - y) .* log(1 - H_theta)) + ...
   (lambda/(2*m)) * norm(theta([2:end]))^2;

G = (lambda/m) .* theta;
G(1) = 0; % extra term for gradient

% Gradient
grad = ((1/m) .* X' * (H_theta - y)) + G;

% =============================================================

end

2.3.1 Learning parameters using fminunc

이전과 같이 ex2_reg.m에서 fminunc 함수를 이용해서 $\theta$를 최적화 한다.

2.4 Plotting the decision boundary

plotDecisionBoundary.m에 의해서 non-linear decision boundary를 그리게 된다.

그리고 최종적인 train accuracy는 다음과 같다.

Train Accuracy: 83.050847

2.5 Optional (ungraded) exercises

$\lamda$를 조절해 가면서 overfitting과 underfitting을 적용해 볼 수 있다.
e2_reg.m에서 lamda 값만 변경하면 아래와 같이 수행 할 수 있다.

lamda= = 0
Train Accuracy:86.440678

lamda = 100
Train Accuracy: 61.016949


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 홍콩과기대 김성훈 교수


Programming Exercise 2: Logistic Regression 


Introduction

여기선 logistic regression을 구현하고 서로다른 두개의 datasets에 적용해 본다.

작업해야할 파일들은 아래와 같다.

  • ex2.m - Octave/MATLAB script that steps you through - the exercise
  • ex2 reg.m - Octave/MATLAB script for the later parts of the exercise
  • ex2data1.txt - Training set for the first half of the exercise
  • ex2data2.txt - Training set for the second half of the exercise
  • submit.m - Submission script that sends your solutions to our servers
  • mapFeature.m - Function to generate polynomial features
  • plotDecisionBoundary.m - Function to plot classifier’s decision boundary

  • [*] plotData.m - Function to plot 2D classification data

  • [*] sigmoid.m - Sigmoid Function
  • [*] costFunction.m - Logistic Regression Cost Function
  • [*] predict.m - Logistic Regression Prediction Function
  • [*] costFunctionReg.m - Regularized Logistic Regression Cost

*가 들어간 것들이 구현해야될 파일 이다.

ex2.m과 ex2_reg.m의 파일이 전체적인 exercise를 다루고 있는 것들이다. 이 두 파일은 dataset을 set up하고 문제를 해결하기 위해서 우리가 작성해야할 function들을 호출하는 순서로 구성 되어 있다.

직접적으으로 ex2.m과 ex2_reg.m을 수정할 필요는 없다. 그저 각각의 다른파일에 저장된 function의 내용을 채우면 된다.

1. Logistic Regression

학생들이 대학에 입할 할 수 있는지 아닌지에 대한 예측을 가능 하도록 하는 Logistic regression classifier를 구현 한다.

과거 지원자의 두 과목 시험 점수와 그에 따른 admission결과를 training set으로 하여 model을 생성하게 된다.

모델로 만약 어떤 사용자의 시험 성정 2개가 주어진다면 이 사용자가 과거 대비 입학을 할 수 있을지에 대한 probability를 구하게 된다.

1.1 Visualizing the data

데이터 형태 파악을 위해서 일단 plot을 그려 보는것이 효과 적이다.

plotData function을 호출해서 plot을 그리게 된다.

당연히 plotData.m 파일의 함수를 구현해야 그래프가 그려 진다.

ex2.m

#파일 읽기
data = load('ex2data1.txt')

data = 

   34.62366   78.02469    0.00000
   30.28671   43.89500    0.00000
   35.84741   72.90220    0.00000
   60.18260   86.30855    1.00000
   79.03274   75.34438    1.00000
   45.08328   56.31637    0.00000
   61.10666   96.51143    1.00000
   ....

size(data)

ans =

   100     3

# 총 100개의 데이터가 있다.
# 1-2 열이 과목 점수고, 3번째 열이 admission 여부를 나타낸다. 각각을 X와 Y로 끄집어 낸다.
X = data(:,[1,2])
y = data(:,3)

# 두개를 그래프 그리기 위해서 인자로 넘겨 준다.
plotData(X,y)

plotData.m

function plotData(X, y)
%PLOTDATA Plots the data points X and y into a new figure
%   PLOTDATA(x,y) plots the data points with + for the positive examples
%   and o for the negative examples. X is assumed to be a Mx2 matrix.

% Create New Figure
figure; hold on;

% ====================== YOUR CODE HERE ======================
% Instructions: Plot the positive and negative examples on a
%               2D plot, using the option 'k+' for the positive
%               examples and 'ko' for the negative examples.
%

% Find Indices of Positive and Negtive Example
pos = find(y == 1);
neg = find(y == 0);

% Plot Example
plot(X(pos, 1), X(pos, 2), 'k+', 'LineWidth', 2, 'MarkerSize', 7);
plot(X(neg, 1), X(neg, 2), 'ko', 'MarkerFaceColor', 'yellow', 'MarkerSize', 7);


% =========================================================================

1.2 Implementation

1.2.1 Warmup exercise: sigmoid function

그냥 몸풀기 정도로 logistic regression에서 사용하는 hypothesis는 다음과 같다.

$$ h_{\theta} = g(\theta^{T} x) $$

여기서 g는 sigmoid function이다. sigmoid는 아래와 같다.

$$ g(z) = \frac{1}{1+e^{-z}} $$
위 sigmoid를 sigmoid.m에다가 구현 한다.

function g = sigmoid(z)
%SIGMOID Compute sigmoid functoon
%   J = SIGMOID(z) computes the sigmoid of z.

% You need to return the following variables correctly 
g = zeros(size(z));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the sigmoid of each value of z (z can be a matrix,
%               vector or scalar).

g = 1.0 ./ (1.0 + exp(-z));

% =============================================================
end

코드에서 ./는 엘리먼트 나눗셈이다.
즉, 두개의 배열이 있을때 각각의 엘리먼트 끼리 나누는 것이다.
z인자가 matrix로 들어올 수 있기 때문에 이렇게 해줘야 한다.

sigmoid test
아래와 같이 잘 구현 되었는지 확인해보면
큰 positive value면 1이, 큰 negative value면 0이
0이면 0.5로 잘 나오는것을 알 수 있다.

octave:7> sigmoid(100000000)
ans =  1
octave:8> sigmoid(-100000000)
ans = 0
octave:9> sigmoid(0)
ans =  0.50000

그리고 matrix형태로 z 값을 넣어보면, 아래와 같이 각각에 대해서 sigmoid가 잘 적용되는 것을 알 수 있다.

octave:10> sigmoid(data)
ans =

   1.00000   1.00000   0.50000
   1.00000   1.00000   0.50000
   1.00000   1.00000   0.50000
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.50000
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.50000
   1.00000   1.00000   0.50000
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.50000
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.50000
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.73106
   1.00000   1.00000   0.50000

제출

octave:1> submit()
== Submitting solutions | Logistic Regression...
Use token from last successful submission (leejaymin@gmail.com)? (Y/n): 
== 
==                                   Part Name |     Score | Feedback
==                                   --------- |     ----- | --------
==                            Sigmoid Function |   5 /   5 | Nice work!
==                    Logistic Regression Cost |   0 /  30 | 
==                Logistic Regression Gradient |   0 /  30 | 
==                                     Predict |   0 /   5 | 
==        Regularized Logistic Regression Cost |   0 /  15 | 
==    Regularized Logistic Regression Gradient |   0 /  15 | 
==                                   --------------------------------
==                                             |   5 / 100 | 

1.2.2 Cost function and gradient

logistic regression의 cost function을 설계해 본다.
costFunction.m을 구현 하면 된다.

$$ J(\theta) = \frac{1}{m} \sum_{i=1}^{m}{-y^{(i)} log(h_{\theta}(x^{(i)})) - (1-y^{(i)}) log(1-h_{\theta}(x^{(i)})) } $$

vectorized cost function
$$ J(\theta) = \frac{1}{m}\big((\,log\,(g(X\theta))^Ty+(\,log\,(1-g(X\theta))^T(1-y)\big) $$

이 Cost function을 gradient descent 알고리즘을 적용 하면 아래와 같다.

Partial derivative
$$ \frac{\delta J(\theta)}{\delta\theta_{j}} = \frac{1}{m}\sum_{i=1}^{m} ( h_\theta (x^{(i)})-y^{(i)})x^{(i)}_{j} $$

Vectorized partial derivative
$$ \frac{\delta J(\theta)}{\delta\theta_{j}} = \frac{1}{m} X^T(g(X\theta)-y) $$

gradient descent formula 자체는 linear regression 때와 동일하다. 하지만 $h_{\theta}x$의 정의가 다른 것이다.

이제 초기 $\theta$의 값을 0,0,0 으로해서 계산을 수행해 보면
cost 값은 0.693이 나와야 한다.

costFunction.m

function [J, grad] = costFunction(theta, X, y)
%COSTFUNCTION Compute cost and gradient for logistic regression
%   J = COSTFUNCTION(theta, X, y) computes the cost of using theta as the
%   parameter for logistic regression and the gradient of the cost
%   w.r.t. to the parameters.

% Initialize some useful values
m = length(y); % number of training examples

% You need to return the following variables correctly
J = 0;
grad = zeros(size(theta));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta.
%               You should set J to the cost.
%               Compute the partial derivatives and set grad to the partial
%               derivatives of the cost w.r.t. each parameter in theta
%
% Note: grad should have the same dimensions as theta
%

H_theta = sigmoid(X * theta);

J = (1.0/m) * sum(-y .* log(H_theta) - (1.0 - y) .* log(1.0 - H_theta));

grad = (1.0/m) .* X' * (H_theta - y);


% =============================================================

end

X matrix에 theta를 모두 곱한것이 z가 된다.
즉, $\theta^{T}x$인 향태인 것이다.
theta_0,1,2 순으로 저장이 되어 있다.

결국

octave:31> size(X)
ans =

   100     3

octave:32> size(initial_theta)
ans =

   3   1

[100,3] * [3,1] 을 수행해서 [100,1] 짜리 matrix를 생성 한다.
당연히 초기 theta들은 모두 0이므로 sigmoid(0)은 0.5이므로 H_thetha는 0으로 채워져 있다.

-y .* log(H_theta) - (1.0 - y) .* log(1.0 - H_theta)

의 값은 0.69315이고 이것이 100개 있다. 이대로 쭉 계산하면

1/100 * (0.69315) * 100 이므로 결과는 0.69315가 나온다.

두 번쨰로 gradient descent formula구현한 코드는

grad = (1.0/m) .* X' * (H_theta - y);

이다. 위와 같이 matrix 연산을 통해서 모든 training data와 모든wegiht vector ($\theta$)에 대해서 한번에 처리하게 된다.

그리고 이것에 대한 초기 gradient 조정 값은 아래와 같다.

Gradient at initial theta (zeros): 
 -0.100000 
 -12.009217 
 -11.262842 

제출

==                                   Part Name |     Score | Feedback
==                                   --------- |     ----- | --------
==                            Sigmoid Function |   5 /   5 | Nice work!
==                    Logistic Regression Cost |  30 /  30 | Nice work!

1.2.3 Learning parameters using fminunc

Linear regression에서는 gradient descent algorithm을 직접 구현 했었다. 하지만 여기서는 Octave에서 제공하는 fminunc라는 함수를 이용할 것이다.

fminunc

  • initial values of the parameters we are trying to optimize.
  • A function that, when given the training set and a particular $\theta$, computes the logistic regression cost and gradient with respect to $\theta$ for the dataset (X,y)

이것을 위해서는 어떤 parameters를 넣으면 될지는 아래와 같다.

%  Set options for fminunc
options = optimset('GradObj', 'on', 'MaxIter', 400);

%  Run fminunc to obtain the optimal theta
%  This function will return theta and the cost 
[theta, cost] = ...
    fminunc(@(t)(costFunction(t, X, y)), initial_theta, options);

GradObj를 option on으로 설정 했다.
gradient를 수행해서 최적화 하겠다는 의미이다.
MaxIter의 option은 400으로 설정 했다. 400번 이후로는 그냥 terminates 된다.

fminunc는 최적의 costfunction 값이 나올 때가지 400번 반복 한다. 그다음 최적의 weight vector가 저장된 theta와 그때의 cost를 반환 하게 된다.

재밌는 것은 지난번과 달리 loop를 만들지도 않았고learning rate도 따로 설정하지 않았다.
fminunc를 사용할때 설정할것은 cost와 gradient를 계산해줄 함수만 넣어주면 된다.

결국 아래의 과정이 수행된 것이다.

ex2.m을 실행하면 최적의 $\theta$ 값과 cost값으로 아래와 같이 출력 한다.

Program paused. Press enter to continue.

Cost at theta found by fminunc: 0.203498

theta: 
 -25.161272 
 0.206233 
 0.201470 

그리고 이미 작성된 코드 plotDecisionBoundary.m에 의해서 아래와 같이 Decision Boundary가 그려 진다.

1.2.4 Evaluating logisitic regression

이제 학습된 파라메터들을 이용해서 (wegiht vector, $\theta$) 어떤 학생의 시험점수 2개가 있다면 이 학생이 admission을 받을지 안받을지를 예측해 볼 수 있다.

예로
Exam 1 score: 45
Exam 2 score: 85
위와 같을때 admission probability는 0.776이다. 코드는 아래와 같다.

prob = sigmoid([1 45 85] * theta);
fprintf(['For a student with scores 45 and 85, we predict an admission ' ...
         'probability of %f\n\n'], prob);

이것을 위해서 predict.m파일을 구현 한다.

predict.m

function p = predict(theta, X)
%PREDICT Predict whether the label is 0 or 1 using learned logistic
%regression parameters theta
%   p = PREDICT(theta, X) computes the predictions for X using a
%   threshold at 0.5 (i.e., if sigmoid(theta'*x) >= 0.5, predict 1)

m = size(X, 1); % Number of training examples

% You need to return the following variables correctly
p = zeros(m, 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Complete the following code to make predictions using
%               your learned logistic regression parameters.
%               You should set p to a vector of 0's and 1's
%

p = sigmoid(X * theta);

idx_1 = find(p >= 0.5);
idx_0 = find(p < 0.5);

p(idx_1) = ones(size(idx_1));
p(idx_0) = zeros(size(idx_0));

% =========================================================================
end

이제 작성된 predict함수를 이용해서 training data에 대한 prediction 정확도를 보자.

% Compute accuracy on our training set
p = predict(theta, X);

fprintf('Train Accuracy: %f\n', mean(double(p == y)) * 100);

정확도가 높이 나왔다. 이러한 검증 방식은 사실 문제가 있다.
학습 데이터로 모델을 평가하면 상당히 성능이 좋게 나오기 때문이다. overffting이 되면 될 수록 성능은 더 좋기 때문이다.
substitution error라고도 부른다.

Train Accuracy: 89.000000

여기까지 했을 때의 점수 이다.

==                                   Part Name |     Score | Feedback
==                                   --------- |     ----- | --------
==                            Sigmoid Function |   5 /   5 | Nice work!
==                    Logistic Regression Cost |  30 /  30 | Nice work!
==                Logistic Regression Gradient |  30 /  30 | Nice work!
==                                     Predict |   5 /   5 | Nice wor


Week 03: Regularization and Quiz


1. The problem of overfitting

첫 번째 그림의 모델의 상태를 underfitting이라고 하고 high bias인 상태라고 한다.

세 번째를 overfitting 이라고 부르며 high variance로도 알려져 있다.
이것은 high oder polynomial (고차 다항식)을 이용한 것으로 트레이닝 data에 거의 완벽히 fit 시키게 된다.
당연히 hypothesis의 space는 많은 공간을 차지하게 된다.

Overffting을 간단히 요약하면,
엄청나게 많은 feature들을 이용해서 학습하게 된다 그러면 cost function은 거의 zero에 다가서게 하는
함수를 만들 수 있다.

Addressing overfitting:

  1. Reduce number of features.
    1. Manually select which features to keep
    2. Model selection algorithm (later in course)
  2. Regularization
    1. Keep all features, but reduce magnitude of parameters θ
    2. Works well when we have a lot of features, each of which contributes a bit to predicting y

2. Cost Function

고차 다항식의 경우 좀더 구불 구블한 선을 만들어서
Training data에 더 fit한 모델을 생성 할 수 있다.

Regularization의 기본적인 아이디어는

$\theta_n$에 엄청나게 큰 값을 줘서 패널티를 주는 것이다.
그렇게 하면 min function에 의해서 $\theta_n$값은 결국 0에 가까워 질 수 밖에 없는 것이다.

결국 이것을 수식으로 나타내면 아래와 같다.

$$ J(\theta )=\frac { 1 }{ 2m } \left[ \sum { i=1 }^{ m }{ (h{ \theta }(x^{ (i) })-y^{ (i) })^{ 2 }+\lambda \sum _{ j=1 }^{ n }{ \theta _{ j }^{ 2 } } } \right] $$

그냥 convention에 의해서 \theta_0부터 시작하지 않고 \theta_1부터 시작 하는 것이다.
위에서 \lambda는 Regularization의 rate이 된다.

3. Regularized Linear Regression

  • Previously, we looked at two algorithms for linear regression
    • Gradient descent
    • Normal equation
  • Our linear regression with regularization is shown below

Regularization with the normal equation

  • Normal equation is the other linear regression model
    • Minimize the J(θ) using the normal equation
    • To use regularization we add a term (+ λ [n+1 x n+1]) to the equation
      • [n+1 x n+1] is the n+1 identity matrix

4. Regularized Logistic Regression

logistic regression은 feature의 수가 늘어나면, overffting 되는 경향이 존재한다.

Logistic regression cost function은 다음과 같다.

이것에 아래의 추가 term을 더해서 regularization을 한다.

함수는 아래와 같다.



퀴즈 문제는 아래와 같다.


Quize week03_Regularization.pdf



Github Page로 개인 홈페이지 제작, Private Git 얻기


Private 공짜로 얻기

아랴의 링크에서 학생이라면 Github를 약 2년간 공짜로 Private 하게 사용할 수 있다.
지원 할 때는 반드시 University E-mail을 사용해서 지원 해야 한다.
https://education.github.com/pack

목적과 사유를 적어서 보내면 빠르면 2틀 늦어도 15일 이내로 아래와 같은 답장을 받을 수 있다.

목적과 사유는 길게 적을 필요 없다.
필자의 경우 한 3~4줄 영어로 적은것 같다.

GitHub에 로그인해서 Account를 확인해보면 아래와 같은 상태로 변경된 것을 알 수 있다.

2년간 지원해주고 unlimited private repositories를 보장한다.
2년이 지나고 또 메일을 보내면 해주는 것 같다.

Github page 제작

github pages란 static site hosting service를 말한다.

Github pages는 개인홈피, 조직 홈피 또는 project 페이지를 위해서 직접적으로 GitHub repository를 이용해서 디자인 되어 진다.

  • 2016년 6월 이후에 만들어진 page는 github.io domain으로 시작하게 된다.
  • 신용카드 정보 등의 senstive information은 허용하지 않는다.
  • page는 1달에 100,000 요청과 100GB 이하의 트래픽을 허용 한다.
  • 개인 repository의 용량은 1GB 미만을 허용 한다.
  • private repository라도 page자체는 public으로 접근이 가능 하다.

github page의 종류는 크게 두가지 이다.

  • personal page 제작
  • project page 제작

perosnal page 생성 방법

  1. 저장소 생성 반드시 <계정>.github.io 이름으로 생성 한다.

계정이 leejaymin라면, leejaymin.github.io으로 생성 해야한다.
계정 이름은 leejaymin인데 저장소 이름을 jemin.github.io이라고 하면 안된다.
github.io 이것도 전부 저장소 이름 만들때 넣어줘야한다.
당연하겠지만, 이러한 제약으로 인해서 perosnal page는 계정당 1개 뿐이 못만드는것이다.
따라서 project 마다 static web page를 생성하기 위해서는 따른 방법이 존재한다.

  1. 아래의 커맨드를 수행
git clone https://github.com/username/username.github.io
cd username.github.io
~$echo "Hello World" > index.html
git add --all
~$git commit -m "Initial commit"
~$git push -u origin master

http://username.github.io <-- 주소로 접속해보자. 당연히 username은 본인 계정이다.

404 not found같은 것이 뜨면 repository 이름이 잘못된 것이니 수정하면 된다.
setting으로 가서 저장소 이름을 변경하자.

정상적으로 잘 했다면 setting에 아래처럼 주소가 나와야한다.
주의사항을 보면 page는 저장소가 private 이어도 공개된다는 말이 나온다.
개인정보가 유출 되지 않도록 주의 하자.

마크다운으로 html 작업해서 index.html로 commit 후 push하면 심플한 이력 페이지가 된다.
최종 페이지: https://leejaymin.github.io/


+ Recent posts