#경고 무시, 모듈 호출
import warnings
warnings.filterwarnings(action='ignore')
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_digits
#데이터 준비
digits = load_digits()
y = digits.target == 9
X_train, X_test, y_train, y_test = train_test_split(
digits.data, y, random_state=0)
from sklearn.dummy import DummyClassifier
dummy_majority = DummyClassifier(strategy = 'most_frequent').fit(X_train, y_train)
pred_most_frequent = dummy_majority.predict(X_test)
print("예측된 레이블의 고유값:", np.unique(pred_most_frequent))
print("테스트 점수: {:.2f}".format(dummy_majority.score(X_test, y_test)))
DummyClassifier(): 실제로 학습 안하고, 단순한 규칙이나 통계 기반으로 예측하는 분류기. => 더 복잡한 머신러닝 모델의 성능을 상대 평가하기 위한 기준선(baseline) 설정. from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier(max_depth=2).fit(
X_train, y_train)
pred_tree = tree.predict(X_test)
print('테스트 점수: {:.2f}'.format(tree.score(X_test, y_test)))
from sklearn.linear_model import LogisticRegression
dummy = DummyClassifier(strategy='stratified').fit(X_train, y_train)
pred_dummy = dummy.predict(X_test)
print('dummy 점수: {:.2f}'.format(dummy.score(X_test, y_test)))
logreg = LogisticRegression(C=0.1, max_iter=1000).fit(X_train, y_train)
pred_logreg = logreg.predict(X_test)
print('logreg 점수: {:.2f}'.format(logreg.score(X_test, y_test)))
from sklearn.metrics import confusion_matrix
confusion = confusion_matrix(y_test, pred_logreg)
print('오차 행렬:\n', confusion)

print('빈도 기반 더미 모델:')
print(confusion_matrix(y_test, pred_most_frequent))
print('\n무작위 더미 모델:')
print(confusion_matrix(y_test, pred_dummy))
print('\n결정 트리:')
print(confusion_matrix(y_test, pred_tree))
print('\n로지스틱 회귀:')
print(confusion_matrix(y_test, pred_logreg))


from sklearn.metrics import f1_score
print('빈도 기반 더미 모델 f1 score: {:.2f}'.format(f1_score(y_test, pred_most_frequent)))
print('\n무작위 더미 모델 f1 score: {:.2f}'.format(f1_score(y_test, pred_dummy)))
print('\n결정 트리 f1 score: {:.2f}'.format(f1_score(y_test, pred_tree)))
print('\n로지스틱 회귀 f1 score: {:.2f}'.format(f1_score(y_test, pred_logreg)))

