728x90
반응형

본 글에서는 👉이전글에서 전처리된 데이터를 기반으로 선형회귀, 로지스틱 회귀, 의사결정나무 모델에 학습시키고 성능을 평가해볼 것입니다.

데이터 준비

  • 샘플데이터 : boston.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/boston.csv")
  1. 데이터 분리
    : 모델의 Overfitting(과적합)을 방지하기 위해 학습용, 평가용, 검증용(Option) 데이터를 나누는 과정입니다.
    Overfitting(과적합) : 학습용(train) 데이터에 과도하게 적합해져서 새로운 데이터에 대한 예측력이 떨어지는 현상
# Feature는 x, Target은 y 로 저장합니다.
x = df.drop(columns=['MEDV'])
y = df['MEDV']

# sklearn 패키키 증 train_test_split 함수 불러오기
from sklearn.model_selection import train_test_split

# Feature와 Target을 train, test 데이터 셋으로 나누기
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42)



지도학습 회귀 - 선형회귀

  • 샘플데이터 : boston.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/boston.csv")
  1. 데이터 분리
# Feature는 x, Target은 y 로 저장합니다.
x = df.drop(columns=['MEDV'])
y = df['MEDV']

# sklearn 패키키 증 train_test_split 함수 불러오기
from sklearn.model_selection import train_test_split

# Feature와 Target을 train, test 데이터 셋으로 나누기
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42)
  1. 단순선형회귀 (Linear Regression)
    : 1개의 feature를 기반으로 수치를 예측하는 모델, 👉Linear Regression글 참고
# 라이브러리 호출
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# 모델 선언
model = LinearRegression()

# 학습하기
model.fit(x_train[['RM']], y_train)

# 예측하기
y_pred = model.predict(x_test)

# 평가하기
print("MSE : ", mean_squared_error(y_test, y_pred))
# MSE(Mean Squared Error) : 평균제곱오차, 예측값과 실제값과의 차이를 제곱한 것의 평균
# 모델의 성능과 MSE는 반비례

# 선형회귀 분석 결과 시각화
# 회귀계수 확인
w = model.coef_
b = model.intercept_
print("기울기 : ", w)    # 기울기
print("절편 : ", b)     # 절편

# 선형회귀식
x = x_test[['RM']]
y = w * x + b

# 시각화
import matplotlib.pyplot as plt
plt.scatter(x_test[['RM']], y_test)
plt.plot(x, y, color='r')
plt.xlabel('RM')
plt.ylabel('MEDV')

plt.show()

# 예측값 실제값 비교
# 실제값과 예측값을 비교하기 위해 데이터프레임으로 만들기
df_lr = pd.DataFrame()
df_lr['y_test'] = y_test
df_lr['y_pred'] = y_pred
df_lr.reset_index(drop=True, inplace=True)

# 시각화
plt.plot(df_lr['y_test'], label='Actual')
plt.plot(df_lr['y_pred'], label='Predicted')
plt.legend()
plt.show()
  • MSE (Mean Squared Error)
  1. 다중선형회귀 (Linear Regression)
    : 다수의 feature를 기반으로 수치를 예측하는 모델, 👉Linear Regression글 참고
# 라이브러리 호출
from sklearn.linear_model import LinearRegression

# 모델 선언
model2 = LinearRegression()

# 학습하기
model2.fit(x_train, y_train)

# 예측하기
y_pred = model2.predict(x_test)

# 평가하기
print("MSE : ", mean_squared_error(y_test, y_pred))

# 선형회귀 분석 결과 시각화
# 회귀계수 확인
w = model.coef_
b = model.intercept_
print("기울기 : ", w)    # 기울기
print("절편 : ", b)     # 절편

# 선형회귀식
formula = "MEDV = {:.2f}".format(b)
for i, feature_name in enumerate(x_test.columns):
    formula += " + {:.2f} * {}".format(w[i], feature_name)
print("선형회귀식: " + formula)

# 시각화
import matplotlib.pyplot as plt
plt.plot(y_test.values[:50], label='Actual')
plt.plot(y_pred[:50], label='Predicted')
plt.legend()
plt.show()



지도학습 분류

  • 샘플데이터 : wine.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/wine.csv")
  1. 데이터 분리
# Feature는 x, Target은 y 로 저장합니다.
x = df.drop(columns=['class'])
y = df['class']

# sklearn 패키키 증 train_test_split 함수 불러오기
from sklearn.model_selection import train_test_split

# Feature와 Target을 train, test 데이터 셋으로 나누기
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
  1. 로지스틱 회귀 (Logistic Regression)
    : 다수의 feature를 기반으로 이진분류하는 모델, 👉Logistic Regression글 참고
# 라이브러리 호출
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# 모델 선언
model = LogisticRegression()

# 이진분류를 위한 테스트데이터 세팅
x_train_b = x_train.loc[y_train[y_train !='class_2'].index]
y_train_b = y_train[y_train !='class_2']
x_test_b = x_test.loc[y_test[y_test !='class_2'].index]
y_test_b = y_test[y_test !='class_2']

# 학습하기
model.fit(x_train_b, y_train_b)

# 예측하기
y_pred = model.predict(x_test_b)

# 평가하기
print("accuracy : ", accuracy_score(y_test_b, y_pred))
# accuracy_score : 정확도를 계산하기 위한 sklearn패키지 함수 (예측결과가 동일한 데이터 건수 / 전체 예측 데이터 건수)

