KT AIVLE School 3기/머신러닝

KT Aivle DX 트랙 26일차

Do잇 2023. 3. 9. 21:49

🔍머신러닝 4일차

 

👨‍🏫 질의응답 시간!

 

💡 kNN 모델 성능을 높이기 위한 방법

       - MinMaxScaler

       - StandardScaler

       - MaxAbsScaler

       - BobustScaler 등등

 이 많은 스케일링 중에 수업시간에는 한정된 시간을 고려하여 MinMaxScaler를 사용하는 것이지, MinMax 정규화를 사용할 것을 강조한 것은 아니다. 또한, 우리 입장에서는 독립변수가 1개인 경우 스케일링을 진행할 필요없다.

 

❓❗ x_train, x_test만 스케일링을 하고 y는 왜 하지 않는건가요?

우리가 예측해야 하는 타겟인 y는 독립변수들 값에 따른 거리를 비교해 최근접 이웃을 골라 예측하기 때문에 스케일링 하지 않는다.

 

💡 선형회귀 모델을 이용해서 도출한 회귀선(가중치, 편향)과 seaborn패키지의 regplot으로 그린 회귀선은 항상 같은 것이다. 우리는 회귀선을 도출하는 과정을 배우기 위해 따로 그려주는 것.

 

 

❓❗ speed = np.array [x_train.min(), x_train.max()] 하면 [4,25]가 왜 안나오나요?

저렇게 하면 [[4]

                     [25]]가 나왔을 것.

speed = np.array ([x_train.min()[0], x_train.max()[0]])하면 [ 4  25]가 나온다. 

x_train.min() 이 시리즈이기 때문에 

 

 

❓❗ 범주형 변수를 일일이 변수에 저장할 수 없을 때,  혹시 범주형 변수만을 따로 추출해서 변수에 담아 더미 변수화를 할 수 있는 방법이 있을까요?

 

#1. 범주형 변수는 대부분 str이므로 

x = pd.get_dummies(x, columns = dumm_cols, drop_first = True)에서 columns = dumm_cols,를 지우고,

x = pd.get_dummies(x,drop_first = True) 라고 입력하면 object형 변수를 모두 가변수화한다는 뜻!

 

#2. object 형 변수 이름 얻기

x.dtypes를 하면 object들을 알 수 있다.

이를 cols로 선언하고 ( cols = x.dtypes)

dumm_cols = list(cols.loc[cols.values == 'object'].index)

그리고 나서 x = pd.get_dummies(x, columns = dumm_cols, drop_first = True)를 해주면 된다.

 

이후 필요하다면 dumm_cols.append('Education')으로 해서 추가해주면 된다.

 

 

❓❗ 모델이 유의미한지 알려면 회귀계수의 t통계량의 p-v를 보고 유의미한지 봐야한다고 알고 있는데 회귀계수의 유의미와 별개로 그냥 r2_score만 보고 설명력을 따지고 넘어가는 게 맞나요?

 

 회귀계수의 유의성을 따지는 것은 너무 통계적이다. 우리는 한정된 시간으로 인해 통계를 깊이 있게 들어갈 수 없고, 깊이있게 따져볼 수 없다.

 

 

 

❓❗ x_train에 대한 스케일링을 하는 것은 스케일링을 통해 feature들의 데이터 범위를 같게 하기 위함이라고 이해를 했습니다. 그렇다면 x_test에 대한 스케일링이 y_pred를 구할 때, feature들의 데이터 범위를 같게 하기 위해서 스케일링을 진행한다고 이해하면 될까요? 

 

 


 

위 질문말고도 더 많은 질문이 있었지만 내가 다 담아내지 못 했다. 같은 에이블러이고 같은 수업을 들었는데  다 다른 생각을 한다는 것이 새삼 신기하다.  매번 많은 것을 얻어가는 질의응답시간이다. 
질문해주신 🐛에이블러분들에게 정말 감사하다. ❤ 

 


 

 

💻 kNN 분류문제(실습03_04_KNN(Attrition))

 

📌 target(Attrition)에 대한 값 분포 확인

# target 값 분포 확인
data['Attrition'].value_counts()   # 불균형 클래스

# 이직한 사람보다 안한 사람이 더 많음. 정확도는 나쁘지 않을 것이다는 걸 예측할 수 있다.
# 1에 대한 성능이 낮다. 1의 precision과 recall이 낮을 것. 하지만 0이 높으므로 accuracy는 높을 것

 

 

📌 변수 제거

