24.10.22 Day68

최지원·2024년 10월 22일

머신 러닝

# 데이터를 학습용과 테스트용으로 분할
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(x,
                                                    y,
                                                    test_size=0.2,
                                                    stratify=y)
print("X's shape: {}".format(x.shape))
print("X_train's shape: {}".format(X_train.shape))
print("X_test's shape: {}".format(X_test.shape))

y_test.value_counts()
  • 교차검증
    cpu를 다 써서 병렬 처리
from sklearn.model_selection import cross_val_score

# 분류기 생성
clf = DecisionTreeClassifier(random_state=11)

scores = cross_val_score(clf, x, y, scoring='accuracy', cv=3, n_jobs=-1)
scores.sum()/len(scores)

데이터 전처리

  • 레이블 인코딩
from sklearn.preprocessing import LabelEncoder

items = ['TV','냉장고','전자레인지','컴퓨터','선풍기','선풍기','냉장고']
encoder = LabelEncoder()
encoder.fit(items) # 매핑키를 만들어준다.
labels = encoder.transform(items)
print(labels)
import pandas as pd
df = pd.read_csv('data/iris.csv')

iris_encoder = LabelEncoder()
iris_encoder.fit(df['variety'])
df['variety_num'] = iris_encoder.transform(df['variety'])

df['variety_num'].value_counts()


조회 하기

iris_encoder.classes_

원-핫 인코딩

data = {'item' : ['TV','냉장고','전자레인지','컴퓨터','선풍기','선풍기','냉장고']}
df = pd.DataFrame(data)
pd.get_dummies(df)

  • 데이터 표준화 : x에 있는 숫자에 적용
iris_x = df_iris.drop(['variety_Setosa', 'variety_Versicolor', 'variety_Virginica'], axis=1)
print('평균 값')
print(iris_x.mean())
print('분산 값')
print(iris_x.var())
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(iris_x)
iris_x_scaled = scaler.transform(iris_x)
iris_x_scaled = pd.DataFrame(iris_x_scaled)
print('평균 값')
print(iris_x_scaled.mean())
print('분산 값')
print(iris_x_scaled.var())
iris_x_scaled.head(5)

정규화와 분포화

  • 데이터 정규화
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(iris_x)
iris_minmax = scaler.transform(iris_x)
iris_minmax = pd.DataFrame(iris_minmax)
iris_minmax

이상치인지 판단

  • 상자수염차트
import matplotlib.pyplot as plt
df_eq = pd.read_csv('data/earthquakes.csv')
df_eq['Depth'].plot(kind='box')

q1 = df_eq['Depth'].quantile(0.25)
q3 = df_eq['Depth'].quantile(0.75)
iqr = q3 - q1

q1 = df_eq['Depth'].quantile(0.25)
q3 = df_eq['Depth'].quantile(0.75)
iqr = q3 - q1

# 이상치 경계값 계산
upper_bound = q3 + 1.5 * iqr
lower_bound = q1 - 1.5 * iqr

# 필터 조건
cond1 = df_eq['Depth'] >= lower_bound
cond2 = df_eq['Depth'] <= upper_bound
df_eq_filtered = df_eq[cond1 & cond2]

df_eq_filtered['Depth'].mean()

실습

  1. 새로운 노트북 파일생성: 03_EuropeHotel.ipynb
  2. 다음 파일을 pandas dataframe 형태로 불러오기
  • Europe Hotel Booking Satisfaction Score.csv
  1. 데이터 전처리
  • id열 제거
  • 레이블 인코딩: satisfaction 열
  • 원-핫 인코딩: Gender, purpose_of_travel, Type of Travel, Type Of Booking
  • 표준화 혹은 정규화: X의 모든 열
  1. 데이터 분할: 학습 7, 테스트 3
  2. 학습(DecisionTree)
  • satisfaction: y
  • 나머지: x
  1. 정확도 출력
import pandas as pd
df = pd.read_csv('data/Europe Hotel Booking Satisfaction Score.csv')
# df.head(5)
df.info()
from sklearn.preprocessing import LabelEncoder

def preprocess(df, label_column, drop_columns=None, onehot_colums=None):
    if drop_columns:
        df.drop(drop_columns, axis=1, inplace=True)

    le = LabelEncoder()
    le.fit(df[label_column])
    df[label_column] = le.transform(df[label_column])

    # 원-핫 인코딩
    if onehot_colums:
        df = pd.get_dummies(df, columns=onehot_colums)    

    # X, y로 데이터 분할
    X = df.drop(label_column, axis=1)
    y = df[label_column]

    return X, y

X, y = preprocess(df, 'satisfaction', ['id'], ['Gender', 'purpose_of_travel', 'Type of Travel', 'Type Of Booking'])
# id열 제거
df.drop('id', axis=1, inplace=True)
# 레이블 인코딩: satisfaction 열
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit(df['satisfaction'])
df['satisfaction'] = le.transform(df['satisfaction'])
# 원-핫 인코딩
df = pd.get_dummies(df, columns=['Gender', 'purpose_of_travel', 
                                 'Type of Travel', 'Type Of Booking'])
