본문 바로가기

Study/class note

머신러닝 / 파이썬으로 의사결정트리 모델 만들기

ㅇ복습

1. R문법과 판다스 비교

2. 머신러닝을 배우기 위해 필요한 문법

3. KNN (이론 : 유클리드 거리 공식, R구현, 파이썬 구현)

4. 나이브베이즈(이론 : 나이브베이즈 확률, R구현, 파이썬 구현)

5. 의사결정트리(이론 : 정보획득량(엔트로피) , R구현, 파이썬 구현)

    > 데이터 : 화장품 고객데이터 , 독일은행 데이터, iris 데이터

 

ㅇ의사결정트리 모델의 불순도 평가방법 3가지

1. 엔트로피(p202)

2. 지니계수

3. 카이제곱 검정

- 파이썬으로 의사결정트리 모델 생성하는 코드

#python
from  sklearn.tree  import   DecisionTreeClassifier

model = DecisionTreeClassifier( criterion='entropy',  max_depth=5)

criterion 에 사용할 수 있는 2가지 수학공식

> 엔트로피 (criterion='entropy')

> 지니계수 (criterion='gini')

 

메뉴얼 : https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html

 

1. 엔트로피

엔드로피(불순도)가 낮을수록 순도가 높아짐.

 

2. 지니계수

지니계수가 낮을수록 순도가 높아짐.

 

 

49 파이썬으로 의사결정트리 모델 만들기

실험 데이터 : 독버섯 데이터, 독일은행, iris

 

ㅇ독버섯 데이터를 파이썬으로 이용해서 의사결정 모델 만들기

# 1. 데이터 로드

# 2. 결측치 확인

# 3. 문자 데이터를 숫자로 변경

# 4. 훈련 데이터와 테스트 데이터 분리

# 5. 훈련 데이터 정규화

# 6. 의사결정트리 모델 생성

# 7. 모델 훈련

# 8. 훈련된 모델로 테스트 데이터 예측

# 9. 모델 평가

# 10. 모델 성능 개선

 

# 1. 데이터 로드
import pandas as pd

mush = pd.read_csv("c:\\data\\mushrooms.csv")
mush.shape  #(8124, 23)
mush.head()

type이 label이 되는 정답컬럼

# 2. 결측치 확인
mush.isnull().sum()  #결측치 없음 확인

# 3. 문자 데이터를 숫자로 변경(R은 문자데이터 그대로 사용 가능)
mush2 = pd.get_dummies(mush.iloc[:,1:]) # label(type컬럼) 제외하고 데이터 넣어야함
mush2.shape #(8124, 117)

x = mush2  #학습시킬 데이터 구성
y = mush['type']  #정답컬럼 구성

# 4. 훈련 데이터와 테스트 데이터 분리
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 = 1)

print(x_train.shape)  #(6499, 117)
print(x_test.shape)  #(1625, 117)
print(y_train.shape)  #(6499,)
print(y_test.shape)  #(1625,)

# 5. 훈련 데이터 정규화
# 위에서 0과1로 데이터를 변경했기 때문에 정규화 작업 불필요

# 6. 의사결정트리 모델 생성
from sklearn.tree import DecisionTreeClassifier

model = DecisionTreeClassifier(criterion = 'entropy', max_depth = 5)

정보획득량을 구하는 기준 criterion은 entropy, gini 2가지가 있는데 지금은 entropy를 사용하겠음. 

max_depth는 가지의 깊이를 나타냄. 가지의 깊이가 너무 깊으면 훈련 데이터의 정확도는 높은데 테스트 데이터의 정확도가 떨어지는 과대적합 현상이 발생함.

# 7. 모델 훈련
model.fit(x_train, y_train)

# 8. 훈련된 모델로 테스트 데이터 예측
result = model.predict(x_test)
result

# 9. 모델 평가
sum(result == y_test) / len(y_test) * 100   # 100%