더보기
# 제거 대상: EmployeeNumber
drop_cols = ['EmployeeNumber']

# 변수 제거
data.drop(drop_cols, axis = 1, inplace = True)

# 확인
data.head()

 

 

📌 x,y분리

더보기
# target 확인
target = 'Attrition'

# 데이터 분리
x = data.drop(target, axis=1)
y = data.loc[:,target]

 

 

📌 가변수화

더보기
# 확인
x.info()

# 가변수화 대상: Gender, JobSatisfaction, MaritalStatus, OverTime
dumm_cols = ['Gender', 'JobSatisfaction', 'MaritalStatus', 'OverTime']

# 가변수화
x = pd.get_dummies(x, columns = dumm_cols, drop_first = True)

# 확인
x.info()

 

 

📌학습용, 평가용 데이터 분리 

더보기
# 모듈 불러오기
from sklearn.model_selection import train_test_split

# 데이터 분리
x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=0.3,random_state=1)

 

 

📌 정규화

# 확인
x_train.head(5)

# 모듈 불러오기
from sklearn.preprocessing import MinMaxScaler

# 정규화
scaler = MinMaxScaler()
scaler.fit(x_train)                   
# fit하기 = x_train의 최솟값/최댓값 찾기, 정규화 기반 쌓기

x_train = scaler.transform(x_train)   
# fit한 결과를 바탕으로 x_train 실제 정규화 수행

x_test = scaler.transform(x_test)     
# fit한 결과를 바탕으로 x_test 실제 정규화 수행

# 결과
x_train # 배열이므로 x_train.head(5)하면 오류남.

 

💡kNN분류문제에서의 정규화 모듈 불러오기

  from sklearn.preprocessing import MinMaxScaler

 

 

💡x_train = scaler.fit_transform(x_train)    # fit과 transform을 한번에 한다. 
    x_test = scaler.transform(x_test) 
    # x_test = scaler.transform(x_test)에는 fit_transform을 하면 안된다. fit은 x_train만 해주는 것.

 

⭐ 잘 기억할 것

  1. 평가(미래)데이터가 학습(현재)데이터에 영향을 못 미친다.

  2. 평가데이터를 정규화할 때는 학습데이터의 규칙을 그대로 적용한다.

 

 

 

📌 모델링

# 1단계: 불러오기
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import confusion_matrix, classification_report, r2_score


# 2단계: 선언하기
model = KNeighborsClassifier()

# 3단계: 학습하기
model.fit(x_train,y_train)

# 4단계: 예측하기
y_pred = model.predict(x_test)

💡여기 분류문제인 KNeighborsClassifier에서  r2_score가 되는 이유는 0과 1을 연속된 값으로 보기 때문.
   하지만 r2_score는 분류문제에서는 전혀 의미가 없다. 이 점을 주의할 것.

   따라서 위 r2_score는 지워주어야 한다.

 

잠깐❗) 분류 => from sklearn.metrics import confusion_matrix, classification_report

           회귀 => from sklearn.metrics import mean_absolute_error, r2_score

 

더보기
# 내가 한 것.
# 5단계: 평가하기
print(accuracy_score(y_test,y_pred))

from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix

print(precision_score(y_test,y_pred))
print(recall_score(y_test,y_pred))     
print(classification_report(y_test,y_pred))       # precision과 recall을 할 필요 없다.
print(confusion_matrix(y_test,y_pred))
# 이장래 강사님께서 하신 것.
# 5단계: 평가하기

print(classification_report(y_test,y_pred))
print(confusion_matrix(y_test,y_pred))

# 여기서 정확도는 높지만 1의 recall이 많이 낮은 것을 볼 수 있다.

 

 

📕 Decision Tree(결정 트리, 의사결정 나무)

 

- 특정 변수에 대한 의사결정 규칙을 나무 가지가 뻗는 형태로 분류해 나간다.

- 분류와 회귀 모두에 사용되는 지도학습 알고리즘이다.

  분석 과정이 직관적이며, 이해와 설명하기가 쉬움.

  스케일링 등의 전처리 영향도가 크지 않음.

  분석 과정을 실제로 눈으로 확인할 수 있음 → 화이트박스 모델

- 스무고개와 비슷하게 의미 있는 질문을 먼저 하는 것이 중요.

- 과적합으로 모델 성능이 떨어지기 쉬움 → 트리 크기를 제한하는 튜닝이 필요

- 정보이득이 가장 큰 변수를 선택

- 확률에 근거해 예측을 한다.

 

📌불순도(Impurity)

