스물세번째 수업 | 공공 자전거 수요 예측 마무리 | 붓꽃 품종 예측 | 로켓 발사

Faithful Dev·2024년 10월 15일
0

김자영 강사님

공공자전거 수요예측

원핫인코딩

데이터 분리 및 원핫인코딩

모델 학습에 앞서 데이터를 훈련 세트와 테스트 세트로 나누고, 범주형 변수에 대해 원핫인코딩을 진행.

from sklearn.model_selection import train_test_split
X_ohe = pd.get_dummies(X, columns=['year', 'month', 'hour', 'dayofweek', 'day', 'season', 'weather'])
X_train, X_test, y_train, y_test = train_test_split(X_ohe, y, random_state=42)

pd.get_dummies: 범주형 데이터를 숫자로 변환하는 방법으로, 각각의 범주를 이진 값으로 처리하여 모델이 데이터를 인식할 수 있게 한다. Azure Machine Learning Studio에서 Convert to Indicator Values와 같은 역할인 것 같다.

from sklearn.linear_model import LinearRegression
model = LinearRegression() # 모델 생성
model.fit(X_train, y_train) # 훈련 데이터로 모델 학습
pred = model.predict(X_test) # 테스트 데이터로 예측 수행

from sklearn.metrics import mean_absolute_error, root_mean_squared_error, r2_score
mae = mean_absolute_error(y_test, pred)
rmse = root_mean_squared_error(y_test, pred)
r2 = r2_score(y_test, pred) # 결정계수 계산

print(f'MAE: {mae:.2f}')
print(f'RMSE: {rmse:.2f}')
print(f'R2: {r2:.2f}')

로그 변환

종속 변수(y)에 대해 로그 변환을 사용하여 데이터의 분포를 안정화시키고, 예측 정확성을 높인다.

y_log = np.log1p(y) # 로그 변환 적용

로그 변환을 통해 큰 값과 작은 값 사이의 차이를 줄이고, 모델 예측 성능을 향상시킨다. 예측 후에는 다시 로그 역변환을 적용한다.

pred_original = np.expm1(pred) # 예측값 로그 역변환
y-test_original = np.expm1(y_test) # 실제값 로그 역변환

로그 변환 후 예측값에 대한 성능 평가도 로그 역변환을 사용하여 수행한다.

mae = mean_absolute_error(y_test_original, pred_original)
rmse = root_mean_squared_error(y_test_original, pred_original)
r2 = r2_score(y_test_original, pred_original)

print(f'MAE: {mae:.2f}')
print(f'RMSE: {rmse:.2f}')
print(f'R2: {r2:.2f}')

모델 변경 (DecisionTree Regressor)

from sklearn.tree import DecisionTreeRegressor
model = DecisionTreeRegressor()
model.fit(X_train, y_train)
  • 변수가 많아질수록 과적합의 위험이 있으며,
  • tree 모델은 트리의 깊이를 제한하지 않을 경우 트리가 끝까지 분할되면 과적합의 위험이 있다.

교차 검증

KFold 교차 검증은 데이터를 K개의 부분으로 나누고, 그 중 하나를 테스트용 데이터로, 나머지를 훈련용 데이터로 사용하여 학습과 평가를 진행한다. 이를 K번 반복해서 평균 성능을 계산한다.

from sklearn.model_selection import KFold, cross_val_score

kf = KFold(n_splits=5, shuffle=True, random_state=42) # 5개의 폴드로 데이터를 나눔
  • n_splits=5: 데이터를 5개로 나누어 교차 검증을 수행
  • shuffle=True: 데이터를 섞어서 각 폴드에 고르게 분배하도록 설정
  • random_state=42: 재현 가능한 결과를 위해 난수 시드를 고정
model = LinearRegression()
cross_val_score(model, X, y, scoring='r2', cv=kf).mean()
  • model = LinearRegression(): 선형 회귀 모델 생성
  • cross_val_score: KFold로 나눈 데이터를 기반으로 모델을 학습 및 평가하는 함수
    - scoring='r2': 모델의 평가 기준으로 R^2 스코어 사용.
    • cv=kf: 교차 검증 방법으로 kf에 설정한 KFold 객체를 사용
  • mean(): 5번의 교차 검증 결과에서 나온 R^2 스코어들의 평균값을 계산하여 반환