from sklearn.metrics import confusion_matrix

a = confusion_matrix(y_test, result)
print(a)

[[820   0]
 [  0 805]]  > 정확도 100% 

> 나이브 베이즈때는 FN이 1개가 나왔음. 그런데 의사결정트리는 FN이 0이고 정확도도 100%임

 

문제274. 이번에는 불순도를 계산하는 기준을 entropy말고 gini로 실행하시오.

# 6. 의사결정트리 모델 생성
from sklearn.tree import DecisionTreeClassifier

model_gini = DecisionTreeClassifier(criterion = 'gini', max_depth = 5)

# 7. 모델 훈련
model_gini.fit(x_train, y_train)

# 8. 훈련된 모델로 테스트 데이터 예측
result_gini = model_gini.predict(x_test)
result_gini 

# 9. 모델 평가
sum(result_gini  == y_test) / len(y_test) * 100    # 99.87692307692308 %

from sklearn.metrics import confusion_matrix

a = confusion_matrix(y_test, result_gini)
print(a)

[[820   0]
 [  2 803]] 

> gini는 entropy와 달리 FN이 2로 증가함. 그러면서 정확도도 떨어짐.

> 실험결과 gini는 max_dept를 7 정도 주면 그때부터 정확도 100%의 모델이 나옴.

(cf. max_dept를 지정하지 않으면 기계가 알아서 순수도가 높아질때까지 가지를 치는데 그렇게되면 과대적합이 일어날 수 있으므로 사람이 과대적합이 발생하지 않도록 적절한 값을 지정해줘야함, max_depth의 default는 None)

 

R에서는 trials 파라미터로 의사결정트리 나무의 갯수를 늘려서 성능을 높였는데 파이썬에서 model = DecisionTreeClassifier(criterion= 'gini', max_depth = 5)에는 trials가 없고 RandomForest를 사용해야 R에서와 같은 trials기능을 사용할 수 있음. 랜덤포레스트는 뒤에서 다룰 예정

 

 

ㅇ독일은행 데이터를 파이썬으로 이용해서 의사결정 모델 만들기

R에서 훈련 데이터의 정확도를 91.88889%까지 올렸고, 테스트 데이터의 정확도는 73%까지 올렸음. FN은 21개까지 줄임.

# 1. 데이터 로드
import pandas as pd

credit = pd.read_csv("c:\\data\\credit.csv")
credit.shape #(1000, 17)
credit.head()

# 2. 결측치 확인
credit.isnull().sum()  #결측치 없음 확인

# 3. 문자 데이터를 숫자로 변경
# credit.info()  # 데이터가 문자, 숫자 섞여있음

credit2 = pd.get_dummies(credit.iloc[:,:-1])  # default컬럼이 label, 숫자데이터는 그대로 문자데이터만 숫자로 변경
credit2.shape #(1000, 44)로 늘어남

x = credit2  # 훈련시킬 데이터
y = credit['default']  # 정답 데이터

# 4. 훈련 데이터와 테스트 데이터 분리
from sklearn.model_selection import train_test_split

x_train,x_test,y_train,y_test = train_test_split(x,y, test_size=0.1, random_state = 1)

print(x_train.shape)  #(900, 44)
print(x_test.shape)  #(100, 44)
print(y_train.shape)  #(900,)
print(y_test.shape)  #(100,)


# 5. 훈련 데이터 정규화
# 숫자형 데이터는 단위가 다르므로 모두 정규화작업을 진행해야함
from sklearn.preprocessing import MinMaxScaler # 0~1 사이의 데이터로 정규화

scaler = MinMaxScaler()
scaler.fit(x_train) # 훈련데이터로 Min/Max 정규화 계산

x_train2 = scaler.transform(x_train) # 계산된 내용으로 훈련 데이터를 변경
x_test2 = scaler.transform(x_test) # 계산된 내용으로 테스트 데이터 변경

