2018년 12월 23일 일요일

PyThon tsv 파일 읽어서 범주형 데이터 one hot encoding 하기

TSV file read and One hot encoding categorical data


범주형 데이터는 숫자의 값으로 표현되지 않는 데이터를 의미합니다. 이러한 데이터는 대표적으로 남,여 성별이나 지역명이 있습니다. 머신 러닝에서 이러한 데이터를 다룰 때 일반적으로 one hot encoding 을 사용하게 됩니다.
one hot encoding 외에 어떤 방법이 있는지는 아래 링크를 참고하시기 바랍니다.
https://blog.myyellowroad.com/using-categorical-data-in-machine-learning-with-python-from-dummy-variables-to-deep-category-66041f734512
https://blog.myyellowroad.com/using-categorical-data-in-machine-learning-with-python-from-dummy-variables-to-deep-category-42fd0a43b009

github 자료를 통해서 예를 들어 보겠습니다. 아래와 같은 Account  Network      Device 컬럼을 가지는 데이터가 있다고 가정할때, 각 종류에 따라서 1차원의 데이터를 가지고 1로 encoding 하게됩니다.


    Account  Network      Device
0  Account1   Search  Smartphone
1  Account1  Display      Tablet
2  Account2   Search  Smartphone
3  Account3  Display  Smartphone
4  Account2   Search      Tablet
5  Account3   Search  Smartphone

정상적으로 encoding이 되었다면 아래와 같습니다.
Account 예를 들어보면 Account_Account1, Account_Account2, Account_Account3 3가지 데이터 종류가 있으며 해당값을 만족하면 1 데이터를 갖고 나머지는 0이 됩니다. 즉 3가지 데이터 종류가 있으므로 3차원(배열)이 추가 되었습니다. 따라서 종류가 증가함에 따라 차원이 증가하게 됩니다.
   Account_Account1  Account_Account2  Account_Account3  Network_Display  \
0                 1                 0                 0                0   
1                 1                 0                 0                1   
2                 0                 1                 0                0   
3                 0                 0                 1                1   
4                 0                 1                 0                0   
5                 0                 0                 1                0   

   Network_Search  Device_Smartphone  Device_Tablet  
0               1                  1              0  
1               0                  0              1  
2               1                  1              0  
3               0                  1              0  
4               1                  0              1  
5               1                  1              0 

출처
https://github.com/pandas-dev/pandas/issues/12042

구현하기

이러한 encoding을 쉽게 하기 위해서 python pandas 모듈에 쉽게 준비가 되어있습니다. 구현을 하기전에 데이터가 필요하므로 데이터를 생성하는 부분도 함께 준비하였습니다.

데이터 생성 소스
import numpy as np
import csv

MAX_COLMUM = 5
MAX_ITEM = 20
AREA_INDEX = 2
AREA_INDEX2 = 4

# 지역 범주를 만들기 위하여
area = '서울 부산 대구 인천 광주 대전 울산 세종 경기 강원'.split()

f = open('train.tsv', 'w', encoding='utf-8', newline='')
wr = csv.writer(f, delimiter='\t')

# 첫째줄은 컬럼의 제목을 위해서 write합니다.
# 그중에서 AREA_INDEX 여기 위치는 지역명이 들어갑니다.
title = np.arange(MAX_COLMUM).tolist()
title[AREA_INDEX] = "지역"
wr.writerow(title)

for index in range(0,MAX_ITEM):
 random_data = np.random.rand(MAX_COLMUM).tolist()
 random_data[AREA_INDEX] = area[int((random_data[AREA_INDEX]*100)%10)]
 random_data[AREA_INDEX2] = area[int((random_data[AREA_INDEX2]*100)%10)]
 wr.writerow(random_data)

f.close()