Logistic Regression

선형 회귀와 비슷하지만 예측하고자 하는 값이 0 또는 1처럼 두 개의 범주로 나뉠 때 주로 사용된다.

시그모이드 함수

S자 모양의 곡선으로 입력값이 클수록 출력값이 1에 가까워지고 입력값이 작을수록 출력값이 0에 가까워진다. 즉, 모델은 결과가 0과 1중 어느 쪽에 더 가까운지 확률을 계산한다.

f(x)=11+exf(x) = \frac{1}{1 + e^{-x}}

K-Nearest Neighbours, KNN 알고리즘

KNN 알고리즘은 분류와 회귀 문제 모두에 사용할 수 있는 간단하고 직관적인 알고리즘이다. 데이터 포인트가 주어졌을 때 그 주위의 가까운 데이터 포인트들을 참고하여 해당 데이터가 속할 그룹을 결정한다.

기본 원리

KNN 알고리즘의 기본 아이디어는 비슷한 데이터끼리 가까이 모여있다는 것. 새로운 데이터 포인트가 주어지면, 그 데이터와 가장 가까운 K개의 이웃 데이터를 찾아서 그 이웃들이 속한 그룹에 따라 새로운 데이터를 분류하거나 예측한다.

  • 분류: K개의 이웃 중 다수결로 새로운 데이터의 클래스를 결정한다.
  • 회귀: K개의 이웃의 평균값을 계산해 예측값을 구한다.

단계

  1. 데이터 준비
  2. 거리 측정
  3. K개의 이웃 선택: 계산된 거리 중에서 가장 가까운 K개의 이웃을 선택한다.
  4. 다수결 투표: 선택된 K개의 이웃 중 가장 많이 등장하는 클래스를 새로운 데이터의 클래스로 결정한다. (회귀일 경우 이웃들의 평균값을 사용)

K값 선택

K값몇 개의 이웃을 참고할지 결정하는 중요한 하이퍼파라미터이다.

  • 작은 K: 모델이 과적합될 위험이 있어 노이즈에 민감해짐
  • 큰 K: 모델이 과소적합될 수 있어 중요한 패턴을 놓칠 가능성이 큼

보통 K는 홀수로 선택하는데 이는 동점 상황을 방지하기 위함.

장단점

장점

  • 단순함
  • 훈련 과정이 없음

단점

  • 이상치에 민감
  • 거리 계산에 피처 스케일링이 중요: 데이터의 각 특성의 범위가 다르면 거리가 왜곡될 수 있으므로 정규화표준화가 필요하다.

Decision Tree

Decision Tree는 데이터를 트리 구조로 분류하거나 예측하는 데 사용하는 알고리즘이다. 매우 직관적이고 해석이 쉬운 머신러닝 알고리즘으로 분류와 회귀 모두에 사용할 수 있다.

기본 개념

Decision Tree는 데이터를 반복적으로 분할하면서 규칙을 만들어내는 방식으로 작동한다. 이 트리는 Root Node에서 시작해 데이터를 점점 더 작은 그룹으로 나누며, 최종적으로 Leaf Node에서 예측값을 결정한다.

  • Root Node
  • Internal Node
  • Leaf Node

작동 원리

  1. 특성 선택: 트리의 각 분기점에서 데이터를 나누기 위한 가장 중요한 특성을 선택한다. 이때 Information Gain이나 Gini Impurity 같은 지표를 사용해 데이터를 나누는 기준을 찾는다.
  2. 데이터 분할
  3. 반복
  4. 예측: 새로운 데이터가 들어오면, 해당 데이터를 트리의 분기 규칙을 따라 내려가면서 최종 결과를 예측한다.

데이터 분할 기준

  • 정보이득(Information Gain): 데이터의 혼잡도를 나타내는 엔트로피(Entropy) 를 기반으로 하며, 분할 전후 엔트로피의 차이로 가장 정보가 많이 증가하는 특성을 선택한다.
  • 지니 불순도(Gini Impurity): 데이터의 혼합 정도를 나타내는 지표로, 불순도가 낮을수록 데이터가 더 순수해진다. 지니 값이 낮은 특성을 기준으로 데이터를 분할한다.

