[실전 머신러닝] 결정 트리:연봉 예측하기 ❷

트리 모델 계열의 근간인 결정 트리를 학습시켜 연봉을 예측합니다. 모델링에서 발생하는 중요한 이슈인 오버피팅 개념과 해결 방법을 알아봅니다. 2편은 범주형 데이터, 전처리 : 결측치 처리 및 더미 변수 변환입니다.

 

1. 전처리 : 범주형 데이터

가장 먼저 처리할 변수는 종속변수인 class입니다. 차후 해석에 혼선이 없도록 50K 이하를 0, 초과를 1로 변경하겠습니다.

 

data['class'] = data['class'].map({'<=50K': 0, '>50K': 1}) # 숫자로 변환

 

💡사실 이 데이터의 원본에는 ‘<=50K’의 맨 앞부분에 공란이 하나 포함되어 있습니다. 그래서 위의 코드가 제대로 작동하지 않을 수 있는데, 앞서 데이터를 불러오는 과정에서 맨 앞자리의 공란을 모두 제거해주었기 때문에 아무런 이슈 없이 처리할 수 있습니다.

 

1.1 object형의 변수 정보 확인하기

다음은 독립변수의 범주형 데이터를 다루겠습니다. 이 데이터에 변수는 13개뿐입니다. 그래서 어떤 변수가 object형인지 쉽게 눈으로 확인할 수 있으나, 변수가 100개 이상이 된다면 다른 접근 방법이 필요합니다. 범주형 데이터가 얼마나 있는지 확인하는 방법을 알아보겠습니다.

 

data['age'].dtype

dtype('int64')

 

age 변수는 int64형의 데이터입니다(object형은 object로 출력됩니다). for문를 활용하여 모든 변수의 자료형을 확인하겠습니다.

 

for i in data.columns:   # ❶ 순회
    print(i, data[i].dtype) # ❷ 컬럼명과 데이터 타입 출력

age int64
workclass object
education object
education-num int64
marital-status object
occupation object
relationship object
race object
sex object
capital-gain int64
capital-loss int64
hours-per-week int64
native-country object
class int64

 

❶ data.columns로 컬럼명을 지정하고 ❷ 해당 변수의 자료형을 dtype으로 확인했습니다. 출력 결과는 아직까지 info( ) 함수와 크게 다르지 않습니다.

 

obj_list = [] # 빈 리스트
for i in data.columns:
    if data[i].dtype == 'object': # ❶ 데이터타입이 object이면
        obj_list.append(i) # ❷ 리스트에 변수 이름을 추가

 

❶ dtype이 object인지 아닌지를 확인합니다. object가 맞으면 ❷ 리스트( obj_list)에 추가합니다. 그럼 obj_list를 확인하겠습니다.

 

obj_list # 모아진 변수 확인

['workclass',
 'education',
 'marital-status',
 'occupation',
 'relationship',
 'race',
 'sex',
 'native-country']

 

1.2 전처리할 변수 선별하기

이번에는 각 변수의 고윳값 개수를 nunique( ) 함수를 이용하여 확인하겠습니다.

 

for i in obj_list:
    print(i, data[i].nunique()) # ❶ 변수 이름과 고윳값 개수 확인

workclass 8
education 16
marital-status 7
occupation 14
relationship 6
race 5
sex 2
native-country 41

 

❶ 변수의 이름과 값의 개수를 같이 볼 수 있도록 print() 안에 둘 다 넣어 출력했습니다. describe( ) 로 본 정보와 같습니다. 변수 개수가 상당히 많을 때는 describe( ) 함수 대신 이와 같은 방법을 사용하면 간결하게 확인할 수 있답니다.

