기본 콘텐츠로 건너뛰기

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

torch

내용

import tensorflow as tf
from tensorflow import keras
import numpy as np
import pandas as pd
from scipy import stats
from sklearn import preprocessing
import matplotlib.pyplot as plt

텐서(Tensor)

텐서란?

텐서는 숫자로 구성된 데이터의 컨테이너입니다. 즉, 숫자를 담는 그릇입니다. 가장 많이 접할 수 있는 2D 텐서인 행렬이 텐서의 예입니다. 결과적으로 텐서는 행렬을 임의의 수의 차원으로 일반화한 것으로 텐서의 맥락에서 차원(dimension)은 종종 축(axis)이라고 할 수 있습니다.

tensorflow에서 텐서는 tf.constant() 함수에 의해 생성됩니다. 생성된 텐서의 값은 동일한 객체에서 변경, 수정 될 수 없습니다.

생성된 텐서의 타입은 tf.dtypes.DType에서 확인 할 수 있습니다.

  • 스칼라는 0차원 텐서이므로 축은 없습니다.(rank 0)
  • 벡터는 1차원 텐서로서 1개의 축을 가집니다.(rank 1)
  • 행렬은 2차원 텐서이며 2개 축을 가집니다.(rank 2)
  • 3차원 텐서는 3개의 축을 가집니다.(rank 3)
  • 계속 확장할 수 있습니다.
rank0=tf.constant(4)
rank0
<tf.Tensor: shape=(), dtype=int32, numpy=4 >
rank1=tf.constant([2,3])
rank1
<tf.Tensor: shape=(2,), dtype=int32, numpy=array([2, 3], dtype=int32) >
rank2=tf.constant([[1,2],[3,4],[5,6]])
rank2
<tf.Tensor: shape=(3, 2), dtype=int32, numpy=
    array([[1, 2],
           [3, 4],
           [5, 6]], dtype=int32) >
rank3 = tf.constant([[[0, 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]],])
rank3
<tf.Tensor: shape=(3, 2, 5), dtype=int32, numpy=
    array([[[ 0,  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]]], dtype=int32) >

주요속성

축(axis)
텐서의 특정 차원
축 수(순위, rank)
예를 들어 3D 텐서에는 3개의 축이 있고 행렬에는 2개의 축이 있습니다.
tf.rank() 속성으로 확인
모양(shape)
텐서가 각 축을 따라 얼마나 많은 차원을 가지고 있는지를 설명하는 정수 튜플입니다.
shape 속성으로 확인
데이터 유형(일반적으로 Python 라이브러리에서는 dtype이라고 함)
텐서에 포함된 데이터 유형입니다.
float32 , uint8, float64 등이 될 수 있습니다. 드문 경우지만 char 텐서를 볼 수 있습니다.
문자열 텐서는 Numpy(또는 대부분의 다른 라이브러리)에 존재하지 않습니다. 왜냐하면 텐서는 사전 할당된 연속 메모리 세그먼트에 존재하는 것으로 문자열은 가변 길이이므로 메모리 할당을 사전에 지정할 수 없으므로 이 구현을 사용할 수 없습니다.
데이터 총수
tf.size()로 확인 할 수 있습니다.
a=tf.zeros([2,2,5,5])
a
<tf.Tensor: shape=(2, 2, 5, 5), dtype=float32, numpy=
    array([[[[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., 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., 0.],
             [0., 0., 0., 0., 0.],
             [0., 0., 0., 0., 0.],
             [0., 0., 0., 0., 0.]]]], dtype=float32) >
pd.DataFrame([a.dtype, tf.rank(a).numpy(), a.shape, tf.size(a).numpy()],index=['type','rank','shape','total'])
0
type <dtype: 'float32'>
rank 4
shape (2, 2, 5, 5)
total 100

텐서 a는 다음 그림과 같이 나타낼 수 있습니다.

텐서의 형태

위 객체 a의 각 축의 의미는 다음과 같습니다. 이러한 축 배열의 의미는 텐서 인덱스의 일반적인 순서입니다.

Batch Width Height Features
a의 축 인덱스 2 2 5 5

위와 같이 축의 인덱스는 전역에서 로컬로 정렬되는 경우입니다. 배치 축이 먼저 오고 그 다음에 공간 차원과 각 위치의 특성이 마지막에 옵니다.

딥러닝 등에서 필수적인 dataset인 MNIST의 데이터를 예로 소개하면 다음과 같습니다.

keras.datasets으로부터 호출한 이 데이터는 특성(feature, 설명변수)와 라벨(label, 반응변수)로 구분되어 있으며 이를 다시 학습데이터(training data)와 검증 데이터(test data)로 구분되어 있습니다.

