분류 전체보기 (321)

반응형


로지스틱 회귀분석


로지스틱 회귀분석은 반응변수가 1 또는 0인 이진형 변수에서 쓰이는 회귀분석 방법입니다. 종속변수에 로짓변환을 실시하기 때문에 로지스틱 회귀분석이라고 불립니다. 로지스틱 회귀분석의 좋은점은 우선 계수가 Log Odds ratio가 되기 때문에 해석이 매우 편리하고, case-control과 같이 반응 변수에 따라 샘플링된 데이터에 대해서 편의(bias)가 없는 타당한 계수 추정치를 계산할 수 있다는 것입니다. 이 부분에 초점을 맞추어 로지스틱 회귀분석에 대해 간단히 정리해보려고합니다. 



1. 로지스틱 회귀분석의 원리


반응변수(y)가 1/0인 상황에서 마치 선형 회귀분석처럼 아래의 식에서 계수를 추정한다고 해봅시다. 


$$ y = \beta_0 + \beta X $$


로지스틱 회귀분석에서는 보통 우리가 예측하고자 하는 y의 "예측값"이 P[Y=1] 이라는 믿음을 갖는데, 그러면, y의 예측값은 0-1사이로 고정이 되어야합니다. 하지만 위 식의 경우 특정 X 값에서는 y의 예측값이 0-1 사이로 고정되는 것이 아니라 0보다 작아질 수도 있고, 1보다 커질 수도 있습니다. 


즉, 좌변의 범위는 0-1이며 우변의 범위는 마이너스 무한대에서 플러스 무한대의 값을 갖게됩니다. 이를 해결하기 위해 로지스틱 회귀분석에서는 반응 변수 대한 로짓 변환을 실시합니다. 로짓변환은 y를 log(y/1-y)로 만드는 함수적 변환을 말합니다.



우변을 0-1 사이로 변환하기


$$ P(y=1) = \frac {1} {(1+e^{-(\beta_0 + \beta X)})} $$



이 함수를 시그모이드 함수라고 부릅니다. y의 값이 0-1 사이로 고정됩니다. 이것이 왜 로짓변환이냐고 할 수 있지만 아래의 식을 보면 이해할 수 있습니다.



좌변을 마이너스 무한대에서 플러스 무한대로 변환하기


$$ \log(\frac{P(y=1)}{1-P(y=1)}) = \log(\frac{P(y=1)}{P(y=0)}) = \beta_0 + \beta X $$



이것이 y에 로짓변환을 한 식입니다. 위 두식은 모양만 다르지 결국 풀어서 보면 같은 식입니다. 보통 머신러닝 쪽에서는 위의 식을, 통계학에서는 아래식을 더 좋아하는 것 같아 보입니다. 위의 식이 더 이해하기 쉽지만, 아래 식은 해석이 좋은 특징이 있습니다.


왜냐하면 좌변이 X가 주어진 상황에서 로그 오즈(log odds)가 되기 때문입니다.  즉, 로지스틱 회귀분석은의 계수 추정은 독립변수 X에 대한 선형 회귀식을 X가 주어졌을 때의 반응 변수 Y의 로그 오즈에 적합시킨다." 라고 할 수 있습니다. 



2. 계수의 해석


로지스틱 회귀분석에서 계수에 exponential을 취하면, 해당 변수가 한 단위 증가했을 때, OR 이 됩니다.


$$ \log(\frac{P(y=1| x_1)}{P(y=0 | x_1)}) = \beta_0 + \beta_1 x_1 $$

$$ \log(\frac{P(y=1| x_1 + 1)}{P(y=0 | x_1 + 1)}) = \beta_0 + \beta_1 (x_1 +1) $$


이 때, 아래 식에서 위 식을 빼면, $$ \beta_1 $$ 만 남고, $$ \beta_1 = \log(\frac{P(y=1| x_1 + 1)}{P(y=0 | x_1 + 1)}) -\log(\frac{P(y=1| x_1)}{P(y=0 | x_1)}) $$ 가 됩니다. 


$$ \exp(\beta_1) = \frac{\frac{P(y=1| x_1 + 1)}{P(y=0 | x_1 + 1)}}{\frac{P(y=1| x_1)}{P(y=0 | x_1)}} $$

양변에 exponential을 취해주고, 로그함수의 성질에 의해 exponential된 계수는 X가 X+1이 됐을 때, 오즈의 비율 즉, 오즈 Ratio가 됩니다 (OR). 



3. Case-Control 연구에서 로지스틱 회귀분석의 계수 추정은 편의가 없다.


case-control 연구는 인구집단에서 case와 control을 샘플링해서 이를 대상으로 질병의 원인이 되거나 연관성이 있는 요인을 원인을 찾는 연구입니다. 예를 들어 전체 인구집단 중에 유병률이 0.001 밖에 되지 않는 질병이 있다면, 전체 인구 집단을 대상으로 연구를 수행하면 질병에 걸린 사람(case)를 연구에 포함하기가 매우힘들어지겠죠. 따라서 case-control study에서는 질병이 있는 사람들을 더 많이 샘플링을 해서 case와 control의 비율을 최대 1:1 까지 맞춥니다. 그렇다면 이 연구용 집단은 전체 모집단과는 특성이 다르게 됩니다. 따라서 많은 수치가 잘못된 계산값을 내놓게 됩니다. 예를 들어 상대위험도(Relative Risk)의 경우 참값과 다른 값이 나오게 됩니다.


