본문 바로가기
AI/머신러닝

[머신러닝] 데이터셋 다루기

by snow_white 2022. 4. 11.

 

sklearn(scikit-learn)은 2007년 구글 썸머 코드에서 처음 구현됐으며 현재 파이썬으로 구현된 가장 유명한 기계학습 오픈 소스 라이브러리입니다.

뿐만 아니라 통일된 인터페이스를 가지고 있기 때문에 간단하게 여러 기법을 적용할 수 있어서 쉽고 빠르게 결과를 얻을수 있습니다.

sklearn.dataset 안에는 빌트인 (built-in) 데이터 셋들이 존재합니다. 물론 튜토리얼 진행을 위한 수준이므로, 규모가 크지는 않습니다. (Toy Dataset 이라고도 불립니다.)

이번에는 Built-in 데이터 셋을 활용하는 방법에 대해서 알아봅시다.

 

데이터 셋의 종류

  • load_boston: 보스톤 집값 데이터
  • load_iris: 아이리스 붓꽃 데이터
  • load_diabetes: 당뇨병 환자 데이터
  • load_digits: 손글씨 데이터
  • load_linnerud: multi-output regression 용 데이터
  • load_wine: 와인 데이터
  • load_breast_cancer: 위스콘신 유방암 환자 데이터

 

데이터 셋 조회

빌트인 데이터셋은 sklearn.utils.Bunch 라는 자료구조를 활용.

key-value 형식으로 구성되어 있으며, 사전(dict)형 타입과 유사한 구조를 가집니다.

공통 key는 다음과 같습니다.

  • data: 샘플 데이터, Numpy 배열.
  • target: Label 데이터, Numpy 배열.
  • feature_names: Feature 데이터의 이름
  • target_names: Label 데이터의 이름
  • DESCR: 데이터 셋의 설명
  • filename: 데이터 셋의 파일 저장 위치 (csv)

 

간단한 실습으로 빌트인 데이터셋의 활용법에 대하여 알아봅시다.

 

붓꽃의 경우 잎 크기, 길이에 따라 꽃 종류가 정해집니다.

지도 학습 중 분류에 해당하는 예제입니다.

from IPython.display import Image
Image(url='<https://user-images.githubusercontent.com/15958325/56006707-f69f3680-5d10-11e9-8609-25ba5034607e.png>')

  • 붓꽃 데이터셋 불러오기
    • feature은 data로 ⇒ data 키로 값 가져옴
    • label은 target으로 제공됨 ⇒ target 키로 값 가져옴
from sklearn.datasets import load_iris
iris = load_iris()
iris
'''
{'data': array([[5.1, 3.5, 1.4, 0.2],  => Data(Feature, X)
        [4.9, 3. , 1.4, 0.2],
        [4.7, 3.2, 1.3, 0.2],
        [4.6, 3.1, 1.5, 0.2],
        [5. , 3.6, 1.4, 0.2],
'target': array([0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2 => Label(Y)
'frame': None,
'target_names': array(['setosa', 'versicolor', 'virginica'], dtype='<U10'),
'feature_names': ['sepal length (cm)',
  'sepal width (cm)',
  'petal length (cm)',
  'petal width (cm)'],
'''

 

data는 무조건 이차원 구조로 넣어야 합니다!

데이터를 shuffle 해주지 않으면 test dataset에서는 성능 바닥이 됩니다..

 

data : 모든 data(feature)를 가지고 옴

target: target 모든 label을 가지고 옴

target_names : 컬럼명, feature 이름들을 가지고 옴

feature_names : 0,1,2가 아니라 label의 이름을 가지고 옴

 

  • 데이터에 대한 상세한 정보
iris['DESCR'] # 데이터에 대한 상세한 정보.. 보기가 어렵다
print(iris['DESCR']) # 보기 쉽게 나옴