df.columns
# X, y로 데이터 분할
X = df.drop('satisfaction', axis=1)
y = df['satisfaction']
# 표준화 혹은 정규화: X의 모든 열
from sklearn.preprocessing import StandardScaler, MinMaxScaler
scaler = StandardScaler()
scaler.fit(X)
scaled_value = scaler.transform(X)
X = pd.DataFrame(scaled_value, columns=X.columns)
X
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression

X_train, X_test, y_train, y_test = train_test_split(X, 
                                       y, 
                                                    test_size=0.3, 
                                                    stratify=y,
                                                    random_state=121)
clf = LogisticRegression()
clf.fit(X_train, y_train)
from sklearn.metrics import accuracy_score

pred = clf.predict(X_test)
print('정확도: {}'.format(accuracy_score(y_test, pred)))

타이타닉 생존자 예측

맷플롯립과 시본을 이용해 차트와 그래프를 함께 시각화 하면서 데이터 분석 시행

# 필요한 라이브러리 임포트
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 타이타닉 탑승자 파일을 판다스의 read_scv()를 이용해 DataFrame으로 로딩
titanic_df = pd.read_csv('data/titanic_train.csv')
titanic_df.head(3)
  • 로딩된 데이터 칼럽 타입 확인 - info()메서드
print('\n### 학습 데이터 정보 ### \n')
print(titanic_df.info())
  • DataFrame의 fillna()함수를 사용해 간단하게 Null 값을 평균 또는 고정 값으로 변경
  • Age는 평균 나이, 나머지 칼럼은 'N'값으로 변경
titanic_df['Age'].fillna(titanic_df['Age'].mean(), inplace=True)
titanic_df['Cabin'].fillna('N',inplace=True)
titanic_df['Embarked'].fillna('N',inplace=True)
print('데이터 세트 Null 값 개수', titanic_df.isnull().sum().sum())

# 모든 칼럼의 Null값이 없는지 확인
  • 현재 남아있는 문자열 피처는 Sex, Cabin, Embarked
  • 이 피처들의 값 분류 확인
print('Sex 값 분포 : \n', titanic_df['Sex'].value_counts())
print('\n Cabin 값 분포 : \n', titanic_df['Cabin'].value_counts())
print('\n Embarked 값 분포 : \n', titanic_df['Embarked'].value_counts())
  • Cabin의 경우 선실 번호 중 선실 등급을 나타내는 첫 번째 알파벳 중요
  • 부자와 가난한 사람에 대한 차별이 있었던 시절
  • 일등실에 투숙한 사람이 삼등실에 투숙한 사람보다 더 살아날 확률 높음
# Sex, Embarked 값은 문제 X
# Cabin의 경우 N이 687건으로 가장 많으며 속성값 정리 X
# Cabin 앞 문자 추출
titanic_df['Cabin'] = titanic_df['Cabin'].str[:1]
print(titanic_df['Cabin'].head(3))
  • 어떤 유형의 승객이 생존 확률이 높았는지 확인
  • 여성, 아이들, 노약자 구조 대상
  • 성별이 생존 확률에 어떤 영향을 미쳤는지, 성별에 따른 생존자 수 비교
titanic_df.groupby(['Sex','Survived'])['Survived'].count()

# 0은 사망 1은 생존
  • 시각화 : 시본 패키지
# x축에 'Sex' 칼럼, Y축은 'Survived'칼럼
sns.barplot(x='Sex', y='Survived', data=titanic_df)

  • 부자와 가난한 사람 간의 생존 확률
  • 일등실, 이등실, 삼등실 & 성별 생존 확률
sns.barplot(x='Pclass', y='Survived', hue='Sex',data=titanic_df)


여성의 경우 일, 이등실에 따른 생존 확률이 차이는 크지 않으나, 삼등실의 경우 생존 확률이 상대적으로 떨어짐
남성의 경우 일등실의 생존 확률이 이, 삼등실의 생존 확률보다 월등히 높음

  • Age에 따른 생존확률
# 0 ~ 5 : Baby
# 6 ~ 12 : Child
# 13 ~ 18 : Teenager
# 19 ~ 25 : Student
# 26 ~ 35 : Young Adult
# 36 ~ 60 : Adult
# 61 ~    : Elderly
# -1 이하 : Unkown

# 입력 age에 따라 구분 값을 반환하는 함수 설정
# DataFrame의 apply lambda 식에 사용
def get_category(age):
    cat = ''
    if age <= -1: cat = 'Unkown'
    elif age <= 5: cat = 'Baby'
    elif age <= 12: cat = 'Child'
    elif age <= 18: cat = 'Teenager'
    elif age <= 25: cat = 'Student'
    elif age <= 35: cat = 'Young Adult'
    elif age <= 60: cat = 'Adult'
    else : cat = 'Elderly'

    return cat

# 막대그래프의 크기 figure를 더 크게 설정
plt.figure(figsize=(10,6))

# X축의 값을 순차적으로 표시하기 위한 설정
group_names = ['Unkown','Baby','Child','Teenager','Student','Young Adult','Adult','Elderly']

