3 분 소요

머신러닝에서는 데이터 분석이 가장 중요합니다.


오늘 학습 할 내용

데이터 수집 탐색 전처리

시간 될 때 자료 없이 코딩 해보는게 도움이 될것입니다.

data preprocessing

데이터 전처리에 대해 5단계로 나누어 배워보겠습니다.

데이터 전처리(Data Preprocessing)
- data → model → insight
- data preprocessing : data = raw data(날 것), clean, processing
- data → model : model(컴퓨터) : 숫자가 비어있으면 안된다!
titanic_dataset

- 어떤 feature 들이 주어졌나요? column이 있는지 없는지
- 각 feature 가 의미하는 바는 무엇인가요? column이 어떤 의미를 갖는지
- train set, test set 이 따로 주어졌나요?
- 어떤 feature 가 categorical 이고 어떤 feature가 numerical 인가요?
    - feature가 범주형, 수치형

문제를 어떤게 정의하냐에 따라 y는 바뀔 수 있습니다.

Kaggle의 Titanic dataset을 예시로

1. 어떤 데이터가 주어졌는지 확인

📈Numerical(수치형)

  • 👆✌🤟Discret : sibsp, parch
  • 📏📐🧭Continuous : age, fare
titanic.describe()

describe() 함수를 통해 numerical 데이터에 대해 count, mean, std, min, max 등을 확인할 수 있습니다.

📊Categorical(범주형)

  • 🍊🍎🍇Nominal : survived, sex, embarked
  • 🥇🥈🥉ordinal : pclass
titanic.describe(include=['o'])

categorical 데이터에 대해 분석하고 싶다면 describe 함수에 인자값으로 include=[’o’] 를 넣어줍니다.(알파벳)

데이터의 형태와 분포를 살펴보는 것이 처음에는 쉽지 않지만 다양한 데이터를 분석해보며 보는 눈을 길러야 유의미한 가설을 세우고 검증을 할 수 있게됩니다.

titanic 데이터에는 문자와 숫자가 혼합되어 사용되고 있습니다.

문자 부분은 Categorical 하며 숫자 부분은 Numerical 합니다.

이러한 경우에 데이터를 전처리 해주어야합니다.

ex)특징을 찾을 수 없고 고유하기 때문에 특별히 고려하지 않아도 된다고 파악하여 ticket이라는 컬럼을 지웠습니다.

비어있거나 (NaN) 틀린 값이 있는 feature 가 있다면

기계학습 모델에서 비어있는 값은 인식이 되지 않습니다. 데이터의 특성에 따라, 의도하는 방향에 따라 여러 처리 방법이 있지만

통상적으로 다음과 같은 방법을 이용합니다.

  1. 0 값으로 대체 (numerical의 경우) , “empty” “null” 등의 값으로 대체 (categorical 경우)
  2. 중간값으로 대체 (numerical의 경우) , 가장 많이 등장하는 category 로 대체 (categorical의 경우)
  3. 작은 수의 경우, 해당 instance 를 삭제하여 사용하지 않음. 많이 비어있는 경우 해당 feature 를 아예 사용하지 않음.

isna()를 사용하여 결측값을 확인합니다.

titanic.isna()

결과에 True값이 비어있는 값입니다.

titanic.insa().sum()

위 코드를 통해 각 컬럼별로 결측치가 얼마나 있는지 알 수 있습니다.

의미없는 컬럼을 날려야만하는 이유

  • 메모리, 효율성 증대
  • 차원의 문제

데이터 안에서 어떤 컬럼들이 중요한지 우선순위를 두고 학습을 시키는게 중요합니다.

데이터를 최적화하고 정제하면 할수록 성능은 올라갑니다.


2. 가설검증

데이터를 어느정도 살펴봤다면 가설을 세우고 데이터를 더 깊게 살펴보며 어떤 feature를 학습에 적용할 것인지 판단해야합니다.


3. Missind data

drop.([제거하려는  이름], axis = -0 -1, inplace = True)

위와 같은 코드를 통해 필요가 없다고 판단되는 값을 drop할 수 있습니다.

df.dropna(how='all') # how='any'

모든 값이 nan이라면 위 코드를 통해 지워줍니다.

데이터프레임.fillna(0)

비교적 비어있는 값(NaN)이 적고 해당 데이터가 유의미하여 이용할만하다고 판단되는 경우 0이나 다른 값으로 대치해줍니다.

  • 데이터는 정규분포를 따른다고 가정!