'''
.. _iris_dataset:

Iris plants dataset
--------------------

**Data Set Characteristics:**

    :Number of Instances: 150 (50 in each of three classes)
    :Number of Attributes: 4 numeric, predictive attributes and the class
    :Attribute Information:
        - sepal length in cm
        - sepal width in cm
        - petal length in cm
        - petal width in cm
        - class:
                - Iris-Setosa
                - Iris-Versicolour
                - Iris-Virginica
                
    :Summary Statistics:

    ============== ==== ==== ======= ===== ====================
                    Min  Max   Mean    SD   Class Correlation
    ============== ==== ==== ======= ===== ====================
    sepal length:   4.3  7.9   5.84   0.83    0.7826
    sepal width:    2.0  4.4   3.05   0.43   -0.4194
    petal length:   1.0  6.9   3.76   1.76    0.9490  (high!)
    petal width:    0.1  2.5   1.20   0.76    0.9565  (high!)
    ============== ==== ==== ======= ===== ====================
'''

 

Feature 데이터 (X)

 

feature 데이터 값 조회하기

feature data는 data 키로 접근하여 가져올 수 있습니다.

아래 두 표현식은 동일합니다.

iris.data
iris['data']
'''
array([[5.1, 3.5, 1.4, 0.2],
       [4.9, 3. , 1.4, 0.2],
       [4.7, 3.2, 1.3, 0.2],
       [4.6, 3.1, 1.5, 0.2],
       [5. , 3.6, 1.4, 0.2],
       [5.4, 3.9, 1.7, 0.4],
       [4.6, 3.4, 1.4, 0.3],
'''
iris.feature_names
iris['feature_names']
'''
['sepal length (cm)',
 'sepal width (cm)',
 'petal length (cm)',
 'petal width (cm)']
'''

 

  • 슬라이싱 가능
feature = iris['data']
feature[:5]
'''
array([[5.1, 3.5, 1.4, 0.2],
       [4.9, 3. , 1.4, 0.2],
       [4.7, 3.2, 1.3, 0.2],
       [4.6, 3.1, 1.5, 0.2],
       [5. , 3.6, 1.4, 0.2]])
'''

 

feature data 에 대한 이름은 feature_names 로 가져올 수 있습니다.

iris 데이터의 경우 총 4개의 feature를 가지고 있음을 확인할 수 있습니다.

 

[참고]

  • sepal: 꽃받침
  • petal: 꽃잎

 

  • 데이터프레임의 칼럼명으로 넣어주기
feature_names = iris['feature_names']
feature_names
'''
['sepal length (cm)',
 'sepal width (cm)',
 'petal length (cm)',
 'petal width (cm)']
'''

 

Label 데이터 (y)

label data는 target 키로 접근

label = iris['target']
label
'''
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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
'''

 

데이터 셋을 DataFrame으로 변환

첫번째로 data와 feature_names 키로 가져온 데이터를 활용하여 데이터 프레임을 만듭니다.

 

  • target(label) 칼럼 생성
import pandas as pd
# feature는 values로 넣어주기
# feature_names는 데이터프레임의 칼럼명으로 넣어주기
df = pd.DataFrame(feature, columns=feature_names)
df = pd.DataFrame(iris['data'], columns=iris['feature_names'])

# target(label)은 target이라는 칼럼으로 넣어주기
df['target'] = label
df['target'] = iris['target']
df.head()

 

로드한 DataFrame 시각화

1️⃣ Sepal (꽃받침)의 길이 넓이에 따른 꽃의 종류가 어떻게 다르게 나오는지 확인.

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(10,7))
sns.scatterplot(df.iloc[:, 0], df.iloc[:, 1], hue=df['target'], palette='muted') # 꽃받침의 길이 컬럼은 인덱스 0번임
plt.title('Sepal', fontsize=15)
plr.show()

학습할 때 난이도가 높은 것은 Iris Versicolor와 Iris Virginica 둘을 분류하는 것!

따라서 위의 그래프 보면 Iris Versicolor와 Iris Virginica의 꽃받침의 길이와 넓이의 중복되는 부분이 많이 보입니다.

