기본 콘텐츠로 건너뛰기

[ML] 결정트리(Decision Tree) 모델

Multiclass Classification

내용

이 글은 'Deep Learning with Python'의 3.5절의 내용입니다.

다중 그룹 분류

로이터 뉴스와이어를 46개의 상호 배타적인 주제로 분류하는 네트워크를 구축합니다. 클래스가 많기 때문에 이 문제는 다중 클래스 분류의 인스턴스입니다. 각 데이터 포인트는 하나의 범주로만 분류되어야 하기 때문에 문제는 보다 구체적으로 단일 레이블, 다중 클래스 분류의 인스턴스입니다. 각 데이터 포인트가 여러 범주(이 경우 주제)에 속할 수 있는 경우 다중 레이블, 다중 클래스 분류 문제에 직면하게 됩니다.

1986년에 Reuters에서 발행한 짧은 뉴스와 해당 주제의 집합인 Reuters 데이터 세트를 사용하여 작업할 것입니다. 이것은 텍스트 분류를 위해 널리 사용되는 간단하고 널리 사용되는 장난감 데이터 세트입니다. 46개의 다른 주제가 있습니다. 일부 주제는 다른 주제보다 더 많이 표시되지만 각 주제에는 교육 세트에 최소 10개의 예가 있습니다. IMDB 및 MNIST와 마찬가지로 Reuters 데이터 세트는 Keras의 일부로 패키지로 제공됩니다..

Reuters dataset

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.datasets import reuters
from tensorflow.keras import models, layers
(datr, latr),(date, late)=reuters.load_data(num_words=10000)
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/reuters.npz
2113536/2110848 [==============================] - 0s 0us/step
2121728/2110848 [==============================] - 0s 0us/step

num_words=10000 인수는 훈련 데이터에서 가장 자주 발생하는 상위 10,000개의 단어만 유지한다는 것을 의미합니다.

학습그룹과 검정 그룹의 데이터 수는 다음과 같습니다.

len(datr), len(date)
(8982, 2246)
print(datr[0])
[1, 2, 2, … 15, 17, 12]

위에서 보는 것과 같이 각 데이터는 정수로 코드화 되어 있습니다. 이들의 의미를 살펴보기 위해 다음과 같이 decode화 해 봅니다.

wordIndex=reuters.get_word_index()
reverseWordIndex=dict([(value, key) for (key, value) in wordIndex.items()])
decodeNews=' '.join([reverseWordIndex.get(i-1, '?') for i in datr[0]])
decodeNews
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/reuters_word_index.json
557056/550378 [==============================] - 0s 0us/step
565248/550378 [==============================] - 0s 0us/step
'? the the a not 3 move in by should 22 in rebates dollar 000 reuters four after about and may in on february said on some reuter after about revs that secretary at and which to but a right would sale 31 said end said been for reuter that earlier for reuter and which mln representation improved noted said domestic said high for reuter that under loss for reuter 000 a sources versus after about last with sale 2 was 12 said co reuter 1 vs'
latr[0]
3

데이터 준비

feature를 원-핫 인코딩 합니다.

def oneHotVector(da, dims=10000):
  result=np.zeros((len(da), dims))
  for i, sequence in enumerate(da):
    result[i, sequence]=1
  return(result)
xtr=oneHotVector(datr)
xte=oneHotVector(date)
xtr.shape
(8982, 10000)
laDim=len(np.unique(latr))
laDim
46
ytr=oneHotVector(latr, dims=laDim)
yte=oneHotVector(late, dims=laDim)
ytr[0]
array([0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

신경망 구축

Dense 레이어 스택에서 각 레이어는 이전 레이어의 출력에 있는 정보에만 액세스할 수 있습니다. 한 계층이 분류 문제와 관련된 일부 정보를 삭제하면 이 정보는 이후 계층에서 절대 복구할 수 없습니다.

이 자료는 feature를 46개의 클래스 중의 하나로 분류하는 것으로서 한 계층에서의 출력은 46개가 됩니다. 그러므로 설정하는 layer unit은 이 보다 큰 규모이어야 합니다. 여기서는 64 단위로 설정하였습니다.

model=models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation="relu"))
model.add(layers.Dense(46, activation='softmax'))