print(x_train2.max(), x_train2.min())  #1.0 0.0
print(x_test2.max(), x_test2.min())  #1.2142857142857142 0.0

> 테스트 데이터는 최대값이 1이 아님. scaler를 따로 x_test데이터로 훈련시켜서 적용시키면 최대값 1은 맞출 수 있지만 굳이 그럴 필요도 없을 뿐더러 나중에 정확도가 더 떨어짐. 어차피 모델들이 훈련데이터로 학습하기 때문에 훈련데이터에 맞추면 될 듯.

# 6. 의사결정트리 모델 생성
from sklearn.tree import DecisionTreeClassifier

model = DecisionTreeClassifier(criterion = 'entropy', max_depth = 5)

# 7. 모델 훈련
model.fit(x_train2, y_train)

#훈련데이터로 모델 연습 해봄
train_result = model.predict(x_train2)
print(sum(train_result  == y_train) / len(y_train) * 100)   # 77.0%  정확도

# 8. 훈련된 모델로 테스트 데이터 예측
result = model.predict(x_test2)
result

# 9. 모델 평가
print(sum(result == y_test) / len(y_test) * 100)   # 76.0%  정확도

> 훈련데이터의 정확도 R에서는 91.8%였는데 파이썬은 77%, 테스트 데이터의 정확도가 R에서는 73%였는데 파이썬은 76%까지 출력됨.

from sklearn.metrics import confusion_matrix

a = confusion_matrix(y_test, result)
print(a)

[[58 12]
 [12 18]] > FN값이 12개로 출력되고 있음.

 

 

문제275. (점심시간 문제) 위의 머신러닝 의사결정트리 모델의 성능이 조금 더 올라갈 수 있는지 max_depth를 조정해서 실험하시오.

max_depth = 5

훈련 데이터의 정확도 : 77%

테스트 데이터의 정확도 : 76%

FN값 : 12개

# 10. 모델 성능 개선
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import confusion_matrix
import pandas as pd

df_model = []
for i in range(5,31):
    model_test = []
    model = DecisionTreeClassifier(criterion = 'entropy', max_depth = i,random_state = 1)

    model.fit(x_train2, y_train)

    train_result = model.predict(x_train2)
    train_pct = sum(train_result  == y_train) / len(y_train) * 100   # 77.0%  정확도

    result = model.predict(x_test2)

    test_pct = sum(result == y_test) / len(y_test) * 100   # 76.0%  정확도

    a = confusion_matrix(y_test, result)
    FN = a[1,0]
    
    model_test.append(i)
    model_test.append(round(train_pct,2))
    model_test.append(round(test_pct,2))
    model_test.append(FN)
    
    df_model.append(model_test)

df = pd.DataFrame(df_model)
df.columns = ['max_depth','train_pct','test_pct','FN']
df

>훈련과 테스트 데이터의 정확도 차이가 크면 오버피팅(과적합). 훈련과 테스트 데이터의 정확도가 적정한 것을 찾아야함.

> 오버피팅이 적으면서 FN값이 작은 max_depth를 정하면 됨.

> 어느 자리에서든지 동일한 결과로 출력되게끔 하려면,

훈련데이터와 테스트 데이터 나눌때, 모델 생성할 때 random_state를 설정해줘야함.

 

 

ㅇ iris데이터를 파이썬으로 이용해서 의사결정 모델 만들기

# 1. 데이터 로드
import pandas as pd

iris = pd.read_csv("c:\\data\\iris2.csv")
iris.head()  # Sepal.Length,Sepal.Width,Petal.Length,Petal.Width,Species
iris.shape  #(150, 5)

# 2. 결측치 확인
iris.isnull().sum()  # 결측치 없음

# 3. 문자 데이터를 숫자로 변경
iris.info()  # 문자데이터 없음
 
x = iris.iloc[:,:-1]  # 학습데이터
y = iris.iloc[:,-1]  # 정답데이터  Sepcies 컬럼