다음 코드에서 feature와 label을 나타냅니다.

  • xtr: training data - training feature
  • ytr: training data - training label
  • xte: test data - test feature
  • yte: test data - test label
from tensorflow.keras.datasets import mnist
(xtr, ytr), (xte, yte) = mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
    11493376/11490434 [==============================] - 0s 0us/step
    11501568/11490434 [==============================] - 0s 0us/step
print(f'축의 수 :{xtr.ndim}, 형태: {xtr.shape}, 자료형: {xtr.dtype}')
축의 수 :3, 형태: (60000, 28, 28), 자료형: uint8

여기에 있는 것은 8비트 정수의 3D 텐서입니다. 보다 정확하게는 28 × 8 정수로 구성된 60,000개(batch) 행렬의 배열입니다. 이러한 각 행렬은 0에서 255 사이의 계수를 갖는 회색조 이미지입니다. 위 데이터 셋의 4번째 데이터를 나타내면 다음과 같습니다.

img=xtr[4]
plt.figure(dpi=50)
plt.imshow(img, cmap=plt.cm.binary)
plt.show()
![png](tf_tensor_files/tf_tensor_13_0.png)

Numpy에서 텐서 조작

객체에서 특정 요소를 선택하는 것을 슬라이싱(slicing)이라고 합니다. 슬라이싱은 각 축의 부분을 지정합니다. 즉, 인덱스 선택은 대괄호와 콜론을 사용하여 다음과 같이 일반화 할 수 있습니다.

인덱스의 전형적인 형식: [시작:마지막:간격]
객체[시작인덱스:(마지막 인덱스+1):간격]
인덱스는 0을 포함하는 양의 정수로서 0부터 시작
마지막은 포함되지 않음
선택요소가 한 개일 경우는 정수만을 입력
객체[:]와 같이 수치 없이 콜론만을 입력하는 경우 그 축에 대해 객체의 모든 요소를 선택
예를 들어 위 객체 xtr에서 1축의 2번째와 나머지 축의 모든 차원을 선택한다면 다음과 같습니다.
xtr[1] = xtr[1,:,:] = xtr[1, 0:28, 0:28]
음의 정수일 경우는 객체의 역순을 의미 즉, 객체[-1]은 객체의 마지막 요소를 의미

10~100번째 부분을 선택한다면 다음과 같습니다.

x1=xtr[10:101]
x1.shape
(91, 28, 28)
x1=xtr[10:101, :,:]
x1.shape
(91, 28, 28)
x1=xtr[10:101, 0:28, 0:28]
x1.shape
(91, 28, 28)
ytr[len(ytr)-1] # 훈련데이터의 마지막 라벨 
8
ytr[-1]
8

np.array() 또는 tensor객체.numpy() 메서드를 사용하여 텐서를 numpy 배열로 변환할 수 있습니다.

x=tf.constant([[1,2],[3,4],[5,6]], dtype=tf.float16)
x
<tf.Tensor: shape=(3, 2), dtype=float16, numpy=
    array([[1., 2.],
           [3., 4.],
           [5., 6.]], dtype=float16) >
x.numpy()
array([[1., 2.],
           [3., 4.],
           [5., 6.]], dtype=float16)
np.array(x)
array([[1., 2.],
           [3., 4.],
           [5., 6.]], dtype=float16)

차원의 변경

객체의 형태 변경을 위해서는 tf.reshape() 함수를 적용합니다.

다음 코드에서 열 차원으로 -1을 전달하였습니다. 이는 지정한 다른 차원을 기준으로 자동으로 정렬한다는 의미입니다. 다른 차원을 지정하지 않고 -1만을 전달하는 경우 참고할 축이 없으므로 1차원 텐서로 변경됩니다.

x=tf.constant([1, 2, 3])
x.shape
TensorShape([3])
tf.reshape(x, [3,1])
<tf.Tensor: shape=(3, 1), dtype=int32, numpy=
    array([[1],
           [2],
           [3]], dtype=int32) >
x1=tf.reshape(x, [-1,1])
x1
< tf.Tensor: shape=(3, 1), dtype=int32, numpy=
    array([[1],
           [2],
           [3]], dtype=int32) >
tf.reshape(x1, [-1])
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 2, 3], dtype=int32) >

다음은 3차원 텐서를 2차원 텐서로 변경한 경우입니다.

y=np.random.randint(1, 20, size=(2, 2, 3))
y=tf.constant(y)
y
<tf.Tensor: shape=(2, 2, 3), dtype=int64, numpy=
    array([[[13, 18,  9],
            [ 1,  5, 12]],
    
           [[ 5,  8, 17],
            [ 8, 12,  2]]])>
