from sklearn.datasets import load_iris
import pandas as pd
from sklearn.preprocessing import StandardScaler # 표준화 스케일링 함수
import seaborn as sns
import matplotlib.pyplot as plt
import scipy as sp
import scipy.stats
iris = load_iris() # 붓꽃 데이터 셋을 로딩, DataFrame으로 변환
iris_data = iris.data
iris_df = pd.DataFrame(data=iris_data, columns=iris.feature_names)
표준화: 입력된 x들을 평균 0이고 분산 1인 표준 정규 분포로 변환하는 것. StandardScaler 잘 알아두자!
표준화는 전처리의 한 방법이다.
단점: 데이터 내 이상치 有 -> 평균 분산에 큰 왜곡 -> 부적절한 방법.
기존 평균 분산값 확인
print('feature 들의 평균 값')
print(iris_df.mean())
print('\nfeature 들의 분산 값')
print(iris_df.var())
feature 들의 평균 값
sepal length (cm) 5.843333
sepal width (cm) 3.057333
petal length (cm) 3.758000
petal width (cm) 1.199333
dtype: float64
feature 들의 분산 값
sepal length (cm) 0.685694
sepal width (cm) 0.189979
petal length (cm) 3.116278
petal width (cm) 0.581006
dtype: float64
표준화 스케일링 함수 StandardScaler 사용: 학습 -> 변환 필요.
scaler = StandardScaler() # StandardScaler객체 생성 (1)
scaler.fit(iris_df) # StandardScaler가 iris_df 데이터 학습 (2)
iris_scaled = scaler.transform(iris_df) # 그리고 데이터 변형 transform (3)
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
#transform( )시 scale 변환된 데이터 셋이 numpy ndarry로 반환되어 이를 DataFrame으로 변환 (4)
즉, scaler로 객체 생성 -> fit으로 학습 -> transform으로 데이터 변형 -> df로 다시 변환
하면 표준화 스케일링 함수 적용 완료!
표준화하기
print('feature 들의 평균 값')
print(iris_df_scaled.mean())
print('\nfeature 들의 분산 값')
print(iris_df_scaled.var())
feature 들의 평균 값
sepal length (cm) -1.690315e-15
sepal width (cm) -1.842970e-15
petal length (cm) -1.698641e-15
petal width (cm) -1.409243e-15
dtype: float64
feature 들의 분산 값
sepal length (cm) 1.006711
sepal width (cm) 1.006711
petal length (cm) 1.006711
petal width (cm) 1.006711
dtype: float64
# 각 값들의 정규 분포 모양 비교
f,ax = plt.subplots(1,2,figsize=(8,5))
# 표준화 전 정규분포
x0 = iris_df['petal length (cm)'].dropna().values
sns.distplot(x0, kde=False, rug=False, fit =sp.stats.norm, ax = ax[0])
#커널 밀도 함수, 러그밀도함수 는 안보이고(False) / 정규분포만 보이게(Fit)
#norm = normal. 정규분포로 바꿔라
# 표준화 이후 정규 분포
x1 = iris_df_scaled['petal length (cm)'].values
sns.distplot(x1, kde=False, rug=False, fit =sp.stats.norm, ax = ax[1])
plt.show()