하지만 꽃잎의 크기는 다르기 때문에 꽃잎을 기준으로 구분하는 전략을 세워봅시다!

 

2️⃣ 꽃잎을 기준으로 분류하자 꽆잎을 기준으로 분류해보니 명확하게 세 부분으로 나뉩니다.

하지만 target 0과 1을 한 범주로 여길 수 있기 때문에 이 부분 역시 이후에 데이터 처리 과정이 발생할 수 있음을 알고 있읍시다.

plt.figure(figsize=(10,7))
sns.scatterplot(df.iloc[:, 2], df.iloc[:, 3], hue=df['target'], palette='muted') # 꽃잎
plt.title('Sepal', fontsize=15)
plr.show()

 

데이터 분할 (train_test_split)

기계학습에서 데이터 분할은 중요한 전처리 과정입니다.

sklearn.model_selection의 train_test_split 함수는 클래스 이름 그대로 학습과 검증 (혹은 테스트) 셋을 나누어 주는 역할을 합니다.

학습 (Train) / 검증 (Validation or Test) 세트로 나누며, 검증 세트로 과대 적합여부를 모니터링 할 수 있습니다.

또한, 검증 세트를 활용하여 모델의 성능 평가를 진행할 수 있습니다.

 

샘플 데이터 확인

df.head()

feature(x), label(y) 데이터를 분할 합니다.

주요 hyperparameter

  • test_size: Test(validation) Set에 할당할 비율 (20% -> 0.2), 기본값 0.25
  • stratify: 분할된 샘플의 class 갯수(Y, label)가 동일한 비율로 유지
  • random_state: 랜덤 시드값
  • shuffle: 셔플 옵션, 기본값 True
iris['data'].shape # (150, 4)

같은 모델에 대하여 seed값을 다르게 했을 때 random 하게 데이터를 섞을텐데 만약 A가 한 번, B가 한 번 학습시켰을 때 학습률이 A가 87%, B는 84% 나온다고 가정합시다.

어떤 seed 값을 주느냐에 따라 학습률이 달라집니다.

seed값을 바꿔야 할 것 같지만, seed값을 고정해두고 다른 옵션값을 변경하며 학습률을 높이는 방법을 선택해야합니다. (최상의 seed값을 찾는 것은 의미없는 행동임..!)

 

데이터가 총 150개, 칼럼이 4개인데 150개의 데이터를 모두 학습 데이터로 사용하게 되면 과대적합 가능성 높아집니다!

따라서 traing data(75%) 와 test data(25%)를 train_test_split() 함수로 자동으로 나눠서 작업 진행해봅시다!

from sklearn.model_selection import train_test_split # traing data 와 test data를 알아서 나눠서 적용해줌

# X 데이터만 추출하기
X = df.iloc[:, :4] # 데이터프레밍의 맨 마지막 칼럼인 target은 X에 포함되지 않음!
X = df.iloc[:, :-1] # 맨 마지막 칼럼 인덱스(-1)을 제외하고 모두 가져오기

# target이라는 칼럼은 제거하고 남은 앞의 data(X)만 가져오기
# 칼럼 순서가 뒤섞여 있어도 target(label)만 제거할 수 있음
X = df.drop('target', axis=1)

# y(label)만 추출하기
y = df['target']
'''
0      0
1      0
2      0
3      0
4      0
      ..
145    2
146    2
147    2
148    2
149    2
Name: target, Length: 150, dtype: int32
'''

X.head() 출력한 결과

train_test_split의 반환 값은 총 4개입니다다.

순서대로 X의 train data, X의 test data, Y의 train data, Y의 test data를 의미합니다.

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1234)

# 원본의 X
X.shape # (150, 4)
# 분할된 X
X_train.shape, X_test.shape # ((120, 4), (30, 4))
# 원본의 Y
y.shape # (150,)
# 분할된 Y
y_train.shape, y_test.shape # ((120,), (30,))

댓글