# 예측값 실제값 비교
# 실제값과 예측값을 비교하기 위해 데이터프레임으로 만들기
df_result = pd.DataFrame()
df_result['y_test_b'] = y_test_b
df_result['y_pred'] = y_pred
df_result.reset_index(drop=True, inplace=True)
  1. 소프트맥스 회귀 (Softmax Regression)
    : 다수의 feature를 기반으로 다중분류하는 모델, 👉Softmax Regression글 참고
# 라이브러리 호출
from sklearn.linear_model import LogisticRegression

# 모델 선언
model_softmax = LogisticRegression(multi_class='multinomial')

# 학습하기
model_softmax.fit(x_train, y_train)

# 예측하기
y_pred = model_softmax.predict(x_test)

# 평가하기
print("accuracy : ", accuracy_score(y_test, y_pred))

# 예측값 실제값 비교
# 실제값과 예측값을 비교하기 위해 데이터프레임으로 만들기
df_result = pd.DataFrame()
df_result['y_test'] = y_test
df_result['y_pred'] = y_pred
df_result.reset_index(drop=True, inplace=True)



지도학습 - 의사결정나무

: 의사결정나무 모델은 아래 그림처럼 여러 target으로 분기하는 과정에서 여러 기준에 의거하여 데이터를 분류하거나 결과값을 예측하는 모델
학습을 통해 기준 수치를 조정하여 모델을 일반화하게 되고, 회귀/분류 모델로서 활용 가능합니다.
아래 그림은 outlook, humidity, windy 기준으로 경기가 열릴지 안열리지를 판단하는 모델을 도식화한 그림입니다.

  • 샘플데이터 : wine.csv, boston.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/wine.csv"
  1. 데이터 분리
# Feature는 x, Target은 y 로 저장합니다.
x = df.drop(columns=['class'])
y = df['class']

# sklearn 패키키 증 train_test_split 함수 불러오기
from sklearn.model_selection import train_test_split

# Feature와 Target을 train, test 데이터 셋으로 나누기
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
  1. 의사결정나무 - 분류
# 라이브러리 호출
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

# 모델 선언
model = DecisionTreeClassifier()

# 학습하기
model.fit(x_train, y_train)

# 예측하기
y_pred = model.predict(x_test)

# 평가하기
print("accuracy : ", accuracy_score(y_test, y_pred))

# 의사결정나무(Decision Tree) 구조 보기
# 시각화 모듈 불러오기
from sklearn.tree import export_graphviz

# 이미지 파일 만들기
export_graphviz(model,                        # 모델이름
                out_file='tree_wine.dot',
                feature_names=x.columns,      # Feature 이름
                class_names=y.unique(),       # Target Class 이름
                rounded=True, 
                precision = 3, 
                filled = True)
!dot -Tpng tree_wine.dot -o tree_wine.png -Gdpi=300

# 이미지 파일 로딩
from IPython.display import Image
Image(filename='tree_wine.png', width=600)        # 사이즈 조정

# 예측값 실제값 비교
# 실제값과 예측값을 비교하기 위해 데이터프레임으로 만들기
df_result = pd.DataFrame()
df_result['y_test'] = y_test
df_result['y_pred'] = y_pred
df_result.reset_index(drop=True, inplace=True)
  1. 의사결정나무 - 회귀
# 데이터 불러오기
df = pd.read_csv("./data/boston.csv")

# 데이터 분리
# Feature는 x, Target은 y 로 저장합니다.
x = df.drop(columns=['MEDV'])
y = df['MEDV']

# sklearn 패키키 증 train_test_split 함수 불러오기
from sklearn.model_selection import train_test_split

# Feature와 Target을 train, test 데이터 셋으로 나누기
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)



# 라이브러리 호출
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error

# 모델 선언
model = DecisionTreeRegressor()

# 학습하기
model.fit(x_train, y_train)

# 예측하기
y_pred = model.predict(x_test)

# 평가하기
print("MSE : ", mean_squared_error(y_test, y_pred))

# 의사결정나무(Decision Tree) 구조 보기
# 시각화 모듈 불러오기
from sklearn.tree import export_graphviz

# 이미지 파일 만들기
export_graphviz(model,                        # 모델이름
                max_depth=5,
                out_file='tree_boston.dot',
                feature_names=x.columns,      # Feature 이름
                rounded=True, 
                precision = 3, 
                filled = True)
!dot -Tpng tree_boston.dot -o tree_boston.png -Gdpi=300

# 이미지 파일 로딩
from IPython.display import Image
Image(filename='tree_boston.png', width=600)        # 사이즈 조정

# 예측값 실제값 비교
# 실제값과 예측값을 비교하기 위해 데이터프레임으로 만들기
df_result = pd.DataFrame()
df_result['y_test'] = y_test
df_result['y_pred'] = y_pred
df_result.reset_index(drop=True, inplace=True)

# 시각화
plt.plot(y_test.values[:50], label='Actual')
plt.plot(y_pred[:50], label='Predicted')
plt.legend()
plt.show()



예측과 성능 평가

  • 샘플데이터 : boston.csv, wine.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv("./data/boston.csv")
  1. 데이터 분리
# Feature는 x, Target은 y 로 저장합니다.
x = df.drop(columns=['MEDV'])
y = df['MEDV']

# sklearn 패키키 증 train_test_split 함수 불러오기
from sklearn.model_selection import train_test_split

# Feature와 Target을 train, test 데이터 셋으로 나누기
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
  1. 회귀모델 성능 평가
# 라이브러리 호출
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score

# 모델 선언
model_lr = LinearRegression()
model_dt = DecisionTreeRegressor()

# 모델 학습
model_lr.fit(x_train, y_train)
model_dt.fit(x_train, y_train)