# lambda 식에 위에서 생성한 get_category() 함수를 반환값으로 지정
# get_category(X)는 입력값으로 'Age' 칼럼 값을 받아서 해당하는 cat 반환
titanic_df['Age_cat'] = titanic_df['Age'].apply(lambda x : get_category(x))
sns.barplot(x='Age_cat', y='Survived', hue='Sex',data=titanic_df,order=group_names)
titanic_df.drop('Age_cat',axis=1, inplace=True)

from sklearn.preprocessing import LabelEncoder

def encode_features(dataDF):
    features = ['Cabin','Sex','Embarked']
    for feature in features:
        le = LabelEncoder()
        le = le.fit(dataDF[feature])
        dataDF[feature] = le.transform(dataDF[feature])

    return dataDF
titanic_df = encode_features(titanic_df)
titanic_df.head()
from sklearn.preprocessing import LabelEncoder

# Null 처리 함수
def fillna(df):
    df['Age'].fillna(df['Age'].mean(), inplace=True)
    df['Cabin'].fillna('N', inplace=True)
    df['Embarked'].fillna('N', inplace=True)
    df['Fare'].fillna(0, inplace=True)
    return df

# 머신러닝 알고리즘에 불필요한 피처 제거
def drop_features(df):
    df.drop(['PassengerId', 'Name', 'Ticket'], axis=1, inplace=True)
    return df

# 레이블 인코딩 수행.
def format_features(df):
    df['Cabin'] = df['Cabin'].str[:1]
    features = ['Cabin', 'Sex', 'Embarked']
    for feature in features:
        le = LabelEncoder()
        le = le.fit(df[feature])
        df[feature] = le.transform(df[feature])
    return df

# 앞에서 설정한 데이터 전처리 함수 호출
def transform_features(df):
    df = fillna(df)
    df = drop_features(df)
    df = format_features(df)
    return df
# 원본 데이터를 재로딩 하고, feature데이터 셋과 Label 데이터 셋 추출.
titanic_df = pd.read_csv('https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv')
y_titanic_df = titanic_df['Survived']
X_titanic_df= titanic_df.drop('Survived',axis=1)

X_titanic_df = transform_features(X_titanic_df)
# 원본 데이터를 재로딩하고, 피처 데이터 세트와 레이블 데이터 세트 추출
titanic_df = pd.read_csv('data/titanic_train.csv')
y_titanic_df = titanic_df['Survived']
X_titanic_df = titanic_df.drop('Survived', axis=1)

X_titanic_df = transform_features(X_titanic_df)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test=train_test_split(X_titanic_df, y_titanic_df,
                                                  test_size=0.2, random_state=11)
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# 결정트리, Random Forest, 로지스틱 회귀를 위한 사이킷런 Classifier 클래스 생성
dt_clf = DecisionTreeClassifier(random_state=11)
rf_clf = RandomForestClassifier(random_state=11)
lr_clf = LogisticRegression(solver='liblinear')

# DecisionTreeClassifier 학습/예측/평가
dt_clf.fit(X_train , y_train)
dt_pred = dt_clf.predict(X_test)
print('DecisionTreeClassifier 정확도: {0:.4f}'.format(accuracy_score(y_test, dt_pred)))

# RandomForestClassifier 학습/예측/평가
rf_clf.fit(X_train , y_train)
rf_pred = rf_clf.predict(X_test)
print('RandomForestClassifier 정확도:{0:.4f}'.format(accuracy_score(y_test, rf_pred)))

# LogisticRegression 학습/예측/평가
lr_clf.fit(X_train , y_train)
lr_pred = lr_clf.predict(X_test)
print('LogisticRegression 정확도: {0:.4f}'.format(accuracy_score(y_test, lr_pred)))

from sklearn.model_selection import KFold

def exec_kfold(clf, folds=5):
    # 폴드 세트를 5개인 KFold객체를 생성, 폴드 수만큼 예측결과 저장을 위한  리스트 객체 생성.
    kfold = KFold(n_splits=folds)
    scores = []

    # KFold 교차 검증 수행.
    for iter_count , (train_index, test_index) in enumerate(kfold.split(X_titanic_df)):
        # X_titanic_df 데이터에서 교차 검증별로 학습과 검증 데이터를 가리키는 index 생성
        X_train, X_test = X_titanic_df.values[train_index], X_titanic_df.values[test_index]
        y_train, y_test = y_titanic_df.values[train_index], y_titanic_df.values[test_index]

        # Classifier 학습, 예측, 정확도 계산
        clf.fit(X_train, y_train)
        predictions = clf.predict(X_test)
        accuracy = accuracy_score(y_test, predictions)
        scores.append(accuracy)
        print("교차 검증 {0} 정확도: {1:.4f}".format(iter_count, accuracy))

    # 5개 fold에서의 평균 정확도 계산.
    mean_score = np.mean(scores)
    print("평균 정확도: {0:.4f}".format(mean_score))
# exec_kfold 호출
exec_kfold(dt_clf , folds=5)

0개의 댓글