장단점

장점

  • 해석이 쉬움: 트리의 구조를 시각화하면 모델이 어떻게 작동하는지 직관적으로 이해할 수 있다.
  • 비선형 데이터 처리 가능
  • 피처 스케일에 민감하지 않음
  • 이상치에 강건

단점

  • 과적합 가능성: 트리가 너무 깊어질 경우 모델이 학습 데이터에 과적합 될 위험이 있다. 이를 방지하기 위해 트리의 깊이를 제한하는 등의 가지치기(Pruning) 기법이 사용된다.
  • 작은 변화에 민감
  • 최적 트리 찾기 어려움

가지치기 (Pruning)

과적합을 방지하기 위해 트리의 복잡성을 줄이는 방법이다. 트리가 너무 깊어져 학습 데이터에 과적합되지 않도록 트리의 최대 깊이(max_depth), 최소 샘플 수(min_samples_split, min_samples_leaf) 등의 파라미터를 설정하여 가지치기를 수행한다.

시각화

의사결정 트리는 트리 형태로 시각화할 수 있어서 어떤 기준으로 데이터를 나누었는지 쉽게 확인할 수 있다. 이를 통해 모델의 결정 과정을 직관적으로 이해할 수 있다.

앙상블

앙상블(Ensemble) 학습은 여러 개의 모델을 결합하여 더 나은 예측 성능을 얻는 기법이다. 개별 모델들이 가지는 약점을 보완하고 강력한 예측 성능을 내는 데 주로 사용된다. 앙상블 기법은 특히 과적합을 줄이고, 예측 정확도를 높이는 데 매우 유용하다.

보팅 (Voting)

보팅은 서로 다른 여러 모델을 학습시킨 후 각 모델의 예측 결과를 투표해서 최종 결과를 도출하는 방법이다.

  • 하드 보팅(Hard Voting): 각 모델의 예측 결과 중 다수결로 최종 예측을 결정한다.
  • 소프트 보팅(Soft Voting): 각 모델이 예측한 확률을 평균 내서 최종 예측을 결정한다.
# 개별 모델 생성
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier

lr = LogisticRegression(solver='liblinear')
knc = KNeighborsClassifier(n_neighbors=3)
dt = DecisionTreeClassifier(max_depth=8, random_state=1)

# VotingClassifier 생성
from sklearn.emsemble import VotingClassifier
vc = VotingClassifier(estimators = [('lr_model', lr), ('knc_model', knc), ('dt_model', dt)\, voting='soft')

# VotingClassifier 학습, 예측, 평가
vc.fit(X_train, y_train)
pred = vc.predict(X_test)

from sklearn.metrics import accuracy_score
vc_accuracy = accuracy_score(y_test, pred)
print(f'VotingClassifier accuracy >>> {vc_accuracy}')

# 개별모델 학습, 예측, 평가
for model in [lr, knc, dt]:
	model.fit(X_train, y_train)
    pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, pred)
    print(f'{model.__class__.__name__} accuracy >>> {accuracy}')
  • 세 가지 모델(로지스틱 회귀, KNN, 의사결정 트리)을 각각 학습
  • VotingClassifier: 세 모델의 예측 결과를 기반으로 소프트 보팅을 수행
  • 각 모델과 votingclassifier의 정확도를 출력하여 비교

배깅 (Bagging)

배깅같은 알고리즘을 사용하지만, 각 모델은 다른 데이터 샘플을 학습한다. 이를 통해 모델 간의 상관성을 줄여 과적합을 방지할 수 있다.

부스팅 (Boosting)

부스팅순차적으로 모델을 학습시키며, 이전 모델에서 잘못 예측한 데이터에 더 높은 가중치를 부여하여 다음 모델이 이를 더 잘 예측할 수 있도록 하는 방법이다.

장단점

장점

  • 여러 모델을 결합하여 개별 모델보다 더 높은 정확도를 얻을 수 있다.
  • 데이터에 과적합되는 것을 방지할 수 있으며, 더 일반화된 모델을 만들 수 있다.
  • 다양한 알고리즘의 조합을 통해 성능을 향상시킬 수 있다.