모든 입력 샘플에 대해 네트워크는 46차원 출력 벡터를 생성합니다. 여기서 output[i]는 샘플이 클래스 i에 속할 확률입니다. 46개 점수의 합은 1입니다.

이 경우에 사용하기에 가장 좋은 손실 함수는 categorical_crossentropy입니다. 이 함수는 두 확률 분포 사이의 거리를 측정합니다. 여기에서는 네트워크의 확률 분포 출력과 레이블의 실제 분포 사이입니다. 이 두 분포 사이의 거리를 최소화하여 실제 레이블에 가능한 한 가까운 것을 출력하도록 네트워크를 훈련시킵니다.

model.compile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])

학습과 검정 그리고 추정

학습 데이터 중의 1000개를 검정에 사용합니다.

xtr[:1000].shape
(1000, 10000)
xtr_val=xtr[:1000]
xtr_part=xtr[1000:]
ytr_val=ytr[:1000]
ytr_part=ytr[1000:]
list(map(lambda x: x.shape, [xtr_val, ytr_val, xtr_part, ytr_part]))
[(1000, 10000), (1000, 46), (7982, 10000), (7982, 46)]
hist=model.fit(xtr_part, ytr_part, epochs=20, batch_size=512, validation_data=(xtr_val, ytr_val))
Epoch 1/20
16/16 [==============================] - 1s 56ms/step - loss: 2.5102 - accuracy: 0.5036 - val_loss: 1.6760 - val_accuracy: 0.6640
…
Epoch 19/20
16/16 [==============================] - 1s 43ms/step - loss: 0.1158 - accuracy: 0.9560 - val_loss: 1.1234 - val_accuracy: 0.7950
Epoch 20/20
16/16 [==============================] - 1s 44ms/step - loss: 0.1155 - accuracy: 0.9567 - val_loss: 1.0559 - val_accuracy: 0.8090
hist.history.keys()
dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])
plt.figure(dpi=100)
epochs=range(1, 21)
plt.plot(epochs, hist.history['loss'], label='loss')
plt.plot(epochs, hist.history['val_loss'], label='val_loss', alpha=0.3)
plt.legend(loc='best', prop={'weight':'bold'})
plt.xlabel("Epoch", weight='bold') 
plt.ylabel("loss", weight='bold') 
plt.show()
plt.figure(dpi=100)
epochs=range(1, 21)
plt.plot(epochs, hist.history['accuracy'], label='accuracy')
plt.plot(epochs, hist.history['val_accuracy'], alpha=0.3, label='val_accuracy')
plt.legend(loc='best', prop={'weight':'bold'})
plt.xlabel("Epoch", weight='bold') 
plt.ylabel("accuracy", weight='bold') 
plt.show()

위 결과에 의하면 약 9 epoch 이후에 과적합이 시작됩니다. 그러므로 새롭게 학습한 모델을 구축하여 검정 데이터 셋에 적용합니다.

model=models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(64, activation="relu"))
model.add(layers.Dense(46, activation='softmax'))
model.compile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])
model.fit(xtr_part, ytr_part, epochs=9, batch_size=64, validation_data=(xtr_val, ytr_val))
result=model.evaluate(xte, yte)
Epoch 1/9
125/125 [==============================] - 2s 14ms/step - loss: 1.6471 - accuracy: 0.6490 - val_loss: 1.1359 - val_accuracy: 0.7440
…
Epoch 9/9
125/125 [==============================] - 2s 13ms/step - loss: 0.1552 - accuracy: 0.9565 - val_loss: 1.2883 - val_accuracy: 0.7870
71/71 [==============================] - 0s 3ms/step - loss: 1.4367 - accuracy: 0.7725
result
[1.4366565942764282, 0.7724844217300415]

위 reult는 검정 데이터 셋에 대한 정확도 입니다. 학습 데이터 셋에 대한 추정치와 실제 라벨값과의 정확도를 계산합니다.

latr
array([ 3,  4,  3, ..., 25,  3, 25])
 retr=model.predict(xtr)