from sklearn.metrics import classification_report
print(classification_report(y_test, pred_most_frequent,
target_names=['9 아님', '9'], zero_division=0))
print(classification_report(y_test, pred_logreg,
target_names=['9 아님', '9']))
classification_report: 실제 데이터셋 배열, 모델의 예측 배열로 => 분류 모델의 성능 평가하는 메서드. 정밀도, 재현율, F1스코어, 각 클래스에 대한 지지도(support, 각 클래스에 실제로 속하는 데이터포인트수)를 포함한 보고서 생성.target_names는 대상 클래스의 이름 설정. 여기선 True를 9 아님, False를 9로.zero_division=0은 0으로 나누는 경우 거기 0을 할당. 재현율, 정밀도, F1 스코어 등 계산할 때 분모 0이 될 때 그냥 0으로. 어떤 클래스에 대한 예측이 전혀 없을 때 발생.
#모듈 호출
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score, roc_auc_score
from sklearn.metrics import f1_score, confusion_matrix, precision_recall_curve, roc_curve
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
#데이터 호출
diabetes_data = pd.read_csv('../data/diabetes.csv')
#데이터 파악 => 1이 당뇨병, 0이 당뇨병 아님
print(diabetes_data['Outcome'].value_counts())
diabetes_data.head()
diabetes_data.info() #null 값 없다
def get_clf_eval(y_test, pred=None, pred_proba=None):
confusion = confusion_matrix( y_test, pred)
accuracy = accuracy_score(y_test , pred)
precision = precision_score(y_test , pred)
recall = recall_score(y_test , pred)
f1 = f1_score(y_test,pred)
# ROC-AUC
roc_auc = roc_auc_score(y_test, pred_proba)
print('오차 행렬')
print(confusion)
# ROC-AUC print
print('정확도: {0:.4f}, 정밀도: {1:.4f}, 재현율: {2:.4f},\
F1: {3:.4f}, AUC:{4:.4f}'.format(accuracy, precision, recall, f1, roc_auc))
roc_auc_score: ROC-AUC(Receiver Operating Characteristic Curve) 아래의 면적으로 1에 가까울수록 좋은 성능이다. => 여기서 pred_proba가 필요. 나머지는 다 pred만. # 데이터 준비
X = diabetes_data.iloc[:, :-1]
y = diabetes_data.iloc[:, -1]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size = 0.2, random_state = 156, stratify=y)
#로지스틱 회귀로 학습
lr_clf = LogisticRegression()
lr_clf.fit(X_train, y_train)
pred = lr_clf.predict(X_test)
pred_proba = lr_clf.predict_proba(X_test)[:, 1]
get_clf_eval(y_test, pred, pred_proba)
lr_clf.predict(): X_test에 대해서 각 값이 어떤지 1차원 배열로 예측을 반환. lr_clf.predict_proba(): 각 클래스의 예측 확률을 반환. 즉, 모델이 각 클래스에 속한다고 예측하는 확률을 각각 반환.

def precision_recall_curve_plot(y_test=None, pred_proba_c1=None):
precisions, recalls, thresholds = precision_recall_curve( y_test, pred_proba_c1)
# X축을 threshold값으로, Y축은 정밀도, 재현율 값으로 각각 Plot 수행
#정밀도는 점선으로 표시
plt.figure(figsize=(8,6))
threshold_boundary = thresholds.shape[0]
plt.plot(thresholds, precisions[0:threshold_boundary], linestyle='--', label='precision')
plt.plot(thresholds, recalls[0:threshold_boundary],label='recall')
# threshold 값 X 축의 Scale을 0.1 단위로 변경
start, end = plt.xlim()
plt.xticks(np.round(np.arange(start, end, 0.1),2))
plt.xlabel('Threshold value'); plt.ylabel('Precision and Recall value')
plt.legend(); plt.grid()
plt.show()
precision_recall_curve: y_test와 pred_proba_c1을 입력 받아서, 3개의 배열을 반환. 1 정밀도 값(precision), 재현율(recall), 정밀도와 재현율의 임계값. => 그것들을 각각의 변수에 넣는다.
threshold_boundary = thresholds.shape[0]로 하고 plt.plot(thresholds, precisions[0:threshold_boundary], linestyle='--', label='precision')로 하는 이유는, thresholds보다 precisions와 recalls가 항상 1개 더 많은 요소를 가지고 있기 때문. thresholds는 임계값들만 포함하지만, 정밀도와 재현율은 모든 걸 양성으로 분류하는(임계값이 0인 경우)의 스코어 포함. (임계값이 100인 경우, 모두 음성으로 분류하는 경우는 의미가 없어서 안들어간다)plt.xlim()은 X축의 한계값을 2개 반환 => start, end 변수에 넣는다. => plt.xticks(): X축 눈금 설정. np.arange()로 start~end까지 0.1 간격으로 설정 후, np.round(, 2)로 소수점 둘째자리까지 반올림. pred_proba_c1 = lr_clf.predict_proba(X_test)[:, 1]
precision_recall_curve_plot(y_test, pred_proba_c1)