범주형 변수를 다룰 때는 더미 변수로 바꾸어 활용하는 방법을 기본으로 생각하는 게 좋습니다. 이전 장에서 배웠다시피, 더미 변수를 사용하면 값의 종류만큼 새로운 변수들이 생겨나기 때문에, 값의 종류가 수백 개면 그만큼 많은 변수가 생겨납니다. 필요하다면 수백 개의 변수를 감수하고서 모델링을 해야 하지만 꼭 필요하지 않다면 변수 수를 줄일 방법을 강구할 필요가 있습니다.

값의 종류가 10개 미만인 변수는 그대로 두고, 10개 이상인 변수만 확인하여 조치할지를 검토하겠습니다.

위의 코드에 if절을 추가해 unique가 10개 이상인 변수들만 다시 추려보겠습니다.

 

for i in obj_list: # 순회
    if data[i].nunique() >= 10: # 변수의 고윳값이 10보다 크거나 같으면
        print(i, data[i].nunique()) # 컬럼명과 고윳값 개수 출력

 

세 가지 변수(education, occupation, native-country)가 출력되었군요. 각각을 살펴보고 각기 다른 방법으로 처리하는 연습을 하겠습니다.

 

1.3 education 변수 처리

우선 education 변수의 정보를 value_counts( ) 로 살펴봅시다.

 

data['education'].value_counts() # 고윳값 출현 빈도 확인

HS-grad         15784
Some-college    10878
Bachelors        8025
Masters          2657
Assoc-voc        2061
11th             1812
Assoc-acdm       1601
10th             1389
7th-8th           955
Prof-school       834
9th               756
12th              657
Doctorate         594
5th-6th           509
1st-4th           247
Preschool          83
Name: education, dtype: int64

 

미국의 교육 시스템에 대한 정보라 완전하게 이해하기는 어려울 겁니다. 초중고에 속하는 1~12학년까지의 값과, Bachelors나 Masters 같은 학위 이름들이 있습니다. 이 경우는 범주형 변수지만 서열화가 가능하기 때문에 비교적 다루기 쉬운 편입니다. 예를 들어 초등학교를 가장 낮은 숫자로, 박사학위를 가장 높은 숫자로 나타낼 수 있습니다.

기본적으로 범주형 변수를 숫자로 대체시킬 때는 주의를 해야 합니다. 5.4절 ‘전처리 : 범주형 변수 변환하기(더미 변수와 원-핫 인코딩)’에서 더미 변수를 설명할 때 말씀드렸죠? 하지만 지금과 같은 경우는 각 값들의 서열이 명백하기 때문에, 숫자로 바꿔주어도 전혀 문제가 없습니다. 앞에서 class를 0과 1로 바꾸어주었을 때처럼 map( ) 함수를 활용하여 숫자로 변경하면 되는데, 공교롭게도 해당 데이터에는 이에 대한 변수가 이미 준비되어 있습니다. 잠시 head( ) 함수로 확인한 결과물을 다시 보겠습니다.

 

 

❶ education-num 변수를 보니 education 정보를 숫자로 표현한 것 같습니다. 기대하는 바처럼 서열순인지 확인은 해봐야겠죠?

education-num에 어떤 숫자들이 들어 있는지 unique( ) 함수를 써서 알아봅니다. 변수가 제대로 서열화되었는지를 넘파이의 sort( ) 를 사용하여 오름차순으로 정리해 확인하겠습니다.

 

np.sort(data['education-num'].unique())

array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16]),
            dtype=int64)

 

1에서부터 16까지의 숫자가 있습니다. 각 숫자가 어떤 education값과 매칭되는지를 확인할 차례입니다. 기대하는 바는 일대일 매핑인데, 실제로 그렇지 않을 가능성도 염두에 두고 확인을 해야 합니다.

1에 대한 매핑을 확인합시다. education-num이 1인 데이터만 모아서 그중 education 변수에 어떤 값들이 있는지를 확인하면 됩니다. 한 번에 한 줄씩 코드를 늘려가며 최대한 쉽게 설명하겠습니다.

우선 education-num이 1인지 확인합니다.

 