# 예측하기
y_pred_lr = model_lr.predict(x_test)
y_pred_dt = model_dt.predict(x_test)

# 평가하기
print("LinearRegression 모델")
print("MSE : ", mean_squared_error(y_test, y_pred_lr))
print("RMSE :", mean_squared_error(y_test, y_pred_lr)**(1/2))
print("MAE : ", mean_absolute_error(y_test, y_pred_lr))
print("R2 Score : ", r2_score(y_test, y_pred_lr))
print("")
print("DecisionTreeRegressor 모델")
print("MSE : ", mean_squared_error(y_test, y_pred_dt))
print("RMSE :", mean_squared_error(y_test, y_pred_dt)**(1/2))
print("MAE : ", mean_absolute_error(y_test, y_pred_dt))
print("R2 Score : ", r2_score(y_test, y_pred_dt))

# R2_Score (결정계수) = SSR/SST = 1 - SSE/SST, 해당 수치가 클 수록 회귀 모델의 성능이 높음
# SST (Total Sum of Squares) : 실제값에서 실제값의 평균을 뺀 차이의 제곱을 모두 합한 수치
# SSR (Sum of Squares due to Regression) : 예측값에서 실제값의 평균을 뺀 차이의 제곱을 모두 합한 수치
# SSE (Sum of Squares Residual of Error) : 실제값에서 예측값을 뺀 차이의 제곱을 모두 합한 수치
  • SST/SSR/SSE
  1. 분류모델 성능 평가
# 데이터 불러오기
df = pd.read_csv("./data/wine.csv")

# 데이터 분리
# Feature는 x, Target은 y 로 저장합니다.
x = df.drop(columns=['class'])
y = df['class']

# sklearn 패키키 증 train_test_split 함수 불러오기
from sklearn.model_selection import train_test_split

# Feature와 Target을 train, test 데이터 셋으로 나누기
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42)

# 라이브러리 호출
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import confusion_matrix, precision_score, recall_score, accuracy_score, f1_score, classification_report

# 모델 선언
model_lr = LogisticRegression()
model_dt = DecisionTreeClassifier()

# 모델 학습
model_lr.fit(x_train, y_train)
model_dt.fit(x_train, y_train)

# 예측하기
y_pred_lr = model_lr.predict(x_test)
y_pred_dt = model_dt.predict(x_test)

# 평가하기
print("LogisticRegression 모델")
print("Precision : ", precision_score(y_test, y_pred_lr, average='macro'))
print("Recall :", recall_score(y_test, y_pred_lr, average='macro'))
print("Accuracy : ", accuracy_score(y_test, y_pred_lr))
print("F1 Score : ", f1_score(y_test, y_pred_lr, average='macro'))
print("")
print("DecisionTreeClassifier 모델")
print("Precision : ", precision_score(y_test, y_pred_dt, average='macro'))
print("Recall :", recall_score(y_test, y_pred_dt, average='macro'))
print("Accuracy : ", accuracy_score(y_test, y_pred_dt))
print("F1 Score : ", f1_score(y_test, y_pred_dt, average='macro'))

# precision_score : 정밀도, 모델이 1이라고 예측한 것중에 실제로 1인 것의 정도
# accuracy_score : 정확도, 모델이 예측한 값과 실제 값이 일치하는 정도
# recall_score : 재현율, 실제로 1인 것중에 모델이 1이라고 예측한 비율
# f1_score : 정밀도와 회수율을 고르게 활용하기 위한 조화평균, 1에 가까울수록 성능이 좋음
  • Precision/Recall



Cross Validation (교차 검증)

: 데이터를 train set과 test set으로 나누는 방식에서 train set을 train set + validation set으로 추가로 나누어 검증하는 방식
데이터를 train set과 test set으로 나누고, test set을 활용하여 모델의 성능을 검증 및 개선 과정을 반복하면 모델이 test set 과적합(overfitting)될 우려가 있음. 이를 방지하기 위해 교차 검증으로 모델의 성능 검증 및 개선을 진행함.

교차검증

  • 샘플데이터 : boston.csv, wine.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv("./data/boston.csv")

# Feature는 x, Target은 y 로 저장합니다.
x = df.drop(columns=['MEDV'])
y = df['MEDV']
  1. 회귀모델 교차검증
# 라이브러리 호출
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score

# 모델 선언하기
model_lr = LinearRegression()
model_dt = DecisionTreeRegressor()

# 학습, 예측, 평가하기
lr_cv_score = cross_val_score(model_lr, x, y, cv=10, scoring='neg_mean_squared_error')    
dt_cv_score = cross_val_score(model_dt, x, y, cv=10, scoring='neg_mean_squared_error')    # cv는 위 사진에서 Fold의 갯수를 가리킴

# 결과 확인
# 확인
print("LinearRegression 모델")
print(lr_cv_score)
print("MSE : ", -lr_cv_score.mean())
print("DecisionTreeRegressor 모델")
print(dt_cv_score)
print("MSE : ", -dt_cv_score.mean())
  1. 분류모델 교차검증
# 데이터 불러오기
df = pd.read_csv("./data/wine.csv")

# Feature는 x, Target은 y 로 저장합니다.
x = df.drop(columns=['class'])
y = df['class']

# 라이브러리 호출
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score

# 모델 선언하기
model_lr = LogisticRegression()
model_dt = DecisionTreeClassifier()

# 학습, 예측, 평가하기
lr_cv_score = cross_val_score(model_lr, x, y, cv=5, scoring='f1_macro')
dt_cv_score = cross_val_score(model_dt, x, y, cv=5, scoring='f1_macro')

