728x90
seaborn에 있는 타이타닉 데이터를 가져와서 결측치와 스케일링을 적용시켜 보겠다.
import pandas as pd
import numpy as np
import seaborn as sns
from sklearn.preprocessing import OneHotEncoder
from sklearn.model_selection import train_test_split
df = sns.load_dataset("titanic")
SEED = 42
df_train, df_test = train_test_split(df, random_state=SEED, test_size=0.2)
df_train
먼저 필요한 라이브러리를 불러와주고, 데이터를 train과 test에 담아준다.
df_train = df_train.reset_index(drop=True)
df_test = df_test.reset_index(drop=True)
cols = ["pclass","sex","age","sibsp","parch","fare","embarked"]
x_train = df_train[cols]
x_test = df_test[cols]
x_train.shape, x_test.shape
=> ((712, 7), (179, 7))
이 후 인덱스를 reset한 후 drop해주고, 컬럼을 지정해준다.
결측치(Missing Value)
결측치를 다루기 전에 데이터의 정보를 알아보는 것이 중요하다.
x_train.info()
=>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 712 entries, 0 to 711
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 pclass 712 non-null int64
1 sex 712 non-null object
2 age 572 non-null float64
3 sibsp 712 non-null int64
4 parch 712 non-null int64
5 fare 712 non-null float64
6 embarked 710 non-null object
dtypes: float64(2), int64(3), object(2)
memory usage: 39.1+ KB
결측치가 age, embarked에 존재하는 것을 알 수 있다.
통계치를 이용하여 결측값 채우기
pandas 메소드를 이용한 방법
age_median = x_train["age"].median()
x_train["age"].fillna(age_median)
=>
0 45.5
1 23.0
2 32.0
3 26.0
4 6.0
...
707 21.0
708 28.0
709 41.0
710 14.0
711 21.0
Name: age, Length: 712, dtype: float64
위 코드에서 test에 채우려고 하는 새로운 변수에 담는다. (test는 모르는 값이기 때문에)
sklearn 모듈을 이용한 방법
- 주요 메소드
- fit : 통계치를 추출
- fit_transformn : 통계치 추출과 함께 데이터 변환 (numpy 배열로 반환)
- transformn : fit 또는 fit_transform 통해서 추출된 통계치를 반영해서 데이터 변환
예시
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy="mean")
imputer.fit_transform(x_train[["age"]]) # 2차원형태로 넣으라해서 [[]]을 사용
=>
array([[45.5 ],
[23. ],
[32. ],
[26. ],
[ 6. ],
[24. ],
[45. ],
[29. ],
[29.49884615],
[29.49884615],
.
.
결측치에 평균값을 넣었다.
머신러닝 모델을 이용하여 결측치 채우기
- 결측치가 아닌 다른 변수들을 이용하여 결측치를 추정
- 주변에 결측치가 아닌 값들을 이용해서 결측치를 예측하여 채우는 방식
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
결측치 확인
x_train.tail()
=>
pclass sex age sibsp parch fare embarked
3 female 21.0 0 0 7.6500 S
1 male NaN 0 0 31.0000 S
3 male 41.0 2 0 14.1083 S
1 female 14.0 1 2 120.0000 S
1 male 21.0 0 1 77.2875 S
age에 결측치가 존재하는 것을 확인
from sklearn.linear_model import LinearRegression
imputer = IterativeImputer(estimator = LinearRegression(),random_state=SEED) # IterativeImputer에서 다양한 옵션이 있다. (estimator는 머신러닝 옵션!)
tmp = imputer.fit_transform(x_train[["pclass","age","sibsp","parch","fare"]])
tmp[-5:]
=>
array([[ 3. , 21. , 0. , 0. ,
7.65 ],
[ 1. , 40.63970136, 0. , 0. ,
31. ],
[ 3. , 41. , 2. , 0. ,
14.1083 ],
[ 1. , 14. , 1. , 2. ,
120. ],
[ 1. , 21. , 0. , 1. ,
77.2875 ]])
결측치를 LinearRegression을 이용하여 결측치를 채웠다.
결측치 채우기
display(x_train.info())
display(x_test.info())
=>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 712 entries, 0 to 711
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 pclass 712 non-null int64
1 sex 712 non-null object
2 age 572 non-null float64
3 sibsp 712 non-null int64
4 parch 712 non-null int64
5 fare 712 non-null float64
6 embarked 710 non-null object
dtypes: float64(2), int64(3), object(2)
memory usage: 39.1+ KB
None
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 179 entries, 0 to 178
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 pclass 179 non-null int64
1 sex 179 non-null object
2 age 142 non-null float64
3 sibsp 179 non-null int64
4 parch 179 non-null int64
5 fare 179 non-null float64
6 embarked 179 non-null object
dtypes: float64(2), int64(3), object(2)
memory usage: 9.9+ KB
None
x_train에는 결측치가 age, embarked에 있고, x_test에는 결측치가 age가 있다.
age_median = x_train["age"].median()
x_train["age"] = x_train["age"].fillna(age_median)
x_test["age"] = x_test["age"].fillna(age_median)
embarked_mode = x_train["embarked"].mode()[0]
x_train["embarked"] = x_train["embarked"].fillna(embarked_mode)
각 결측치가 중앙값과 최빈값으로 채워진 것을 볼 수 있다.
display(x_train.info())
display(x_test.info())
=>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 712 entries, 0 to 711
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 pclass 712 non-null int64
1 sex 712 non-null object
2 age 712 non-null float64
3 sibsp 712 non-null int64
4 parch 712 non-null int64
5 fare 712 non-null float64
6 embarked 712 non-null object
dtypes: float64(2), int64(3), object(2)
memory usage: 39.1+ KB
None
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 179 entries, 0 to 178
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 pclass 179 non-null int64
1 sex 179 non-null object
2 age 179 non-null float64
3 sibsp 179 non-null int64
4 parch 179 non-null int64
5 fare 179 non-null float64
6 embarked 179 non-null object
dtypes: float64(2), int64(3), object(2)
memory usage: 9.9+ KB
None
범주형 인코딩
- label encoding
- 범주형 변수의 N개 종류의 값들을 0에서 n-1 값으로 숫자를 부여하는 인코딩이다.
- 원핫인코딩과 다르게 범주의 개수와 상관없이 피처가 1개만 나온다.
- 대소관계가 들어가 학습에 방해가 될 수 있다.
- 우연히 높게 나올 수 있어서 추천하는 방법은 아니다.
예시
from sklearn.preprocessing import LabelEncoder
enc = LabelEncoder()
enc.fit_transform(x_train["embarked"]) # 1차원 넣어야함!
=>
array([2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
2, 2, 2, 0, 0, 2, 2, 0, 2, 0, 2, 1, 1, 2, 2, 2, 0, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 2, 2, 2, 2, 0, 1, 2, 2, 0, 2, 0,
2, 2, 2, 2, 2, 2, 2, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 0, 2, 1, 2, 2,
2, 2, 1, 0, 0, 2, 2, 1, 0, 0, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2,
2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 0, 0, 2,
2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 1, 2, 0, 2, 0, 2, 0, 2, 2, 2, 2,
2, 2, 2, 1, 2, 2, 2, 1, 2, 0, 1, 2, 2, 2, 2, 0, 0, 1, 2, 2, 2, 2,
2, 0, 0, 0, 2, 2, 0, 2, 2, 2, 0, 2, 1, 0, 0, 0, 2, 2, 2, 2, 2, 2,
2, 2, 1, 0, 2, 0, 1, 0, 2, 2, 2, 0, 2, 2, 0, 2, 1, 2, 2, 2, 0, 0,
2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 1, 1,
2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 2, 2, 2, 2, 0, 2, 0, 1, 1, 0, 1, 2,
0, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 0, 0, 1, 2, 2,
2, 2, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
0, 0, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 1,
2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 0, 2, 2, 2, 2, 0, 2, 1, 0, 2, 2, 2,
2, 1, 0, 2, 2, 2, 2, 1, 1, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 2,
2, 1, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 2, 0, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 0, 0, 2,
1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0,
1, 2, 2, 0, 1, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 0, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2,
0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
0, 2, 2, 2, 0, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 1, 2,
2, 2, 2, 2, 0, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,
2, 2, 1, 1, 2, 1, 1, 1, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
2, 2, 0, 0, 2, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 2,
2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2,
0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 2, 1, 2, 2, 2, 2, 1, 2,
2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2,
2, 0, 2, 2, 2, 2, 2, 2])
- Ordinal encoding
- 순서형 변수에 매우 적합한 인코딩 방식
- class 같이 대소관계가 있는 경우 적합하다.
- 범주형 데이터가 많으면 일일이 바꿔야해서 힘들 수 있다.
예시
ordinal_dict = {
1 : 0,
2 : 1,
3 : 2
}
x_train["pclass"].map(ordinal_dict)
=>
0 0
1 1
2 2
3 2
4 2
..
707 2
708 0
709 2
710 0
711 0
Name: pclass, Length: 712, dtype: int64
Feature Scaling
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(random_state=SEED)
model.fit(x_train,y_train)
=>
/usr/local/lib/python3.7/dist-packages/sklearn/linear_model/_logistic.py:818: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
extra_warning_msg=_LOGISTIC_SOLVER_CONVERGENCE_MSG,
LogisticRegression(random_state=42)
오차가 최고점에 수렴하지 못해서 오류 발생! 그래서 스케일링을 해야한다.
728x90
'AI 공부 > 머신러닝' 카테고리의 다른 글
(머신러닝) 머신러닝 모델 (2) | 2022.09.13 |
---|---|
(머신러닝) sklearn (0) | 2022.09.11 |
(머신러닝) 교차검증과 과적합 (0) | 2022.09.07 |
(머신러닝) 성능측정 (0) | 2022.09.06 |
인공지능과 머신러닝의 개념 (2) | 2022.09.05 |
댓글