Titanic dataset에서 ‘Age’의 경우 .drop()을 사용해서 버리기에는 너무 중요한 값입니다. 그렇다고 일괄적으로 빈칸에 0 등의 값을 넣기에는 분석에 도움이 되지 않습니다. 그래서 이런 숫자 데이터에 일반적으로 평균(mean)에 분산(std) 만큼 차이 나는 사이의 임의값을 넣어주게 됩니다.

하지만 모든 값을 평균으로 대체한다면 분산이 영향을 많이 받게되므로 아래와 같은 임의의 값을 넣어줍니다.

np.std()
np.mean()
np.random.unifrom()
.extend()

4. Feature Engineering

titanic['Name'].str.extract(' ([A-Za-z]+)\.', expand=False)

정규표현식을 사용하여 ‘Name’ 컬럼에 대해 처리해줍니다.

정규표현식이란? 문자열을 처리하는 방법의 하나로 특정한 조건의 문자를 ‘검색’하거나 ‘치환’하는 과정을 매우 간편하게 처리 할 수 있도록 하는 수단입니다.

titanic['age_band'] = pd.cut(titanic['Age'], 5)    

pd.cut() 을 사용하면 원하는 컬럼을 구간별로 나눌 수 있습니다.

pd.pivot_table(titanic, values='Survived', columns='Title')

PivotTable을 사용하면 요약된 통계량을 확인할 수 있습니다.

위 코드를 실행하면 pd.cut()을 통해 나눈 나이 구간에 따라 생존률이 차이나는 것을 확인할 수 있습니다.


5. 데이터 검수

titanic.info()

위 코드를 통해 모든 컬럼이 numerical한 값인지 확인합니다.

titanic['Fare'] = titanic['Fare'].astype(int)

‘Fare’ 컬럼이 소수점 5자리까지 쓰는 float64 형태의 값이라 위 코드를 통해 int로 바꿔줍니다.

titanic['Age'] = titanic['Age'].astype(int)

‘Age’ 컬럼 또한 int로 바꿔줍니다.

titanic['Title'] = titanic['Title'].replace(['Capt', 'Col', 'Countess', 'Don','Dona', 'Dr', 'Jonkheer', 'Lady','Major', 'Rev', 'Sir'], 'Other')
titanic['Title'] = titanic['Title'].replace('Mlle', 'Miss')
titanic['Title'] = titanic['Title'].replace('Mme', 'Mrs')
titanic['Title'] = titanic['Title'].replace('Ms', 'Miss')

아까 정규식을 통해 처리해줬던 ‘Title’ 컬럼에 중복되는 뜻을 가진 표현들이 여러가지로 되어있어 통일해줍니다.

from sklearn.preprocessing import LabelEncoder    # LabelEncoder를 불러오기
encoder = LabelEncoder()      # encoder라는 변수를 선언
encoder.fit(titanic['Title']) # title 열에 맞게 인코딩
titanic['Title'] = encoder.transform(titanic['Title']) # 인코딩 결과를 실제 행에 적용
titanic.head()

그런 다음, 사이킷런의 LabelEncoder를 통해 numerical 데이터로 인코딩해줍니다.

titanic.drop('Name',axis=1,inplace=True)
titanic.head()

‘Name’ 컬럼은 굳이 필요하지 않으므로 drop해줍니다.

encoder.inverse_transform([3])

inverse transform 을 이용하면 역으로 원래 문자열 데이터를 알 수 있습니다.

genders = {"male": 0, "female": 1}
titanic['Sex'] = titanic['Sex'].map(genders)
titanic.head()

map() 함수를 통해 성별정보도 numeric으로 변환합니다.

titanic['Embarked'] = titanic['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)

‘Embarked’ 항목도 0과1,2로 변환합니다. 이 때, 소숫점이 나오지 않게 .astype(int)를 추가해줍니다.


이후 강의에서는 scikit-learn 모델을 통해 간단한 성능검증을 해보았으나

해당 내용은 차후에 모델 관련 본강의에서 정리하는게 나을거 같아 생략하였습니다.

다만 강사님이 하신 말씀을 남깁니다.

모델학습은 한번 하고 끝나는게 아니라 여러번 반복을 통해 변화 추이를 살피는 것입니다. baseline을 잡고 시작해야하는게 맞지만 baseline을 잡는데 너무 공을 들일 필요는 없습니다.


댓글남기기