티스토리 뷰

Study/AI

[DL] 해보면서 배우는 딥러닝 - ANN 구현 (1)

생각많은 소심남 2017. 4. 23. 14:29

* 여기에 담긴 내용은 Udemy에서 진행되는 DeepLearning A-Z(https://www.udemy.com/deeplearning)의 일부를 발췌했습니다.

 나도 딥러닝이라는 것을 잘 모르는 상태에서 뭔가를 해보려는데 마침 간단한 python 예제(?)가 있어 같이 코드를 보면서 진행해보고자 한다. 우선 학습의 목적은 고객 정보가 담긴 Dataset을 분석해 성향을 분석하는 일종의 Churn Modeling이 되겠다.

우선 spyder를 실행하고 필요한 Library를 불러온다. 일단 수치연산을 위한 numpy와 pandas, 시각화를 위한 matplotlib을 가져온다.

1
2
3
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
cs

그 후에 Dataset을 읽어와서 특정변수에 저장한다. 여기서는 그대로 dataset라고 이름짓고 아래의 csv 파일을 읽어온다.

Churn_Modelling.csv

1
2
3
4
5
6
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
 
# Importing the dataset
dataset = pd.read_csv('Churn_Modelling.csv')
cs

여기까지 왔으면 spyder의 Variable Explorer 창으로 Dataset이 있는 것을 볼 수 있다. 이걸 확인하면 시각화까지 해준다. 잠깐 데이터를 살펴보면 다양한 변수들이 들어가 있다.

 많은 변수들이 있지만, 잘보면 변수 중에도 우리가 학습을 시켜줘야 할 변수가 있고, 학습에 전혀 상관이 없는 변수들도 존재한다. Data Scientist라면 그런 변수를 구분해는 역할을 수행해줘야 한다. 일단 간단히 봤을때 RowNumber나 CustomerId, Surname 같은 경우는 학습에 전혀 상관없는 변수들이다. 그도 그럴 것이 여기에 저장되어 있는 값은 어떤 결과를 통해서, 혹은 어떤 결과를 구하기 위한 인자로 들어가는 요소가 아니기 때문이다. 이와 반대로 CreditScore나 Geography, Gender, 나이, 정년 같은 항목은 고객 성향 분석을 위한 요소로 작용할 수 있기 때문에 이를 학습시킬 변수로 선정할 수 있다. 마지막으로 마지막 열에 있는 Exited가 바로 우리가 학습한 결과와 비교할 대조군이다. 아마 기계 학습을 공부한 사람이라면 알겠지만, 이런 기계 학습의 목적은 예측 결과와 실제 값간의 차이를 최소화하는 것이다. 다르게 표현하면 Cost Function을 Minimize한다고 할 수 있는데, 위의 Exited의 결과와 우리가 학습을 통해 얻어낸 예측값간의 오차를 측정하고 이를 반영할 것이다. 

 아무튼 위의 Dataset에서 우리가 입력으로 활용할 변수들은 python array index 규칙에 따르면 3열(CreditScore)부터 12열(EstimatedSalary)까지가 될 것이고, 우리가 비교할 실제값은 13열이 될 것이다. 

1
2
3
4
5
6
7
8
9
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
 
# Importing the dataset
dataset = pd.read_csv('Churn_Modelling.csv')
= dataset.iloc[:, 3:13].values
= dataset.iloc[:, 13].values
                
cs

이렇게 하면 spyder의 Variable 창으로 해당 항목들이 mapping되는 것을 볼 수 있다. 그런데 여기서 X array에 저장된 데이터를 살펴보자

우리가 학습 시켜야할 데이터들이 하나의 2차원 배열로 저장되어 있는 것은 확인했는데, 값이 제각각이다. 어떤 건 0~1000사이의 점수가 들어가 있고, 어떤건 문자로 표시되어 있고... 어떤건 그냥 True or False만을 나타내는 Binary형태로 되어 있다. 컴퓨터도 만능이 아닌 이상 이 값들을 잘 정리해주고, 계산에 용이하게끔 Dataset을 재정의해줘야 한다. 우선은 문자열을 그대로 학습시킬 수 없으니 이 데이터를 정리하기 해본다. 잘 보면 우리가 학습시키려 하는 고객의 성향을 분석하는 것이다. 즉, 이 사람이 어디 사는지가 궁금한게 아니라 어디 사는 사람의 성향은 어떤거다 라는 것을 도출해내는 것이 목적이라는 것이다. 다시 말해 어디 산다는 개념은 고객을 구분짓기 위한 요소일뿐 그게 결과물이 아니라는 뜻이다. 보통 이런 성향을 가진 변수들을 Categorical(분류할수 있는) Variable라고 하는데, 당연히 이를 수학적으로 변환해주는 과정이 필요하다. 마찬가지고 바로 뒤에 나와있는 성별도 그런 맥락에서는 Categorical Variable이라고 할 수 있다. 가령 France는 0, Spain은 1, France는 2 이런식으로 말이다. 여기서는 이런 과정 자체를 Encoding/Decoding이라고 표현했고, python에서는 scikit library에서 이런 과정을 해주는 함수를 제공한다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
 
# Importing the dataset
dataset = pd.read_csv('Churn_Modelling.csv')
= dataset.iloc[:, 3:13].values
= dataset.iloc[:, 13].values
 
# Encodeing Categorical data
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X_1 = LabelEncoder()
X[:, 1= labelencoder_X_1.fit_transform(X[:, 1])
labelencoder_X_2 = LabelEncoder()
X[:, 2= labelencoder_X_2.fit_transform(X[:, 2])               
cs

이렇게 하면 X가 앞에서와 같은 문자열이 아닌 정수형태로 저장된 것을 확인할 수 있다.

그런데 사실 이게 끝이 아니다. 엄밀히 말해서는 Categorical Variable도 Binary 형태로 바꿔줘야 이 Encoding의 의미가 존재한다. 예를 들어 위와 같이 France = 0, Germany = 1, Spain = 2 라고 표시되어 있는 것도 우리가 학습해야 될 데이터는 이 값 자체가 아니기 때문에 isFrance? , isGermany? , isSpain? 의 변수형태로 바꿔 표시를 해줘야한다. 보통 이런 걸 Dummy variable을 삽입해준다고 말하는데, 말은 거창하게 했어도 역시 python에서는 이를 한번에 처리해주는 함수(OneHotEncoder)를 제공한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
 
# Importing the dataset
dataset = pd.read_csv('Churn_Modelling.csv')
= dataset.iloc[:, 3:13].values
= dataset.iloc[:, 13].values
                
# Encodeing Categorical data
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X_1 = LabelEncoder()
X[:, 1= labelencoder_X_1.fit_transform(X[:, 1])
labelencoder_X_2 = LabelEncoder()
X[:, 2= labelencoder_X_2.fit_transform(X[:, 2])
onehotencoder = OneHotEncoder(categorical_features=[1])
= onehotencoder.fit_transform(X).toarray()            
cs

이렇게 바꾸고 난후 Variable Explorer 상의 X를 살펴보면 Geological로 표시된 문자열이 3열의 Binary array로 변환된 것을 확인할 수 있다.

 여기서 한가지 더 말하고 싶은 내용이 있다. 지금 보면 Geological 을 설명하는데 있어 Category가 총 3개 있는 것을 확인했다. 그런데 과연 앞에서 말한 것처럼 모든 변수에 대해서 isFrance? isGermany? isSpain?을 다 물어볼 필요가 있을까? 가령 isGermany?도 0이고, isSpain?도 0이면 isFrance? 는 굳이 질문을 하지 않아도 1임을 알수 있다. 이처럼 아무리 Categorical Variable을 Binary 형태로 다 바꿔줄 필요가 없다는 것이다. 이럴 때는 보통 첫번째 열을 빼주는 작업을 한다. 이는 찾아보니까 보통 Dummy Variable Trap을 방지하지 위함이라고 표현을 하는 거 같은데, 큰 맥락에서는 모든 변수를 다 표현할 필요없이 하나의 변수를 다른 변수들로 대체함으로써 연산을 조금이나마 줄일 수 있다는 것으로 생각하면 좋을거 같다. 그래서 이런 Encoding의 마지막 과정이 첫째 열을 삭제하는 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
 
# Importing the dataset
dataset = pd.read_csv('Churn_Modelling.csv')
= dataset.iloc[:, 3:13].values
= dataset.iloc[:, 13].values
                
# Encodeing Categorical data
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X_1 = LabelEncoder()
X[:, 1= labelencoder_X_1.fit_transform(X[:, 1])
labelencoder_X_2 = LabelEncoder()
X[:, 2= labelencoder_X_2.fit_transform(X[:, 2])
onehotencoder = OneHotEncoder(categorical_features=[1])
= onehotencoder.fit_transform(X).toarray()
 
# To avoid Dummy variable Trap
= X[:, 1:]
cs

여기까지가 Dataset 생성이었고, 이제 학습을 시키기 위해서는 Training set과 Test set을 나누는 작업을 해야 한다. 이것 역시 scikit에서 제공한다. 일단 우리는 전체 Dataset에서 Training set과 Test set의 비중을 8:2로 구분하고, 이를 test_size라는 인자에 값으로 반영했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
 
# Importing the dataset
dataset = pd.read_csv('Churn_Modelling.csv')
= dataset.iloc[:, 3:13].values
= dataset.iloc[:, 13].values
                
# Encodeing Categorical data
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X_1 = LabelEncoder()
X[:, 1= labelencoder_X_1.fit_transform(X[:, 1])
labelencoder_X_2 = LabelEncoder()
X[:, 2= labelencoder_X_2.fit_transform(X[:, 2])
onehotencoder = OneHotEncoder(categorical_features=[1])
= onehotencoder.fit_transform(X).toarray()
 
# To avoid Dummy variable Trap
= X[:, 1:]
                
# Spitting the dataset into the Training set and Test set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state=0)
cs

이렇게 하면 training_set = 8000개 test_set = 2000개로 나눠진 dataset이 생성된다.

마지막으로 앞에서 잠깐 소개했는데, 지금 출력되고 있는 값의 단위가 제각기 다르다. 어떤 0~1000 사이의 값이고, 어떤 수십만 단위를 표현하는데, 이를 효과적으로 학습시키기 위해서는 모든 변수들의 단위를 정규화해줘야 한다. 아마 확률과 분포 수업을 들었다면 정규분포에 대한 이야기를 들었을 거고, 그 원리는 평균이 0이고, 각각의 값은 상대적으로 표현하는 것이라고 알고 있을 것이다. 보통은 Feature Scaling이라고 하는데, 역시 scikit에서 해당 기능도 제공한다.

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
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
 
# Importing the dataset
dataset = pd.read_csv('Churn_Modelling.csv')
= dataset.iloc[:, 3:13].values
= dataset.iloc[:, 13].values
                
# Encodeing Categorical data
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X_1 = LabelEncoder()
X[:, 1= labelencoder_X_1.fit_transform(X[:, 1])
labelencoder_X_2 = LabelEncoder()
X[:, 2= labelencoder_X_2.fit_transform(X[:, 2])
onehotencoder = OneHotEncoder(categorical_features=[1])
= onehotencoder.fit_transform(X).toarray()
 
# To avoid Dummy variable Trap
= X[:, 1:]
                
# Spitting the dataset into the Training set and Test set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state=0)
 
# Feature Scaling
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
cs

여기까지가 학습을 위한 training set과 test set을 생성하는 과정이었다. 

다음 포스트에서 본격적인 ANN 구현이 진행될 예정이다.


( 여기까지 한 내용은 파일로 전달해드립니다. )

ann_part1.py

댓글