- 순도의 반대말 

- 불순도는 0과 0.5 사이(불순도가 가장 높은 것은 0.5)

- 불순도를 수치화 할 수 있는 지표=> 지니 불순도(Gini Impurity), 엔트로피(Entropy)

 

📌 지니 불순도(Gini Impurity) : 대표적인 불순도 수치화 지표

 - 분류 후에 얼마나 잘 분류했는지 평가하는 지표

   (얼마나 순도가 증가했는지, 불순도가 감소했는지)

- 이진 분류로 나뉠 때 사용됨

- 지니 불순도가 낮을수록 순도가 높음

- 지니 불순도는 0(순수,완벽하게 분류)과 0.5( 50:50으로 섞임)사이의 값 (이진 분류의 경우)

  지니 불순도가 낮은 속성으로 의사결정 트리 노드 결정.

 

💡 gini = 0.66❓

 - 분류해야할 값이 2개인 경우에만 0.5가 최대!

   분류해야할 값이 3개인 경우 0.5보다 큰 값이 나올 수 있다.

 

 

📌 정보 이득(Information Gain)

- 우리가 알고 싶은 것 = 정보 이득 = 어떤 속성이 얼마나 많은 정보를 제공하는가

  엔트로피는 단지 속성의 불순도를 표현

- 정보 이득이 크다 = 어떤 속성에서 분할할 때 불순도가 줄어든다.

  모든 속성에 대해 분할한 후 정보 이득 계산

  정보 이득이 가장 큰 속성부터 분할한다.

- 정보 이득 = 부모의 불순도 - 자식의 불순도

  자식 중 한 자식의 불순도가 더 클 수도 있다.

  하지만 가중치를 계산해보면 자식 전체의 불순도는 크지 않다.

 

📌 가지치기

- 가지치기를 하면 학습 데이터에 대한 성능은 낮아지지만, 평가데이터에 대한 성능을 높일 수 있다.

  가지치기를 하지 않으면 모델이 학습 데이터에는 매우 잘 맞지만, 평가데이터에는 잘 맞지 않을 수 있다.

 → 과대적합, 일반화되지 못함.

- 여러 하이퍼파라미터 값을 조정해서 가지치기 할 수 있다.

  가장 적절한 하이퍼파라미터 값을 찾도록 노력해야한다.

 

📌 주요 하이퍼파라미터

 

max_depth(대표적인 하이퍼파라미터)

- 트리의 최대 깊이(기본값:None)

- 값이 클수록 더 깊이있게 분할

- 계속 분할되면 트리 깊이가 너무 깊어져 과적합이 발생할 수 있으니 적절한 값 설정 필요

✔ min_samples_split - 값이 작을수록 더 깊이 있게 분할

✔ min_samples_leaf - 값이 작을수록 더 깊이 있게 분할

✔ max_feature

✔ max_leaf_node

 

 

 

💻 Decision Tree 분류문제(ML03_03_Decision Tree(Attrition))

 

📌 변수제거

더보기
# 제거 대상: PassengerId, Name, Ticket, Cabin
drop_cols = ['PassengerId', 'Name', 'Ticket', 'Cabin']

# 변수 제거
data.drop(drop_cols, axis=1, inplace=True)

# 확인
data.head()

 

 

📌 결측치 처리

# Age 결측치를 중앙값으로 채우기
age_median = data['Age'].median()
data['Age'].fillna(age_median, inplace=True)
# Embarked 최빈값으로 채우기
emb_freq = data['Embarked'].mode()[0]
data['Embarked'].fillna(emb_freq, inplace=True)

 

 

📌 x,y분리

더보기
# target 확인
target = 'Survived'

# 데이터 분리
x = data.drop(target, axis=1)
y = data.loc[:, target]

 

 

📌 범주형 변수에 대한 가변수화

더보기
# 확인
x.info()

# 가변수화 대상: Pclass, Sex, Embarked
dumm_cols = ['Pclass', 'Sex', 'Embarked']

# 가변수화
x = pd.get_dummies(x, columns=dumm_cols, drop_first=True)
# columns=dumm_cols가 없이 get_dummies를 하면 Pclass는 int이므로 가변수화가 안된다.
# 확인
x.head()

 

 

📌 학습용, 평가용 데이터 분리

더보기
# 모듈 불러오기
from sklearn.model_selection import train_test_split

# 7:3으로 분리
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=1)

 

 

📌 모델링

# 1단계: 불러오기
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import confusion_matrix, classification_report