# 결과 확인
# 확인
print("LogisticRegression 모델")
print(lr_cv_score)
print("F1 Score : ", lr_cv_score.mean())
print("DecisionTreeClassifier 모델")
print(dt_cv_score)
print("F1 Score : ", dt_cv_score.mean())
반응형

'개발 > AI' 카테고리의 다른 글

[LLM] LLM 발전기  (0) 2025.01.05
[AI] pandas를 활용한 데이터 핸들링 및 전처리  (2) 2024.04.10
KT AI 해커톤 회고 (2)  (1) 2023.11.02
KT AI 해커톤 회고 (1)  (0) 2023.10.27
[AI] Softmax Regression  (0) 2023.10.01
728x90
반응형

👉이전글에서 소개된 것처럼 AI 모델은 많은 데이터를 기반으로 생성됩니다.
그렇기때문에 양질의 데이터는 높은 퀄리티의 AI 모델을 생성하기 위해 반드시 필요한 요소죠.

본 글에서는 일반적인 데이터를 AI 모델에 활용할 양질의 데이터로 가공하기 위한 방법들을 다뤄보겠습니다.

사용 환경은 아래와 같습니다.

  • IDE : Jupyter Notebook
  • Language : python
  • library : pandas

데이터 탐색

  • 샘플데이터 : ratings.csv
  1. 데이터 확인
# 라이브러리 불러오기
import pandas as pd

# 샘플데이터 가져오기
df = pd.read_csv("./data/ratings.csv")

# 앞에서부터 데이터확인
df.head() # 앞 10개 (default)
df.head(5) # 앞 5개

# 뒤에서부터 데이터확인
df.tail() # 뒤 10개 (default)
df.tail(5) # 뒤 5개
  1. 데이터프레임 정보 확인
    : 데이터 컬럼정보 확인
df.info()

## 결과
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 100836 entries, 0 to 100835
# Data columns (total 4 columns):
#  #   Column     Non-Null Count   Dtype  
# ---  ------     --------------   -----  
#  0   userId     100836 non-null  int64  
#  1   movieId    100836 non-null  int64  
#  2   rating     100836 non-null  float64
#  3   timestamp  100836 non-null  object 
# dtypes: float64(1), int64(2), object(1)
# memory usage: 3.1+ MB
  1. 통계적 특성 확인
    : 데이터의 row수와 평균, 최소/최대값 등을 확인
df.describe()

#     userId    movieId    rating
# count    100836.000000    100836.000000    100836.000000
# mean    326.127564    19435.295718    3.501557
# std    182.618491    35530.987199    1.042529
# min    1.000000    1.000000    0.500000
# 25%    177.000000    1199.000000    3.000000
# 50%    325.000000    2991.000000    3.500000
# 75%    477.000000    8122.000000    4.000000
# max    610.000000    193609.000000    5.000000



데이터 결합과 정렬

  • 샘플데이터 : movies.csv, links.csv, ratings.csv, users.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df_movies = pd.read_csv("./data/movies.csv")
df_links = pd.read_csv("./data/links.csv")
df_ratings = pd.read_csv("./data/ratings.csv")
df_users = pd.read_csv("./data/users.csv")
  1. 데이터 붙이기 : concat()
# 단순 위/아래로 row를 붙임
df_concat_1 = pd.concat([df_movies, df_ratings])

# 옆으로 row를 붙임
df_concat_2 = pd.concat([df_movies, df_ratings], axis=1)

# 합치는 두 데이터프레임에 모두 존재하는 row의 인덱스만 가져옴
df_concat_3 = pd.concat([df_movies, df_ratings], join='inner')
  1. 데이터 병합하기 : merge()
# on='key값'이 없을 경우, default 설정대로 같은 이름을 가진 열이 자동으로 key값으로 지정됨
pd.merge(df_movies, df_ratings)

# movieId 기준 병합
pd.merge(df_movies, df_ratings, on='movieId')

# join 방법 설정
pd.merge(df_movies, df_ratings, how='outer' on='movieId') # outer join
pd.merge(df_movies, df_ratings, how='left' on='movieId') # left outer join
pd.merge(df_movies, df_ratings, how='right' on='movieId') # right outer join
  1. 정렬하기 : sort_values()
# movieId기준 오름차순 정렬
df.sort_values(by='movieId')

# movieId기준 내림차순 정렬
df.sort_values(by='movieId', ascending=False)

# movieId기준 오름차순 정렬 후 바로 적용
df.sort_values(by='movieId', inplace=True)

# 정렬로 인해 뒤섞인 인덱스를 재배열
df.reset_index()
df.reset_index(drop=True, inplace=True) # 기존 인덱스 삭제 후, 재배열된 인덱스 적용



데이터 필터링과 편집

  • 샘플데이터 : preprocessing_03.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_03.csv")
  1. 데이터 필터링
# 성별의 구성을 확인합니다. 
df['gender'].value_counts()

# 성별이 남자인지를 확인해 봅니다.
df['gender']=='M'

# 전체 데이터프레임에서 성별이 남자인 사람으로 필터링한 정보를 가져옵니다.
df[df['gender']=='M']

# 전체 데이터프레임에서 'userId'가 5인 고객이 본 영화 목록을 확인합니다.
df[df['userId']==5]
len(df[df['userId']==5])

# 전체 데이터프레임에서 'userId'가 5인 고객이 평점 2점 이하를 준 영화 목록을 확인합니다.
df[(df['userId']==5) & (df['rating']<=2) ]