랜덤 데이터이므로 실행할때마다 데이터가 다릅니다.
생성된 데이터
0 1 지역 3 4
0.30789676210454797 0.3160718715457761 광주 0.618074061962662 부산
0.4779143261004096 0.7640950473377978 인천 0.7554662967547567 인천
0.46356805076582885 0.5837447431729355 대전 0.793675978965779 광주
0.5695109222857196 0.05089301078346342 인천 0.9556152127770076 부산
0.04493729261707624 0.14316706161067427 경기 0.3853064558624778 울산
0.4211392967613088 0.4223696769241083 울산 0.5668579921124862 광주
0.6968309725237914 0.9771633054896907 서울 0.8357267917293922 경기
0.11353740126056755 0.7601654905557846 대전 0.743158407293178 부산
0.22370034270270966 0.3115915771469119 대전 0.11848968372403645 부산
0.137646137601257 0.600286886461799 광주 0.7007352606121582 강원
0.031428666050948184 0.39108944068098905 대전 0.8733145643417124 강원
0.9964849451141898 0.1515641318053479 인천 0.5335673749065628 인천
0.22542471556473298 0.8561772376533481 서울 0.9362096685200896 울산
0.4686621433360696 0.17537990374522128 대구 0.3499523151304561 울산
0.046060811241397714 0.8299155100569963 경기 0.21535901604117658 경기
0.1899909553960777 0.21936448957471155 인천 0.6575452140509177 경기
0.41758513381425333 0.42277109702047366 서울 0.8529515809615816 부산
0.3197992908993763 0.13481439248189842 강원 0.4037015504523124 대구
0.0562629654450455 0.551939153390536 인천 0.9260164254116474 세종
0.587953265713976 0.6413981811587487 대구 0.023584307830762707 대전


변환 소스
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import pandas as pd

dataset = pd.read_csv("train.tsv", delimiter='\t', header=0)
print("raw data")
print(dataset)

one_hot_encoded = pd.get_dummies(dataset['지역'])
print("[4] only")
print(one_hot_encoded)

one_hot_encoded = pd.get_dummies(dataset,columns=['지역'])
print("pd.get_dummies(dataset,columns=['지역'])")
print(one_hot_encoded)

one_hot_encoded = pd.get_dummies(dataset)
print("pd.get_dummies(dataset)")
print(one_hot_encoded)

결과
raw data
           0         1  지역         3   4
0   0.307897  0.316072  광주  0.618074  부산
1   0.477914  0.764095  인천  0.755466  인천
2   0.463568  0.583745  대전  0.793676  광주
3   0.569511  0.050893  인천  0.955615  부산
4   0.044937  0.143167  경기  0.385306  울산
5   0.421139  0.422370  울산  0.566858  광주
6   0.696831  0.977163  서울  0.835727  경기
7   0.113537  0.760165  대전  0.743158  부산
8   0.223700  0.311592  대전  0.118490  부산
9   0.137646  0.600287  광주  0.700735  강원
10  0.031429  0.391089  대전  0.873315  강원
11  0.996485  0.151564  인천  0.533567  인천
12  0.225425  0.856177  서울  0.936210  울산
13  0.468662  0.175380  대구  0.349952  울산
14  0.046061  0.829916  경기  0.215359  경기
15  0.189991  0.219364  인천  0.657545  경기
16  0.417585  0.422771  서울  0.852952  부산
17  0.319799  0.134814  강원  0.403702  대구
18  0.056263  0.551939  인천  0.926016  세종
19  0.587953  0.641398  대구  0.023584  대전
[4] only
    강원  경기  광주  대구  대전  서울  울산  인천
0    0   0   1   0   0   0   0   0
1    0   0   0   0   0   0   0   1
2    0   0   0   0   1   0   0   0
3    0   0   0   0   0   0   0   1
4    0   1   0   0   0   0   0   0
5    0   0   0   0   0   0   1   0
6    0   0   0   0   0   1   0   0
7    0   0   0   0   1   0   0   0
8    0   0   0   0   1   0   0   0
9    0   0   1   0   0   0   0   0
10   0   0   0   0   1   0   0   0
11   0   0   0   0   0   0   0   1
12   0   0   0   0   0   1   0   0
13   0   0   0   1   0   0   0   0
14   0   1   0   0   0   0   0   0
15   0   0   0   0   0   0   0   1
16   0   0   0   0   0   1   0   0
17   1   0   0   0   0   0   0   0
18   0   0   0   0   0   0   0   1
19   0   0   0   1   0   0   0   0
pd.get_dummies(dataset,columns=['지역'])
           0         1         3   4  지역_강원  지역_경기  지역_광주  지역_대구  지역_대전  지역_서울  지역_울산  지역_인천
