240614_TIL

J Lee·2024년 6월 14일
0

아무리 사소하더라도 배움이 없는 날은 없다.

오늘은 머신러닝 과제 제출일.

풀이 자체는 수요일에 끝냈지만
팀원들과의 코드리뷰가 있어서 제출은 오늘 했다.
베이직(1~3)과 챌린지(4~6번)으로 나눠서 TIL에 풀이를 리뷰해 보기로 한다.

과제 1번 리뷰

#1. 데이터 불러오기
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target

#2. train 데이터와 test 데이터 분리하기
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y, shuffle=True, random_state=42, test_size = .3, stratify=y)
#shuffle = True : 데이터를 무작위로 섞어서 test와 train으로 나누겠다
#random_state = 42 : 난수 생성기의 시드 고정
#test_size = .3 : 테스트 데이터의 비율을 30%로 하겠다 (= 학습 데이터는 70%)
#stratify=y : train과 test로 분리될 때, 원 데이터 y의 분포를 그대로 따라가도록 분리 (이거 넣으면 .93 나오고 빼면 1 나옴)

#3. train 데이터와 test 데이터가 7:3 비율로 잘 쪼개졌는지 확인
#print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)

#4. Logistic Regression 모델 불러오기
from sklearn.linear_model import LogisticRegression
model_lor = LogisticRegression(max_iter=150)

#5. model_lor에 X_train과 y_train을 기준으로 학습시키기
model_lor.fit(X_train,y_train)

#6. model_lor은 학습이 끝났으니 X_test데이터를 기반으로 예측해 보기
y_pred_test = model_lor.predict(X_test)

#7. 모델 평가
from sklearn.metrics import accuracy_score, f1_score
print(accuracy_score(y_test,y_pred_test).round(3))

train(훈련) 데이터와 test(테스트) 데이터를 나누는 단계

#2. train 데이터와 test 데이터 분리하기
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y, shuffle=True, random_state=42, test_size = .3, stratify=y)
	#shuffle = True : 데이터를 무작위로 섞어서 test와 train으로 나누겠다
	#random_state = 42 : 난수 생성기의 시드 고정
	#test_size = .3 : 테스트 데이터의 비율을 30%로 하겠다 (= 학습 데이터는 70%)
	#stratify=y : train과 test로 분리될 때, 원 데이터 y의 분포를 그대로 따라가도록 분리 (이거 넣으면 .93 나오고 빼면 1 나옴)
  1. 디폴트는 shuffle = True다. 즉, 굳이 안 써도 되긴 하다.
  2. (필수) random_state = 42
    • 난수 생성기의 시드를 고정하는 옵션이다.
    • 이게 무슨 말이냐면, 훈련 데이터와 테스트 데이터를 쪼개는 연산을 여러 번 하더라도 처음 결과를 그대로 고정시켜 준다는 뜻이다.
    • 저걸 안 쓰면 매번 연산을 수행할 때마다 데이터가 다르게 쪼개질 것이고, 결과도 조금씩 바뀔 것이기 때문에 안정성을 담보하기 어렵다고 한다.
    • 여담으로 42라는 숫자의 유래는 <은하수를 여행하는 히치하이커를 위한 안내서>라고. 숫자 자체에 큰 의미는 없고 그냥 양덕의 로망을 실현해놓은 것이다.
  3. stratify=y
    • 훈련 데이터와 테스트 데이터를 나눌 때, 원래 데이터의 분포를 그대로 따라가게끔 설정하는 옵션이다. 이건 왠만하면 넣는 것을 권장한다고 한다.
    • 예를 들어 모델을 통해 예측하려는 y에 흰 공 60개, 검은 공 40개가 들어있다고 치고 훈련 데이터와 테스트 데이터를 7:3으로 나눈 상황이라고 가정하면, 훈련 데이터의 양은 70개고 이 안에서 흰 공과 검은 공의 비율은 원본 데이터 y의 비율을 그대로 따라간 3:2, 즉 흰 공 42개와 28개가 된다.
    • 그리고 테스트 데이터의 양은 30개, 그리고 흰 공과 검은 공의 비율은 원본 데이터 y의 비율을 그대로 따라간 3:2, 즉 흰 공 18개와 검은 공 12개가 된다.
    • 만약 저 옵션을 설정하지 않으면, 정말 재수가 없으면 훈련 데이터 70개가 뽑혔는데 흰 공만 왕창 들어가 있는 상황이 생길 "수도" 있다. 이렇게 되면 이 훈련 데이터를 기반으로 학습시킨 모델의 예측력도 자연히 낮아질 수밖에 없으니, 저 옵션을 넣어서 그와 같은 상황을 방지해 주는 것.
    • 이 옵션은 분류의 경우에만 유의하다. 단일 숫자를 예측하는 회귀의 경우에 저 옵션을 넣으면 에러가 난다.
  4. test size = .3 : 이건 그냥 테스트 데이터의 사이즈를 정해주는 옵션.

