본문 바로가기
카테고리 없음

230224_ADP code 모음 - python

by stherhj 2023. 2. 24.

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))

댓글