# 2단계: 선언하기
model = DecisionTreeClassifier(random_state=1)

# 3단계: 학습하기
model.fit(x_train,y_train)

# 4단계: 예측하기
y_pred = model.predict(x_test)

# 5단계 평가하기
print(confusion_matrix(y_test,y_pred))
print(classification_report(y_test,y_pred))

💡 2단계 선언하기 model = DecisionTreeClassifier(random_state=1)에서 

    model = DecisionTreeClassifier(max_depth=5 ,random_state=1) 를 넣어주었을 때,

    5단계까지만 분류를 진행한다.

 

 

📌트리 시각화

# 시각화 모듈 불러오기
from sklearn.tree import export_graphviz
from IPython.display import Image

# 이미지 파일 만들기
export_graphviz(model,                              # 모델 이름
                out_file='tree.dot',                # 파일 이름 
                feature_names=x.columns,            # Feature 이름(list(x)써도 됨.)**
                class_names=['die', 'survived'],    # Target Class 이름**
                rounded=True,                       # 둥근 테두리
                precision=2,                        # 불순도 소숫점 자리수
                max_depth=5,                        # 보고싶은 Tree 깊이 설정
                filled=True)                        # 박스 내부 채우기

# 파일 변환
!dot tree.dot -Tpng -otree.png -Gdpi=300

# 이미지 파일 표시
Image(filename='tree.png')

- 불순도가 낮을수록(0에 가까울수록) 진한 배경색

 

 

💡** Feature 이름과 Target Class 이름만 바꿀 수 있다. 

   Target Class 이름(class_names=[' '])의 경우 회귀에서는 제외, 회귀는 class가 아니니까)

  ⭐ class_names=[ 'No', 'Yes' ])의 경우 0과 1을 잘 고려해서 넣을 것!

 

💡 이미지 파일 만들기에서 export_graphviz(model, max_depth=5, ...)를 넣으면

    이미지 파일에 5단계의 가지만 그려진다.  

 

 

💡!dot tree.dot -Tpng -otree.png -Gdpi=300    이 줄은 마음대로 띄어쓰면 안된다. 

 ex) -Gdpi = 300 이렇게하면 오류남.

 

-Gdpi 300이면 고해상도이다. 기본값이 90정도 밖에 안되므로

 

 

💡이미지 파일 이름을 바꿔주려면 여기 표시되어 있는 부분 전부 바꿔주어야한다.

# 이미지 파일 만들기
export_graphviz(model,                              # 모델 이름
                out_file='tree.dot',                # 파일 이름 
                feature_names=x.columns,            # Feature 이름 (list(x)써도 됨.)**
                class_names=['die', 'survived'],    # Target Class 이름**
                rounded=True,                       # 둥근 테두리
                precision=2,                        # 불순도 소숫점 자리수
                max_depth=5,                        # 보고싶은 Tree 깊이
                filled=True)                        # 박스 내부 채우기

# 파일 변환
!dot tree.dot -Tpng -otree.png -Gdpi=300

# 이미지 파일 표시
Image(filename='tree.png')

 

💡 sklearn에 플롯트리(plot_tree)도 있지만 플롯트리는 가독성이 떨어진다.

    강사님이 그래프비즈(graphviz)를 더 좋아하심 😊

 

 

📌변수 중요도 시각화

# 변수 중요도 시각화
plt.figure(figsize=(6,8))
plt.barh(list(x),model.feature_importances_)
plt.ylabel('Features')
plt.xlabel('Importances')
plt.show()

- Feature 순서대로 값을 가짐.

- 트리 구성에 중요한 역할을 한 변수를 시각화해서 확인할 수 있음.

- plt.barh(y = list(x), width = model.feature_importances_)

- sns.barplot(y = list(x), x = model.feature_importances_)

seaborn은 x와 y의 위치를 바꾸면 막대그래프가 가로로 나온다.

 

 

 

💡 변수 중요도를 얻고자 Decision Tree를 쓰지 마라.

    Decision Tree를 쓰는 목적은 변수 중요도를 알아보기 위한 것이 아니다.

    Decision Tree를 쓰게 됐다면, 변수 중요도를 부수적으로 확인하라는 것이지 목적이 아니다.

 

💡 Decision Tree는 첫 분석에서 정보이득을 가장 크게 얻을 수 있는 feature(독립변수)를 찾는 것이 중요.

 

💡 max_depth = 5로 하는 튜닝은 train으로만 계속 해보는 것.

    따라서 우리는 계속 튜닝하면 안됨. 우리는 test값이기 때문에

 

 

 