Logistic Regression 모델 불러오기

Logistic Regression 모델 불러오기
from sklearn.linear_model import LogisticRegression
model_lor = LogisticRegression(max_iter=150)

이 문제에서는 예측하려는 y(붓꽃의 종류)가 범주형 데이터이므로 logistic regression을 쓴다.
어떤 모델을 쓸지는 추정하려는 종속변수가 뭐냐에 따라 결정하면 된다.

  1. max_iter
    • maximum iteration의 줄임말로, 모델이 특정한 결과로 수렴(Convergence)할 때까지 최적화 알고리즘이 최대(max) 몇 번의 연산을 반복(iteration)할 것인지를 결정하는 옵션이다. 디폴트는 100으로 설정되어 있는데, 가끔씩 이 정도로 최적해에 도달하기 어려울 경우 워닝 메시지를 띄우는 경우가 있다고 한다. 내 경우에는 max_iter를 150으로 설정했더니 워닝 메시지가 사라졌다.
    • 다만, 저기서 max_iter를 150에서 200, 300, 500 등으로 계속 높여도 정확도가 올라간다거나 성능이 더 좋아지는 것은 아니었다. 이걸 잘 해석하는 게 중요한데, 150번 정도에 문제의 해결이 가능할 만큼 문제의 복잡도가 낮고 데이터가 간단하기 때문이다. 만약 훨씬 더 복잡한 데이터를 다룬다면 150번 정도의 연산으로도 부족할 수 있다.
    • 따라서 max_iter는 어떤 정해진 최적의 값이 있다거나 한 건 아니고, 학습 시간이 길어지는 것과 모델의 정확도를 높이는 사이의 trade-off를 생각하면서 다양하게 시도해 보고 결정해야 하는, 일종의 하이퍼파라미터로 생각해야 한다.

모델에 학습시키기 + test 데이터에 적용하기 + 평가

#5. model_lor에 X_train과 y_train을 기준으로 학습시키기
model_lor.fit(X_train,y_train)

#6. model_lor은 학습이 끝났으니 X_test데이터를 기반으로 예측해 보기
y_pred_test = model_lor.predict(X_test)

#7. 모델 평가
from sklearn.metrics import accuracy_score, f1_score
print(accuracy_score(y_test,y_pred_test).round(3))
  1. fit(X_train, y_train)
    • 사전에 분리해 놓았던 X_train과 y_train을 넣어서 모델을 학습시키는 단계.
    • 여기서 test 데이터를 쓰지 않도록 각별히 주의할 것. 아직은 test 데이터에 대해 아무것도 모르는 단계다.
  2. y_pred_test = model_lor.predict(X_test)
    • 모델 학습이 완료되고 나면 그 때 가서 test 데이터를 넣어서 y를 예측해 본다.
    • 이 때 변수명을 y_pred_test로 설정한 것은 X_test 데이터를 기반으로 예측(prediction, pred)한 y이기 때문. (y_test가 아니다)
  3. 예측까지 끝났으면 마지막으로 y_test와 y_pred_test를 놓고 비교해 본다. 시험으로 비유하자면 정답을 맞춰보는 것. accuracy_score를 구할 때는 답지에 해당하는 y_test가 앞에 오고, 우리가 제출한 답인 y_pred_test가 뒤에 온다.

과제 2번 리뷰

#1. 데이터 불러오기
from sklearn.datasets import fetch_california_housing
housing = fetch_california_housing()
X, y = housing['data'], housing['target']

#2. train 데이터와 test 데이터 분리하기
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, shuffle=True, random_state=42, test_size = .3)

#3. Linear Regression 모델 불러오기
from sklearn.linear_model import LinearRegression
model_lr = LinearRegression()

#4. model_lr에 X_train과 y_train을 기준으로 학습시키기
model_lr.fit(X_train,y_train)