# 필터링 결과 중 'title'만 출력
df[(df['userId']==5) & (df['rating']<=2)]['title']
  1. 컬럼명 변경
# 기존 컬럼명 확인하기
df.columns

# 새로운 컬럼명 List를 작성하여 대체하기
df.columns = ['movieId', 'imdbId', 'tmdbId', '영화제목', 'genres', 'userId', 'rating',
       'timestamp', 'gender', 'age', 'occupation', 'zipcode']

# 기존 컬럼명 선택하여 변경 ( df.rename(columns={'기존 컬럼명' : '새 컬럼명'}) )
df = df.rename(columns={'zipcode':'우편번호'})
  1. 컬럼 생성
# 컬럼 생성 후 기본값 세팅 ( df['새로운 컬럼명'] = 기본값 )
df['new'] = 0

# df['영화제목']의 정보를 문자열 처리한 후 괄호'(',')'를 제외한 4자리의 숫자만 가져온 후에 새로운 컬럼 'year'에 세팅
df['year'] = df['영화제목'].str[-5:-1]

# 데이터 분리 후 새로운 컬럼 생성
df['genres'].str.split('|')    # 배열 형태
df['genres'].str.split('|', expand=True).head() # 'expand=True' 옵션을 통해 새로운 데이터프레임으로 생성
  1. 컬럼 삭제
# new 컬럼 삭제
df.drop(columns=['new'])
df.drop(columns=['new'], inplace=True) # 변경내용 적용

# 필요한 컬럼만 선택하여 다시 저장
new_columns = ['movieId', 'imdbId', 'tmdbId', '영화제목', 'year', 'genres', 'userId', 'rating', 'timestamp', 'gender', 'age', 'occupation', '우편번호']
df = df[new_columns]



데이터 결측치 처리

  • 샘플데이터 : preprocessing_04.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_04.csv")
  1. 결측치 확인
# 결측치 행 확인 ( 결측치가 있을 경우 True를 반환 )
df.isnull()

# 각 열별 결측치 갯수 확인
df.isnull().sum()
  1. 결측치 제거
# 결측치가 있는 행 모두 삭제
df_temp = df.dropna()

# 결측치가 있는 열 모두 삭제
df_temp2 = df.dropna(axis=1)

# 행 전체가 결측치인 행만 모두 삭제
df_temp3 = df.dropna(how ='all')

# 행의 결측치가 n초과인 행만 모두 삭제
df_temp4 = df.dropna(thresh=n)

# 특정 열 중 결측치가 있는 경우의 행만 모두 삭제
df_temp5 = df.dropna(subset=['MovieId'])
df.dropna(subset=['MovieId'], inplace=True) # 데이터프레임에 바로 적용
  1. 결측치 채우기
# 결측치를 단일 값(0)으로 대체
df.fillna(0)

# 특정 열의 결측치만 0으로 대체하기
df_na_sample2['UserId'].fillna(0, inplace=True) # 데이터프레임에 바로 적용

# 특정 열의 결측치만 평균값으로 대체하기
df['Age'].fillna(df_na_sample2['Age'].mean(), inplace=True)

# 특정 열의 결측치만 최빈값으로 대체하기
df['Gender'].fillna(df_na_sample2['Gender'].mode()[0], inplace=True)

# 결측치 이전값으로 채우기
df.fillna(method='ffill')

# 결측치 이후값으로 채우기
df.fillna(method='bfill')



데이터 타입 변환/중복데이터 제거

  • 샘플데이터 : preprocessing_05.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_05.csv")
  1. 데이터 타입 확인
# 모든 컬럼의 데이터타입을 확인
df.dtypes

# 컬럼별 데이터타입 확인
df['MovieId'].dtype
  1. 데이터 타입 변경
# 모든 Columns의 데이터 타입을 'object' 형으로 변경
df_temp = df.astype('object')

# 특정 컬럼의 데이터 타입을 변경
df = df.astype({'Year':'int'})
  1. 중복데이터 처리
# 중복 데이터 확인 ( 첫 번째 값은 False, 두 번째 값부터는 True 반환 )
df.duplicated()

# 데이터프레임 df의 'Title'과 'UserId' 컬럼이 중복이 되는 데이터를 확인
df[df.duplicated(['Title','UserId'])]

# 예제 : 영화 제목이 같은 영화를 두번 본 고객이 존재한다고?!
df[(df['Title']=='Iron Man') & (df['UserId']==550)]
df[df.duplicated(['Title','UserId'])]

# 중복데이터 제거
df.drop_duplicates(['Title','UserId', 'Year'], ignore_index=True)    # 기존 인덱스를 무시하고 새로 인덱스를 부여



데이터 이상치 처리

  • 샘플데이터 : preprocessing_06.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_06.csv")
  1. 이상치 탐지
# 컬럼별 통계적 특성 확인
df.describe()

# 시각화를 통한 이상치 탐지
# 라이브러리 불러오기 
import matplotlib.pyplot as plt

# 차트 영역 설정하기 ( box plot 차트 )
plt.figure()
plt.boxplot(df['Age'], labels=['Age'])
plt.show()

  1. 이상치 확인
# IQR의 1.5배 이상 크거나 작은 데이터를 이상치로 판별
# IQR 계산
# 중앙값 계산
Q2 = df['Age'].median()

# 하위 25%, 상위 25% 범위 계산
Q1 = df['Age'].quantile(0.25)
Q3 = df['Age'].quantile(0.75)
IQR = Q3 - Q1