retr
array([[8.9551882e-05, 1.8371086e-03, 5.7139728e-06, ..., 3.4539548e-07,
        1.4424126e-08, 1.9418226e-06],
        …
        [1.2145936e-05, 1.1056991e-06, 1.9900976e-09, ..., 5.8124328e-09,
        1.1078960e-11, 2.6042404e-05]], dtype=float32)
retrMax=np.argmax(retr, axis=1)
retrMax
array([ 3,  4,  3, ..., 25,  3, 25])
np.sum(np.equal(latr, retrMax))/len(latr)
0.94333110665776
#검정 데이터 셋에 대한 정확도 
rete=model.predict(xte)
reteMax=np.argmax(rete, axis=1)
np.sum(np.equal(reteMax, late)/len(late))
0.7724844167408726

댓글

이 블로그의 인기 게시물

[Linear Algebra] 유사변환(Similarity transformation)

유사변환(Similarity transformation) n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사행렬(similarity matrix)이 되며 행렬 A를 가역행렬 P와 B로 분해하는 것을 유사 변환(similarity transformation) 이라고 합니다. $$\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B $$ 식 2는 식 1의 양변에 B의 고유값을 고려한 것입니다. \begin{align}\tag{식 2} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align} 식 2의 행렬식은 식 3과 같이 정리됩니다. \begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \textsf{det}(I)\end{aligned}\end{align} 유사행렬의 특성 유사행렬인 두 정방행렬 A와 B는 'A ~ B' 와 같

[matplotlib] 히스토그램(Histogram)

히스토그램(Histogram) 히스토그램은 확률분포의 그래픽적인 표현이며 막대그래프의 종류입니다. 이 그래프가 확률분포와 관계가 있으므로 통계적 요소를 나타내기 위해 많이 사용됩니다. plt.hist(X, bins=10)함수를 사용합니다. x=np.random.randn(1000) plt.hist(x, 10) plt.show() 위 그래프의 y축은 각 구간에 해당하는 갯수이다. 빈도수 대신 확률밀도를 나타내기 위해서는 위 함수의 매개변수 normed=True로 조정하여 나타낼 수 있다. 또한 매개변수 bins의 인수를 숫자로 전달할 수 있지만 리스트 객체로 지정할 수 있다. 막대그래프의 경우와 마찬가지로 각 막대의 폭은 매개변수 width에 의해 조정된다. y=np.linspace(min(x)-1, max(x)+1, 10) y array([-4.48810153, -3.54351935, -2.59893717, -1.65435499, -0.70977282, 0.23480936, 1.17939154, 2.12397372, 3.0685559 , 4.01313807]) plt.hist(x, y, normed=True) plt.show()

R 미분과 적분

내용 expression 미분 2차 미분 mosaic를 사용한 미분 적분 미분과 적분 R에서의 미분과 적분 함수는 expression()함수에 의해 생성된 표현식을 대상으로 합니다. expression expression(문자, 또는 식) 이 표현식의 평가는 eval() 함수에 의해 실행됩니다. > ex1<-expression(1+0:9) > ex1 expression(1 + 0:9) > eval(ex1) [1] 1 2 3 4 5 6 7 8 9 10 > ex2<-expression(u, 2, u+0:9) > ex2 expression(u, 2, u + 0:9) > ex2[1] expression(u) > ex2[2] expression(2) > ex2[3] expression(u + 0:9) > u<-0.9 > eval(ex2[3]) [1] 0.9 1.9 2.9 3.9 4.9 5.9 6.9 7.9 8.9 9.9 미분 D(표현식, 미분 변수) 함수로 미분을 실행합니다. 이 함수의 표현식은 expression() 함수로 생성된 객체이며 미분 변수는 다음 식의 분모의 변수를 의미합니다. $$\frac{d}{d \text{변수}}\text{표현식}$$ 이 함수는 어떤 함수의 미분의 결과를 표현식으로 반환합니다. > D(expression(2*x^3), "x") 2 * (3 * x^2) > eq<-expression(log(x)) > eq expression(log(x)) > D(eq, "x") 1/x > eq2<-expression(a/(1+b*exp(-d*x))); eq2 expression(a/(1 + b * exp(-d * x))) > D(eq2, "x") a * (b * (exp(-d * x) * d))/(1 + b