# 4. 훈련 데이터와 테스트 데이터 분리
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x,y,test_size = 0.1, random_state = 1)

print(x_train.shape)  #(135, 4)
print(x_test.shape)  #(15, 4)
print(y_train.shape)  #(135,)
print(y_test.shape)  #(15,)

# 5. 훈련 데이터 정규화
# 숫자데이터의 단위들이 모두 다르기때문에 정규화과정 필요
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()  # 정규화 모델 생성
scaler.fit(x_train)  # 훈련 데이터로 계산

x_train2 = scaler.transform(x_train)  # 계산된 값으로 훈련 데이터 변경해서 변수에 담음
x_test2 = scaler.transform(x_test)

print(x_train2.max(), x_train2.min())   #1.0 0.0
print(x_test2.max(),x_test2.min())   #1.0588235294117647 0.033898305084745756

# 6. 의사결정트리 모델 생성
from sklearn.tree import DecisionTreeClassifier

model = DecisionTreeClassifier(criterion = 'entropy', max_depth = 5, random_state = 1)

# 7. 모델 훈련
model.fit(x_train2, y_train)

# 8. 훈련된 모델로 테스트 데이터 예측
train_result = model.predict(x_train2)
test_result = model.predict(x_test2)

# 9. 모델 평가
print(sum(train_result == y_train) / len(y_train) * 100)  # 100% 정확도
print(sum(test_result == y_test ) / len(y_test) * 100)  # 100% 정확도

# 10. 모델 성능 개선
# 11. 모델 시각화
from sklearn.tree import plot_tree   #의사결정트리를 그리는 모듈
from sklearn import tree   #의사결정트리 모듈
import matplotlib.pyplot as plt 

plt.figure(figsize = (12,12))
tree.plot_tree(model, filled = True, rounded = True)  #filled = True하면 색깔이 표시됨
                                                      #rounded = True는 반올림
#plt.savefig('c:\\data\\tree_visualization.jpg')  #저장
plt.show()

문제276. (빅데이터 실기시험 3유형) 아래의 wine데이터를 분류하는 분류모델을 생성하고 테스트 데이터의 정확도를 확인하시오. (훈련데이터와 테스트 데이터는 9:1)

데이터 : wine.csv

# 1. 데이터 로드
import pandas as pd

wine = pd.read_csv("c:\\data\\wine.csv")
wine.shape  #(178, 14)
wine.head() #Type컬럼이 label

# 2. 결측치 확인
wine.isnull().sum()  #결측치 없음

# 3. 문자 데이터를 숫자로 변경
# 문자 데이터 없음
x = wine.iloc[:,1:]
y = wine.iloc[:,0]

# 4. 훈련 데이터와 테스트 데이터 분리
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x,y,test_size = 0.1, random_state = 1)

# 5. 훈련 데이터 정규화
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
scaler.fit(x_train)

x_train2 = scaler.transform(x_train)
x_test2 = scaler.transform(x_test)

print(x_train2.min(), x_train2.max())  #0.0 1.0000000000000002
print(x_test2.min(), x_test2.max())  #-0.0326530612244898 0.9051355206847361

# 6. 의사결정트리 모델 생성 
from sklearn.tree import DecisionTreeClassifier

model_wine = DecisionTreeClassifier(criterion = 'entropy', max_depth = 5, random_state = 1)
model_wine

# 7. 모델 훈련
model_wine.fit(x_train2, y_train)

# 8. 훈련된 모델로 테스트 데이터 예측
result_train = model_wine.predict(x_train2)
result_test = model_wine.predict(x_test2)

# 9. 모델 평가
print(sum(result_train == y_train)/len(y_train) * 100)  #100.0
print(sum(result_test == y_test)/len(y_test) * 100)  #88.88888888888889

from sklearn.metrics import confusion_matrix
cross = confusion_matrix(y_test, result_test)
cross