# 이상치 판별
df['IsOutlier_Age'] = (df['Age'] < Q1 - 1.5 * IQR) | (df['Age'] > Q3 + 1.5 * IQR)
  1. 이상치 처리
# 위에서 생성한 이상치여부 컬럼(IsOutlier_Age) 활용하여 이상치 삭제
df = df[df['IsOutlier_Age'] == False]

# 이상치 대체
df.loc[df['IsOutlier_Age'], 'Age'] = df['Age'].median() # 중앙값 대체



데이터 인코딩

  • 샘플데이터 : preprocessing_07.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_07.csv")
  1. 레이블 인코딩
    : 범주형 데이터를 숫자로 변환하는 방법으로, 각 범주에 고유한 숫자를 할당하는 방식입니다.
    예를 들어, "남성", "여성"과 같은 범주형 데이터를 각각 0과 1로 변환하는 방법이 있습니다.
# 라이브러리 불러오기
from sklearn.preprocessing import LabelEncoder

# Label Encoder 호출하기
le = LabelEncoder()

# 'Occupation' 컬럼의 데이터를 Label 인코딩하기.
le_occupation = le.fit_transform(df['Occupation'])
df_le['Occupation_Le'] = le_occupation
df_le['Occupation_Le']
# array([ 0, 20,  1, ..., 11, 11,  7])

# label Encoding 매핑 클래스 확인
le.classes_
# array(['K-12 student', 'academic/educator', 'artist', 'clerical/admin',
#        'college/grad student', 'customer service', 'doctor/health care',
#        'executive/managerial', 'farmer', 'homemaker', 'lawyer', 'other',
#        'programmer', 'retired', 'sales/marketing', 'scientist',
#        'self-employed', 'technician/engineer', 'tradesman/craftsman',
#        'unemployed', 'writer'], dtype=object)

# Pandas의 map() 함수를 사용하여 레이블 인코딩
# 'Occupation' 컬럼의 값들을 lable mapping
label_mapping = { "other" : 0 , 
                  "academic/educator" : 1, 
                  "artist" : 2, 
                  "clerical/admin" : 3, 
                  "college/grad student" : 4, 
                  "customer service" : 5, 
                  "doctor/health care" : 6, 
                  "executive/managerial" : 7, 
                  "farmer" : 8, 
                  "homemaker" : 9, 
                  "K-12 student" : 10,
                  "lawyer" : 11, 
                  "programmer" : 12, 
                  "retired" : 13, 
                  "sales/marketing" : 14, 
                  "scientist" : 15, 
                  "self-employed" : 16, 
                  "technician/engineer" : 17, 
                  "tradesman/craftsman" : 18, 
                  "unemployed" : 19, 
                  "writer" : 20 }

# pandas replace() 메소드를 사용해서 값을 대체
df_le['Occupation_Map'] = df['Occupation'].map(label_mapping)
  1. 더미 변수 생성
    : 각 카테고리를 이진 형태로 표현하는 방법
    각각의 값을 고유한 이진 벡터로 변환하여 해당하는 값의 위치에 1을 표시하고, 나머지 위치에는 0을 표시합니다. (원-핫 인코딩)
# | 구분자 기준으로 데이터를 분할하여 생성된 list type 데이터를 다시 저장
df['Genres'] = df['Genres'].str.split('|')

# list type으로 저장된 데이터를 모두 나누어 새로운 row로 생성
df = df.explode('Genres')

# get_dummies() 함수를 사용 더미변수 생성
pd.get_dummies(df, columns=['Genres'])
pd.get_dummies(df['Genres'])
pd.get_dummies(df['Genres'], prefix='Genre_')    # 더미변수 컬럼의 prefix 설정
pd.get_dummies(df['Genres'], drop_first=True)    # 더미변수 첫번째 컬럼 삭제
df = pd.get_dummies(df, columns=['Genres'], prefix='Genre', drop_first=True)    # 최종

# 더미변수 컬럼 외의 컬럼들을 키값으로 그룹화하여 중복데이터 제거
# 'groupby()'는 특정 컬럼의 값을 기준으로 데이터프레임을 그룹화하여 그룹별로 연산을 수행할 수 있습니다.
# 'agg()'는 그룹화된 데이터프레임에 대해 다양한 집계 함수들을 적용하여 그룹 별로 연산 결과를 집계한 결과를 반환합니다.
df = df.groupby(['MovieId', 'ImdbId', 'TmdbId', 'Title', 'Year', 'UserId', 'Rating', 'Gender', 'Age', 'Occupation']).agg('sum').reset_index()



데이터 스케일링

  • 샘플데이터 : preprocessing_08.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_08.csv")
  1. 데이터 정규화
    : 데이터를 일정 범위로 변환하는 스케일링 방법으로, 데이터를 0과 1 사이의 값으로 변환하는 것을 의미
    정규화는 다양한 스케일을 가진 변수들을 동일한 범위로 맞춰줌으로써, 변수 간의 크기 차이를 제거하여 모델이 각 변수를 공평하게 처리할 수 있도록 돕습니다.
# 라이브러리 불러오기
from sklearn.preprocessing import MinMaxScaler

# MinMaxScaler 호출하기
min_max_scaler = MinMaxScaler()

# 'Age', 'Rating' 컬럼의 데이터를 Min Max Scaling 하기
df_normalized = min_max_scaler.fit_transform(df[['Age', 'Rating']])
  1. 데이터 표준화
    : 데이터를 평균이 0이고 표준편차가 1인 분포로 변환하는 스케일링 방법으로, 데이터를 표준정규분포에 따르는 값으로 변환하는 것을 의미
    표준화는 데이터의 분포를 중심으로 조절하여 이상치에 덜 민감하게 만들어줌으로써, 모델의 안정성을 높이고 예측 결과를 개선하는 데 도움을 줍니다.