data['education-num'] == 1

0        False
1        False
2        False
3        False
4        False
         ...  
48837    False
48838    False
48839    False
48840    False
48841    False
Name: education-num, Length: 48842, dtype: bool

 

1이면 True, 아니면 False입니다. 이 정보를 가지고 인덱싱을 하여, True인 경우만 불러오겠습니다(즉 1인 경우).

 

data[data['education-num'] == 1]

 

data[‘education-num’] == 1의 결과는 True 아니면 False입니다. 이 결과를 인덱스에 다시 넣음으로써 education-num이 1인 경우만 불러왔습니다. 이게 판다스에서 가장 기본적으로 필터링하는 방법이오니 잘 알아둡시다.

다음은 이 안에서 education이 어떤 종류가 있는지를 확인하기 위하여 해당 변수를 인덱싱하고 unique( ) 함수를 쓰겠습니다.

 

data[data['education-num'] == 1]['education'].unique()
# education-num이 1인 데이터들의 education 고윳값 확인

array(['Preschool'], dtype=object)

 

 

이번에는 모든 숫자에 대해 확인하겠습니다.

 

for i in np.sort(data['education-num'].unique()):
    print(i, data[data['education-num'] == i]['education'].unique())
# education-num의 고윳값별 education의 고윳값 확인

1 ['Preschool']
2 ['1st-4th']
3 ['5th-6th']
4 ['7th-8th']
5 ['9th']
6 ['10th']
7 ['11th']
8 ['12th']
9 ['HS-grad']
10 ['Some-college']
11 ['Assoc-voc']
12 ['Assoc-acdm']
13 ['Bachelors']
14 ['Masters']
15 ['Prof-school']
16 ['Doctorate']

 

그리고 print 부분에는 해당 education-num의 숫자와, 그에 응하는 education 고윳값들을 동시에 보여주기 위해서 이 둘을 같이 넣어줍니다.

완전히 우리가 기대했던 형태의 결과입니다. 낮은 숫자부터 높은 숫자까지, 점점 고학력순으로 나열되어 있습니다. 우리가 하려던 작업이 이미 별도의 변수로 마련이 되어 있습니다. (중복 정보이므로) 별도의 작업 없이 기존 변수를 drop( ) 함수로 제거시킵니다.

 

data.drop('education', axis=1, inplace= True)

 

1.4 occupation 변수 처리

다음은 occupation 변수를 살펴보겠습니다.

 

data['occupation'].value_counts()

Prof-specialty       6172
Craft-repair         6112
Exec-managerial      6086
Adm-clerical         5611
Sales                5504
Other-service        4923
Machine-op-inspct    3022
Transport-moving     2355
Handlers-cleaners    2072
Farming-fishing      1490
Tech-support         1446
Protective-serv       983
Priv-house-serv       242
Armed-Forces           15
Name: occupation, dtype: int64

 

다양한 직업군이 표기되는데, 이미 비슷한 직업군끼리는 묶인 상태로 정리된 데이터로 보입니다. 예를 들어 Farming과 fishing이 하나의 이름으로 묶여 있습니다. 유사한 직업군끼리 묶여 있지 않았다면 이를 묶는 작업을 하려했으나 이미 정리가 되어 있고, 각 직업 간의 서열이라고 할 만한 않았다면 이를 묶는 작업을 하려했으나 이미 정리가 되어 있고, 각 직업 간의 서열이라고 할 만한부분도 딱히 정의할 수가 없습니다. 더미 변수로 변환을 하면 변수 14개가 생기겠군요. 그 정도면 감당할 수 있는 수준이니 별도의 작업을 하지 않고 나중에 더미 변수로 처리하겠습니다.

 

1.5 native-country 변수 처리

마지막으로 native-country 변수를 살펴보겠습니다.

 

data['native-country'].value_counts()