# 10. 모델 성능 개선
for i in range(1,30):
    model_wine = DecisionTreeClassifier(criterion = 'entropy', max_depth = i, random_state = 1)
    
    model_wine.fit(x_train2, y_train)
    
    result_train = model_wine.predict(x_train2)
    result_test = model_wine.predict(x_test2)
    
    train_pct = sum(result_train == y_train)/len(y_train) * 100
    test_pct = sum(result_test == y_test)/len(y_test) * 100
    print('i = %d ---> train_pct : %s%%, test_pct : %s%%'%(i,train_pct, test_pct))

> max_depth가 2일때 테스트 데이터의 정확도 94.44% 모델이 가장 적합해 보임.

> 파이썬의 의사결정트리는 R의 의사결정트리처럼 여러개의 의사결정트리를 만들 수 있는 trials가 없음. 그래서 R에서처럼 의사결정트리를 여러개로 만들어서 샘플 데이터로 훈련하여 정답을 voting(다수결)로 구현하려면 RandomForest를 쓰면 됨.

 

문제277. 위의 wine데이터를 분류하는 모델을 RandomForest(의사결정트리 + 앙상블)로 구현

> 의사결정트리 모델

from sklearn.tree import DecisionTreeClassifier

model_wine = DecisionTreeClassifier(criterion = 'entropy', max_depth = 5, random_state = 1)

> 랜덤포레스트 모델

# 랜덤포레스트
from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(n_estimators = 5, random_state = 1)

model.fit(x_train2, y_train)

result_train = model.predict(x_train2)
result_test = model.predict(x_test2)

print(sum(result_train == y_train)/len(y_train) * 100)  #100.0
print(sum(result_test == y_test)/len(y_test) * 100)  #100.0

+) 전체 코드

# 1. 데이터 로드
import pandas as pd

wine = pd.read_csv("c:\\data\\wine.csv")
wine.shape  #(178, 14)
wine.head() #Type컬럼이 label

# 2. 결측치 확인
wine.isnull().sum()  #결측치 없음

# 3. 문자 데이터를 숫자로 변경
# 문자 데이터 없음
x = wine.iloc[:,1:]
y = wine.iloc[:,0]

# 4. 훈련 데이터와 테스트 데이터 분리
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x,y,test_size = 0.1, random_state = 1)

# 5. 훈련 데이터 정규화
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
scaler.fit(x_train)

x_train2 = scaler.transform(x_train)
x_test2 = scaler.transform(x_test)

# print(x_train2.min(), x_train2.max())  #0.0 1.0000000000000002
# print(x_test2.min(), x_test2.max())  #-0.0326530612244898 0.9051355206847361

# 6. 의사결정트리 모델 생성 
from sklearn.tree import DecisionTreeClassifier

model_wine = DecisionTreeClassifier(criterion = 'entropy', max_depth = 5, random_state = 1)
model_wine

# 7. 모델 훈련
model_wine.fit(x_train2, y_train)

# 8. 훈련된 모델로 테스트 데이터 예측
result_train = model_wine.predict(x_train2)
result_test = model_wine.predict(x_test2)

# 9. 모델 평가
train_pct = sum(result_train == y_train)/len(y_train) * 100
test_pct = sum(result_test == y_test)/len(y_test) * 100
print(train_pct, test_pct)

# from sklearn.metrics import confusion_matrix
# cross = confusion_matrix(y_test, result_test)
# cross

# # 10. 모델 성능 개선
# 랜덤포레스트
from sklearn.ensemble import RandomForestClassifier

model_rd = RandomForestClassifier(n_estimators = 5, random_state = 1)

model_rd.fit(x_train2, y_train)

result_train = model_rd.predict(x_train2)
result_test = model_rd.predict(x_test2)

train_pct_rd = sum(result_train == y_train)/len(y_train) * 100
test_pct_rd = sum(result_test == y_test)/len(y_test) * 100
print(train_pct_rd, test_pct_rd)

 

반응형