tf.reshape(y, [-1, 2,6])
< tf.Tensor: shape=(1, 2, 6), dtype=int64, numpy=
    array([[[13, 18,  9,  1,  5, 12],
            [ 5,  8, 17,  8, 12,  2]]])>
tf.reshape(y, [2,6])
<tf.Tensor: shape=(2, 6), dtype=int64, numpy=
    array([[13, 18,  9,  1,  5, 12],
           [ 5,  8, 17,  8, 12,  2]])>

위 객체 y의 차원은 2 × 2 × 3 으로 위와 같이 차원 인덱스 [0] 을 조정함으로서 2차원으로 축소할 수 있습니다. 또한 다음과 같은 방법을 적용할 수 있습니다. (2×2)×3 또는 (2×2×3)와 같이 인수로 전달 함으로서 차원을 축소할 수 있습니다.

tf.reshape(y, [2*2, 3])
< tf.Tensor: shape=(4, 3), dtype=int64, numpy=
    array([[13, 18,  9],
           [ 1,  5, 12],
           [ 5,  8, 17],
           [ 8, 12,  2]])>
tf.reshape(y, [2*2*3])
< tf.Tensor: shape=(12,), dtype=int64, numpy=array([13, 18,  9,  1,  5, 12,  5,  8, 17,  8, 12,  2])>
tf.reshape(y, [-1])
<tf.Tensor: shape=(12,), dtype=int64, numpy=array([13, 18,  9,  1,  5, 12,  5,  8, 17,  8, 12,  2]) >

텐서의 형태 변경을 위해 tf.reshape()을 적용하는 경우 변경 전과 후의 총 요소 수는 같아야 합니다. 원시(raw) 객체의 각 축의 수를 보존하면서 축을 교환하기 위해 tf.transpose() 함수를 적용합니다.

tf.transpose(x, perm=[])
축의 순서를 변경하기 위해 인수를 perm에 전달합니다.
예를 들어 2 × 2 × 3는 축인덱스 0, 1, 2에 대응하는 차원이 각각 2, 2, 3임을 의미합니다. 이 객체를 perm=(1,2,0) 지정하여 transpose를 적용하는 경우 차원은 2 × 3 × 2로 전환됩니다.
tf.transpose(y, [1,2,0])
<tf.Tensor: shape=(2, 3, 2), dtype=int64, numpy=
    array([[[13,  5],
            [18,  8],
            [ 9, 17]],
    
           [[ 1,  8],
            [ 5, 12],
            [12,  2]]]) >
tf.transpose(y, [1, 0, 2])
< tf.Tensor: shape=(2, 2, 3), dtype=int64, numpy=
    array([[[13, 18,  9],
            [ 5,  8, 17]],
    
           [[ 1,  5, 12],
            [ 8, 12,  2]]]) > 

데이터 배치의 개념 (The notion of data batches)

일반적으로 딥 러닝에서 접하게 되는 모든 데이터 텐서의 첫 번째 축(인덱싱이 0에서 시작하기 때문에 축 0)은 샘플 축(샘플 차원)이 됩니다. MNIST 예에서 샘플은 숫자 이미지입니다. 또한 딥 러닝 모델은 전체 데이터 세트를 한 번에 처리하지 않습니다. 오히려 데이터를 작은 배치(batch)로 나눕니다. 구체적으로 다음은 배치 크기가 128인 MNIST 숫자의 배치입니다.

batch=xtr[:128]
batch.shape
(128, 28, 28)

배치 텐서를 고려할 때 첫 번째 축(축 0)을 기준으로 구분합니다. 이러한 축을 배치(batch) 축 또는 배치 차원이라고 합니다. 이것은 Keras 및 기타 딥 러닝 라이브러리를 사용할 때 자주 접하게 되는 용어입니다.

실제로 조작할 데이터는 다음의 범주 중에 하나일 것입니다. 다음에서 samples는 features(변수들)이 모두 포함되어 있는 인스턴스로서 batch로 고려할 수 있습니다. 예를 들어 2차원 텐스 즉, 행렬의 경우 하나의 행이 sample이며 batch가 됩니다.

  • 벡터 데이터 - 모양의 2D 텐서(samples, features)
  • 시계열 데이터 또는 시퀀스 데이터 - 모양의 3D 텐서(samples, timesteps, features)
  • 이미지 - 4D 텐서의 모양 (samples, height, width, channels) 또는 (samples, channels, height, width)
  • 비디오 — 5D 텐서의 (samples, frames, height, width, channels) 또는 (samples, frames, channels, height, width)

댓글

이 블로그의 인기 게시물

[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