단점

  • 앙상블은 여러 모델을 사용하기 때문에 계산 비용이 증가할 수 있다.
  • 모델이 복잡해져서 해석이 어려워질 수 있다.

붓꽃 품종 예측

데이터 준비

# 필요한 라이브러리 임포트
from sklearn.datasets import load_iris
from sklearn.model_selection improt train_test_split
import pandas as pd

# 데이터셋 로드
iris = load_iris()

# 특징(독립 변수)과 타겟(종속 변수) 확인
X = iris.data
y = iris.target

# 학습 데이터와 테스트 데이터로 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 데이터프레임 구조로 변환하여 보기
df_iris = pd.DataFrame(X, columns=iris.feature_names)
df_iris['species'] = y
df_iris.head()
  • 라이브러리 임포트: 붓꽃 데이터셋을 불러오기 위해 load_iris, 학습과 테스트 데이터를 나누기 위해 train_test_split, 데이터 시각화를 위해 pandas를 불러온다.
  • Iris 데이터셋 로드: load_iris() 함수를 사용하여 데이터를 불러온다.
  • 특징(X)와 타겟(y)
  • 데이터 분할: train_test_split 함수를 사용하여 데이터를 학습용 80%테스트용 20% 로 나눈다.
  • 데이터프레임 변환: pandasDataFrame을 사용해 데이터셋을 표 형태 로 변환, 보기 쉽게 타겟 데이터를 'species'라는 새로운 열로 추가한다.

데이터 분할 결과 확인

# 데이터 분할 결과 확인
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)

# 타겟 분포 확인
print(pd.Series(y_train).value_counts())
print(pd.Series(y_test).value_counts())
  • X_train, X_test, y_train, y_test 크기를 출력하여 학습용 데이터와 테스트용 데이터의 크기가 올바르게 분할되었는지 확인
  • 타겟 값의 분포를 출력하여 학습 데이터와 테스트 데이터의 세 가지 품종이 적절히 분포되었는지 확인

데이터 탐색

데이터 프레임 정보 확인

df_iris.info()

info() 메서드는 데이터프레임의 전체 구조를 보여준다. 각 열의 데이터 타입결측치 여부를 확인할 수 있다.

특성 간의 관계 시각화

import seaborn as sns
import matplotlib.pyplot as plt

# 시각화: 특성 간 관계를 나타내는 산점도 행렬
sns.pairplot(df_iris, hue='species', palette='muted')
plt.show()

Seaborn의 pairplot을 사용하여 각 특성 간의 산점도히스토그램 시각화. hue='species'로 각 붓꽃 품종을 색으로 구분할 수 있다.

데이터 전처리

Stratified Split (계층적 분할)

X_train, X_test, y_train, y_test = train_test_split(
	X, y, test_size=0.2, random_state=42, stratify=y
)
  • stratifiy=y: 데이터 분할 시 각 클래스의 비율을 유지한다. 즉, 학습 데이터와 테스트 데이터에서 클래스 비율이 동일하게 유지된다.
  • 계층적 분할은 특히 데이터 불균형 문제가 있는 경우에 매우 중요하다.

모델링

from sklearn.tree import DecisionTreeClassifier

# 모델 생성
model = DecisionTreeClassifier(random_state=42)

# 모델 학습
model.fit(X_train, y_train)
  • DecisionTreeClassifier: 의사결정 트리 알고리즘을 사용하여 학습 모델을 만든다.
  • fit: 학습 데이터를 이용해 모델을 학습시킨다.

모델 성능 평가

정확도(Accuracy)

from sklearn.metrics import accuracy_score

# 정확도 계산
pred = model.predict(X_test)
accuracy = accuracy_score(y_test, pred)
print(f'정확도: {accuracy:.2f}')
  • 정확도는 예측한 값 중에서 맞춘 값을 전체 예측값으로 나눈 값이다.
  • 데이터가 고르게 분포되어 있을 때 유용하다.

classification_report

from sklearn.metrics import classification_report