#그림 그려서 파악
plt.hist(diabetes_data['Glucose'], bins=100)
zero_features = ['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI']
#전체 데이터 건수
total_count = diabetes_data['Glucose'].count()
#피처별로 반복하면서 데이터 값이 0인 데이터 건수 추출하고, 퍼센트 계산
for feature in zero_features:
zero_count = diabetes_data[diabetes_data[feature] == 0][feature].count()
print('{0} 0 건수는 {1}, 퍼센트는 {2:.2f} %'.format(feature, zero_count,
100*zero_count/total_count))
# zero_features 리스트 내부에 저장된 개별 피처들에 대해서 0값을 평균값으로 대체
diabetes_data[zero_features] = \
diabetes_data[zero_features].replace(0, diabetes_data[zero_features].mean())
X = diabetes_data.iloc[:, :-1]
y = diabetes_data.iloc[:, -1]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size = 0.2, random_state = 156, stratify=y)
lr_clf = LogisticRegression()
lr_clf.fit(X_train, y_train)
pred = lr_clf.predict(X_test)
pred_proba = lr_clf.predict_proba(X_test)[:, 1]
get_clf_eval(y_test, pred, pred_proba)
from sklearn.preprocessing import Binarizer
def get_eval_by_threshold(y_test , pred_proba_c1, thresholds):
# thresholds 리스트 객체내의 값을 차례로 iteration하면서 Evaluation 수행.
for custom_threshold in thresholds:
binarizer = Binarizer(threshold=custom_threshold).fit(pred_proba_c1)
custom_predict = binarizer.transform(pred_proba_c1)
print('임곗값:',custom_threshold)
get_clf_eval(y_test , custom_predict, pred_proba_c1)
Binarizer(threshold=값): sklearn의 전처리 도구로, 지정된 임곗값을 기준으로 연속형 변수롤 0 또는 1로 변환한다. => 여기 위의 thresholds 를 돌려서 하나씩 넣는다. binarizer.transform()으로 값을 이진으로 실제로 바꾸고, 그걸 custom_predict로 집어넣는다. #데이터 준비
bike_df = pd.read_csv('../data/bike_train.csv')
print(bike_df.shape)
bike_df.head(3)
bike_df.info()
#datetime 열을 string에서 datetime으로 바꾸고, 각 연월일시를 추출해서 칼럼으로
bike_df['datetime'] = bike_df.datetime.apply(pd.to_datetime)
bike_df['year'] = bike_df.datetime.apply(lambda x: x.year)
bike_df['month'] = bike_df.datetime.apply(lambda x: x.month)
bike_df['day'] = bike_df.datetime.apply(lambda x: x.day)
bike_df['hour'] = bike_df.datetime.apply(lambda x: x.hour)
print(bike_df.info())
bike_df.head()
#필요 없는 열을 drop
drop_columns = ['datetime', 'casual', 'registered']
bike_df.drop(drop_columns, axis=1, inplace=True)
bike_df.head()
y_target = bike_df['count']
X_features = bike_df.drop(['count'], axis=1, inplace=False)
X_train, X_test, y_train, y_test = train_test_split(
X_features, y_target, test_size = 0.3, random_state=0)
lr_reg = LinearRegression()
lr_reg.fit(X_train, y_train)
pred = lr_reg.predict(X_test)
evaluate_regr(y_test, pred)
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error, mean_squared_log_error
origin = np.array([1, 2, 3, 2, 3, 5, 4, 6, 5, 6, 7])
pred = np.array([1, 1, 2, 2, 3, 4, 4, 5, 5, 7, 7])
MAE = mean_absolute_error(origin, pred)
# MAE = 0.45454545454545453
MSE = mean_squared_error(origin, pred)
# MSE = 0.45454545454545453
RMSE = np.sqrt(MSE)
# RMSE = 0.674199862463242
MSLE = mean_squared_log_error(origin, pred)
# MSLE = 0.029272467607503516
RMSLE = np.sqrt(mean_squared_log_error(origin, pred))
# RMSLE = 0.1710919858073531
R2 = r2_score(origin, pred)
# R2 = 0.868421052631579
mean_absolute_error: MAE, 평균 절대 오차. 예측값과 실제값 차이의 절대값의 평균. mean_squared_error: MSE, 평균 제곱 오차. 예측값과 실제값 차이의 제곱값의 평균. 큰 오차에 가중치가 더 크게 부여. np.squrt(MSE): RMSE(Root MSE), MSE의 제곱근. 마찬가지로 큰 오차에 더 큰 가중치 부여되지만, 오차 단위가 실제값과 동일해져서 해석이 더 쉽다. mean_squared_log_error: MSLE, 평균 제곱 로그 오차. 예측값과 실제값에 1을 더한 => 로그를 취한 값 => 의 차이 => 의 제곱 => 의 평균. 0에 가까운 값들에서 발생하는 큰 상대적 오차에 더 민감. np.sqrt(MSLE):RMSLE(Root MSLE). MSLE의 제곱근으로, 오차의 상대적 크기에 초점을 맞추고, 과대 예측과 과소 예측을 동일하게 취급. r2_score: R^2로 결정 계수. 1에 가까울수록 모델이 잘 설명하고 있는 것. np.log1p(): log(1+x)와 동일. log(0)은 정의되지 않지만, log1p(0)은 0으로 계산된다. def get_top_error_data(y_test, pred, n_tops = 5):
# DataFrame에 컬럼들로 실제 대여횟수(count)와 예측 값을 서로 비교 할 수 있도록 생성.
result_df = pd.DataFrame(y_test.values, columns=['real_count'])
result_df['predicted_count']= np.round(pred)
result_df['diff'] = np.abs(result_df['real_count'] - result_df['predicted_count'])
# 예측값과 실제값이 가장 큰 데이터 순으로 출력.
print(result_df.sort_values('diff', ascending=False)[:n_tops])
y_target.hist()
y_log_transform = np.log1p(y_target)
y_log_transform.hist()