United-States                 43832
Mexico                          951
Philippines                     295
Germany                         206
Puerto-Rico                     184
Canada                          182
El-Salvador                     155
India                           151
Cuba                            138
England                         127
China                           122
South                           115
Jamaica                         106
Italy                           105
Dominican-Republic              103
Japan                            92
Guatemala                        88
Poland                           87
Vietnam                          86
Columbia                         85
Haiti                            75
Portugal                         67
Taiwan                           65
Iran                             59
Greece                           49
Nicaragua                        49
Peru                             46
Ecuador                          45
France                           38
Ireland                          37
Hong                             30
Thailand                         30
Cambodia                         28
Trinadad&Tobago                  27
Yugoslavia                       23
Outlying-US(Guam-USVI-etc)       23
Laos                             23
Scotland                         21
Honduras                         20
Hungary                          19
Holand-Netherlands                1
Name: native-country, dtype: int64

 

수많은 값이 있습니다. 그리고 특이사항으로 United-States가 압도적으로 큰 비중을 차지합니다. 그럼 해당 변수를 처리하는 여러 방법을 살펴봅시다. 우선 이 경우는 United-States가 약 90%를 차지하고 있기 때문에, 아주 단순하게는 United-States 이외의 국가들을 하나로 묶어 Others 같은 이름으로 변경하는 방식도 가능합니다. 데이터가 간소화되는 장점이 있으나, 그만큼 정보가 줄어드는 단점이 있습니다. 만약 해당 예측 모델에서 United-States가 아닌 국가 사이에 큰 차이가 없다면 이 방법을 써도 무방합니다. 또 다른 방법으로는 비슷한 값들끼리 묶는 겁니다. 예를 들어 지역별로 묶는 거죠. 즉, North America, South America, Asia 등과 같이 구분할 수 있습니다. 이 방법 또한 해당 지역에 속한 국가끼리 어느 정도 유사성을 보여야 무리가 없습니다. 여기서 말하는 유사성은, 종속변수의 값에 대한 유사성을 의미합니다. 즉 국가별로 class에 대한 평균값을 내었을 때, 만약 Asia 국가들이 다소 비슷한 수치를 보여준다면 이렇게 묶는 데에 큰 무리가 없을 겁니다. 유사성은 처음에 말한 United-States 이외의 국가들끼리 묶는 때도 필요하니 국가별로 class값의 평균을 확인해봅시다.

국가별 평균을 확인해야 하기 때문에 groupby( ) 함수를 사용하여 국가별로 묶어주겠습니다.

 

 

우리는 국가별로 class의 평균값을 볼 것이기 때문에 mean( ) 함수를 사용하겠습니다.

 

# 아래 코드는 참고용이므로, 실행할 필요가 없습니다.
data.groupby('native-country').mean() # 그룹별 평균 계산

 

여기까지만 코드를 작성해도 원하는 아웃풋을 볼 수 있으나, 국가가 너무 많아서 쉽게 눈에 들어오는 상황은 아닙니다. 같은 지역에 있는 국가들끼리 비슷한 수준의 class 평균값을 가지는지를 확인하는 것이 목적이므로 지역 혹은 class 기준으로 정렬시키겠습니다. 이 데이터에는 지역에 대한 변수가 없어, class 기준으로 정렬시키겠습니다.

 

data.groupby('native-country').mean().sort_values('class')
# 그룹별 평균 계산 후 class 기준으로 오름차순 정렬

 

 

