본문 바로가기
네이버클라우드/AI

AI 7일차 (2023-05-16) 인공지능 기초 _머신러닝 - 데이터 전처리_결측치 처리와 log 변환

by prometedor 2023. 5. 16.

결측치 처리

ㄴ 주어진 데이터프레임에서 결측치를 확인하고 처리하는 방법

 

ml19_bogan01.py

import numpy as np
import pandas as pd

data = pd.DataFrame([[2, np.nan, 6, 8, 10],
                     [2, 4, np.nan, 8, np.nan],
                     [2, 4, 6, 8, 10],
                     [np.nan, 4, np.nan, 8, np.nan]])	# 주어진 데이터로 데이터프레임을 생성
# print(data)
# print(data.shape)

data = data.transpose()	# 행과 열을 바꿈
data.columns = ['x1', 'x2', 'x3', 'x4']	# 열의 이름을 설정
# print(data)
# print(data.shape)

# 결측치 확인
# print(data.isnull())	
print(data.isnull().sum())	# 데이터프레임에서 각 열의 결측치 개수를 확인
print(data.info())  # 데이터프레임의 정보를 출력하여 결측치 유무와 데이터 타입을 확인

# 1. 결측치 삭제
# print(data.dropna(axis=1))    # nan 값 없애기 --> axis=1 : 열 제거
print(data.dropna(axis=0))    # nan 값 없애기 --> axis=0 : 행 제거 / 컬럼은 다 살아있음
# print(data.dropna())    # nan 값 있는 행,열 모두 없애기
print(data.shape)


# 2. 특정 값으로 대체
means = data.mean() # 열의 평균값을 계산
median = data.median()  # 열의 중간값을 계산

data2 = data.fillna(means)	# 결측치를 열의 평균값으로 대체
print(data2)

data3 = data.fillna(median)	결측치를 열의 중간값으로 대체
print(data3)

ㄴ data.dropna(axis=0, inplace=True)  --> inplace=True를 설정하여 원본 데이터프레임에서 삭제할 수 있음

                                                                  --> axis=0로 설정하면 결측치가 있는 행을 삭제할 수 있음

                                                                  --> axis=1로 설정하면 결측치가 있는 열을 삭제할 수 있음

 

ml19_bogan02.py

import numpy as np
import pandas as pd

data = pd.DataFrame([[2, np.nan, 6, 8, 10],
                     [2, 4, np.nan, 8, np.nan],
                     [2, 4, 6, 8, 10],
                     [np.nan, 4, np.nan, 8, np.nan]])
# print(data)
# print(data.shape)

data = data.transpose()	# 행,열 서로 변환
data.columns = ['x1', 'x2', 'x3', 'x4']
# print(data)
# print(data.shape)

# from sklearn.impute import IterativeImputer   # 실험 중
# from sklearn.experimental import enable_iterative_imputer # object 사용 불가
from sklearn.impute import SimpleImputer

# imputer = SimpleImputer()   # 평균 값으로 대체(default)
# imputer = SimpleImputer(strategy='mean')    # 평균값
# imputer = SimpleImputer(strategy='median')  # 중간값
# imputer = SimpleImputer(strategy='most_frequent')   # 가장 많이 사용된 값
imputer = SimpleImputer(strategy='constant')    # 상수(default = 0)
# imputer = SimpleImputer(strategy='constant', fill_value=777)    # 특정한 값 --> 상수(default = 0) 입력
imputer.fit(data)	# SimpleImputer를 훈련시킴
data2 = imputer.transform(data)	# 훈련된 SimpleImputer를 사용하여 결측치를 대체
print(data2)

# [[ 2.  2.  2.  0.]
#  [ 0.  4.  4.  4.]
#  [ 6.  0.  6.  0.]
#  [ 8.  8.  8.  8.]
#  [10.  0. 10.  0.]]

 

# from sklearn.impute import IterativeImputer   # 실험 중이므로 사용 불가
# from sklearn.experimental import enable_iterative_imputer # object 사용 불가능하여 사용불가
from sklearn.impute import SimpleImputer	# 해당 라이브러리 이용

 

imputer = SimpleImputer()   # 평균 값으로 대체(default)
imputer = SimpleImputer(strategy='mean')    # 평균값
imputer = SimpleImputer(strategy='median')  # 중간값
imputer = SimpleImputer(strategy='most_frequent')   # 가장 많이 사용된 값
imputer = SimpleImputer(strategy='constant')    # 상수(default = 0)
imputer = SimpleImputer(strategy='constant', fill_value=777)    # 특정한 값 --> 상수(default = 0) 입력

 

 

log변환

데이터의 스케일을 조정하거나 분포를 변환하는 데 사용되는 일반적인 전처리 기법

ㄴ 데이터의 값에 자연로그 (또는 다른 로그 함수)를 취하는 것을 의미함


로그 변환을 적용하는 이유