#타겟 컬럼인 count 값을 log1p로 log 변환
y_target_log = np.log1p(y_target)
#로그 변환된 y_target_log를 반영해 학습/테스트 데이터셋 분할
X_train, X_test, y_train, y_test = train_test_split(
X_features, y_target_log, test_size=0.3, random_state=0)
lr_reg = LinearRegression()
lr_reg.fit(X_train, y_train)
pred = lr_reg.predict(X_test)
print(evaluate_regr(y_test, pred))
#테스트 데이터 셋의 Target 값은 log 변환되었으므로 expm1을 이용해 원래 스케일로
y_test_exp = np.expm1(y_test)
pred_exp = np.expm1(pred)
evaluate_regr(y_test_exp, pred_exp)

np.expm1으로 돌린다. => 그렇게 MSE 등을 구한다X_features_ohe = pd.get_dummies(X_features,
columns=['year','month','hour', 'holiday',
'workingday','season','weather'])
X_train, X_test, y_train, y_test = train_test_split(
X_features_ohe, y_target_log, test_size = 0.3, random_state=0)
get_dummies를 이용해 칼럼의 값들을 각각 True, False로 바꾼다. => 원-핫 인코딩(One-hot encoding)을 적용. 원-핫 인코딩이란 범주형 변수를 각각 이진 벡터로 변환해서 기계 학습에 적용하는 것. 빨노파를 [1, 0, 0], [0, 1, 0], [0, 0, 1] 정도로. def get_model_predict(model, X_train, X_test, y_train, y_test, is_expm1=False):
model.fit(X_train, y_train)
pred = model.predict(X_test)
if is_expm1 :
y_test = np.expm1(y_test)
pred = np.expm1(pred)
print('###',model.__class__.__name__,'###')
evaluate_regr(y_test, pred)
lr_reg = LinearRegression()
ridge_reg = Ridge(alpha=10)
lasso_reg = Lasso(alpha=0.01)
for model in [lr_reg, ridge_reg, lasso_reg]:
get_model_predict(model,X_train, X_test, y_train, y_test,is_expm1=True)
https://www.kaggle.com/c/bike-sharing-demand
https://www.kaggle.com/c/bike-sharing-demand/overview/evaluation
RMSLE(실제 값과 예측값의 오류를 로그로 변환한 뒤 RMSE를 적용) kaggle.comkaggle.com Bike Sharing Demand Forecast use of a city bikeshare s
https://daewonyoon.tistory.com/281
https://wikidocs.net/34063
https://hjryu09.tistory.com/33ystem
https://m.blog.naver.com/hajuny2903/222375600616