# 라이브러리 불러오기
from sklearn.preprocessing import StandardScaler

# StandardScaler 호출하기
standard_scaler = StandardScaler()

# 'Age', 'Rating' 컬럼의 데이터를 StandardScaling 하기
df_standardized = standard_scaler.fit_transform(df[['Age', 'Rating']])



이어서

다음은 전처리된 데이터를 이용하여 AI 모델링을 진행하는 과정을 살펴보겠습니다.

반응형

'개발 > AI' 카테고리의 다른 글

[LLM] LLM 발전기  (0) 2025.01.05
[AI] pandas/sklearn을 활용한 머신러닝 모델링  (0) 2024.04.12
KT AI 해커톤 회고 (2)  (1) 2023.11.02
KT AI 해커톤 회고 (1)  (0) 2023.10.27
[AI] Softmax Regression  (0) 2023.10.01
728x90
반응형

👉이전글에서 Container환경과 Kubernetes와 같은 Container Ochestration툴이 뭔지 알아봤습니다.

그리고 이번글에서는 Container Ochestration툴 중 가장 대중적인 툴인 Kubernetes의 클러스터에 대해 알아보겠습니다.

Kubernetes 클러스터

Kubernetes 클러스터오토스케일링, 버전관리 등과 같은 Container Ochestration의 다양한 기능들을 제공하기 위해 배포된 Kubernetes 환경이라고 보면 될 것 같습니다.

위 사진과 같은 Kubernetes 클러스터의 구조를 통해 Kubernetes(k8s)기반의 애플리케이션을 안정성있고 확장성있게 운영할 수 있습니다.
k8s클러스터는 크게 Control PlaneApplication Node로 구분할 수 있습니다.

  • Control Plane : k8s클러스터 내부에서 발생하는 이벤트는 실시간으로 감지하거나 배포관리 등과 같은 클러스터 전반의 관리를 수행하기 위한 컴포넌트
  • Application Node : 실제 application이 배포되는 컴포넌트

위 두 개의 컴포넌트는 하나의 노드상에 같이 배포되거나 개별 노드로 배포될 수 있습니다. (한 개의 노드는 한 개의 VM이라고 생각하면 이해하기 쉬움)
이제 클러스터를 구성하는 컴포넌트들을 세부적으로 살펴보겠습니다.

Control Plane

kube-apiserver

kube-apiserver는 application node를 제어하기 위한 여러 동작을 호출하는 Control Plane의 프론트엔드 api server입니다. (application node 입장에서는 endpoint api server)

Control Plane의 CLI(Command Line Interface) 환경에서 사용자가 직접 kuber-apiserver를 호출할 수도 있습니다. (명령어 : kubectl)
해당 명령어는 실습을 진행할 때 자주 활용될 것입니다. (다음글)

etcd

k8s클러스터 내부에 application을 어떤 방식으로 배포할지? scaling은 어떻게 진행할지? 등과 같은 클러스터 정보들을 key-value 형태로 저장하는 저장소입니다. 해당 정보들은 사용자가 yaml파일 형태로 작성하여 적용될 수 있는데, 이 또한 실습에서 작성해볼 것입니다. (다음글)

kube-scheduler

application node가 배정되지 않아 미배포 상태인 pod를 실시간으로 감지하고, 해당 pod를 실행시키기 위해 application node를 선택하는 기능을 가진 컴포넌트입니다. pod가 배포될 application node는 컴퓨팅 리소스pod의 리소스 요구사항 등과 같은 기준에 따라 결정됩니다.

  • pod : k8s에서의 배포 최소단위, application이 동작하는 여러개의 Container를 k8s에서의 최소단위로 묶어놓은 컴포넌트 (다음글에서 다룰 예정)

kube-controller-manager

k8s클러스터에서 실행되는 여러 개의 컨트롤러를 통합 관리하는 프로세스입니다. 해당 컨트롤러들은 복잡성을 낮추기 위해 모두 단일 바이너리로 컴파일되는데, 클러스터 내의 리소스를 감시하고 사용자가 정의한 상태로 클러스터를 유지하기 위해 조치를 취하는 역할을 수행합니다.

해당 컨트롤러들은 대표적으로 아래를 포함합니다.

  • node controller : Node를 실시간으로 모니터링합니다. Node에 문제가 발생하였을 경우, 이상이 있는 pod를 종료시켜 node를 정상화합니다.

  • replication controller : kube-apiserver를 통해 각 노드의 상태를 받아오고, 사용자가 설정한 Replica의 수에 일치하도록 노드상에 배포된 pod를 생성하거나 삭제하는 역할을 수행합니다.
  • job controller : 일회성 작업을 수행하는 오브젝트를 실시간으로 모니터링하고, 수행이 필요한 작업이 있을 경우 해당 작업을 위한 일회성 pod를 생성합니다.

이외에도 아래 사진과 같은 다양한 컨트롤러가 포함됩니다.




cloud-controller-manager

k8s클러스터가 AWS와 같은 public cloud에 배포되어 있을 경우, application node를 제어하기 위한 controller-manager입니다. 해당 컴포넌트는 클라우트 플랫폼(ex. AWS, Azure 등)별 전용 cloud-controller-manager를 실행합니다.

Application Node

kubelet

