Tools/Python (38)

반응형

강화학습 Q-Learning 기초 실습



Q-Learning을 통해 Frozen Lake 문제를 해결하는 방법에 대한 포스팅입니다. 실습 코드의 내용 및 출처는 김성훈 교수님의 강화학습강의( https://www.youtube.com/watch?v=VYOq-He90bE&feature=youtu.be) 입니다.



이 코드를 이해하기 위해서는 강화학습에 대한 기본적인 내용과 Frozen Lake 문제에 대하여 알아야합니다. Frozen Lake 문제는 간단히 말하면 위와 같은 상황에서 state를 이동하여 H(Hall)에 빠지지 않고 G(Goal)로 이동하는 문제입니다. 이 포스팅에서 강화학습에 대한 기본 내용들은 다루지 않겠고, 코드만 정리하여 포스팅 하려고 합니다.



환경 세팅


실습에서 사용하는 환경은 gym 패키지 환경인데, 이 환경에서 강화학습으로 해결할만한 여러 toy example들을 로드할 수 있습니다.

gym이 설치되지 않은 경우 pip install gym 으로 설치하시면 됩니다.

import gym
import numpy as np
import matplotlib.pyplot as plt
from gym.envs.registration import register

register(
    id='FrozenLake-v3',
    entry_point = 'gym.envs.toy_text:FrozenLakeEnv',
    kwargs={'map_name':'4x4',
           'is_slippery':False}
)

env = gym.make('FrozenLake-v3')

위와 같이 FrozenLake 게임을 로드할 수 있습니다.



Q-Table 초기화 및 하이퍼 파라미터 초기화

# Q Table을 모두 0으로 초기화 한다. : 2차원 (number of state, action space) = (16,4)
Q = np.zeros([env.observation_space.n, env.action_space.n])

# discount 정의 => 미래의 reward를 현재의 reward 보다 조금 낮게 본다.
dis = 0.99

# 몇 번 시도를 할 것인가 (에피소드)
num_episodes = 2000

# 에피소드마다 총 리워드의 합을 저장하는 리스트
rList = []


Q-learning은 결국 Q 를 배우는 것입니다. Q는 주어진 state에서 어떤 action을 취할 것인가에 대한 길잡이입니다. 이 문제에서 Q라는 2차원 배열에는 현재 state에서 action을 취할 때 얻을 수 있는 reward를 저장하고 있습니다. 이 Q 2차원 배열에서 argmax 함수를 이용하면 어떤 action을 취할지를 얻어낼 수 있는 것이죠. 이 문제에서 state는 16, action은 4입니다. (4x4 Frozen Lake 그리고 action은 위, 아래, 왼쪽, 오른쪽 4개)


Q-learning 알고리즘에서 Q를 업데이트하는 것


Q(state, action) = R + max(Q(new state)) 로 업데이트하게 됩니다. R은 reward로 게임 내부에서 지정되는 값입니다. 현재 state에서의 어떤 action을 취할 때의 Q 값은 그 action을 통해 얻어지는 reward와 action으로 변화된 state에서 얻을 수 있는 reward의 최댓값을 더한 것입니다. 즉 의미는 현재 리워드와 미래에 가능한 리워드의 최대치를 더하는 것입니다.


근데 이 때, Q(state, action) = R + discount * max(Q(new state)) 로 미래 가능한 리워드에 1 미만의 discount factor를 곱해주어(이 실습에서는 0.99) 미래 리워드에 약간의 패널티를 주기도 하는데 이런 방식을 통해 Q가 조금 더 optimal한 방법으로 learning 될 수 있습니다. 이 때 discount는 하이퍼 파라미터(hyperparameter)로 여러번 시도하면서 좋은 값을 찾을 수 있습니다.



Q-learning 알고리즘에서 Action을 고르는 것


강화학습에서 action 을 고르는 것은 이슈중 하나입니다. 이 실습에서는 두 가지 방법을 쓰는데 첫 번째, random noise 방식, 두 번째, E-Greedy 방식입니다. 둘 다 exploit & exporation 방법을 구현한 것으로 볼 수 있는데 약간의 차이가 있습니다. 둘의 공통적인 아이디어는 '무조건 Q 가 시키는대로만 가지말고 새로운 길로도 가보자는 것' 입니다. 왜냐하면 Q가 시키는 것이 optimal한 것이 아닐 수 있기 때문입니다.



1. random noise 방식


random noise 방식이란 현재 state에서 가능한 action에 따른 Q값(총 4가지)에 random noise를 주어서, 이 것이 최대값이 되는 action을 action으로 선택하게 됩니다. 그러면 무조건 최대 Q 값만 따르지 않고 가끔은 다른 action을 취하기도 합니다. random noise를 (i+1)로 나누는 것은 여러번 해보면서 어느 정도 Q 값이 optimal하게 될 것이기 때문에 exploration을 줄이고 exploit 위주로 한다는 것입니다.

for i in range(num_episodes) : 
    state = env.reset()
    rAll = 0
    done = False
    
    # Q learning 알고리즘
    while not done : 
        # Action 중에 가장 R(Reward)이 큰 Action을 고른다. 
        # 이 때, random noise 방식으로 decaying Exploit & Exploration 구현 
        action = np.argmax(Q[state, :] + np.random.randn(1, env.action_space.n) / (i+1))
        
        # 해당 Action을 했을 때 environment가 변하고, 새로운 state, reward, done 여부를 반환 받음
        new_state, reward, done, _ = env.step(action)
        
        # Q = R + Q 
        Q[state, action] = reward + dis * np.max(Q[new_state, :])
        
        rAll += reward
        state = new_state
        
    rList.append(rAll)

2. E-greedy 방식


E-Greedy 방식은 어떠한 확률값 e를 주어, e의 확률로 exploration한다는 것입니다. 예를 들어 e=0.99 이면 99%의 확률로 exploration 하고, 1%의 확률로 exploit해서 새로운 길을 찾게 됩니다. 이 값을 (i/100) 으로 나눈 것은 위 1번과 마찬가지로 여러버 해보면서 Q 값이 optimal 해질 것이기 때문에 exploration을 줄이면서 exploit 위주로 한다는 뜻입니다.

for i in range(num_episodes) : 
    state = env.reset()
    rAll = 0
    done = False
    
    # exploration의 확률 (decaying)
    e = 1./((i / 100) + 1)
    
    # Q learning 알고리즘
    while not done : 
        
        # E-Greedy 알고리즘으로 action 고르기
        if np.random.rand(1) < e :
            action = env.action_space.sample()
        else : 
            action = np.argmax(Q[state, :])
        
        # 해당 Action을 했을 때 environment가 변하고, 새로운 state, reward, done 여부를 반환 받음
        new_state, reward, done, _ = env.step(action)
        
        # Q = R + Q 
        Q[state, action] = reward + dis * np.max(Q[new_state, :])
        
        rAll += reward
        state = new_state
        
    rList.append(rAll)

최종 결과


Success rate는 Goal까지 실패 안하고 갈 확률입니다. 그래프를 보면 초반에만 실패하고 나중에는 다 성공하도록 Q 가 학습되어 나간다는 것을 볼 수 있습니다.

print("Success rate : "+str(sum(rList) / num_episodes))
print("Final Q-Table Values")
print(Q)

plt.bar(range(len(rList)), rList, color="blue")
plt.show()
Success rate : 0.807
Final Q-Table Values
[[ 0.94148015  0.95099005  0.95099005  0.94148015]
 [ 0.94148015  0.          0.96059601  0.95099005]
 [ 0.95099005  0.970299    0.95099005  0.96059601]
 [ 0.96059601  0.          0.95099005  0.        ]
 [ 0.95099005  0.96059601  0.          0.94148015]
 [ 0.          0.          0.          0.        ]
 [ 0.          0.9801      0.          0.96059601]
 [ 0.          0.          0.          0.        ]
 [ 0.96059601  0.          0.970299    0.95099005]
 [ 0.96059601  0.9801      0.9801      0.        ]
 [ 0.970299    0.99        0.          0.970299  ]
 [ 0.          0.          0.          0.        ]
 [ 0.          0.          0.          0.        ]
 [ 0.          0.9801      0.99        0.970299  ]
 [ 0.9801      0.99        1.          0.9801    ]
 [ 0.          0.          0.          0.        ]]



반응형
반응형


Python Scaling 방법 정리


/* 2017.8.27 by. 3months */


머신러닝에서 데이터를 모델에 트레이닝할 때, 일반적으로 데이터를 Scaling 해서 사용한다. Scaling을 통해 데이터의 Scale을 맞추면 Weight의 scale도 일관성 있도록 맞출 수 있을 것이다.


MinMax Scaling은 최댓값 = 1, 최솟값 = 0으로 하여, 그 사에 값들이 있도록 하는 방법이다.

즉 데이터 X의 scaling된 값 Xscale은 아래와 같다.


Xscale = (X-Xmin) / (Xmax-Xmin)


from sklearn.preprocessing import MinMaxScaler
a = [[10], [9], [8], [6], [2]]
scaler = MinMaxScaler(feature_range=(0,1))
a = scaler.fit_transform(a)
print(a)

결과

[[ 1.   ]
 [ 0.875]
 [ 0.75 ]
 [ 0.5  ]
 [ 0.   ]]



StandardScaling은 평균=0과 표준편차=1이 되도록 Scaling 하는 방법이다. 이는 표준화라고도 부른다.


Xscale = (X-X_mean) / Xstd


from sklearn.preprocessing import StandardScaler
a = [[10], [9], [8], [6], [2]]
scaler = StandardScaler()
a = scaler.fit_transform(a)
print(a)
print(a.mean())
print(a.std())

결과

[[ 1.06066017]
 [ 0.70710678]
 [ 0.35355339]
 [-0.35355339]
 [-1.76776695]]
0.0
1.0




반응형
반응형

아나콘다에서 제공하는 IDE인 Spyder를 아나콘다 virtual environment 위에서 실행하기 위해서는 Spyder를 virtual environment 안에도 설치를 해야한다.

conda install -n myenv spyder

myenv는 직접 지정한 virtual environment 이름이다. 위 명령어를 통해 virtual environment 상에 spyder를 설치하게 되고, 그 환경에서 spyder를 실행할 수 있다.


설치 후,


윈도우의 경우


activate myenv spyder

명령어를 통해 해당 virtual environment 안에서 spyder를 실행할 수 있다.


(MAC은 activate 대신에 source activate)

반응형
반응형

/* 2017.6.29

파이썬 선형회귀분석 

by 3개월

*/


파이썬 선형회귀분석 (sklearn 라이브러리 사용)



필요한 라이브러리 임포트

import pandas as pd
from sklearn import datasets, linear_model
import matplotlib.pyplot as plt
import numpy as np


데이터 모양 출력

birth = pd.read_csv("C:/workspace/python/data/birth.csv")
print birth.head()
   case  gram  weeks  smoke
0     1  3147     40      0
1     2  2977     41      0
2     3  3119     38      0
3     4  3487     38      0
4     5  4111     39      0


데이터를 간단히 설명하면 산모의 임신주차(weeks)와 흡연여부(smoke)변수를 통해 태아의 몸무게(gram)을 예측하기 위한 예제 데이터입니다. 관측치(row)는 100개가 있습니다.



데이터 나누기

# split data
print len(birth)
birth_train = birth[0:90]
birth_test = birth[91:100]


90%의 데이터를 트레이닝 데이터, 10%의 데이터를 테스트 데이터로 쓰겠습니다.


# basic linear regression
model1 = linear_model.LinearRegression()
x_vars1 = ["weeks", "smoke"]
model1.fit(birth_train[x_vars1], birth_train["gram"])
print model.coef_, model.intercept_

x = np.linspace(25,50,100)

plt.scatter(birth_train['weeks'], birth_train['gram'], c=birth_train["smoke"])
plt.plot(x, x*model.coef_[0]+model.coef_[1]+model.intercept_)
plt.plot(x, x*model.coef_[0]+model.intercept_)
plt.show()


첫 번째 모델 : gram = W1*weeks + W2*smoke + Intercept



우선 교호작용을 고려하지 않은 첫번째 모델입니다. smoke는 0, 1만 갖는 이진 변수이므로 smoke=1 일 때만, W2*smoke는 하나의 상수가 됩니다. smoke=0 인 경우 W2*smoke는 0입니다. 그러므로 smoke=1일 때 W2 값만큼 회귀식의 절편이 이동합니다.


[ 123.76004061 -283.69489986] -1504.60207489


다음 결과를 통해 W1 = 123.76004, W2 = -283.69, Intercept = -1504.60임을 알 수 있습니다.




따라서 결과 플롯은 위와 같습니다. smoke=1일때가 밑에있는 주황색 선입니다. 또한 보라색 점은 smoke=0인 사람을 나타낸 것이고 노란색 점은 smoke=1 인 사람을 나타낸 것입니다.



교호작용을 고려한 모델


# with interaction term
birth["weekssmoke"] = birth["weeks"]*birth["smoke"]
birth_train = birth[0:90]
birth_test = birth[91:100]
model2 = linear_model.LinearRegression()
x_vars2 = ["weeks", "smoke", "weekssmoke"]
model2.fit(birth_train[x_vars2], birth_train["gram"])
print model.coef_, model.intercept_

x = np.linspace(25,50,100)

plt.scatter(birth_train['weeks'], birth_train['gram'], c=birth_train["smoke"])
plt.plot(x, x*(model.coef_[0]+model.coef_[2])+model.coef_[1]+model.intercept_)
plt.plot(x, x*model.coef_[0]+model.intercept_)
plt.show()


교호작용은 effect modification 이라고도 불리며, 한 변수에 의해 다른 변수의 효과가 변하는 것을 말합니다. 이 경우 모델의 식은 아래와 같습니다.



두 번째 모델 : gram = W1*weeks + W2*smoke + W3*(weeks*smoke) + Intercept


왜 weeks*smoke를 곱한 텀을 넣어주나면 이를 통해 weeks의 gram에 대한 effect를 변화시킬 수 있기 때문입니다. smoke=1인경우 (W1+W3)*weeks가 되기 때문에 smoke에 의한 weeks의 effect의 변화를 고려할 수 있게 됩니다.



[  132.01926109  1316.00125169   -41.03706632] -1820.91949297

위 결과를 통해 coefficient와 intercept를 알 수 있습니다.




Mean Squared Error 구하기

print "Model1 Training Mean squared error: %.2f" % np.mean((model1.predict(birth_train[x_vars1]) - birth_train['gram']) ** 2)
print "Model2 Training Mean squared error: %.2f" % np.mean((model2.predict(birth_train[x_vars2]) - birth_train['gram']) ** 2)

print "Model1 Test Mean squared error: %.2f" % np.mean((model1.predict(birth_test[x_vars1]) - birth_test['gram']) ** 2)
print "Model2 Test Mean squared error: %.2f" % np.mean((model2.predict(birth_test[x_vars2]) - birth_test['gram']) ** 2)

마지막으로 Training MSE와 test MSE를 구하는 코드입니다.


Model1 Training Mean squared error: 227136.45
Model2 Training Mean squared error: 223972.58
Model1 Test Mean squared error: 220233.22
Model2 Test Mean squared error: 226638.72


반응형
반응형

이 포스트는 아래 포스팅을 참고한 포스팅입니다.

https://www.dataquest.io/blog/jupyter-notebook-tips-tricks-shortcuts/


Jupyter Notebook


기존에는 IPython Notebook으로 알려졌던 Jupyter Notebook은 코드, 이미지, 분석 결과, 코멘트, 수식 등을 분석자가 "노트북"처럼 Keep할 수 있게하여 다른 사람들이 분석의 흐름을 읽기 쉽게 만들 수 있는 유연하고 강력한 툴입니다. Jupyter Notebook은 여러가지 언어를 지원합니다. (Python, R, Julia 등) 또한 어떤 컴퓨터에서든지 쉽게 호스팅할 수 있습니다. http나 ssh로 접속하기만 하면 됩니다. 또 무엇보다도 Jupyter Notebook은 무료입니다. IPython 프로젝트에서부터 시작된 Juypter Notebook는 Julia, Python, R의 앞 글자를 따시 지어졌고, 파이썬 이외의 여러가지 언어를 지원하기 위하여 시작되었습니다. 주피터에서 파이썬 코드를 실행할 때 내적으로는 IPython Kernel이 돌아가게 됩니다.


1. 키보드 단축키


Help > Keyboard Shortcuts에 가면 키보드 단축키들을 확인할 수 있습니다. 아시다시피 키보드 단축키는 개발에서 시간을 많이 단축해줍니다. 위 메뉴를 주피터가 업데이트될 때마다 확인하시면 좋은데, 키보드 단축키들이 자주 추가되기 때문입니다.


또는 Cmd + Shift + P (또는 Ctrl + Shift + P 리눅스, 윈도우의 경우) 을 누르면 대화창이 뜨는데 키보드 단축키들을 이름으로 검색해서 실행시킬 수 있습니다. 키보드 단축키가 생각나지 않으실 때는 이 기능을 활용하시면 좋습니다.


몇 가지 유용한 단축키롤 소개합니다. 


esc : command 모드로 변경한다.


command 모드 안에서

  • A : 현재 셀의 위에 새로운 셀을 추가한다.
  • B : 현재 셀 밑에 새로운 셀을 추가한다.
  • M : 현재 셀을 markdown 모드로 변경한다. 
  • Y : markdown 모드를 다시 code 모드로 변경한다.
  • D+D : 현재 셀을 삭제한다.
  • Enter : command 모드에서 edit 모드로 변경한다.
  • F : 코드를 find and replace 한다.
  • O : Output을 toggle한다.
shift + tab : 객체의 docstring(documentation)을 출력한다. 

복수의 셀을 선택하기
  • Shift J 나 Shift down(키보드 방향키)을 누르면 아래방향으로 복수의 셀을 선택할 수 있다. Shift K나 Shift Up을 누르면 위 방향으로 복수의 셀을 선택한다. 
  • 복수의 셀이 선택되면 마찬가지로 delete, copy, cut, paste, run을 할 수 있다. 
  • Shift M을 누르면 선택된 셀들을 merge 한다.

2. 변수를 이쁘게 출력하기


가장 널리쓰이는 방법은 print 문을 안 쓰고 그냥 변수명만 셀에 쓴 다음에 run을 하는 것입니다. 그러면 IPython Kernel이 해당 객체를 이쁘게 나타내주는데 예를 들어 pandas DataFrame을 출력할 때 유용한 방법입니다. 


덜 알려진 방법은 kernel 의 세팅을 바꾸면 여러개의 변수명에 대해서 output을 내줄 수 있다는 것인데

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
import pandas as pd


위와 같이 세팅하면


data = pd.DataFrame({'a':("A", "B","C","D","E","F","G"), 'b':(1,2,3,4,5,6,7)}) data.head() data.tail()

Out[11]:
ab
0A1
1B2
2C3
3D4
4E5
Out[11]:
ab
2C3
3D4
4E5
5F6
6G7


위와 같이 여러개의 statement가 있어도 그 statement의 수만큼의 output을 내줍니다. (세팅을 안 하게 되면 가장 마지막 output 만 나타내줍니다.)


~/.ipython/profile_default/ipython_config.py

 

일일이 세팅을 해주기 귀찮으면 위의 코드를


c = get_config()

# Run all nodes interactively
c.InteractiveShell.ast_node_interactivity = "all"

이렇게 바꾸어주면 일일이 코드상에서 세팅해주지 않아도 됩니다.



3. 라이브러리 도큐먼트를 쉽게 찾기


Help 메뉴에 가시면 Scipy, Numpy, Matplotlib, Pandas와 같은 흔히 쓰이는 라이브러이의 도큐먼트를 확인할 수 있습니다. 또한 코드상에서 ? 접두사를 붙여서 라이브러리의 도큐먼트를 확인할 수도 있습니다.


?str.replace()


Docstring:
S.replace(old, new[, count]) -> str

Return a copy of S with all occurrences of substring
old replaced by new.  If the optional argument count is
given, only the first count occurrences are replaced.
Type:      method_descriptor




반응형
반응형

문제

ImportError: No module named cv2


해결


파이썬 opencv 가 설치되어있지 않아서 생기는 문제로 이를 해결하기 위해 conda install opencv, pip install opencv 등을 해보았지만 제대로 되지 않았습니다. 그래서 opencv 홈페이지에서 직접 윈도우즈용 opencv를 설치하였고 설치된 폴더, opencv\build\python\2.7\x64 이곳에서 파이썬 모듈 cv2.pyd를 Anaconda2\Lib\site-packages에 복사하였더니 문제가 해결되었습니다. 

 

http://speark.tistory.com/9


위 블로그를 참고하였습니다.

반응형
반응형

데이터 분석 대회 Kaggle에 나왔던 타이타닉 데이터로 로지스틱 회귀분석 연습을 해보았습니다. 데이터를 통해 성별, 나이, 객실 등급이 승객의 생존에 어떤 영향을 끼쳤는지 분석해 볼 수 있습니다.



알아보고 싶은 것은 "성별(Sex), 나이(Age), 객실등급(Pclass), 요금?(Fare) 가 생존에 어떻게 어느정도의 영향을 미쳤는가?" 입니다.


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

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
 
# 2015. 8. 5 
 
import pandas as pd
import statsmodels.api as sm
import pylab as pl
import numpy as np
import test2
 
df = pd.read_csv("c:/train2.csv"# read file
 
print df.head()
 
cols_to_keep = ['Survived''Age''Fare'# 분류할 수 없는 컬럼들
 
# 분류할 수 있는 컬럼들은 더미 컬럼를 만든다.
dummy_Pclass = pd.get_dummies(df['Pclass'], prefix='Pclass')
dummy_Sex = pd.get_dummies(df['Sex'], prefix='Sex')
 
# 더미를 데이터에 이어 붙인다.
data = df[cols_to_keep].join(dummy_Pclass.ix[:,'Pclass_2':]) # Pclass_2 부터 이어 붙임. 이래야 분석에 편리함
data = data.join(dummy_Sex.ix[:,'Sex_male':]) # Sex_male만 이어 붙임
 
data['intercept'= 1.0
 
# 지금까지의 데이터 확인
print data.head()
 
 
# 출력창에 다음과 같이 뜸
#   Survived  Age     Fare  Pclass_2  Pclass_3  Sex_male  intercept
#0         0   22   7.2500         0         1         1          1
#1         1   38  71.2833         0         0         0          1
#2         1   26   7.9250         0         1         0          1
#3         1   35  53.1000         0         0         0          1
#4         0   35   8.0500         0         1         1          1
 
 
# logistic regression
train_cols = data.columns[1:] # train_cols는 설명 변수
logit = sm.Logit(data['Survived'], data[train_cols]) # Survived는 목적 변수
 
# fit the model
result = logit.fit() 
 
print result.summary() # 분석결과 출력
 
#==============================================================================
#                 coef    std err          z      P>|z|      [95.0% Conf. Int.]
#------------------------------------------------------------------------------
#Age           -0.0330      0.007     -4.457      0.000        -0.048    -0.019
#Fare           0.0007      0.002      0.340      0.734        -0.003     0.005
#Pclass_2      -1.0809      0.286     -3.778      0.000        -1.642    -0.520
#Pclass_3      -2.2794      0.280     -8.142      0.000        -2.828    -1.731
#Sex_male      -2.6049      0.188    -13.881      0.000        -2.973    -2.237
#intercept      3.4772      0.418      8.318      0.000         2.658     4.297
#==============================================================================
 
# odds ratios only
print np.exp(result.params) # 오즈 비(Odds Ratio) 출력
 
#Age           0.967515
#Fare          1.000714
#Pclass_2      0.339281
#Pclass_3      0.102351
#Sex_male      0.073911
#intercept    32.367967
 
data["predict"= result.predict(data[train_cols])
print data.head()
 
# 최종결과 (predict가 생존확률)
#   Survived  Age     Fare  Pclass_2  Pclass_3  Sex_male  intercept   predict
#0         0   22   7.2500         0         1         1          1  0.106363
#1         1   38  71.2833         0         0         0          1  0.906625
#2         1   26   7.9250         0         1         0          1  0.585365
#3         1   35  53.1000         0         0         0          1  0.913663
#4         0   35   8.0500         0         1         1          1  0.071945
cs




분석 결과 정리


coef(편회귀계수)의 부호만을 봤을 때, 나이가 많을 수록, 여자보다는 남자일 수록, 1등급보다는 2등급, 3등급일 수록, 요금이 적을 수록 생존확률이 낮아졌다. 또한 coef의 절대값으로 미루어보면 성별이 생존여부에 가장 큰 영향을 미치는 것을 알 수 있었다.



용어


Odds Ratio 

Odds Ratio란 Odds의 비율이다. Odds란 성공/실패와 같이 상호 배타적이며 전체를 이루고 있는 것들의 비율을 의미한다. 예를 들어 남자 승객의 경우 577명중 109명이 생존했다. 이 경우 Odds = P(생존)/P(사망) = (109/577)/(468/577) = 0.19/0.81 = 0.23

여자 승객의 경우 314명중 233명이 생존했다. 이 경우 Odds = P(생존)/P(사망) = (233/314)/(81/314) = 2.87

따라서 Odds Ratio = 0.23/2.87 = 약 0.08


반응형
반응형

http://blog.yhathq.com/posts/logistic-regression-and-python.html


알고 싶은 것 : GPA, GRE, 모교 우선순위(prestige) 가 대학원 입학 여부에 어떻게 영향을 미치는가?

---------------------------------------------------------------------------------------------------------------------------

위의 블로그의 내용을 요약한 글입니다. 정리한 글은 위의 블로그에 더욱 자세하게 설명되어 있습니다.
환경 : python 2.7, eclipse pydev

1. 데이터 읽기
 
1
2
3
4
5
6
7
8
9
10
11
12
import pandas as pd
import statsmodels.api as sm
import pylab as pl
import numpy as np
 
 
print df.head()
 
df.columns = ["admit""gre""gpa""prestige"# df의 column 이름 바꾸기
print df.columns
 
cs


2. 데이터 요약하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
print df.describe() # 빈도수, 평균, 분산, 최솟값, 최댓값, 1/4분위수, 중위값, 1/4분위수를 나타냄
 
#             admit         gre         gpa   prestige
# count  400.000000  400.000000  400.000000  400.00000
# mean     0.317500  587.700000    3.389900    2.48500
# std      0.466087  115.516536    0.380567    0.94446
# min      0.000000  220.000000    2.260000    1.00000
# 25%      0.000000  520.000000    3.130000    2.00000
# 50%      0.000000  580.000000    3.395000    2.00000
# 75%      1.000000  660.000000    3.670000    3.00000
# max      1.000000  800.000000    4.000000    4.00000
 
print df.std() # 분산 출력
 
# admit      0.466087
# gre      115.516536
# gpa        0.380567
# prestige   0.944460
 
print pd.crosstab(df['admit'], df['prestige'], rownames=['admit'])
 
# prestige   1   2   3   4
# admit                   
# 0         28  97  93  55
# 1         33  54  28  12
 
df.hist()
pl.show() # pl.show()를 해야 화면에 띄워준다! 결과는 아래와 같다. 모든 컬럼에 대해 히스토그램을 그림
cs

3. 더미변수로 고치기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
dummy_ranks = pd.get_dummies(df['prestige'], prefix='prestige')
print dummy_ranks.head()
 
#    prestige_1  prestige_2  prestige_3  prestige_4
# 0           0           0           1           0
# 1           0           0           1           0
# 2           1           0           0           0
# 3           0           0           0           1
# 4           0           0           0           1
 
cols_to_keep = ['admit''gre''gpa']
data = df[cols_to_keep].join(dummy_ranks.ix[:, 'prestige_2':])
print data.head()
#    admit  gre   gpa  prestige_2  prestige_3  prestige_4
# 0      0  380  3.61           0           1           0
# 1      1  660  3.67           0           1           0
# 2      1  800  4.00           0           0           0
# 3      1  640  3.19           0           0           1
# 4      0  520  2.93           0           0           1
 
data['intercept'= 1.0
 
cs

4. 회귀분석을 시행한다.

1
2
3
4
5
6
train_cols = data.columns[1:]
logit = sm.Logit(data['admit'], data[train_cols])
result = logit.fit()
print result.summary()
 
 
cs
              Logit Regression Results                           
          ==============================================================================
          Dep. Variable:                  admit   No. Observations:                  400
          Model:                          Logit   Df Residuals:                      394
          Method:                           MLE   Df Model:                            5
          Date:                Sun, 03 Mar 2013   Pseudo R-squ.:                 0.08292
          Time:                        12:34:59   Log-Likelihood:                -229.26
          converged:                       True   LL-Null:                       -249.99
                                                  LLR p-value:                 7.578e-08
          ==============================================================================
                           coef    std err          z      P>|z|      [95.0% Conf. Int.]
          ------------------------------------------------------------------------------
          gre            0.0023      0.001      2.070      0.038         0.000     0.004
          gpa            0.8040      0.332      2.423      0.015         0.154     1.454
          prestige_2    -0.6754      0.316     -2.134      0.033        -1.296    -0.055
          prestige_3    -1.3402      0.345     -3.881      0.000        -2.017    -0.663
          prestige_4    -1.5515      0.418     -3.713      0.000        -2.370    -0.733
          intercept     -3.9900      1.140     -3.500      0.000        -6.224    -1.756
          ==============================================================================

coef에 주목한다. gre:0.0023 gpa :0.840, prestige_2 : -0.6754 등등...
coef(편회귀계수)의 값이 양수이면 그 컬럼의 값이 커질수록 목적변수가 TRUE일 확률 즉, admit=1일 확률이 높아진다.
반대로 coef의 값이 음수이면 그 컬럼의 값이 커질수록 목적변수가 FALSE일 확률 즉, admin=0일 확률이 높아진다.

즉 GRE나 GPA가 커질수록 대학원에 입학할 확률은 커지고 prestige_2, prestige_3이 커질수록 대학원에 입학할 확률은 작아진다. 
이러한 경향은 pretige가 낮아질수록 심해진다.


5. odds ratio

1
2
3
4
5
6
7
print np.exp(result.params)
# gre 1.002267
# gpa 2.234545
# prestige_2 0.508931
# prestige_3 0.261792
# prestige_4 0.211938
# intercept 0.018500
cs

 


반응형
반응형