0   0.307897  0.316072  0.618074  부산      0      0      1      0      0      0      0      0
1   0.477914  0.764095  0.755466  인천      0      0      0      0      0      0      0      1
2   0.463568  0.583745  0.793676  광주      0      0      0      0      1      0      0      0
3   0.569511  0.050893  0.955615  부산      0      0      0      0      0      0      0      1
4   0.044937  0.143167  0.385306  울산      0      1      0      0      0      0      0      0
5   0.421139  0.422370  0.566858  광주      0      0      0      0      0      0      1      0
6   0.696831  0.977163  0.835727  경기      0      0      0      0      0      1      0      0
7   0.113537  0.760165  0.743158  부산      0      0      0      0      1      0      0      0
8   0.223700  0.311592  0.118490  부산      0      0      0      0      1      0      0      0
9   0.137646  0.600287  0.700735  강원      0      0      1      0      0      0      0      0
10  0.031429  0.391089  0.873315  강원      0      0      0      0      1      0      0      0
11  0.996485  0.151564  0.533567  인천      0      0      0      0      0      0      0      1
12  0.225425  0.856177  0.936210  울산      0      0      0      0      0      1      0      0
13  0.468662  0.175380  0.349952  울산      0      0      0      1      0      0      0      0
14  0.046061  0.829916  0.215359  경기      0      1      0      0      0      0      0      0
15  0.189991  0.219364  0.657545  경기      0      0      0      0      0      0      0      1
16  0.417585  0.422771  0.852952  부산      0      0      0      0      0      1      0      0
17  0.319799  0.134814  0.403702  대구      1      0      0      0      0      0      0      0
18  0.056263  0.551939  0.926016  세종      0      0      0      0      0      0      0      1
19  0.587953  0.641398  0.023584  대전      0      0      0      1      0      0      0      0
pd.get_dummies(dataset)
           0         1         3  지역_강원  지역_경기  지역_광주  지역_대구  ...   4_광주  4_대구  4_대전  4_부산  4_세종  4_울산  4_인천
0   0.307897  0.316072  0.618074      0      0      1      0  ...      0     0     0     1     0     0     0
1   0.477914  0.764095  0.755466      0      0      0      0  ...      0     0     0     0     0     0     1
2   0.463568  0.583745  0.793676      0      0      0      0  ...      1     0     0     0     0     0     0
3   0.569511  0.050893  0.955615      0      0      0      0  ...      0     0     0     1     0     0     0
4   0.044937  0.143167  0.385306      0      1      0      0  ...      0     0     0     0     0     1     0
5   0.421139  0.422370  0.566858      0      0      0      0  ...      1     0     0     0     0     0     0
6   0.696831  0.977163  0.835727      0      0      0      0  ...      0     0     0     0     0     0     0
7   0.113537  0.760165  0.743158      0      0      0      0  ...      0     0     0     1     0     0     0
8   0.223700  0.311592  0.118490      0      0      0      0  ...      0     0     0     1     0     0     0
9   0.137646  0.600287  0.700735      0      0      1      0  ...      0     0     0     0     0     0     0
10  0.031429  0.391089  0.873315      0      0      0      0  ...      0     0     0     0     0     0     0
11  0.996485  0.151564  0.533567      0      0      0      0  ...      0     0     0     0     0     0     1
12  0.225425  0.856177  0.936210      0      0      0      0  ...      0     0     0     0     0     1     0
13  0.468662  0.175380  0.349952      0      0      0      1  ...      0     0     0     0     0     1     0
14  0.046061  0.829916  0.215359      0      1      0      0  ...      0     0     0     0     0     0     0
15  0.189991  0.219364  0.657545      0      0      0      0  ...      0     0     0     0     0     0     0
16  0.417585  0.422771  0.852952      0      0      0      0  ...      0     0     0     1     0     0     0
17  0.319799  0.134814  0.403702      1      0      0      0  ...      0     1     0     0     0     0     0
18  0.056263  0.551939  0.926016      0      0      0      0  ...      0     0     0     0     1     0     0
19  0.587953  0.641398  0.023584      0      0      0      1  ...      0     0     1     0     0     0     0

[20 rows x 20 columns]

결론

아래와 같이 사용하면 전체 데이터가 모두 one hot encoding 됩니다.
pd.get_dummies(dataset)



댓글 없음:

댓글 쓰기