kubelet은 각 application node에서 실행되는 Agent 프로세스입니다. control plane으로부터 명령을 받아 수행하거나, node내 파드들의 상태를 실시간 감시하고 control plane으로 보고하는 application node내 중추적인 역할을 수행합니다.

주요기능은 아래와 같습니다.

  1. 파드관리 : Control Plane으로부터 할당된 파드를 노드에 배치하고 실행합니다. 해당 파드에 문제가 발생한 경우, 파드를 재시작하거나 재스케줄링하여 안정성을 유지합니다.
  2. 컨테이너 실행 : 컨테이너 런타임(ex. docker 등)을 사용하여 파드에 정의된 컨테이너를 실행하고 관리합니다.
  3. 리소스 모니터링 : node의 리소스 사용량을 파악하여 Control Plane에 보고합니다.
  4. 상태 보고 : node내 배포된 파드의 상태와 노드의 상태를 주기적으로 Control Plane에 보고합니다.
  5. 노드의 자동복구 : 노드가 비정상적으로 종료되었을 때, 자동으로 복구를 시도합니다.

kube-proxy

kube-proxy는 각 application node에서 실행되고, node간 네트워크를 관리하고 클러스터 바깥에서 접근할 수 있도록 해주는 컴포넌트입니다.

해당 컴포넌트는 node나 pod의 교체가 쉬운 k8s클러스터 환경에서의 원활한 통신을 보장합니다.
문제가 생겨 node나 pod가 새로 교체되는 경우가 발생할 수도 있는데, 이 때 ip가 교체되어 통신이 안되는 상황을 방지하기 위해
pod가 새로 생성될 때 별도 node iptable에 신규 생성된 pod의 네트워크 정보를 현행화합니다.

reference

반응형
728x90
반응형




Kubernetes 개요

Kubernetes는 컨테이너를 쉽고 빠르게 배포/확장하고, 관리 또한 자동화해주는 오픈소스 플랫폼입니다. 대량의 컨테이너를 관리해주는 플랫폼을 통칭하는 말인 Container Ochestration중 하나죠. (약칭 : k8s)

Kubernetes를 처음 접하신 분들은 여기서 Container는 무엇이고, Container Ochestration가 뭔지도 궁금해하실 것 같습니다.
먼저, Container에 대해 짚고 넘어가겠습니다.

Container

Container는 애플리케이션 실행 시 필요한 모든 파일을 포함한 전체 실행(runtime) 환경에서 애플리케이션을 패키징하고 격리할 수 있는 기술입니다. 각 애플리케이션당 독립된 실행환경을 제공하기 때문에 애플리케이션간 영향도를 최소화하여 안정성을 확보할 수 있습니다.

또한, 하나의 application이 실행되는 각각의 Container들은 한 개의 VM내에서 서로 Host OS를 공유하기 때문에,
Container환경 배포 시에는 VM에 배포하는 것처럼 OS를 별도 배포하지 않아도 되고, alpine-linux 등과 같은 경량 OS를 활용하게 됩니다.
이를 통해 빠른 배포가 가능하여 확장성을 보장할 수 있습니다.

결론적으로 Container 기술을 활용하면,

  1. 애플리케이션간 독립된 환경을 보장받기 때문에 애플리케이션간 영향도 최소화를 통한 안정성
  2. 애플리케이션 배포 시, 별도 OS의 배포는 필요하지 않기 때문에 빠른 배포를 통한 확장성

위 두 가지 이점을 챙길 수가 있게 됩니다.

그렇다면... Container 기술의 원리가 무엇일까?

Container 기술은 아래 두 가지 linux 기능을 활용하게 됩니다.

  1. namespaces : 프로세스마다 독립적인 공간을 제공하고, 서로가 충돌하지 않게끔 namespaces를 만들어 프로세스를 실행시킬 수 있습니다.
  2. cgroups : 각 컨테이너가 공유 컴퓨팅자원에 대한 제어권을 가질 수 있도록 하는 리눅스 커널의 기능입니다.

본 글에서 Container 기술의 원리까지는 딥하게 다루지 않겠습니다.
자세한 내용은 아래 링크를 참고바랍니다.
https://tech.ssut.me/what-even-is-a-container/

Container Ochestration

Container Ochestration은 Container가 많아짐에 따라 발생하는 관리의 복잡성을 해소하기 위한 플랫폼들을 통칭하는 말입니다. 본 글에서 다룰 kubernetesDocker Swarm 등이 이에 해당합니다.

Container Ochestration은 기본적으로 아래와 같은 기능을 제공합니다.

  1. cluster : 관리자가 컨테이너 서버들을 cluster 단위로 추상화시켜 놓고, master 서버를 통해 해당 cluster 내부를 관리합니다.
  2. state : 특정 애플리케이션이 동일하게 실행되는 container의 갯수를 자동으로 유지시켜줍니다.
  3. scheduling : 여러 노드, 여러 컨테이너 서버에 어떤 프로그램이 있는지 확인한 후에 특정 프로그램을 적절한 공간에 넣어줍니다.
  4. Rollout Rollback : 자동 버전관리가 가능합니다.
  5. Service Discovery : 특정 컨테이너 서버의 정보(ex. host name 등)가 바뀌면 자동으로 확인하고 등록해주는 proxy가 있습니다.
  6. Volume : 데이터를 container 서버의 업/다운과 관계없이 영구히 관리하기 위해 별도 공간을 활용하여 container서버에 자동으로 연결시켜 줍니다.

kubernetes는 위 Container Ochestration의 특징을 모두 갖습니다.

이어서

다음 글에서 Kubernetes cluster에 대해 알아보겠습니다.

반응형

+ Recent posts