1. Anomaly Detection with IsolationForest (비지도학습)
#code from 월간 데이콘 신용카드 사기 거래 탐지 AI 경진대회
import pandas as pd
import numpy as np
from sklearn.ensemble import IsolationForest
from sklearn.metrics import f1_score
from sklearn.metrics import classification_report
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings(action='ignore')
train_df = pd.read_csv('./train.csv') # Train
train_df.head()
val_df = pd.read_csv('./val.csv') # Validation
val_df.head()
train_df.drop(columns=['ID']).hist(bins = 50, figsize = (20,20))
plt.show()
val_df.drop(columns=['ID', 'Class']).hist(bins = 50, figsize = (20,20))
plt.show()
#Validation set 사기 거래 비율
#(*) Validation set의 사기 거래 비율이 다른 데이터집합에서도 비슷하게 발생할 것이라고 가정
val_normal, val_fraud = val_df['Class'].value_counts()
val_contamination = val_fraud / val_normal
print(f'Validation contamination : [{val_contamination}]')
#Model Define & Fit
# Train dataset은 Label이 존재하지 않음
train_x = train_df.drop(columns=['ID']) # Input Data
# 가설 설정 : Train dataset도 Validation dataset과 동일한 비율로 사기거래가 발생 했을 것이다. -> model parameter : contamination=val_contamination(=0.001055) 적용
model = IsolationForest(n_estimators=125, max_samples=len(train_x), contamination=val_contamination, random_state=42, verbose=0)
model.fit(train_x)
#Evaluation : Validation set
def get_pred_label(model_pred):
# IsolationForest 모델 출력 (1:정상, -1:불량(사기)) 이므로 (0:정상, 1:불량(사기))로 Label 변환
model_pred = np.where(model_pred == 1, 0, model_pred)
model_pred = np.where(model_pred == -1, 1, model_pred)
return model_pred
val_x = val_df.drop(columns=['ID', 'Class']) # Input Data
val_y = val_df['Class'] # Label
val_pred = model.predict(val_x) # model prediction
val_pred = get_pred_label(val_pred)
val_score = f1_score(val_y, val_pred, average='macro')
print(f'Validation F1 Score : [{val_score}]')
print(classification_report(val_y, val_pred))
#Inference : Test set
test_df = pd.read_csv('./test.csv') # Train
test_df.head()
test_x = test_df.drop(columns=['ID'])
test_pred = model.predict(test_x) # model prediction
test_pred = get_pred_label(test_pred)
#Submission
submit = pd.read_csv('./sample_submission.csv')
submit.head()
submit['Class'] = test_pred
submit.to_csv('./submit.csv', index=False)
2. minMAX Scaling
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
data_3_temp['absences_norm_s'] = scaler.fit_transform(data_3_temp[['absences']])
3. Train: Test set separation
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=42)
train_test_split(y, shuffle=False)
X_train, X_test, y_train, y_test = train_test_split(X, y,stratify=y, test_size=0.3) #y비율유지
4. Machine Learning EDA Flow
#1. EDA
#1) 데이터 확인
data_1 = pd.read_csv('./sample_data.csv')
data_1.head()
data_1.shape
data_1.info() #결측치 필요 열 파악
data_1['age'] = np.where(data_1['age'].isna(),data_1['age'].dropna().median(),data_1['age'])#먼저, EDA에 앞서 결측치 처리
#KNN 결측치 처리 방법
from sklearn.impute import KNNImputer
imputer = KNNImputer(n_neighbors = 5)
df_filled = imputer.fit_transform(data_1)
pre_df = pd.DataFrame(df_filled, columns = data_1.columns)
data_1.describe()
#2) Y분포 확인 및 수치형 X변수 분포 확인(시각화)
data_1.hist(bins=50,figsize=(20,20)) #수치형 변수들의 histogram (y변수분포 포함)
plt.bar(data_1['absences'].value_counts().index,data_1['absences'].value_counts().index.values)
#3) Y~X & X간 상관관계(시각화)
data_1.corr() #수치형변수간의 correlation 확인(목적1: x간의 높은 상관관계 배제, 2: y의 상관관계가 높은 수치형 x확인)
df_corr = data_1.corr(method='pearson')
sns.heatmap(df_corr,xticklabels = df_corr.columns,yticklabels = df_corr.columns,cmap='RdBu_r',annot=True,linewidth=3)
sns.boxplot(data_1['sex'],data_1['absences']) #명목&수치 확인
#2. 전처리
#1) 명목형변수 가변수화(*baseline삭제)
x = pd.get_dummies(data=x, columns=['group'])
data_2['sex'] = np.where(data_2['sex']=='M',1,0)
#2) 이상치처리
a_mean = data_2['absences'].mean()
a_std = np.std(data_2['absences'])
U_limit = a_mean + 3*a_std
data_3 = data_2[data_2['absences']<U_limit]
#3) normalization(log transformation or scaling 등)
data_1_temp = data_1.copy()
data_1_temp['log_absences'] = np.log1p(data_1['absences'])
#minmaxscaling, normalization 시도
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
data_3_temp['absences_norm_s'] = scaler.fit_transform(data_3_temp[['absences']])
#3. 변수처리
#1) 차원축소_X
#2) 데이터불균형해결_Y
#4. 모델링
#1) 알고리즘 후보 선택, 준비(screeplot 등 초모수 선택 과정), 적합(모델학습)
#2) 학습 성능 확인, 알고리즘 선택(HPO 필요 경우 train:valid)
#3) 테스트 데이터 성능확인, 시각화
5. 차원 축소 알고리즘(PCA 주성분분석, LDA 선형판별분석)
#1.PCA 주성분분석
from sklearn.preprocessing import StandardScaler # PCA 전 표준화 필수
x = df.drop(['target'], axis=1).values # 독립변인들의 value값만 추출
y = df['target'].values # 종속변인 추출
x = StandardScaler().fit_transform(x) # x객체에 x를 표준화한 데이터를 저장
features = ['sepal length', 'sepal width', 'petal length', 'petal width']
pd.DataFrame(x, columns=features).head()
from sklearn.decomposition import PCA
pca = PCA(n_components=2) # 주성분을 몇개로 할지 결정
printcipalComponents = pca.fit_transform(x)
principalDf = pd.DataFrame(data=printcipalComponents, columns = ['principal component1', 'principal component2'])
principalDf.head() # 주성분으로 이루어진 데이터 프레임 구성
pca.explained_variance_ratio_
sum(pca.explained_variance_ratio_) # 두 개의 주성분이 전체 분산의 약 96%를 설명한다.
pca = PCA(n_components=3) #주성분 3개로 시도
printcipalComponents = pca.fit_transform(x)
principalDf = pd.DataFrame(data=printcipalComponents, columns = ['principal component1', 'principal component2', '3'])
pca.explained_variance_ratio_ #3번째 주성분의 분산 설명량은 0.03밖에 되지 않음
import matplotlib.pyplot as plt #두 개의 주성분을 이용한 iris species 시각화
fig = plt.figure(figsize = (8, 8))
ax = fig.add_subplot(1, 1, 1)
ax.set_xlabel('Principal Component 1', fontsize = 15)
ax.set_ylabel('Principal Component 2', fontsize = 15)
ax.set_title('2 component PCA', fontsize=20)
targets = ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']
colors = ['r', 'g', 'b']
for target, color in zip(targets,colors):
indicesToKeep = finalDf['target'] == target
ax.scatter(finalDf.loc[indicesToKeep, 'principal component1']
, finalDf.loc[indicesToKeep, 'principal component2']
, c = color
, s = 50)
ax.legend(targets)
ax.grid()
#2. LDA 선형판별분석
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
lda = LinearDiscriminantAnalysis()
X_lda = lda.fit_transform(X, y)
lda.explained_variance_ratio_
plt.xlabel('LD1')
plt.ylabel('LD2')
plt.scatter(
X_lda[:,0],
X_lda[:,1],
c=y,
cmap='rainbow',
alpha=0.7,
edgecolors='b'
)
6. LinearProgramming 선형계획법(Python)
#Linear Programming
##1) Using scipy.optimize
from scipy.optimize import linprog
c = [-1, 4]
A = [[-3, 1], [1, 2]]
b = [6, 4]
x0_bounds = (None, None)
x1_bounds = (-3, None)
res = linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds])
print(res)
##2) Using PulP
from pulp import *
# LpProblem 함수를 이용해서 목적식의 종류를 지정
prob = LpProblem("The Whiskas Problem", LpMinimize) #("이름",최소최대...)
# LpVariable 함수를 이용해서 사용할 x1,x2 변수의 이름, 상하한, 데이터 유형 지정
x1 = LpVariable ( "ChickenPercent" , 0 , None , LpInteger )
x2 = LpVariable ( "BeefPercent" , 0 )
# LpVariable ( "example" , None , 100 ) # ("이름",이 변수의 하한값,상한값,데이터 유형)
# 또는 LpVariable("example", upBound = 100) # 중간에 비워줄 경우 다음 변수 이름 써줘야함
# 변수 상하한은 숫자로 지정 음수 가능
# 데이터 유형은 LpContinuousor LpInteger이며 기본값은 as LpContinuous
# 목적식
prob += 0.013*x1 + 0.008*x2, "Total Cost of Ingredients per can"
# 제약조건
prob += x1 + x2 == 100, "PercentagesSum"
prob += 0.100*x1 + 0.200*x2 >= 8.0, "ProteinRequirement"
prob += 0.080*x1 + 0.100*x2 >= 6.0, "FatRequirement"
prob += 0.001*x1 + 0.005*x2 <= 2.0, "FibreRequirement"
prob += 0.002*x1 + 0.005*x2 <= 0.4, "SaltRequirement"
# lp파일을 저장하는 코드
prob.writeLP("WhiskasModel.lp")
prob.solve()
# 최적해 구하기
for v in prob.variables():
print(v.name, "=", v.varValue)
# 최적 생산량으로 생산할 때 드는 비용
print("Total Cost of Ingredients per can = ", value(prob.objective))
7. t stats
#Finding the P-Value of a T-Value 누적 t분포 확률 값 계산
import scipy.stats as stats
stats.t.cdf(2.1, 29) #(R) pt(2.1, 29)
#Finding the T-value of a P-Value t분포 분위수 함수 값 계산(cdf<->ppf)
stats.t.ppf(0.75, 29) #(R) qt(0.75, 29)
#정규분포 연습문제
##1. 어느 회사에서 종업원들의 근무기간을 조사하였는데, 종업원들의 근무기간은 평균이 11년이고 표준편차가 4년인 정규분포를 따른다고 한다. 그럼 이 회사에서 14년 이상 근무한 종업원의 비율을 구하시오
rv = stats.norm(11, 4)
1-rv.cdf(14)
##2. 어느 전구회사의 전구의 수명은 평균 800일, 표준편차 30일인 정규분포를 따른다. 전구의 수명이 760일 이하일 확률 구하시오
rv = stats.norm(800,30)
rv.cdf(760)
##3. 어느 고등학교 3학년 학생들의 수학 성적은 평균이 70점이고 분산이 64점인 정규분포를 따른다고 한다. 그럼 점수가 80점 이상이고 90점 이하일 확률을 구하시오
###sol 1
rv = stats.norm(70,math.sqrt(64)) # math.sqrt() = np.sqrt()
rv.cdf(90)-rv.cdf(80)
###sol 2
rv = stats.norm(0,1)
rv.cdf((90-70)/np.sqrt(64))-rv.cdf((80-70)/np.sqrt(64))
8. DataFrame 구성
import pandas as pd
#Method1
data = [['tom', 10], ['nick', 15], ['juli', 14]]
df = pd.DataFrame(data, columns=['Name', 'Age'])
#Method2
data = {'Name': ['Tom', 'nick', 'krish', 'jack'],
'Age': [20, 21, 19, 18]}
df = pd.DataFrame(data)
9. 특정 평균과 분포를 따르는 난수 발생
#각 조건을 따르는 난수를 발생시켜 t test를 시행하는 방법
import numpy as np
random_nums_A = np.random.normal(loc=5.7, scale=0.03, size=12)
random_nums_B = np.random.normal(loc=5.6, scale=0.04, size=12)
import scipy.stats as stats
stats.levene(random_nums_A,random_nums_B)
stats.ttest_ind(random_nums_A, random_nums_B,equal_var = False)
10. 손으로 푸는 독립표본 t검정(등분산, 이분산 가정)
#두집단의 표본수가 동일(표본의 표준편차가 2개 이내임)하므로 등분산 가정 T검정을 수행
mean_var = (5.7-5.6)
S_equal = ((11*0.03**2+11*0.004**2)/22)
equal_t = mean_var/(np.sqrt(S_equal)*np.sqrt(1/12+1/12))
print((1-stats.t.cdf(equal_t,df=22))*2) #pvalue
#등분산 가정없을 때
S_diff = np.sqrt(0.03**2/12+0.04**2/12)
diff_t = mean_var/S_diff
df_diff = (0.03**2/12+0.04**2/12)**2/((0.03**2/11)**2/11+(0.04**2/12)**2/11)#등분산성 깨질 땐 df도 따로 계산해야함
print((1-stats.t.cdf(diff_t,df=df_diff))*2)#pvalue
11. 손으로 푸는 이분산가정 t검정 신뢰구간
from scipy.stats import ttest_ind
from scipy.stats import t
import pandas as pd
def welch_ttest(x1, x2,alternative):
n1 = x1.size
n2 = x2.size
m1 = np.mean(x1)
m2 = np.mean(x2)
v1 = np.var(x1, ddof=1)
v2 = np.var(x2, ddof=1)
pooled_se = np.sqrt(v1 / n1 + v2 / n2)
delta = m1-m2
tstat = delta / pooled_se
df = (v1 / n1 + v2 / n2)**2 / (v1**2 / (n1**2 * (n1 - 1)) + v2**2 / (n2**2 * (n2 - 1)))
# two side t-test
p = 2 * t.cdf(-abs(tstat), df)
# upper and lower bounds
lb = delta - t.ppf(0.975,df)*pooled_se
ub = delta + t.ppf(0.975,df)*pooled_se
return pd.DataFrame(np.array([tstat,df,p,delta,lb,ub]).reshape(1,-1),
columns=['T statistic','df','pvalue 2 sided','Difference in mean','lb','ub'])
welch_ttest(ts1,ts2,"equal")
12. 명목, 수치형 변수 상관관계확인
#연속형 vs 범주형 : Point biserial correlation
from scipy import stats
a = np.array([0, 0, 0, 0, 1, 1, 1, 1])
b = np.arange(8)
stats.pointbiserialr(a, b)
# 범주형 vs 범주형 : 파이 계수(Phi coefficient)
from scipy.stats.contingency import association
X = np.array([[30, 10],
[20, 30]])
association(X, method="tschuprow")
13. 회귀모형 성능평가
from sklearn.metrics import mean_absolute_error
mean_absolute_error(y_test, y_pred) #에러에 따른 손실이 선형적으로 올라갈 때 적합, 이상치가 많을 때 사용하기 적합
from sklearn.metrics import mean_squared_error
MSE = mean_squared_error(y_test, y_pred) #특이값이 존재하면 수치가 많이 늘어남, 에러에 제곱을 하기 때문에 에러가 크면 클수록 그에 따른 가중치가 높이 반영
RMSE = np.sqrt(MSE )#에러에 따른 손실이 기하 급수적으로 올라가는 상황에서 쓰기 적합
14.
#1. Coding Test(U+)
#import
from sklearn import metrics
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score,train_test_split, GridSearchCV
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, roc_auc_score, confusion_matrix
import xgboost as xgb
from xgboost import plot_importance
from xgboost import XGBClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier, AdaBoostClassifier
from sklearn.model_selection import cross_val_score
#결정 트리를 통한 feature importance 추출 from 앞서 선택된 DT2 모형
features = X_var.columns
importances = DT2.fit(X_var,y_var).feature_importances_
indices = np.argsort(importances)
num_features = 5
plt.title('Feature Importances')
plt.barh(range(num_features), importances[indices[-num_features:]], color='orange', align='center')
plt.yticks(range(num_features), [features[i] for i in indices[-num_features:]])
plt.xlabel('Relative Importance')
plt.show()
#XGBoost Classification
XGB4 = XGBClassifier(objective= 'binary:logistic', eval_metrics='auc',n_estimators=100, max_depth=6,reg_lambda=10)
xgb4_auc_scores = cross_val_score(XGB4, X_var, y_var, scoring='roc_auc', cv=5)
xgb4_auc_mean = xgb4_auc_scores.mean()
xgb4_auc_std = xgb4_auc_scores.std()
print('5 folds의 개별 AUC : ', np.round(xgb4_auc_scores, 2))
print('5 folds의 평균 AUC : {0:.3f} '.format(xgb4_auc_mean))
print('5 folds의 AUC std : {0:.3f} '.format(xgb4_auc_std))
#2. KBO Prediction(Binary Classification)
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
x_train_scaled = scaler.fit_transform(x_train)
x_test_scaled = scaler.fit_transform(x_test)
lr = LogisticRegression()
lr.fit(x_train_scaled, y_train)
y_pred = lr.predict(x_test_scaled)
print("Accuracy: %.4f" %accuracy_score(y_test, y_pred))
from sklearn.svm import SVC
svc = SVC(kernel='linear', C=100)
svc.fit(x_train, y_train)
y_pred_svc = svc.predict(x_test)
print('Accuracy: %.4f' % accuracy_score(y_test, y_pred_svc))
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators=150)
rf.fit(x_train, y_train)
y_pred_rf = rf.predict(x_test)
print('Accuracy: %.4f' % accuracy_score(y_test, y_pred_rf))
댓글