이상적으로 case-control 연구는 case, control 여부에 따라서만 샘플링이 결정되어야 합니다. 로지스틱 회귀분석이 좋은 한 가지 이유는 이 가정이 맞은 경우, 편의가 없는 계수 추정치를 추정하게 됩니다. 편의가 없다는 말은 연구 집단에서 구한 계수의 기댓값이 전체 인구집단에서 구할 수 있는 계수의 "참값" 이라는 것입니다. 


왜 이렇게 되는 것인지 살펴보겠습니다. 샘플링된 데이터에서 X가 주어졌을 때, Y의 오즈는 아래와 같이 나타낼 수 있습니다. P의 아래첨자는 각각 population, sample을 나타냅니다. 이 때, 파이(y=1|x)는 case 샘플에 포함될 확률입니다. 파이(y=0|x)도 마찬가지입니다. 


$$ \frac{P_s(y=1| x)}{P_s(y=0 | x)} = \frac{\pi(y=1|x)}{\pi(y=0|x)} \frac{P_p(y=1| x)}{P_p(y=0| x)} $$


근데 샘플링이 잘 되었다면 이론적으로 y=1인 샘플에 포함될 확률은 x와 독립적입니다. 따라서 파이(y=1|x)와 파이(y=0|x)는 상수이기 때문에 아래와 같이 쓸 수 있습니다. 

$$ \frac{P_s(y=1| x)}{P_s(y=0 | x)} = K \frac{P_p(y=1| x)}{P_p(y=0| x)} $$


