일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 30 | 31 |
- 데이터크롤링
- AI
- 머신러닝
- 인공지능
- bias
- 모델평가
- Convolution Neural Network
- pandas
- CRISP-DM
- learning_rate
- MaxPooling2D
- 데이터처리
- CNN
- OneHotEncoding
- NewsWhale
- 데이터분석
- Pooling Layer
- 딥러닝
- 크롤링
- fashion mnist
- CIFAR-10
- CNN 실습
- 키워드 기반 뉴스 조회
- kt에이블스쿨
- Neural Network
- AWS 입문자를 위한 강의
- plot_model
- 뉴스웨일
- 데이터
- explained AI
- Today
- Total
jjinyeok 성장일지
데이터 처리 #2 - 2022/08/08~2022/08/09 본문
앞선 강의는 데이터를 정리하고 이해하는 과정이었다. 이번 과정은 모델링을 위한 데이터 전처리에 관한 과정이다.
1. 전처리가 필요한 이유는?
모델링을 위해 데이터는 필수적인 요건 2가지와 선택적인 요건 1가지를 지닌다.
- 모든 셀은 값이 있어야 한다.
- 모든 셀의 값은 숫자여야 한다.
- (필요에 따라) 숫자의 범위가 일치해야 한다.
따라서 우리는
- NaN 조치
- 가변수화
- (필요에 따라) 스케일링
위 3가지 전처리 방법을 통해 하나의 잘 정리 정제된 데이터프레임을 만들어야 한다.
2. NaN 조치
NaN이란 Not a Number 즉 빈 값이라는 의미이다. 모델링 과정에서 NaN은 존재하면 안되기 때문에 중요해서 버릴 수 없는 데이터라면 반드시 데이터 처리 과정에서 NaN에 대한 조치를 취해주어야 한다. NaN을 조치하는 세가지 방법으로는 제거하기, 채우기, 분리하기가 있는데 주로 제거하기와 채우기를 사용한다. 강의 과정에서도 제거하기, 채우기만 설명을 해주셨기 때문에 두 가지 방법만 정리하도록 하겠다.
NaN 확인하기
NaN을 조치하기 전에 NaN이 있는지 확인하는 과정이 필요하다. 데이터프레임의 isna() 메서드를 사용하면 모든 각각의 셀에 대해 NaN이라면 True를 아니라면 False인 데이터프레임을 반환한다. 여기서 sum() 집계 메서드를 사용하면 각 열에 대해 NaN의 개수를 확인할 수 있다. 과정은 다음과 같다.
"NaN 확인하기"
print(data.isnull().sum())
# Date 0
# Open 5
# High 5
# Low 5
# Close 5
# Volume 5
# exch_Close 0
# exch_Diff 0
# dtype: int64
NaN 제거하기
먼저 NaN을 조치하는 방법 중 NaN을 제거하는 방법이다. NaN은 두가지 방식으로 제거할 수 있는데 NaN이 있는 열을 제거하는 방법과 행을 제거하는 방법으로 나뉜다. 실무에서는 보통 행을 제거하는 방법을 많이 사용하지만 NaN의 개수나 데이터의 중요도에 따라 열을 제거할 수도 있다고 한다. 데이터프레임의 dropna() 메서드를 통해 NaN을 제거할 수 있는데 내부 parameter로 axis=0일 때 NaN이 있는 행을 제거, axis=1일 때 NaN이 있는 열을 제거한다. 또한 axis parameter의 default 값은 0이다. 과정은 다음과 같다.
"NaN 제거하기"
# 기존 데이터
print(data.shape)
print(data.isna().sum())
# (977, 8)
# Date 0
# Open 5
# High 5
# Low 5
# Close 5
# Volume 5
# exch_Close 0
# exch_Diff 0
# dtype: int64
# NaN이 있는 행 제거
data1 = data.dropna(axis=0)
print(data1.shape)
print(data1.isna().sum())
# (972, 8)
# Date 0
# Open 0
# High 0
# Low 0
# Close 0
# Volume 0
# exch_Close 0
# exch_Diff 0
# dtype: int64
# NaN이 있는 열 제거
data2 = data.dropna(axis=1)
print(data2.shape)
print(data2.isna().sum())
# (977, 3)
# Date 0
# exch_Close 0
# exch_Diff 0
# dtype: int64
NaN 채우기
NaN을 새로운 데이터로 채울때는 어떤 값으로 채울지 살펴보아야 한다. 데이터가 연속성을 가지고 있는 시계열 데이터와 같은 데이터라면 앞 혹은 뒤 값으로 데이터를 채우거나 앞 뒤 중간 값으로 채우는 것이 유리하고 경우에 따라서는 전체 데이터의 평균이나 0과 같은 단일 값으로 채우는 것이 더 유리하기 때문이다. 먼저 단일 값이나 앞 혹은 뒤의 값으로 데이터를 채울 때는 데이터프레임의 fillna() 메서드를 활용한다. fillna() 메서드 내부에 값을 넣는 경우 단일 값으로, fillna() 메서드 내부에 method parameter에 'ffill'을 입력하는 경우 앞선 이전 데이터로 'bfill'을 입력하는 경우 뒤에 오는 이후 데이터로 값을 채운다. 데이터 프레임의 interpolate() 메서드를 활용하면 앞 뒤 값의 중간 값으로 NaN을 채우는 것이 가능한데 내부 parameter로 method에 'linear'를 입력해야 한다. 과정은 다음과 같다.
"NaN 채우기"
# 기존 데이터
print(data)
# Date Close Volume
# 943 2019-11-12 269000.0 168608.0
# 944 2019-11-13 263000.0 257602.0
# 945 2019-11-14 NaN NaN
# 946 2019-11-15 270000.0 198430.0
# 947 2019-11-18 275000.0 185370.0
# 단일 값으로 채우기
data1 = data.fillna(0)
print(data1)
# Date Close Volume
# 943 2019-11-12 269000.0 168608.0
# 944 2019-11-13 263000.0 257602.0
# 945 2019-11-14 0.0 0.0
# 946 2019-11-15 270000.0 198430.0
# 947 2019-11-18 275000.0 185370.0
# 이전 데이터로 채우기
data2 = data.fillna(method='ffill')
print(data2)
# Date Close Volume
# 943 2019-11-12 269000.0 168608.0
# 944 2019-11-13 263000.0 257602.0
# 945 2019-11-14 263000.0 257602.0
# 946 2019-11-15 270000.0 198430.0
# 947 2019-11-18 275000.0 185370.0
# 앞-뒤 값의 중간 값으로 채우기
data3 = data.interpolate(method='linear')
print(data3)
# Date Close Volume
# 943 2019-11-12 269000.0 168608.0
# 944 2019-11-13 263000.0 257602.0
# 945 2019-11-14 266500.0 228016.0
# 946 2019-11-15 270000.0 198430.0
# 947 2019-11-18 275000.0 185370.0
3. 가변수화 (Dummy Variable)
모델링을 위해 모든 셀의 값은 숫자여야 한다. 따라서 범주형 입력변수는 가변수화하여 사용해야 한다. pandas의 get_dummies 메서드를 이용해 범주형 변수를 가변수화 할 수 있다. get_dummies 내부 parameter로는 범주형 데이터 열을 필수적으로 넣어야 한다. 또한 prefix parameter를 이용해 가변수화 이후 변수 이름 앞 접두어를 만들 수 있고 drop_first parameter를 True로 하게 되면 가변수화 한 변수 중 하나가 빠지게 된다. drop_first=True를 권장하는데 그 이유는 모든 범주를 가변수화 하면 하나의 변수는 나머지 변수들에 의해 완전 종속된다. 따라서 하나를 빼주는 것이 좋다. 예를 들어 male이라는 칼럼이 존재하고 1은 남성, 0는 여성을 가리킬 때 female이라는 칼럼이 있을 필요가 없다는 것이다. 가변수화를 진행한 뒤 원본 데이터와 가변수화를 진행한 데이터를 붙인다. 이때 앞서 정리한 pandas의 concat() 메서드를 사용한다. 또한 가변수화를 진행했기 때문에 불필요한 기존 범주형 데이터 칼럼을 데이터프레임의 drop() 메서드를 사용하여 삭제하면 과정이 완료된다. 과정은 다음과 같다.
"가변수화"
# 기존 데이터
print(data.head())
# Date Close Volume WeekDay
# 943 2019-11-12 269000.0 168608.0 Tuesday
# 944 2019-11-13 263000.0 257602.0 Wednesday
# 945 2019-11-14 263000.0 257602.0 Thursday
# 946 2019-11-15 270000.0 198430.0 Friday
# 947 2019-11-18 275000.0 185370.0 Monday
# 기존 범주형 데이터 weekday로부터 가변수화 진행
dumm_weekday = pd.get_dummies(data['WeekDay'], drop_first=True)
print(dumm_weekday.head())
# Monday Thursday Tuesday Wednesday
# 943 0 0 1 0
# 944 0 0 0 1
# 945 0 1 0 0
# 946 0 0 0 0
# 947 1 0 0 0
# 원본 데이터와 가변수화를 진행한 데이터 붙이기
data = pd.concat([data2, dumm_weekday], axis=1)
print(data.head())
# Date Close Volume WeekDay Monday Thursday Tuesday Wednesday
# 943 2019-11-12 269000.0 168608.0 Tuesday 0 0 1 0
# 944 2019-11-13 263000.0 257602.0 Wednesday 0 0 0 1
# 945 2019-11-14 263000.0 257602.0 Thursday 0 1 0 0
# 946 2019-11-15 270000.0 198430.0 Friday 0 0 0 0
# 947 2019-11-18 275000.0 185370.0 Monday 1 0 0 0
# 불필요한 칼럼(WeekDay) 삭제
data.drop(['WeekDay'], axis=1, inplace=True)
print(data.head())
# Date Close Volume Monday Thursday Tuesday Wednesday
# 943 2019-11-12 269000.0 168608.0 0 0 1 0
# 944 2019-11-13 263000.0 257602.0 0 0 0 1
# 945 2019-11-14 263000.0 257602.0 0 1 0 0
# 946 2019-11-15 270000.0 198430.0 0 0 0 0
# 947 2019-11-18 275000.0 185370.0 1 0 0 0
4. 스케일링
스케일링은 앞선 NaN 조치와 가변수화처럼 필수적인 데이터 처리 작업은 아니다. 그러나 경우에 따라서 값의 범위를 맞춰주는 과정이 필요하다. 아직은 에이블스쿨에서 간단히 넘어갔지만 학교 생활 중 수업에서 배웠던 내용을 추가적으로 정리하고자 한다. 먼저 여러개의 Feature가 있는 문제에서 어떤 Feature는 범위가 크고 어떤 Feature는 범위가 작을 때 그래프는 높고 얇은 타원형이 된다. 이때 gradient descent를 적용하게 되면 global minimum을 찾아가는데 시간이 너무 오래걸린다. 따라서 우리는 이러한 데이터들을 더 효과적으로 rescale함으로써 그래프를 더 원형처럼 만들 수 있고 시간은 더 적게 걸리게 된다.
따라서 우리의 목표는 대략적으로 -1에서 +1사이의 범위를 가지는 데이터로 스케일링하는 것이다. 실혐을 통해 얻은 결과로는 -3에서 +3 보다는 작은것이 좋고 -1/3에서 +1/3까지보다는 큰 것이 좋다고 한다. 스케일링 과정은 계산을 통해 직접할 수도 있지만 간단하게 사용하기 위해서 sklearn의 model_selection에서 Scaler 클래스 중 선택해서 import 하고 Scaler 클래스를 이용하는 방법이 있다. 과정은 다음과 같다.
"스케일링"
from sklearn.preprocessing import MinMaxScaler
# 사용할 Scaler 선언
scaler = MinMaxScaler()
# 기존 데이터
print(data.head())
# Close Volume Monday Thursday Tuesday Wednesday
# 943 269000.0 168608.0 0 0 1 0
# 944 263000.0 257602.0 0 0 0 1
# 945 263000.0 257602.0 0 1 0 0
# 946 270000.0 198430.0 0 0 0 0
# 947 275000.0 185370.0 1 0 0 0
# 함수 선언
scaler.fit(data)
# 함수 적용하기
data = scaler.transform(data)
print(pd.DataFrame(data))
# 0 1 2 3 4 5
# 0 0.500000 0.000000 0.0 0.0 1.0 0.0
# 1 0.000000 1.000000 0.0 0.0 0.0 1.0
# 2 0.000000 1.000000 0.0 1.0 0.0 0.0
# 3 0.583333 0.335101 0.0 0.0 0.0 0.0
# 4 1.000000 0.188350 1.0 0.0 0.0 0.0
추가적으로 Scaler의 종류로는 StandardScaler, MinMaxScaler, MaxAbsScaler 그리고 RobustScaler 등이 있다. 기본적으로 평균과 표준편차를 이용한 StandardScaler를 많이 사용하며 최대값이 1, 최소값이 0이 되도록 스케일링하는 MinMaxScaler와 최대 절대값과 0이 각각 1, 0이 되도록 스케일링하는 MaxAbsScaler도 많이 사용하며 아웃라이어의 영향을 최소화해야 할 때는 중앙값과 IQR을 사용한 RobustScaler를 많이 사용한다.
'[KT AIVLE School]' 카테고리의 다른 글
데이터 분석 및 의미 찾기 #2 - 개별 변수 분석하기 2022/08/10~2022/08/12 (0) | 2022.08.20 |
---|---|
데이터 분석 및 의미 찾기 #1 - 2022/08/10~2022/08/12 (0) | 2022.08.15 |
데이터 처리 #1 - 2022/08/08~2022/08/09 (0) | 2022.08.15 |
웹크롤링 # 4 Selenium - 2022/08/03~2022/08/05 (0) | 2022.08.14 |
웹크롤링 # 3 정적 페이지 크롤링 - 2022/08/03~2022/08/05 (0) | 2022.08.08 |