- Z score가 -2 미만이거나 2 이상인 값을 추려내는 과정을 거쳤다.
- 이후 해당 값들의 인덱스를 outlier list에 담았고, 표준화를 거친 데이터에서 해당 인덱스 만 삭제했다.
- 이렇게 이상치를 제거하는 과정을 거쳤고 총 11개의 이상치가 삭제되었다.
이상치 제거하기
z score: 자료가 평균으로 표준편차 몇 배만큼 떨어져 있는지. 양은 평균보다 높음. 음은 평균보다 낮음.
# check Z score
df_Zscore = pd.DataFrame()
outlier_dict = {}
outlier_idx_list = []
for one_col in iris_df_scaled.columns:
# print("Check",one_col)
# print("sp.stats.zscore(iris_df_scaled[one_col])",sp.stats.zscore(iris_df_scaled[one_col]))
df_Zscore[f'{one_col}_Zscore'] = sp.stats.zscore(iris_df_scaled[one_col])
print("df_Zscore",df_Zscore)
# print("이상치 딕트 저장",one_col)
outlier_dict[one_col] = df_Zscore[f'{one_col}_Zscore'][(df_Zscore[f'{one_col}_Zscore']>2)|(df_Zscore[f'{one_col}_Zscore']<-2)]
# print("이상치 딕트 저장",outlier_dict)
outlier_idx_list.append(list(outlier_dict[one_col].index))
# print("이상치 리스트에 인덱스 저장",outlier_idx_list)
if len(outlier_dict[one_col]):
print(one_col,'Has outliers\n', outlier_dict[one_col])
else:
print(one_col,"Has Not outlier")
print()
print("Before", iris_df_scaled.shape)
all_outlier_idx = sum(outlier_idx_list,[])
iris_df_scaled = iris_df_scaled.drop(all_outlier_idx)
print("After (drop outlier)", iris_df_scaled.shape)
df_Zscore sepal length (cm)_Zscore
0 -0.933238
1 -1.197004
2 -1.460769
3 -1.592652
4 -1.065121
.. ...
145 1.176886
146 0.649355
147 0.913121
148 0.517472
149 0.121824
[118 rows x 1 columns]
sepal length (cm) Has Not outlier
df_Zscore sepal length (cm)_Zscore sepal width (cm)_Zscore
0 -0.933238 1.605641
1 -1.197004 -0.119911
2 -1.460769 0.570310
3 -1.592652 0.225199
4 -1.065121 1.950751
.. ... ...
145 1.176886 -0.119911
146 0.649355 -1.845463
147 0.913121 -0.119911
148 0.517472 1.260530
149 0.121824 -0.119911
[118 rows x 2 columns]
sepal width (cm) Has Not outlier
df_Zscore sepal length (cm)_Zscore sepal width (cm)_Zscore \
0 -0.933238 1.605641
1 -1.197004 -0.119911
2 -1.460769 0.570310
3 -1.592652 0.225199
4 -1.065121 1.950751
.. ... ...
145 1.176886 -0.119911
146 0.649355 -1.845463
147 0.913121 -0.119911
148 0.517472 1.260530
149 0.121824 -0.119911
petal length (cm)_Zscore
0 -1.450590
1 -1.450590
2 -1.510418
3 -1.390761
4 -1.450590
.. ...
145 0.822897
146 0.703239
147 0.822897
148 0.942554
149 0.763068
[118 rows x 3 columns]
petal length (cm) Has Not outlier
df_Zscore sepal length (cm)_Zscore sepal width (cm)_Zscore \
0 -0.933238 1.605641
1 -1.197004 -0.119911
2 -1.460769 0.570310
3 -1.592652 0.225199
4 -1.065121 1.950751
.. ... ...
145 1.176886 -0.119911
146 0.649355 -1.845463
147 0.913121 -0.119911
148 0.517472 1.260530
149 0.121824 -0.119911
petal length (cm)_Zscore petal width (cm)_Zscore
0 -1.450590 -1.387813
1 -1.450590 -1.387813
2 -1.510418 -1.387813
3 -1.390761 -1.387813
4 -1.450590 -1.387813
.. ... ...
145 0.822897 1.385575
146 0.703239 0.857310
147 0.822897 0.989376
148 0.942554 1.385575
149 0.763068 0.725244
[118 rows x 4 columns]
petal width (cm) Has Not outlier
Before (118, 4)
After (drop outlier) (118, 4)
정규화 작업
- 반드시 이상치 제거 과정을 거친 후 정규화 작업 한다!
- 제거과정 없으면 해당 이상치로 인해 나머지 값들은 0에 가까운 숫자로 왜곡되게 정규화될 가능성이 높다.
- 정규화는 minmaxscaler 로 한다. 정규화 한후 데이터의 최대 최소 값이 1/0 으로 정돈
- StandardScaler와 같이 객체설정 -> fit()로 학습 -> transform()로 변형 -> df로 다시 맞추면 된다.
from sklearn.preprocessing import MinMaxScaler
# MinMaxScaler객체 생성
scaler = MinMaxScaler()
# MinMaxScaler 로 데이터 셋 변환. fit() 과 transform() 호출.
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df)
# transform()시 scale 변환된 데이터 셋이 numpy ndarry로 반환되어 이를 DataFrame으로 변환
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
print('feature들의 최소 값')
print(iris_df_scaled.min())
print('\nfeature들의 최대 값')
print(iris_df_scaled.max())
feature들의 최소 값
sepal length (cm) 0.0
sepal width (cm) 0.0
petal length (cm) 0.0
petal width (cm) 0.0
dtype: float64
feature들의 최대 값
sepal length (cm) 1.0
sepal width (cm) 1.0
petal length (cm) 1.0
petal width (cm) 1.0
dtype: float64
즉 이 방법도 이상치 有 -> 데이터 왜곡 문제점 有
MaxAbsScaler(): 모든 절댓값 in [0, 1] -> 0 기준 가장 큰 수가 -1 or 1. -> 이상치 영향받는 단점 똑같이 有
여기 예제부터는 머신러닝 개념이 들어가있다.
import sklearn
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
cancer_df = pd.DataFrame(data=cancer.data, columns=cancer.feature_names)
cancer_df['target'] = cancer.target
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target,
test_size=0.2, random_state=3)
dtc = DecisionTreeClassifier()
dtc.fit(X_train, y_train) # split 및 분류 method 상태.
from sklearn.preprocessing import MaxAbsScaler # 도입
mas = MaxAbsScaler() #객체화
mas.fit(X_train) #훈련셋 학습
X_train_scaled = mas.transform(X_train)
X_test_scaled = mas.transform(X_test) # train과 test에 적용
dtc.fit(X_train_scaled, y_train) # fit()에 train
print('모델의 정확도 :', round(dtc.score(X_test_scaled, y_test), 4))
모델의 정확도 : 0.8947
X_train_scaled_mas = X_train_scaled.reshape(13650,1)
plt.hist(X_train_scaled_mas, bins=30, color='yellow', alpha = 0.7)
plt.title('MaxAbsScaler')
plt.show()