우선 다른 국가들을 Others로 묶어줄 수 있는지 ❶ ****United-States를 먼저 찾아보겠습니다. class 평균값은 약 0.24입니다. 그리고 다른 국가들은 United-States의 평균값보다 크거나 작아서 전혀 비슷하지 않은 양상입니다. Others로 묶는 방법은 좋지 않아 보입니다. 그럼 지역별로 묶어줄 수 있는지 보겠습니다. class 평균이 가장 높은 ❷ ****France 중심으로 유럽 국가를 찾아보겠습니다. 극단적으로 다른 경우만 몇 개 발견하면 해당 방법이 좋지 않음이 증명되기 때문에, 수치가 낮은 쪽에 유럽 국가가 있는지를 보는 게 빠릅니다. 가장 낮게는 Holand가 있지만 관측치가 1개밖에 안 되므로 고려하지 않아도 될 것 같고, 그다음으로는 Portual이 0.18 정도로 France와 상당한 차이를 보입니다. 다른 지역의 예로 Cuba와 Dominican Republic도 각각 0.25와 0.05로 큰 차이를 보입니다. 물론 다른 많은 나라는 지역별로 비슷한 양상을 보이기도 하지만 큰 차이를 보는 경우가 많으므로 지역별로 묶는 방법은 적합하지 않습니다.

그럼 더미 변수를 사용하지 않고 각 국가명을 숫자로 변환하여 하나의 변수를 그대로 유지하는 건 어떨까요? 제가 처음 더미 변수를 설명할 때, 범주형 데이터를 무작정 숫자로 치환하여 모델링하는 방법은 결코 좋지 않다고 설명드렸습니다. 그러나 이러한 방법이 허용되는 경우가 있는데, 바로 트리 기반의 모델을 사용할 때입니다. 트리 기반의 모델은 연속된 숫자들도 연속적으로 받아들이기보다 일정 구간을 나누어 받아들이기 때문에, 트리가 충분히 깊어지면 범주형 변수를 숫자로 바꾼다고 해도 큰 문제가 없습니다.

범주형 데이터를 숫자로 치환하는 여러 방법이 있습니다. 기본적으로는 랜덤하게 번호를 부여하는 겁니다. 예를 들어 United-States는 1, Peru는 2, Guatemala는 3 등 임의의 번호를 붙여주는 거죠. 단순한 라벨링으로 생각하면 됩니다. 또 다른 방법은 우리가 value_counts( ) 함수로 확인한 숫자들을 부여하는 방법입니다. 이 방법은 종속변수인 class가 이민자 수가 많은 국가인지 적은 국가인지에 따라 유의미한 차이를 보인다면 더 유용한 변수로 활용이 될 것이고, 그렇지 못하더라도 최소한 라벨링 효과는 가지고 가게 됩니다. 단, 라벨링의 목적만으로 이 방법을 사용할 때에는 같은 값을 가지는 국가가 없는지 확인해야 하며, 이 데이터의 경우는 동수인 국가들이 있어서 적합하지 않습니다.

마지막은 우리가 groupby( ) 로 확인했던 class의 평균값을 넣어주는 방법입니다. 이는 조금 극단적인 방법인데, 예상하려는 목푯값을 독립변수의 일환으로 반영하기 때문입니다. 즉, 답을 거의 밀어넣다 시피해서 모델링하는지라 오버피팅 문제가 발생할 수 있습니다. 오버피팅 문제는 잠시 후 매개변수 튜닝에서 더 구체적으로 다루겠습니다.

‘native-counry’별로 class의 평균값을 구하는 코드를 작성하겠습니다.

 

country_group = data.groupby('native-country').mean()['class']
# 그룹별 class의 평균값을 계산하여 저장

 

앞서 작성한 코드에서 정렬에 사용한 sort_values( ) 함수를 빼고, 인덱싱을 추가해 class값만 취했습니다. 그리고 아웃풋을 country_group이라는 이름으로 저장했습니다.

이렇게 평균값을 구해놓은 판다스 시리즈를 기존 데이터에 새로운 변수로 붙여넣어야 합니다. join( ) 이나 merge( ) 를 사용할 수 있는데 이번에는 merge( ) 를 사용해서 데이터를 합치겠습니다.

 

 

국가 이름이 키값이 되어야 하는데 현재 country_group에서 국가 이름은 변수가 아닌 인덱스에 자리하고 있습니다. reset_index( ) 를 써서 변수로 뺄 수 있습니다.

 

 