# 분류 리포트 출력
print(classification_report(y_test, pred, target_names=iris.target_names))
Precision=TPTP+FPPrecision = \frac{TP}{TP + FP}
Recall=TPTP+FNRecall = \frac{TP}{TP + FN}
F1 Score=2PrecisionRecallPrecision+Recall\text{F1 Score} = 2 * \frac{Precision * Recall}{Precision + Recall}
  • precision: 각 품종에 대해 양성으로 예측한 것 중 실제로 양성인 비율
  • recall: 실제 양성인 데이터 중 모델이 양성으로 맞춘 비율
  • f1-score: 정밀도와 재현율의 조화 평균
  • support: 각 클래스에 속하는 실제 샘플의 수

KFold 교차검증

from sklearn.model_selection import KFold
import numpy as np

# KFold 객체 생성
kf = KFold(n_splits=5, shuffle=True, random_state=42)

# 각 fold에 대해 교차검증 수행
cv_scores = [] # 각 fold에서의 정확도를 저장할 리스트
for train_index, test_index in kf.split(X): # X는 전체 특성 데이터
	# 학습 및 테스트 데이터셋 분리
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index] # y는 레이블 데이터
    
    # 모델 생성 및 학습
    model = DecisionTreeClassifier(random_state=42)
    model.fit(X_train, y_train)
    
    # 테스트 데이터로 예측 및 정확도 계산
    pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, pred)
    
    # 각 fold의 정확도 저장
    cv_scores.append(accuracy)
    
# 교차검증 결과 확인
print(f'각 fold의 정확도: {np.round(cv_scores, 4)}')
print(f'cv_scores_mean: {np.mean(cv_scores):.4f}') # 이 부분이 많이 헷갈렸다.
  • KFold(n_splits=5): 데이터를 5개의 폴드로 나눈다.
  • shuffle=True: 데이터를 무작위로 섞은 후 폴드를 나누기 때문에 모델이 데이터에 과적합되는 것을 방지한다.
  • kf.split(X): 데이터셋 X를 K개의 폴드로 나누어 훈련용과 테스트용 인덱스를 반환한다.
  • cv_scores: 각 폴드에서 테스트 데이터로 예측한 결과의 정확도를 저장한 리스트
  • np.round(cv_scores, 4): 각 폴드에서 얻은 정확도를 소수점 네자리까지 반올림하여 출력
  • np.mean(cv_scores): 각 폴드에서 계산된 정확도의 평균값을 출력

Stratified KFold 교차검증

from sklearn.model_selection import StratifiedKFold

# StratifiedKFold 객체 생성
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

# 각 fold에 대해 교차검증 수행
cv_scores = []
for train_index, test_index in skf.split(X, y):
	X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    
    # 모델 생성 및 학습
    model = DecisionTreeClassifier(random_state=42)
    model.fit(X_train, y_train)
    
    # 테스트 데이터로 예측 및 정확도 계산
    pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, pred)
    
    # 각 fold의 정확도 저장
    cv_scores.append(accuracy)
    
# 교차검증 결과 확인
print(f'각 fold의 정확도: {np.round(cv_scores, 4)}')
print(f'cv_scores_mean: {np.mean(cv_scores):.4f}')
  • StratifiedKFold(n_splits=5): 데이터를 5개의 폴드로 나눌 때, 각 폴드에서 클래스 비율을 동일하게 유지한다.
  • skf.split(X, y): 전체 데이터 X와 레이블 y를 각각 K개의 폴드로 나눈다. 이 과정에서 클래스 비율을 유지한다.

cross_val_score()

from sklearn.model_selection import cross_val_score

# cross_val_score로 교차검증 수행
cv_scores = cross_val_score(model, X_train, y_train, cv=skf, scoring='accuracy')

cross_val_score(): skf만큼의 폴드로 교차검증을 수행, 성능 평가는 정확도를 기준으로 한다.

모델의 훈련 결과

의사결정 트리 시각화

from sklearn.tree import plot_tree
import matplotlib.pyplot as plt