RobustScaler(): StandardScaler와 유사. 그러나 SS는 평균, 분산 사용.
RS는 median(중간값, quartile(사분위값) 사용 -> 이상치 영향 방지
-> SS보다 RS가 표준화 후 데이터가 더 넓게 분포
from sklearn.preprocessing import RobustScaler
rbs = RobustScaler() # 객체화
X_train_scaled = rbs.fit_transform(X_train) # 변형
X_test_scaled = rbs.transform(X_test) # 적용
dtc.fit(X_train_scaled, y_train) # 학습
print('모델의 정확도 :', round(dtc.score(X_test_scaled, y_test), 4))
모델의 정확도 : 0.9035
X_train_scaled_rbs = X_train_scaled.reshape(13650,1)
plt.hist(X_train_scaled_rbs, bins=30, color='pink', alpha = 0.7)
plt.title('RobustScaler')
plt.show()

Normalizer() : 각 row로 정규화 (앞 4개는 coulmns; feature 통계치 이용했음)
-> 각 row 모든 피쳐들 사이 유클리드 거리 = 1로 데이터 값 설정 -> 빠른 학습 & overfitting 방지
from sklearn.preprocessing import Normalizer
norm = Normalizer()
X_train_scaled = norm.fit_transform(X_train) # 훈련 및 변형
X_test_scaled = norm.transform(X_test) # 변형
dtc.fit(X_train_scaled, y_train) # 훈련
print('모델의 정확도 :', round(dtc.score(X_test_scaled, y_test), 4))
모델의 정확도 : 0.9123
X_train_scaled_norm = X_train_scaled.reshape(13650,1)
plt.hist(X_train_scaled_norm, bins=30, alpha = 0.7)
plt.title('Normalizer')
plt.show()

결론: dataset과 사용하는 알고리즘에 따라 가장 적절한 스케일링 방법이 다르다
featureing (데이터 특성 조정) 예제
tips['per_one_bill'] = round(tips.total_bill / tips['size'], 2) #반올림해서 정리
더미함수 예제 (카테고리형을 범주형으로 만들어 모형구축할 때 필요. 물론 ML때는 encord() 사용)
pd.get_dummies(df, columns = ['married','gender','nation'])
'Programming > Python' 카테고리의 다른 글
[ML] Scikit_learn introduction (0) | 2023.09.06 |
---|---|
데이터 전처리3 (Correlation) (0) | 2023.09.05 |
데이터 전처리1 (null, outlier, bias, regression) (0) | 2023.09.05 |
[Matplotlib] 히트맵(pcolor) 및 응용 (0) | 2023.09.05 |
[Matplotlib] 기본 (0) | 2023.09.04 |