💡Linear Regression  vs  kNN  vs  Decision Tree

Linear Regression
(선형 회귀)
- 회귀문제만 가능
- feature(독립변수)들이 많을수록 모델이 복잡해진다.
- 적절한 독립변수를 넣는 것이 중요.
- 정말 중요한 변수들에 가중치
kNN - 분류와 회귀 둘 다 가능
  따라서 k값이 중요
- k값의 파라미터 값은 n-neighbors이다. 최적의 이웃의 개수
- 학습데이터가 100개일 때, k값이 100개이면 평균이 된다.
   k가 데이터 개수가 되면 평균이 되고 가장 단순한 모델이 된다.
따라서, k가 클수록 가장 단순한 모델이 된다.
   ( k가 1일 때(작을수록) 가장 복잡한 모델이다.)
   ( k값은 많아야 5 ~ 10 사이이다. 10도 너무 많음) 
Decision Tree
(결정 트리)
- 분류와 회귀 둘 다 가능
- max_depth가 클수록 복잡해진다.
  적절한 max_depth를 넣어주는 것이 중요.

- 모델이 복잡하다는 것과대적합 가능성이 높다는 것.

   너무 학습에 치중한 나머지 평가데이터의 성능이 안좋아진다.

 

 

 

 

📕 Logistic Regression(로지스틱 회귀)

-로지스틱 회귀는 선형 회귀 방식을 '분류'에 적용한 알고리즘이다.

  ex)종양 데이터를 근거로 종양인지(Y=1) 아닌지(N=0)를 판단하는 문제에 적용할 수 있다.

- 시그모이드(sigmoid) 함수라고도 부름

  시그모이드 함수는 X 값이 아무리 커지거나 작아져도 1이나 0 값 만을 반환하는 함수이다.

  (-∞, ∞) 범위를 갖는 선형 선형 판별식 결과로 (0,1)범위의 확률 값을 얻게 됨.

- 확률 값 0.5를 기준으로 이진 분류를 수행할 수 있게 됨.

- 학습을 통해 선형 회귀선을 찾는 것이 아니라 로지스틱 함수에 의해 반환되는 값을 확률로 간주하여 그 확률에 따라 분류를 결정함.

 

💡 로지스틱 회귀는 선형 회귀 방식을 기반으로 하되 시그모이드 함수를 이용하여 '분류'를 수행하는 회귀이다. 지도학습의 대장인 '회귀'와 '분류'가 합쳐진 로직이다. 

 

🌟하지만 잊지 말자 로지스틱 회귀에서 '회귀'는 도구이고 '분류'가 목적이라는 점을!

 

 

😅 [0,1]은  리스트가 아니라 포함.

      (0,1)은 튜플이 아니라 미포함.

 

 

💻  Logistic Regression분류문제(ML03_04_로시즈틱회귀(Iris))

 

📌 모델링

 

# 1단계: 불러오기
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, classification_report
# mean_absolute_error,r2_score가 아님을 기억하자

# 2단계: 선언하기
model= LogisticRegression()

# 3단계: 학습하기
model.fit(x_train,y_train)

# 4단계: 예측하기
y_pred = model.predict(x_test)

# 5단계 평가하기
print(confusion_matrix(y_test,y_pred))
print(classification_report(y_test,y_pred))

💡 # 1단계: 불러오기
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, classification_report
mean_absolute_error,r2_score가 아님을 기억하자

 

잠깐❗) 분류 => from sklearn.metrics import confusion_matrix, classification_report

           회귀 => from sklearn.metrics import mean_absolute_error, r2_score

 

 

 

📌 첫번째 품종(setosa)의 확률값을 시각화하기

# 확률값 얻기
p=model.predict_proba(x_test)
p[:5].round(2)

# 어떤 품종의 확률값인지 확인하기
y_pred[:10]
p=model.predict_proba(x_test)    # 확률값 얻기
plt.plot( np.sort(p[:,0])   )    # 정렬해서 시각화
plt.show()

 

 

 

 

 

 

 

 

 

'KT AIVLE School 3기 > 머신러닝' 카테고리의 다른 글

KT Ailvle DX트랙 29일차  (0) 2023.03.14
KT Aivle DX 트랙 27일차  (0) 2023.03.11
KT Avile DX트랙 25일차  (0) 2023.03.08
KT Avile DX트랙 24일차  (0) 2023.03.07
KT Aivle DX트랙 23일차  (0) 2023.03.06