reset_index( )를 써서 인덱스를 변수로 빼주겠습니다.

 

country_group = country_group.reset_index() # 인덱스를 변수로 불러냄

 

이제 country_group( ) 을 확인하면 다음과 같은 데이터프레임을 확인할 수 있습니다.

 

country_group # 데이터 확인

 

 

이제 merge( ) 를 사용하여 두 데이터를 합치겠습니다.

 

data = data.merge(country_group, on = 'native-country', how='left')
# data와 country_group을 native_country 기준으로 결합 (left join)

 

data 국가 이름은 기준으로 하여 country_group을 붙이는 형태이기 때문에 data를 메인으로 삼아 merge( )를 실행했습니다. 키값은 native-country, 결합 형태는 왼쪽 조인(3.1.8절 ‘데이터프레임 합치기’)으로 처리해줍니다.

그럼 데이터가 잘 합쳐졌는지 data를 불러서 확인해봅시다.

 

data # 데이터 확인

 

합쳐지기는 했는데 문제가 하나 발생했군요, class_x와 class_y라는 변수가 생겼습니다. 기존의 data에 class 변수가 있고, country_group에도 class 변수가 있다 보니, 컬럼 이름이 겹치는 바람에 판다스에서 자동적으로 변경시켜버렸습니다. 우리는 class_y를 국가명 대신 사용해줄 것이기 때문에 기존 native-country를 삭제하고 → class_y를 해당 이름(native-country)으로 바꾸고 → class_x를 class로 다시 변경해주겠습니다.

 

data.drop('native-country', axis=1, inplace=True) # 변수 제거
data = data.rename(columns= {'class_x': 'class', 'class_y': 'native-country'}) # 변수 이름 변환

 

여기서 컬럼 이름을 바꾸는데 rename( ) 함수를 사용했습니다. rename( ) 함수는 위에서 보시는 것처럼 변경할 대상(columns 혹은 index)을 지정해주시고 구체적인 변경 사항은 딕셔너리 형태로 매핑해주면 됩니다.

 

 

2. 전처리 : 결측치 처리 및 더미 변수 변환

결측치를 처리합시다. 먼저 결측치가 있는 변수들과 그 비율을 확인하겠습니다.

 

data.isna().mean() # 결측치 비율 확인

age               0.000000
workclass         0.057307
education-num     0.000000
marital-status    0.000000
occupation        0.057512
relationship      0.000000
race              0.000000
sex               0.000000
capital-gain      0.000000
capital-loss      0.000000
hours-per-week    0.000000
class             0.000000
native-country    0.017546
dtype: float64

 

총 3개의 변수에서 결측치가 보입니다. workclass와 occupation은 약 5%, native-country는 1.7% 정도입니다. 우선 native-country는 각 국가별 class의 평균값으로 대체한 상태입니다. 원래는 범주형 변수이기 때문에 평균치로 채우는 것이 불가능하지만 지금은 숫자로 바뀌었고 그 숫자가 마침 class의 평균값이기 때문에, mean( ) 이나 median( ) 으로 결측치를 채우는 것도 가능합니다. 또는 완전 별개의 숫자를 지정하여 채워주는 방법도 가능합니다. 보통 결측치를 숫자로 채워줄 때 -9나 -99와 같은 임의의 숫자를 사용합니다. 이렇게 임의의 숫자를 채워주는 것은 트리 기반 모델에서는 큰 문제가 없으나 선형 모델에서는 데이터의 왜곡을 불러오니 주의해야 합니다. 지금은 두 가지 방법 모두 가능한데, 여기에서는 -99를 채우겠습니다.

 

data['native-country'] = data['native-country'].fillna(-99) # 결측치를 -99로 대체

 