#5. model_lr 학습이 끝났으니 X_test데이터를 기반으로 예측해 보기
y_pred_test = model_lr.predict(X_test)

#6. MSE 구해보기
from sklearn.metrics import mean_squared_error, r2_score
print(mean_squared_error(y_test,y_pred_test).round(3))
print(r2_score(y_test,y_pred_test).round(3))
  1. 1번 문제와 큰 흐름은 다를 게 없지만, 이번에는 예측하려는 변수 y가 범주형이 아닌 이산형 변수(집값)이므로, 로지스틱이 아닌 선형회귀(Linear Regression)를 써야 한다.
  2. 위에서 언급한 대로, 회귀에 쓸 훈련 데이터와 테스트 데이터를 분리할 때는 stratify = y 옵션을 쓸 수 없다. (train_test_split 함수에서는 회귀 문제에서 stratify를 아예 지원하지 않는다) 타겟 변수가 연속적인 값이기 때문에 원본 데이터 세트와 클래스 비율을 똑같이 가져간다는 개념이 아예 성립하지 않는 것.
  3. 평가 지표 중 accuracy_score는 분류 문제에서 예측이 정확히 맞았는지의 비율을 계산하는 지표이기 때문에 회귀 문제에서 사용하는 것은 적절하지 않다. 따라서, 회귀 문제에서는 예측 값이 실제 값과 얼마나 가까운지를 측정하는 지표인 MSE나, 결정계수(R-squared)를 평가지표로 사용하는 것이 일반적이다.

과제 3번 리뷰

#1. 데이터 불러오기
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target

#2. 훈련 데이터 / 테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state = 42, stratify = y)

#3. 의사결정나무 불러오기 + 학습시키기
from sklearn.tree import DecisionTreeClassifier, plot_tree
model_dt = DecisionTreeClassifier(random_state = 42)
model_dt.fit(X_train,y_train)

#4. X를 기반으로 예측치 y_dt_pred 만들기
y_dt_pred = model_dt.predict(X_test)

#5. 정확도 평가
from sklearn.metrics import accuracy_score, f1_score
print(accuracy_score(y_test,y_dt_pred).round(3))
print(f1_score(y_test,y_dt_pred,average='weighted').round(3))

데이터를 불러오고 훈련 데이터와 테스트 데이터로 나누는 과정까지는 똑같다.

의사결정나무(DecisionTree) 모형 불러오기

#3. 의사결정나무 불러오기 + 학습시키기
from sklearn.tree import DecisionTreeClassifier, plot_tree
model_dt = DecisionTreeClassifier(random_state = 42)
model_dt.fit(X_train,y_train)
  1. 의사결정나무 모형은 사이킷런의 tree에 들어있다.
  2. 여기서도 모델에 X_train과 y_train을 써서 학습(fit)시키는 과정은 똑같다.

test 데이터에 적용하기 + 평가

#4. X를 기반으로 예측치 y_dt_pred 만들기
y_dt_pred = model_dt.predict(X_test)

#5. 정확도 평가
from sklearn.metrics import accuracy_score, f1_score
print(accuracy_score(y_test,y_dt_pred).round(3))
print(f1_score(y_test,y_dt_pred,average='weighted').round(3))
  1. X_test를 기반으로 y를 예측(y_dt_pred)하는 것은 항상 훈련 데이터를 기반으로 모델의 학습이 끝나고 난 뒤다. 순서를 헷갈리거나, 학습을 테스트 데이터로 시키거나 하는 실수에 주의할 것.
  2. 의사결정나무 모형은 독특하게 분류와 회귀를 모두 수행할 수 있다. 다만, 의사결정나무 모형으로 회귀분석을 수행할 경우 과적합의 위험이 있어, 이 문제에서는 다루지 않았지만 가지치기(pruning)나 나무의 최대 깊이(max_depth)를 설정해주는 등의 방식으로 과적합을 피해갈 수 있다. 이 경우 max_depth도 분석가가 재량으로 모델 바깥에서 정해줘야 하는 하이퍼파라미터가 된다.
  3. 이 문제에서는 의사결정나무 모형이 붓꽃의 종류를 분류하는 문제에 사용되었으므로, 모델의 정확도를 평가하는 지표로 accuracy를 사용하였다.
profile
기본기를 소홀히 하지 말자

0개의 댓글

관련 채용 정보