ㄴ 데이터의 스케일 조정 : 로그 변환은 데이터의 크기 차이를 줄여(수치가 너무 크면 의미가 큰 데이터로 인식하므로) 스케일링하는 데 도움을 줌. 큰 값과 작은 값 사이의 스케일을 비슷하게 만들어 모델의 성능을 향상 시킴.
ㄴ 데이터의 분포 변환 : 로그 변환은 데이터의 분포를 정규분포에 가깝게 만들 수 있음. 


np.log1p() 함수

자연로그(밑이 e인 로그)를 계산하고 1을 더하는 함수

ㄴ 양수 값을 가진 데이터에 대해서 로그 변환을 안전하게 수행할 수 있도록 도와줌 

ㄴ 아래 코드에서는 'Population' 열의 값을 로그 스케일로 변환

 

ml20_log변환_california.py

import numpy as np
import pandas as pd     # 추가
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split, KFold
from sklearn.model_selection import cross_val_score, cross_val_predict
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.preprocessing import MaxAbsScaler, RobustScaler

import tensorflow as tf
tf.random.set_seed(77) #weight의 난수값 조절

#1. 데이터
datasets = fetch_california_housing()
x = datasets.data
y = datasets.target


df = pd.DataFrame(x, columns=[datasets.feature_names])
print(df)
print(df.head(10))  # 바꿔야 할 데이터 확인 
print(df['Population'])

df['Population'] = np.log1p(df['Population'])
# 수치가 너무 크면 의미가 큰 데이터로 인식하므로 스케일을 맞춰주기 위해 log 변환을 해주는 것
# 데이터프레임의 'Population' 열에 있는 값들에 로그 변환을 적용하여, 변환된 값을 다시 'Population' 열에 할당하는 것
# 이를 통해 'Population' 열의 값들이 로그 스케일로 변환됨
print(df['Population'].head())


x_train, x_test, y_train, y_test = train_test_split(
    x, y, train_size = 0.7,  random_state=100, shuffle= True 
)

# kfold
n_splits = 11    # 보통 홀수로 들어감
random_state = 42
kfold = KFold(n_splits=n_splits, shuffle=True, 
              random_state=random_state)

# Scaler 적용
# scaler = MinMaxScaler()
# scaler = StandardScaler()
# scaler = MaxAbsScaler()
scaler = RobustScaler()
scaler.fit(x_train)                 # train 은 fit, transform 모두 해줘야 함
x_train = scaler.transform(x_train) # train 은 fit, transform 모두 해줘야 함
x_test = scaler.transform(x_test)   # test 는 transform 만 하면 됨

# 2. 모델
from xgboost import XGBRegressor
model = XGBRegressor()

# 3. 훈련
model.fit(x_train, y_train)


# 4. 평가, 예측
score = cross_val_score(model, 
                        x_train, y_train, 
                        cv=kfold)   # cv : corss validation
# print('cv acc : ', score)   # kfold 에 있는 n_splits 숫자만큼 나옴 
y_predict = cross_val_predict(model,
                              x_test, y_test,
                              cv=kfold)

r2 = r2_score(y_test, y_predict)
print('cv pred r2 : ', r2)
# cv pred r2 :  0.8161893201063641

'''
##### feature impoartances #######
print(model, " : ", model.feature_importances_)
# 시각화
import matplotlib.pyplot as plt
from xgboost.plotting import plot_importance
plot_importance(model)
plt.show()
'''
# 시각화
import matplotlib.pyplot as plt
n_features = datasets.data.shape[1]
plt.barh(range(n_features), model.feature_importances_, align='center')
plt.yticks(np.arange(n_features), datasets.feature_names)
plt.title('california Feature Importances')
plt.ylabel('Feature')
plt.xlabel('Importances')
plt.ylim(-1, n_features)

plt.show()

 

시각화 부분 설명

# 시각화 설명

n_features = datasets.data.shape[1]
ㄴ 데이터셋의 특성 수를 변수 n_features에 저장 
ㄴ datasets는 사용하는 데이터셋 객체임

plt.barh(range(n_features), model.feature_importances_, align='center')
ㄴ barh 함수를 사용하여 바 차트를 그림
ㄴ range(n_features) : y축의 위치를 지정
ㄴ model.feature_importances_ : 특성 중요도 값을 지정

plt.yticks(np.arange(n_features), datasets.feature_names)
ㄴ y축 눈금을 지정
ㄴ np.arange(n_features) : 눈금의 위치를 지정
ㄴ datasets.feature_names : 눈금의 레이블을 지정

plt.title('california Feature Importances')
ㄴ 그래프의 제목을 지정

plt.ylabel('Feature')
ㄴ y축의 레이블을 지정

plt.xlabel('Importances')
ㄴ x축의 레이블을 지정

plt.ylim(-1, n_features)
ㄴ y축의 범위를 지정

plt.show()
ㄴ 그래프를 표시

 

 

ㄴ title, x 와 y 축의 레이블 등을 지정하여 출력시킴

 

ㄴ title, x 와 y 축의 레이블 등을 지정하지 않고 출력시킴 (주석한 부분의 시각화)