1. hr 데이터셋
- 이번에는 승진관련(임의)데이터이고 여기서 이런 정보를 주면 is_promoted 분류를 해보려고 합니다.
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
hr_df = pd.read_csv('hr.csv')
hr_df.head()
hr_df.info()
hr_df.describe()
간단하게 데이터를 확인할 수 있습니다.
이렇게 표로 보다는 barplot으로 한번 확인해보도록 하겠습니다.
즉 독립변수들이 is_promoted에 영향을 받는지 안 받는지를 확인하기 위해서 확인해보도록 하겠습니다.
sns.barplot(x='previous_year_rating', y=is_promoted, data=hr_df)
이렇게 독립변수로 사용할 수 있는 데이터들을 기억해두도록 합니다.
이유는 종속변수에 영향을 주는 데이터들의 값들이기 때문입니다.
확인해보기
확실히 referred가 데이터 수가 더 없다는것을 확인해 볼 수 있습니다.
그래서 심지가 길게 표현됩니다.
마저 살펴보겠습니다.
이 그래프는 성별에따른 승진은 크게 의미 없다는것을 알 수 있습니다.
그래프로 확인해보기
plt.figure(figsize=(12,9))
sns.barplot(x='region', y='is_promoted', data=hr_df)
plt.xticks(rotation=45)
결측값 확인하기
hr_df.isna().mean()
결측값이 있는걸 확인해보기
hr_df['education'].value_counts()
hr_df['previous_year_rating'].value_counts()
이런 데이터들은 drop하는 방향으로 생각하려고 합니다.
hr_df = hr_df.dropna()
hr_df.info()
원핫인코딩대상(오브젝트)의 카테고리값들을 확인하기
for i in['department', 'region', 'education', 'gender', 'recruitment_channel']:
print(i, hr_df[i].nunique())
지역 값들은 상관이 없을거같아서 지역 값은 제거하고 원핫인코딩을 하겠습니다.
hr_df = pd.get_dummies(hr_df, columns=['department', 'education', 'gender', 'recruitment_channel'])
hr_df.head()
hr_df.drop(['employee_id',
'region'], axis=1, inplace=True)
hr_df.head()
테스트값 분리 모델이용
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(hr_df.drop('is_promoted', axis=1),
hr_df['is_promoted'],
test_size=0.2,
random_state=2024)
#학습
X_train.shape, y_train.shape
#((38928, 23), (38928,))
#테스트
X_test.shape, y_test.shape
#((9732, 23), (9732,))
데이터 전처리 끝이 났습니다.
2. 로지스틱 회귀(Logistic Regression)
- 둘 중의 하나를 결정하는 문제(이진 분류)를 풀기 위한 대표적인 알고리즘
- 다항 분류 문제에도 확장될 수 있음
- 종속 변수 Y는 두 가지 범주 중 하나를 가짐(예:0 또는 1)
- 목표는 특정 범주의 속할 확률을 예측하는 것
- 예측 모델은 아닙니다. 이 모델은 분류 모델입니다
로지스틱 회귀 모델은 일반화 선형 모델의 일종으로, 독립 변수의 선형 조합을
로지스틱 함수(시그모이드 함수)를 사용하여 종속 변수에 대한 확률 점수로 변환
from sklearn.linear_model import LogisticRegression
lr= LogisticRegression()
lr.fit(X_train, y_train)
pred = lr.predict(X_test)
from sklearn.metrics import accuracy_score
accuracy_score(y_test, pred)
#0.9205713111385121
정확도가 92%가 나왔지만
지금은 분류문제이기때문에 의미가 살짝 달라질 수 있습니다.
분류로 따지면 0의 값이 훨씬 많기때문에 그냥 0(승지못한거)으로 찍었을때 정확도가 높다는것을 확인할 수 있습니다.
그러니까 정확한 값이 아니라는말인거죠.
그냥 냅다 0으로 찍어버리면 정확도가 높은 느낌!
ai 입장 : 아! 0을 찍으면 정확도가 높아지는구나
입니다. accuracy는 이것을 검증하지 못합니다.
그래서 검증하기 위해서 혼돈 행렬이 필요합니다.
3. 혼돈 행렬(confusion matrix)
- 정밀도와 재현율(민감도)을 활용하는 평가용 지수를 이야기합니다.
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, pred)
#array([[8784, 100],
[ 673, 175]])
T=TRUE N=NAGATIVE F=FALSE P=POSITIVE
*TN(진음성) : 승진하지 못했는데, 승진하지 못했다고 예측해서 맞춤
*FP(위양성) : 승진하지 못했는데, 승진했다고 예측해서 틀림
*FN(위음성) : 승진했는데, 승을 못했다고 예측해서 틀림
*TP(진양성) : 승진했는데 승진 했다고 예측해서 맞춤.
3-1.정밀도(Precision)
- TP / (TP +FP)
- 무조건 양성으로 판단해서 계산하는 방법
- 실제 승진한 사람중에서 얼마만큼 승진했다고 맞췄는가?
3-2. 재현율(recall)
- TP/ (TP+FN)
- 정확하게 감지한 양성 샘플의 비율
- 실제로 긍정인 것들 중에서 긍정으로 예측한 비율
- 민감도 또는 TPR(True Positive Rate)라고도 부름
3-3. f1 score
- 정밀도와 재현율의 조화평균을 나타내는 지표
조화평균은 정밀도와 재현율이 벌어짐에따라 달라집니다
쉽게말해서얼마나 조화로운지(?)를 생각하면 됩니다.
1번은 0.2
2번은 0.4
3번은 0
각각 조화평균은 0.48, 0.42, 0.5로 얼마나 벌어지는지를 확인할 수 있습니다.
차이가 날수록 산술평균값을 비교했을 때 낮아집니다.
from sklearn.metrics import precision_score, recall_score, f1_score
#정밀도
precision_score(y_test, pred)
#0.6363636363636364
#재현율
recall_score(y_test, pred)
#0.20636792452830188
#f1_score
f1_score(y_test, pred)
#0.31166518254674974
lr.coef_
#array([[-0.51687179, -0.06608108, 0.38010122, 0.05941589, 3.53168128,
0.11251127, -1.95349302, -0.35850951, -0.39898613, -0.3578027 ,
0.49199051, -0.28645626, -1.19810409, 1.53916888, -1.24856123,
-1.65001362, -1.02150699, -1.09923293, -1.80257786, -1.96817568,
-1.67721465, -0.44336313, -1.65017577]])
각각 독립변수의 기울기(웨이트)값 입니다.
아직은 웨이트값이 너무 많기때문에 따로 몇개를 뽑았습니다.(가장 많이 영향을 줄 것 같은걸로)
# 독립변수
tempX= hr_df[['previous_year_rating', 'avg_training_score', 'awards_won?']]
#종속변수
tempy = hr_df['is_promoted']
temp_lr = LogisticRegression()
#학습
temp_lr.fit(tempX, tempy)
temp_df = pd.DataFrame({
'previous_year_rating':[4.0, 5.0, 5.0],
'avg_training_score':[100, 90, 100],
'awards_won?':[0, 1, 1]})
이렇게 숫자를 낸 이유는 테스트데이터를 를 넣어준것입니다.
참고로 승진이 가능한 학습자료를 해보려고 합니다.
pred=temp_lr.predict(temp_df)
pred
#array([0, 1, 1])
승진을 한 사람은 2명 못한사람은 1명
temp_lr.coef_ #기울기
#array([[0.51112537, 0.04309755, 2.09583168]])
temp_lr.intercept_#절편
#array([-7.20658921])
proba = temp_lr.predict_proba(temp_df)
#확률을 뽑아줌
proba
#array([[0.70105625, 0.29894375],
# [0.21021186, 0.78978814],
# [0.14746488, 0.85253512]])
왼쪽은 0일 확률 오른쪽은 1일 확률입니다.
즉 오른쪽이 승진이고 그 확률만 뽑아보고싶다면
proba = temp_lr.predict_proba(temp_df)[:,1]
proba
#array([0.29894375, 0.78978814, 0.85253512])
각 29% 79% 85% 정도 승진 확률이 있습니다.
#임계값 설정
threshold = 0.5
pred = (proba >= threshold).astype(int)
pred
#array([0, 1, 1])
만약 50%로 주고싶다 하면 0.5를 두고proba(확률뽑아줌) 예측하면
0,1,1이 됩니다 승진 누락, 승진, 승진 결과가 나옵니다.
4. 교차 검증(Cross Validation)
- ML, DL에서도 나오니 알아둬야합니다!
- train_test_split에서 발생하는 데이터의 섞임에 따라 성능이 좌우되는 문제를 해결하기 위한 방법
- k겹(k-fold)교차 검증을 가장 많이 사용합니다.
from sklearn.model_selection import KFold
kf = KFold(n_splits=5)
kf
*n_splits=5의 뜻은 랜덤으로 5개로 나분리해서 test,train으로 각각 나눠서
그 사이의 평균값을 찾는것입니다.
hr_df
for train_index, test_index in kf.split(range(len(hr_df))):
print(train_index, test_index, len(train_index), len(test_index))
#[ 9732 9733 9734 ... 48657 48658 48659] [ 0 1 2 ... 9729 9730 9731] 38928 9732
#[ 0 1 2 ... 48657 48658 48659] [ 9732 9733 9734 ... 19461 19462 19463] 38928 9732
#[ 0 1 2 ... 48657 48658 48659] [19464 19465 19466 ... 29193 29194 29195] 38928 9732
#[ 0 1 2 ... 48657 48658 48659] [29196 29197 29198 ... 38925 38926 38927] 38928 9732
#[ 0 1 2 ... 38925 38926 38927] [38928 38929 38930 ... 48657 48658 48659] 38928 9732
kf = KFold(n_splits=5, random_state=2024, shuffle=True)
kf
랜덤값을 2024로 맞춰주고 스플리트를 5로 맞춰줍니다.
일관적인 randome_state=2024으로 합니다.
acc_list = []
for train_index, test_index in kf.split(range(len(hr_df))):
X = hr_df.drop('is_promoted', axis=1)
y = hr_df['is_promoted']
X_train = X.iloc[train_index]
X_test = X.iloc[test_index]
y_train = y.iloc[train_index]
y_test = y.iloc[test_index]
lr = LogisticRegression()
lr.fit(X_train, y_train)
pred = lr.predict(X_test)
acc_list.append(accuracy_score(y_test, pred))
kf로 만든 랜덤값을 이용해서 학습을 시켰습니다.
acc_list
#[0.9202630497328401,
# 0.9217016029593095,
# 0.9324907521578298,
# 0.9276613234689683,
# 0.9189272503082614]
np.array(acc_list).mean()
#0.9242087957254418
#5번 섞고도 평균값이 92정도로 높습니다는것을 확인가능함
크로스벨리데이션(교차검증)을 사용하는 이유는 결과를 좋게하는것이 아니라, 믿을만한 검증을 하기 위함입니다.
'AI 컴퓨터 비전프로젝트' 카테고리의 다른 글
[ML/DL] 파이토치로 구현한 논리회귀 (5) | 2024.07.23 |
---|---|
[ML] kMeans_비지도학습, 마케팅데이터셋 활용 (1) | 2024.07.16 |
[ML] 선형 회귀_Rent값 예측 모델 만들기(2) (0) | 2024.07.04 |
[ML] 선형 회귀_Rent값 예측 모델 만들기(1) (0) | 2024.07.02 |
[ML] 아이리스 데이터셋(Iris DataSet) (1) | 2024.07.01 |