workclass와 occupation 변수는 모두 범주형 변수이기 때문에 평균치로 해결할 수가 없습니다. 이 경우는 특정 텍스트를 채워주거나, dropna( )로 해당 라인을 제거해야 하는데, 우선 각 컬럼의 value_counts( ) 출력물을 보고 판단하겠습니다.

 

data['workclass'].value_counts() # 고윳값별 출현 빈도 확인

Private             33906
Self-emp-not-inc     3862
Local-gov            3136
State-gov            1981
Self-emp-inc         1695
Federal-gov          1432
Without-pay            21
Never-worked           10
Name: workclass, dtype: int64

 

workclass에서는 ❶ Private 비율이 압도적입니다. 특정 값이 대부분을 차지하는 경우라면 해당 값으로 결측치를 채워주는 방법도 무난합니다. Private이 70% 정도라서 조금 아쉬운 부분은 있지만, 연습 차원에서 이 값으로 결측치를 채워넣겠습니다.

 

data['workclass'] = data['workclass'].fillna('Private')
# 결측치를 Private으로 대체

 

다음으로 occupation 컬럼을 확인하겠습니다.

 

data['occupation'].value_counts()

Prof-specialty       6172
Craft-repair         6112
Exec-managerial      6086
Adm-clerical         5611
Sales                5504
Other-service        4923
Machine-op-inspct    3022
Transport-moving     2355
Handlers-cleaners    2072
Farming-fishing      1490
Tech-support         1446
Protective-serv       983
Priv-house-serv       242
Armed-Forces           15
Name: occupation, dtype: int64

 

이번에는 어떤 특정값이 압도적으로 많다고 하기가 어렵습니다. 이런 경우에는 알맞지 않습니다. 별도의 텍스트 ‘Unknown’으로 채워보겠습니다.

 

data['occupation'] = data['occupation'].fillna('Unknown')
# 결측치를 Unknown으로 대체

 

이제 모든 결측치를 해결했으니, 범주형 데이터를 더미 변수로 변환하겠습니다.

 

data = pd.get_dummies(data, drop_first=True) # 더미 변수로 변환

 

3편은 모델링 및 평가, 그리고 결정 트리가 어떤 원리로 작동되는지 살펴봅시다.

권시현(데싸노트)

삼성전자에 마케팅 직군으로 입사하여 앱스토어 결제 데이터를 운영 및 관리했습니다. 데이터에 관심이 생겨 미국으로 유학을 떠나 지금은 모바일 서비스 업체 IDT에서 데이터 사이언티스트로 일합니다. 문과 출신이 미국 현지 데이터 사이언티스트가 되기까지 파이썬과 머신러닝을 배우며 많은 시행착오를 겪었습니다. 제가 겪었던 시행착오를 덜어드리고, 머신러닝에 대한 재미를 전달하고자 유튜버로 활동하고 책을 집필합니다.

현) IDT Corporation (미국 모바일 서비스 업체) 데이터 사이언티스트
전) 콜롬비아 대학교, Machine Learning Tutor, 대학원생 대상
전) 콜롬비아 대학교, Big Data Immersion Program Teaching Assistant
전) 콜롬비아 대학교, M.S. in Applied Analytics
전) 삼성전자 무선사업부, 스마트폰 데이터 분석가
전) 삼성전자 무선사업부, 모바일앱 스토어 데이터 관리 및 운영

강의 : 패스트캠퍼스 〈파이썬을 활용한 이커머스 데이터 분석 입문〉

SNS : www.youtube.com/c/데싸노트

Leave a Reply

©2020 GoldenRabbit. All rights reserved.
상호명 : 골든래빗 주식회사
(04051) 서울특별시 마포구 양화로 186, 5층 512호, 514호 (동교동, LC타워)
TEL : 0505-398-0505 / FAX : 0505-537-0505
대표이사 : 최현우
사업자등록번호 : 475-87-01581
통신판매업신고 : 2023-서울마포-2391호
master@goldenrabbit.co.kr
개인정보처리방침
배송/반품/환불/교환 안내