plt.figure(figsize=(20, 10))
plot_tree(model, feature_names=feature_name, class_names=target_name, filled=True)
plt.tight_layout()
plt.show()
  • plot_tree(): 의사결정 트리의 분기 과정 시각화
  • feature_names: 각 노드가 분할된 기준(특성) 표시
  • class_names: 예측된 클래스(붓꽃 품종) 이름 표시
  • filled=True: 노드를 채워서 시각적으로 구분할 수 있게 함

특성 중요도

import seaborn as sns

# 특성 중요도 출력
print(f'특성 중요도 >>> {model.feature_importance_}')

# 특성 중요도 시각화
plt.figure(figsize=(4, 3))
sns.barplot(y=feature_name, x=model.feature_importances_)
plt.show()
  • feature_importances_: 각 특성이 모델 예측에 얼마나 중요한 역할을 했는지 나타내는 값. 값이 클수록 해당 특성이 중요하다.
  • barplot(): 각 특성의 중요도를 막대 그래프로 시각화

트리 깊이

print(f'트리 깊이: {model.get_depth()}')

get_depth(): 의사결정 트리의 최대 깊이 반환

하이퍼파라미터 튜닝

from sklearn.model_selection import GridSearchCV

# 하이퍼파라미터 그리드 설정
parameters = {
	'max_depth': [3, 4, 5], # 트리 최대 깊이
    'min_samples_split': [2, 4] # 분할을 위한 최소 샘플 수
}

# GridSearchCV 객체 생성
gscv = GridSearchCV(model, param_grid=parameters, cv=kf, refit=True)

# 하이퍼파라미터를 순차적으로 변경하면서 학습/평가 수행
gscv.fit(X_train, y_train)

# 최적의 하이퍼파라미터와 성능 출력
print(f'최적의 파라미터 >>> {gscv.best_params_}')
print(f'최고 정확도 >>> {gscv.best_score_:.4f}')
  • param_grid: 튜닝할 하이퍼파라미터와 그 값들의 범위를 설정한다.
  • GridSearchCV(): 하이퍼파라미터 조합마다 교차검증을 수행하는 객체
  • cv=kf: kf개의 교차검증을 사용하여 모델 성능 평가
  • fit(): GridSearchCV는 데이터를 사용해 하이퍼파라미터 조합마다 모델을 학습하고 평가한다.
  • best_params_: 최적의 하이퍼파라미터 조합 반환
  • best_score_: 교차검증 중 가장 높은 정확도 반환
# 최종 모델
best_model = gscv.best_estimator_

# 예측
pred = best_model.predict(X_test)

# 평가
accuracy = accuracy score(y_test, pred)
print(f'테스트세트 정확도 >> {accuracy:.4f}')

best_estimator_: 최적의 하이퍼파라미터로 훈련된 모델

로켓발사

데이터 준비

라이브러리 임포트

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

데이터 불러오기

rocket = pd.read_csv('data/RocketLaunchDataCSV.csv')
rocket.head(3)

데이터 탐색 및 전처리

데이터프레임 정보 확인

rocket.info()

불필요한 열 제거

df = rocket.drop(['Hist Ave Max Wind Speed', 'Hist Ave Visibility',
	'Hist Ave Sea Level Pressure', 'Name', 'Date',
    'Time (East Coast)', 'Location', 'Day Length',
    'Sea Level Pressure', 'Notes'], axis=1)
  • drop(): 지정된 열들을 데이터프레임에서 제거
  • axis=1: 열(column)을 기준으로 제거

결측치 처리

df['Launched?'] = df['Launched?'].fillna('N')
df['Creweed or Uncrewed'] = df['Crewed or Uncrewed'].fillna('Uncrewed')
df['Condition'] = df['Condition'].fillna('Fair')
df['Wind Direction'] = df['Wind Direction'].fillna('Unknown')

# 수치형 변수 결측치 0으로 채우기
df = df.fillna(0)
  • fillna: 결측치를 특정 값으로 채움

범주형 변수 인코딩

# 종속변수 인코딩
df['Launched?'] = df['Launched?'].map({'Y':1, 'N':0})

# 독립변수 레이블 인코딩
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()

cols = ['Crewed or Uncrewed', 'Wind Direction', 'Condition']
for col in cols:
	df[col] = encoder.fit_transform(df[col])
profile
Turning Vision into Reality.

0개의 댓글