$$ K \frac{P_p(y=1| x)}{P_p(y=0| x)} = K \exp(\beta_0 + \beta_1 x) = \exp(\beta_0' + \beta_1 x)$$


따라서, 샘플링 결과에 따라 계수의 추정량에는 영향이 없고 오직 절편만 바뀐다는 것을 알 수 있습니다.

반응형
반응형

가비아 도메인과 구글앱엔진 연동


구글앱엔진으로 구축한 웹 어플리케이션은 따로 설정하지 않으면 [프로젝트명].appspot.com으로 웹에서 접근할 수 있게 됩니다. 하지만 맞춤 도메인을 통해 개인이 소유한 도메인을 연결시킬 수 있습니다. 예를 들어, 가비아에서 도메인을 구입한 뒤 구글앱엔진으로 구축한 웹 애플리케이션에 연결시킬 수 있습니다. 가장 먼저 할 일은 물론 가비아에서 도메인을 구입하여야 하는 것입니다. 가비아에서 도메인을 구입하였고, 구글앱엔진으로 구축하여 appspot으로 돌아가는 웹 애플리케이션이 있다는 가정하에 아래 과정을 진행하면 됩니다.


구글앱엔진 설정


왼쪽 대시보드 설정 - 맞춤 도메인 - 새 맞춤 도메인 추가



그러면 이렇게 해당 도메인의 DNS 구성에 TXT 기록을 추가하라고 나옵니다. 이 화면에서 멈춰놓고 가비아 홈페이지에 접속하여 이 기록을 추가하여야합니다.



가비아 설정


가비아 홈페이지 - DNS 설정 - 레코드 추가



여기서 호스트에는 @를 하고 값/위치에 위에 구글에서 알려준 TXT 기록을 입력한 후 저장을 누릅니다. (호스트에 반드시 @를 쓰셔야합니다. 다른 걸 쓰면 안됩니다..)

다음에 구글앱엔진으로 돌아와 확인을 누르면 도메인에 대한 소유권이 확인됩니다. 여기까지 되었으면 해당 도메인이 본인 거라는 것을 구글이 확인한 것입니다. 이제 그 도메인으로 접속할 수 있으려면 A레코드를 추가해야하는데 위 과정을 진행하면 앱엔진 대시보드 상에 다음과 화면이 나오게 됩니다. 여기에서 "데이터" 란에 표시된 IP 주소를 가비아에 입력해주어야합니다.



아까의 가비아 DNS 설정 화면으로 돌아와서 레코드 추가에서 타입을 A, 호스트는 @그리고 값에는 위의 IP 주소를 넣으면 설정이 완료됩니다. 그러면 해당 도메인으로 구글 앱 엔진에 접속할 수 있게 됩니다.




하위 도메인 설정 방법 


구글 앱엔진에서 하위 도메인(www를 예로 들음)을 추가한 후에, 가비아에서 1. 레코드 추가-타입 CNAME  2. 호스트 - www, 3. 값 - 구글앱엔진 대시보드 상의 "데이터" (저의 경우에는 ghs.googlehosted.com 을 입력하였습니다.) 를 입력한 후 저장하면 www.domain.com 으로도 구글 웹앤진을 접속할 수 있습니다.



반응형
반응형

Python으로 하는 탐색적 자료 분석 (Exploratory Data Analysis)


Python을 통해 탐색적 자료분석을 할 때, 무엇을 해야하고, 순서는 어떻게 해야하는지 막막한 경우가 많은데요. 탐색적 자료분석의 기본은 바로 변수 별로 분포를 그려보는 것이겠죠. 수치형 데이터의 경우는 히스토그램을, 명목형 데이터의 경우는 빈도표를 통해 데이터의 분포를 살펴보게 됩니다. 본 포스팅에서는 파이썬을 통해 탐색적 자료 분석을 하는 방법을 유명한 데이터셋인 타이타닉 데이터를 통하여 차근차근 알아보겠습니다. 


titanic.csv



기본적인 탐색적 자료 분석의 순서는 아래와 같이 정리해보았습니다. 


1. 데이터를 임포트하여 메모리에 올린다.

2. 데이터의 모양을 확인 한다.

3. 데이터의 타입을 확인한다.

4. 데이터의 Null 값을 체크한다. 

5. 종속변수의 분포를 살펴본다.

6. 독립변수 - 명목형 변수의 분포를 살펴본다. 

7. 독립변수 - 수치형 변수의 분포를 살펴본다. 

8. 수치형, 명목형 변수간의 관계를 파악한다. 


1. 데이터를 임포트한다.


아래와 같이 패키지와 데이터를 임포트합니다. numpy, pandas, matplotlib, seaborn은 이 4가지의 패키지는 파이썬을 통한 EDA에서 거의 필수적으로 사용하는 라이브러리입니다.


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
 
titanic = pd.read_csv("titanic.csv")


2. 데이터의 모양을 확인한다. 


titanic.head()

PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S
4503Allen, Mr. William Henrymale35.0003734508.0500NaNS



3. 데이터의 타입을 체크한다.


titanic.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            891 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB


데이터의 타입을 체크하는 이유는 해당 변수의 타입을 제대로 맞추어주기 위해서입니다. 범주형 변수의 경우 object 또는 string, 수치형 변수의 경우 int64 혹은 float 64로 맞추어주면 됩니다. 범주형 변수의 경우 값이 문자열로 들어가 있으면 알아서 object 타입이 되지만, 만약의 숫자로된 범주형 변수의 경우 int64 등으로 잘못 타입이 들어가 있는 경우가 있습니다.  


위 데이터의 경우 Survived와 PClass 변수가 범주형 int64로 잘못 되어있으므로 형변환을 합니다.


titanic['Survived'] = titanic['Survived'].astype(object)
titanic['Pclass'] = titanic['Pclass'].astype(object)


4. 데이터의 Null 값을 체크한다. 


Null Check도 매우 중요한 작업 중 하나입니다. 단순히 Tutorial이나 학습을 위해 제작된 데이터셋이아닌 현실의 데이터셋의 경우, 많은 부분이 Null 인 경우가 많습니다. 따라서 이 Null 값을 어떻게 처리하느냐가 매우 중요합니다. 


titanic.isnull().sum()

PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age              0
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64



Cabin 변수가  687 행이 missing이고 Embarked가 2개의 행이 missing인 것을 확인하였습니다.


Null 값이 있는 경우, 크게 그 값을 빼고 하는지, 혹은 결측치를 대치하는지 2개의 방법으로 나눌 수 있습니다. 각각의 방법에 대한 이름이 다르긴한데 보통 첫 번째 방법을 complete data analysis, 두 번째 방법을 Imputation이라고 이름 붙입니다. 


missing_df = titanic.isnull().sum().reset_index()
missing_df.columns = ['column', 'count']
missing_df['ratio'] = missing_df['count'] / titanic.shape[0]
missing_df.loc[missing_df['ratio'] != 0]

columncountratio
10Cabin6870.771044
11Embarked20.002245


위 명령어를 통해 전체의 몇 %가 missing 인지를 확인할 수 있습니다. 




5. 종속변수 체크


titanic['Survived'].value_counts().plot(kind='bar') plt.show()


기본적으로 종속변수의 분포를 살펴봅니다. 종속변수란 다른 변수들의 관계를 주로 추론하고, 최종적으로는 예측하고자 하는 변수입니다. 



6. 명목형 변수의 분포 살펴보기

 


단변수 탐색


category_feature = [ col for col in titanic.columns if titanic[col].dtypes == "object"]
category_feature
['Survived', 'Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked']

앞에서 명목형 변수의 형을 object로 모두 변경했기 때문에 이처럼 컬럼 중에서 object 타입을 가진 컬럼만 뽑아서 명목형 변수의 리스트를 만듭니다. 이 때, 데이터의 기본키(인덱스), 종속변수 등을 제외하고 분석하는 것이 좋습니다. 



category_feature = list(set(category_feature) - set(['PassengerId','Survived']))
category_feature
  ['Cabin', 'Embarked', 'Ticket', 'Sex', 'Name', 'Pclass']



다음으로는 그래프를 통해 명목형 변수의 분포를 살펴보는 것입니다. 


for col in categorical_feature: titanic[col].value_counts().plot(kind='bar') plt.title(col) plt.show()




이렇게 살펴봄으로써 명목형 변수를 어떻게 다룰지를 판단할 수 있습니다. 예를 들어, 카테고리수가 너무 많고, 종속변수와 별로 관련이 없어보이는 독립 변수들은 빼고 분석하는 것이 나을 수도 있습니다.



이변수 탐색



sex_df = titanic.groupby(['Sex','Survived'])['Survived'].count().unstack('Survived')
sex_df.plot(kind='bar', figsize=(20,10))
plt.title('Sex')
plt.show()


성별-생존의 관계 파악처럼 두 변수의 관계를 파악하기 위해서는 위와 같이 확인할 수 있습니다.


7. 수치형 변수의 분포 살펴보기


단변수 탐색


단변수 탐색은 seaborn 패키지의 distplot 함수를 이용하면 매우 편합니다.


우선 이와 같이 전체 변수 중에서 범주형 변수와 기타 인덱스 변수, 종속변수들을 제외하고 수치형 변수만 골라냅니다.

numerical_feature = list(set(titanic.columns) - set(category_feature) - set(['PassengerId','Survived']))
numerical_feature = np.sort(numerical_feature)
numerical_feature

변수별로 for문을 돌면서 distplot을 그립니다


for col in numerical_feature:
    sns.distplot(titanic.loc[titanic[col].notnull(), col])
    plt.title(col)
    plt.show()


이변수, 삼변수 탐색


seaborn 패키지의 pairplot을 통해 종속변수를 포함한 3개의 변수를 한 번에 볼 수 있도록 플로팅합니다.


sns.pairplot(titanic[list(numerical_feature) + ['Survived']], hue='Survived', 
             x_vars=numerical_feature, y_vars=numerical_feature)
plt.show()



pairplot은 어러 변수의 관계를 한 번에 파악할 수 있으며,  hue 파라미터를 통해 종속변수를 지정함으로써 세 변수의 관계를 파악할 수 있습니다.



8. 수치형, 명목형 변수 간의 관계 탐색


앞서서 수치형-수치형  간의 관계, 그리고 명목형-명목형 간의 관계에 종속변수까지 포함해서 보았습니다. 이 번에는 수치형-명목형 간의 관계를 파악해 보는 것입니다. 예를 들어, 성별, 나이, 생존여부 3개의 변수를 동시에 탐색하고 싶을 수 있습니다. 이 경우에 명목형 변수에 따라 수치형변수의 boxplot을 그려봄으로써 대략적인 데이터의 형태를 살펴볼 수 있습니다. 


unique_list = titanic['Sex'].unique()
 
for col in numerical_feature:
    plt.figure(figsize=(12,6))
    sns.boxplot(x='Sex', y=col, hue='Survived', data=titanic.dropna())
    plt.title("Sex - {}".format(col))
    plt.show()


반응형
반응형

SAS Base 시험 절차



1. 학생의 경우 50% 할인을 받을 수 있는 Voucher 획득


2018년 8월 기준, SAS Base 시험 비용은 무려 180달러인데... Voucher를 쓰면 90달러로 절반의 할인을 받을 수 있습니다. 메일은 certification@sas.com 로 보내시면 되며, 한국의 대학생인데 Voucher를 받고 싶다고 내용을 한 후, 재학증명서를 첨부하면 1-2일 후에 메일 답장이 옵니다. 재학증명서는 본인의 학교 홈페이지에서 출력 후, 스캔을 해서 pdf 파일로 만들면 됩니다. 이 때 스캐너를 사용하셔서 스캔을 하셔도 되지만, CamScanner와 같은 어플을 사용해서 스캔해도 상관 없습니다. (저도 Camscanncer 이용했습니다.) 가끔 학생증으로도 학생임을 확인해서 Voucher를 주는 경우도 있지만 하지만 확실한 건 영어로 된 재학증명서입니다. 


2. 피어슨뷰 회원 가입 후 시험 신청하기


http://www.pearsonvue.com/sas


이 곳에서 피어슨 뷰 회원가입을 합니다. 회원 가입 시, 영문이름을 여권 등 신분증의 영어이름과 같게 해야합니다.



이 곳에서 SAS Base를 선택하고, 시험장, 시험 시간을 선택합니다. 또한 받은 Voucher를 꼭 입력합니다.



카드 정보를 기입하고 결제를 하면 위와 같이 결제 화면이 나옵니다. 학생은 이렇게 90불 할인을 받을 수 있습니다.




이런식으로 본인의 시험 스케쥴을 조회할 수 있습니다. 정해진 시간과 장소에 시험 장소에 가서 시험을 보면 됩니다. 



3. 공부하기


공부에 도움되는 것들


Cram bible

http://sinpong.tistory.com/notice/2


온라인 테스트

https://www.analyticsexam.com/sample-questions/sas-base-programmer-a00-211-certification-exam-sample-questions

http://biexamacademy.com/sas-base-certification-question-4/


SAS Solution Korea
https://www.youtube.com/channel/UC3qc20GAUtUvKfdh76-1uqw

온라인 테스트는 최종정리용으로 대충 보시고 Cram bible을 위주로 공부하면 합격에는 문제가 없을 것 같습니다. SAS Solution Korea 유투브 채널이 잘 모르는 문제를 해결 할 수 있어 정말 좋습니다. 

4. 후기



준비 기간 : 1주 정도 (Cram bible, 유투브 SAS Solution Korea 채널로 공부)


국회의사당역 근처에있는 미르헨지 교육 센터에서 시험을 보고 합격하였습니다. Cram bible에서 못 본 문제도 많긴 했는데 Cram bible에 나온 문제만 다 맞히면 웬만하면 합격 가능할 것 같다고 생각하였습니다. 덤프에 없던 문제 중 기억나는게 Compress 함수 관련된 문제가 나왔었습니다. 인자로 입력된 문자를 제거해주는 함수 같아서 그렇게 정답을 냈었습니다. 자격증 하나 따서 기분은 좋지만 학생할인 50% 받아도 시험 비용이 90달러라는게 압박이네요. ㅎㅎ 90달러 안아까우면서 SAS 좀 하시는 분은 가볍게 따보는 것 괜찮은 것 같습니다.

반응형
반응형


2018 한국 PyCon Tutorial 후기


뒤 늦게 한국 Pycon이 시작된다는 것을 알아서 등록 기간을 놓쳐 본 이벤트라고 할 수 있는 Conference는 놓쳤지만 아쉬운 마음에 Tutorial이라도 들어보기로 했다. Kaggle 관련한 Tutorial 이었는데, 최근 많이 사용되어지는 데이터 분석 (EDA, Feature enginerring, 모델링) 관련한 팁을 얻고자 하는 마음이었다. 장소는 삼성역 코엑스 센터였다. "Dive into diversity" 라는 문구가 행사의 슬로건인듯 했다.   



장소 : 삼성역 코엑스 2F 그랜드볼룸




튜토리얼 후기 


데이터 분석 관련하여 최근 많이 활용되는 방법들에 대한 유용한 정보들을 많이 얻었다. 특히, Feature Engineering 부분에서는 Label encoding, one hot encoding이나 모델에서 importance를 계산해서 차원을 축소하는 등의 기본적인 것을 제외하면 아는 것이 많이 없었는데, 최근 Kaggle에서 많이 쓰이는 방법들을 알 수 있어 좋았다. 예를 들어, frequency encoding, mean encoding 등이었다. 원래 값을 통해 새로운 feature를 생성하는 것이 성능을 높일 수 있다는 것이 신기했다. 


Feature Engineering은 크게, Tree 기반 모델이냐, Tree 기반 모델이 아니냐에 따라 그 방법이 달라진다. 특히 Tree 기반의 모델의 경우 categorial feature를 encoding 할 때, frequency encoding, label encoding 등을 사용한다. 하지만 label encoding 같은 경우, 타겟값과 전혀 상관 없는 값이 코딩되는 것이기 때문에 성능이 안 좋을 수 있다. 반면, frequency encoding 은 타겟값과 관련있는 값이 인코딩 되기 때문에 더 좋다고 할 수 있다. 반면 neural network의 경우, one hot encoding을 주로 하게 된다. 다만 one hot encoding은 차원이 커지는 문제가 존재한다. 특히 categorical feature를 제거하냐 안하냐를 선택할 때는 주로 feature에 따른 타겟값의 분포를 보고 선택한다. 카테고리에 따른 타겟값의 분포에 차이가 없다면 그 feature는 없어도 무방할 것이다. 특히 mean encoding의 경우 feature와 타겟값이 관련을 갖게 만들면서, 차원도 높이지 않는다는 두마리 토끼를 잡을 수 있는 방법이었다. 그래서 최근 많이 사용되는 categorical 변수의 feature encoding 방법이라고 한다.


또한 Kaggle에서는 Cross-validation이 매우 중요하다는 것을 깨달았다. cross-validation 이 잘못된다면, 모델의 성능을 잘못평가하는 것이 되어버리기 때문에 좋은 성적을 얻기 힘들다. 핵심은 validation set과 test set에서 변수들의 값의 분포를 동일하게 해야한다는 것이다. 그렇지 않다면 validation set에서 성능이 높더라도 test set에서의 성능을 보장하기 어렵다. 


머신러닝 관련한 부분에서는 역시 lightgbm, catboost, xgboost 등의 gradient boosting tree 계열의 알고리즘이 많이 사용된다고 하며, 좋은 성적을 낸 사람들은 대부분 stacking을 활용한다. stacking 같은 ensemble 알고리즘이 좋은 이유는 성능이 0.7짜리인 3개의 모델을 결합함으로써 0.8 이상의 성능을 갖는 모델을 만들 수 있다는 것이다. stacking을 어떻게 하느냐에 따라 leader board에서의 등수가 좌우되는 것 같았다.  


아래 코세라 강의에 Kaggle 관련한 많은 팁들이 있는듯하다. 

https://www.coursera.org/learn/competitive-data-science


반응형
반응형

딥러닝 모델의 K겹 교차검증 (K-fold Cross Validation)


K 겹 교차 검증(Cross validation)이란 통계학에서 모델을 "평가" 하는 한 가지 방법입니다. 소위 held-out validation 이라 불리는 전체 데이터의 일부를 validation set 으로 사용해 모델 성능을 평가하는 것의 문제는 데이터셋의 크기가 작은 경우 테스트셋에 대한 성능 평가의 신뢰성이 떨어지게 된다는 것입니다. 만약 테스트셋을 어떻게 잡느냐에 따라 성능이 다르면, 우연의 효과로 인해 모델 평가 지표에 편향이 생기게 됩니다.


이를 해결하기 위해 K-겹 교차 검증은 모든 데이터가 최소 한 번은 테스트셋으로 쓰이도록 합니다. 아래의 그림을 보면, 데이터를 5개로 쪼개 매번 테스트셋을 바꿔나가는 것을 볼 수 있습니다. 첫 번째 Iteration에서는 BCDE를 트레이닝 셋으로, A를 테스트셋으로 설정한 후, 성능을 평가합니다. 두 번째 Iteration에서는 ACDE를 트레이닝셋으로, B를 테스트셋으로하여 성능을 평가합니다. 그러면 총 5개의 성능 평가지표가 생기게 되는데, 보통 이 값들을 평균을 내어 모델의 성능을 평가하게 됩니다. (아래 데이터는 모두 사실은 트레이닝 데이터입니다. Iteration이라는 상황안에서만 테스트셋이 되는 것입니다.) 이 때, 데이터를 몇 개로 쪼갰느냐가 K-겹 교차검증의 K가 됩니다.


교차 검증을 통한 성능 평가의 목적


모델 성능 평가는 보통 2개의 목적이 있습니다. 1. Unseen 데이터에 대한 성능을 예측하기 위해, 2. 더 좋은 모델을 선택하기 위해 (혹은 Hyperparameter Tuning) 입니다. 교차 검증은 1,2를 달성하기 위한 좋은 방법입니다. 파이썬에서 K-겹 CV를 하는 방법은 여러가지가 있지만 scikit-learn이 많이 사용됩니다. 본 포스팅에서는 keras에서 모델을 만들고 이를 K-겹 교차검증하여 성능을 평가하는 방법을 알아보겠습니다. 


코드 & 데이터


pima-indians-diabetes.data.csv

# MLP for Pima Indians Dataset with 10-fold cross validation via sklearn from keras.models import Sequential from keras.layers import Dense from keras.wrappers.scikit_learn import KerasClassifier from sklearn.model_selection import KFold from sklearn.model_selection import cross_val_score import numpy   # Function to create model, required for KerasClassifier def create_model(): # create model model = Sequential() model.add(Dense(4, input_dim=8, activation='relu')) model.add(Dense(4, activation='relu')) model.add(Dense(1, activation='sigmoid')) # Compile model model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) return model   # fix random seed for reproducibility seed = 7 numpy.random.seed(seed)   # load pima indians dataset dataset = numpy.loadtxt("pima-indians-diabetes.data.csv", delimiter=",")   # split into input (X) and output (Y) variables X = dataset[:,0:8] Y = dataset[:,8]   # create model model = KerasClassifier(build_fn=create_model, epochs=150, batch_size=10, verbose=0)   kfold = KFold(n_splits=2, shuffle=True, random_state=seed) results = cross_val_score(model, X, Y, cv=kfold)

설명


create_model()을 통해 Keras Model 객체를 얻음

KerasClassifier Wrapper를 통해 Keras Model을 Scikit learn에서 사용할 수 있는 객체로 변환을 한다.

Scikit learn의 kFold를 통해 KFold의 Rule을 지정한다.

cross_val_score을 통해 해당 모델의 cross validation score를 계산한다.


결과

array([ 0.65104168,  0.59114585])

0.621093765677 (평균)

위 예제 코드에서는 간단하게 보이기 위해 2-Fold cross validation score를 계산하였습니다. results에 다음과 같은 두 개의 성능 지표가 계산되며 accuracy를 지표로합니다. 첫번째 iteration 의 accuracy 는 0.64, 두 번째 iteration 의 accuracy 는 0.59 로, 최종 cross validation score 는 0.62 가 됩니다.


반응형
반응형


Matching 데이터의 예


Matching이란 case의 control에서 혼란변수의 분포를 맞추어주는 방법으로 데이터셋을 구성할 때 자주 쓰이는 방식입니다. 이는 confounding을 방지하는 방법으로 알려져 있습니다. 이번엔 Matching 데이터를 분석할 때 매우 자주 쓰이는 Conditional Logistic Regression에 대해 아주 간단히 알아보겠습니다. R에서 먼저 사용할 데이터셋을 임포트합니다. 종속변수는 d이며, 이진변수입니다. 그래서 logistic regression으로 연관성 분석을 할 수 있는데요.


library(Epi)

data(bdendo)


setdgallhypobestdurnondurationagecestagegrpage3
11.001.00NoNoYesYes4Yes96.0074.00370-7465-74
21.000.00NoNoNo0No0.0075.00070-7465-74
31.000.00NoNoNo0No0.0074.00070-7465-74
41.000.00NoNoNo0No0.0074.00070-7465-74
51.000.00NoNoYesYes3Yes48.0075.00170-7465-74
62.001.00NoNoNoYes4Yes96.0067.00365-6965-74
72.000.00NoNoNoYes1No5.0067.00365-6965-74
82.000.00NoYesYesNo0Yes0.0067.00065-6965-74
92.000.00NoNoNoYes3No53.0067.00265-6965-74
102.000.00NoNoNoYes2Yes45.0068.00265-6965-74
113.001.00NoYesYesYes1Yes9.0076.00175-7975+
123.000.00NoYesYesYes4Yes96.0076.00275-7975+
133.000.00NoYesNoYes1Yes3.0076.00175-7975+
143.000.00NoYesYesYes2Yes15.0076.00275-7975+
153.000.00NoNoNoYes2Yes36.0077.00175-7975+


데이터셋의 대한 설명은 help(bdendo)를 입력하면 나오고, 아래를 참고 바랍니다.

 

Format


This data frame contains the following columns:


set: Case-control set: a numeric vector

d: Case or control: a numeric vector (1=case, 0=control)

gall: Gall bladder disease: a factor with levels No Yes.

hyp: Hypertension: a factor with levels No Yes.

ob: Obesity: a factor with levels No Yes.

est: A factor with levels No Yes.

dur: Duration of conjugated oestrogen therapy: an ordered factor with levels 0 < 1 < 2 < 3 < 4.

non: Use of non oestrogen drugs: a factor with levels No Yes.

duration: Months of oestrogen therapy: a numeric vector.

age: A numeric vector.

cest: Conjugated oestrogen dose: an ordered factor with levels 0 < 1 < 2 < 3.

agegrp: A factor with levels 55-59 60-64 65-69 70-74 75-79 80-84

age3: a factor with levels <64 65-74 75+


하지만 Matching 데이터에 일반적인 Unconditional Logistic regression을 쓰면 bias가 생깁니다. 왜냐하면 Matching을 하면서 가져온 데이터에는 데이터 고유의 특성이 있기 때문입니다. 예를 들어서 time matching을 한 경우에, 비슷한 시기의 데이터를 샘플링을해서 하나의 strata를 만들고 데이터셋을 구성하게 됩니다. 그러면 이 시기에 의한 효과가 추정량에 영향을 주게 됩니다. 따라서 conditional logistic regression 이라는 조금 더 개선된 logistic regression 방법을 사용하여야합니다. (수학적인 설명은 생략하겠습니다..)


## Analysis

res.clogistic <- clogistic(d ~ cest + dur, strata = set, data = bdendo)


R로 conditional logistic regression(clr)을 하는 방법은 간단한 데 Epi 패키지의 clogistic을 활용하면 됩니다.  분석하고자 하는 공변량을 ~ 뒤에 넣고, strata에 matching pair를 나타내는 변수값을 입력합니다. 이 데이터의 경우, set 이라는 변수가 strata의 정보를 갖고 있습니다. 총 5개의 row가 같은 strata임을 알 수 있습니다. 


결과를 돌리면 다음과 같이 나오는 것을 확인할 수 있습니다.


res.clogistic


Call: 

clogistic(formula = d ~ cest + dur, strata = set, data = bdendo)


         coef exp(coef) se(coef)      z    p

cest.L  0.240     1.271    2.276  0.105 0.92

cest.Q  0.890     2.435    1.812  0.491 0.62

cest.C  0.113     1.120    0.891  0.127 0.90

dur.L   1.965     7.134    2.222  0.884 0.38

dur.Q  -0.716     0.489    1.858 -0.385 0.70

dur.C   0.136     1.146    1.168  0.117 0.91

dur^4      NA        NA    0.000     NA   NA


Likelihood ratio test=35.3  on 6 df, p=3.8e-06, n=254


association을 알아보기 위한 변수 cest, dur의 추정량을 볼 수 있습니다. 



반응형
반응형


쉽게 이해하는 민감도, 특이도, False Positive, False Negative, 양성예측도



민감도 (Sensitivity), 특이도(Specificity), 양성 예측도(Positive Predictive Value, PPV) 는 바로 무언가를 예측하는 상황에서 쓰이는 통계적인 지표입니다. 이 지표들이 가장 많이 쓰이는 곳이 바로 검진(Diagnostic)인데요.


우선 검진의 정의에 대해서 명확히 짚고 넘어가보겠습니다. 검진이란 "건강 상태와 질병의 유무를 알아보기 위하여 증상이나 상태를 살피는 일" 입니다. 이처럼 검진은 그 사람의 병의 유무를 알기 위해 일종의 검사를 하여 병의 유무를 예측하는 것입니다. 중요한 건, 검진은 실제와 다를 수 있다는 것입니다.  


예를 들어, 폐암 검진을 위해 흉부를 X-ray로 촬영한다고 해봅시다. X-ray는 저비용으로 폐암 여부를 알아보는 효과적인 방법입니다. 하지만 문제는 X-ray 결과로 그 사람의 폐암 여부가 결정이 나는 것이 아니라는 것입니다. X-ray에서 폐암이 의심이 가는 경우, MRI, CT 등의 더 정밀한 검사를 통해 폐암의 실제 여부를 결정하게 됩니다. 


이 때, X-ray가 "폐암 여부를 정확하게 가려내는 정도" 를 수치화할 수 있겠죠. 이렇게 수치화하는 지표 중에 유명한 것이 바로 민감도, 특이도, 양성 예측도입니다. 이를 이해하기 쉽게 설명하기 위해 다음과 같은 표로 많이 설명합니다.



폐암 X-ray 검진 예제

 

 폐암 O

폐암 X 

 

 X-Ray 양성

 90

100 

190 

 X-Ray 음성

10 

800 

810 

 

 100

 900

 1000


총 1000명이 X-ray 검사를 받았고, 이 중에 폐암환자는 10%인 100명, 비환자는 90% 입니다. 폐암환자 100명 중 90명이 X-ray 양성 판정을 받았고, 비환자 900명중 800명이 X-ray 음성 판정을 받았습니다. X-ray가 꽤 잘 맞춘 것이죠.


이 때, 폐암환자 중 양성 판정을 받은 사람의 비율을 민감도,

비환자 중 음성 판정을 받은 사람의 비율을 특이도라고 합니다. 


이 예에서, 민감도는 90/100 = 0.9, 특이도는 800/900 = 0.89 입니다. 이 때 1-0.9=0.1 = False Negative Rate, 1-0.89 = False Positive Rate 라고 합니다. 


즉, False Negative는 환자인데 검진에서 가려내지 못한 사람의 수, False Positive는 정상인인데 검진에서 환자로 판단한 사람의 수입니다. Rate가 붙으면 분모로 나누어 0과 1 사이의 값으로 나타내게 되는 것입니다. 민감도, 특이도, False Negative, False Positive는 이렇게 세트로 묶어서 이해할 수 있습니다.


그렇다면 양성 예측도, 음성예측도는 무엇일까요?


민감도와 특이도는 검진을 받은 "사람"의 관점에서 그 기기의 검진의 정확도를 판단한 것입니다. 반면, 양성 예측도, 혹은 음성 예측도의 경우 "기기의 관점"에서 검진의 정확도를 판단하게 됩니다. X-ray가 양성이라고 판단했을 때, 실제 폐암 환자일 확률은 90/190 = 0.47 입니다. 바로 이것을 양성 예측도라고 합니다. 반대로, X-ray가 음성이라고 판단했을 때, 진짜 정상인일 확률은 음성 예측도라고 하며, 800/810=0.98 입니다. 


문제는 양성 예측도가 왜이렇게 작게 나왔는가? 하는 것입니다. 양성 예측도는 민감도(0.9)와 특이도(0.89)처럼 그 값이 크지 않다는 것을 확인할 수 있습니다. 관찰력이 좋으신 분들은 직감으로 이걸 이해할 수 있으실 것입니다. 문제는 바로 "데이터의 불균형" 때문인데요. 비환자 900명중에 단지 100명만이 X-ray 양성으로 잘못 판단되었지만 (False Positive) 상대적으로 비환자가 1:9로 많기 때문에 그 값이 상대적으로 크게 잡혔다는 것을 볼 수 있습니다. 


이를 식으로 살펴보면, 양성 예측도 = 90 / 190 = 90 / 90+100 으로 풀어쓸 수 있겠죠. 이 때, 비환자가 환자와 마찬가지로 100명이었다면 90/90+100/9 = 약 0.9가 되었어야합니다. 하지만, 비환자가 환자에 비해 상대적으로 많기 때문에 False Positive가 많아져서 양성 예측도가 적게 나왔다는 것을 이해할 수 있습니다.


이를 두고, 양성 예측도는 유병률이 작을 수록 작다. 라고 표현합니다. 이 예제에서 폐암 유병률은 0.1이겠죠. 이 값이 작으면 작을 수록 False Positive에 의해 양성 예측도, PPV 는 작아지게 됩니다. 이를 보통 아래 식을 통해서 이해를 하게 되는데요. 


이 식은 위 테이블에서 변수를 놓고 방정식을 풀면 나오게 됩니다. (시간이 되시는 분들은 직접 손으로 풀어보시면 나옵니다.) 이 식을 보면, 분모는 검진의 양성 판단 횟수이며, 분자는 환자를 양성으로 판단한 횟수임을 알 수 있습니다. 


근데, sensitivity*prevalance는 분모, 분자에 같이 있으므로, (1-specificity)*(1-prevalence)가 실제 PPV 값에 영향을 주게 되겠죠. specificity가 고정되어있을 경우, prevalence, 유병률이 작아질 수록 분모가 커져 PPV 값은 작아진다는 것을 쉽게 알 수 있습니다. 


민감도, 특이도, 양성 예측도 중 어떤 지표로 검진 기기를 판단해야 할까요?


명확하게 무엇이 절대적인 기준이라는 것은 없습니다. 다만, 민감도의 경우 환자의 생명과 직접적인 관련이 있을 수 있습니다. 민감도가 낮은 검진의 경우, False Negative(환자인데 정상으로 판단)가 많아지게 되겠죠. 환자인데 정상으로 판단하여 적절한 치료를 받지 못하면, 환자의 생명에 지장이 있을 수도 있습니다. 이것이 많은 사람들이 민감도를 중요시하는 이유입니다. 반면, 특이도의 경우 불필요한 비용의 낭비와 관련이 있습니다. 특이도가 낮으면, False Positive(정상인데 환자로 판단)가 많아지게 되겠죠. 정상인이 환자로 판단되면, 환자가 불안감에 시달리거나, 불필요한 정밀한 추가검사를 받아 환자가 아니라는 것을 밝혀야합니다. 따라서 불필요한 손실이 일어나게 됩니다. 하지만 민감도와 특이도는 현실적인 관점에서 trade off의 관계에 있습니다. 민감도를 높이면 특이도는 보통 낮아지게 되죠. 따라서 적절한 수준에서 검진의 민감도와 특이도를 설정할 필요가 있습니다. 양성 예측도의 경우 유병률이 매우 낮은 질병에서는 높은 것을 기대하기가 힘듭니다. 위 식에서 봤듯이 유병률이 매우 낮으면, 데이터의 불균형으로 인해 False positive가 많아지고 양성 예측도는 낮아지게 됩니다. 이를 방지하기 위해서는 검진의 특이도를 매우 높여야하는데, 현실적으로 민감도를 포기할 수 없기 때문에 양성 예측도는 유병률이 낮은 질병에서 보통 낮은 경향이 있습니다. 

반응형
반응형


우분투 그룹 관련 명령어 정리


우분투를 다중 사용자 환경에서 이용하다보면 특정 폴더를 특정 그룹만 접근할 수 있게 하고 싶을 때가 있습니다.

이럴 때 유용한 그룹 관련 명령어를 정리해보려고 합니다.




  • 그룹 생성하기 

groupadd [group]




  • 현재 등록된 그룹 확인

/etc/group


예를 들어, groupadd test_group을 한 후, 

cat /etc/group을 하면 아래와 같이 test_group이 잘 추가 되었음을 볼 수 있습니다.




  • 사용자한테 그룹 추가하기

usermod -a -G [group] [사용자아이디]



  • 사용자 그룹을 변경하기

usermod -g [group] [사용자아이디]

이렇게하면 사용자의 그룹이 [group]으로 변경됨. 나머지 것들은 다 삭제됨



  • 해당 폴더의 그룹 소유권을 변경

chown [소유자]:[그룹] [폴더이름]


해당 폴더의 소유자와 그룹을 변경한다. 




  • 해당 폴더의 권한 변경

chmod xxx [폴더이름]


이 때 xxx에는 0~7사이의 숫자가 들어갑니다. 이 숫자에 따라서 소유자권한, 그룹권한, 기타 사용자권한이 나뉜다. 이것에 관해서는 다른 포스트를 참조하길 바랍니다.



이 정도만 할 줄 알아도 우분투에서 그룹 관련된 권한 관리는 웬만한 건 다 할 수 있을 거라 생각합니다.



반응형
반응형


문제

/usr/bin/x86_64-linux-gnu-ld: cannot find -lgfortran


Bioconductor를 통해 R 라이브러리를 설치할 때, 위와 같은 컴파일 오류로 인해 제대로 설치되지 않는 현상 발생



해결

https://askubuntu.com/questions/1007591/usr-bin-ld-cannot-find-lopencl


아래 위치에 gfortran 라이브러리가 없어서 문제 발생

/usr/lib/x86_64-linux-gnu/

아래 명령어로 문제 해결

sudo ln -s /usr/lib/x86_64-linux-gnu/libgfortran.so.3 /usr/lib/libgfortran.so

반응형
반응형