59doit
[ R ] R과 python을 활용한 데이터 분석 시각화 #2 (1) 본문
[ 분류분석 / 시각화 ]
위스콘신 유방암 데이터셋을 대상으로 분류기법 2개를 적용하여 기법별 결과를 비교하고 시각화하시오. (R과 python 버전으로 모두 실행)
* 종속변수는diagnosis: Benign(양성), Malignancy(악성)
- 해당 데이터는 유방암으로 의심되는 종양의 모양에 따라 양성과 악성을 구분하는 데이터
- 종속변수 diagnosis 에 해당되는 값을 범주형 변수로 바꿔주기 위해서 B(Benign) 양성을 0 으로, M(Malignancy) 음성을 1 로 변경
- 분석하기에 앞서 먼저 데이터를 R 과 python 에서 발생 난수의 순서까지 동일하지 않기 때문에 동일하게 가질 수 있도록 패키지 SyncRNG 를 사용하여 동일한 난수를 통해 분류
- R 에서는 데이터프레임이 1 부터 시작하기 때문에 python 에서 0 행과 R 에서 1 행이 같게 되므로 같은 인덱스 번호를 가진다면 -1 을 해주어 train 과 test 에 같은 데이터를 담았다.
< R >
#1 필요한 패키지 로딩
library(car) library(lmtest) library(ROCR) library(SyncRNG) library(rpart.plot) |
#2 데이터 불러오기
wdbc <- read.csv("C:/wdbc_data.csv") |
- wdbc : 위스콘신 유방암 데이터 프레임
#3 diagnosis 변수를 1, 0 으로 변경 및 필요없는 변수 제거
wdbc$diagnosis_sub <-ifelse(wdbc$diagnosis == 'M', 1, 0) wdbc <- subset(wdbc, select = -c(diagnosis, id)) str(wdbc) |
- diagnosis_sub : diagnosis 에 담긴 변수들이 char 형이므로 factor 형으로 변환하여 샘플링
- 종속변수 diagnosis 에 해당되는 값을 범주형 변수로 바꿔주기 위해서 B(Benign) 양성을 0 으로, M(Malignancy) 음성을 1 로 변경
#4 학습 & 테스트 데이터 생성
#4-1)
v <- 1:nrow(wdbc) s <- SyncRNG(seed=42) #s$shuffle(v)[1:5] - python 코드에서랑 같은 데이터가 불러와지는지 확인 idx <- s$shuffle(v)[1:round(nrow(wdbc)*0.7)] #head(idx) - python 코드에서랑 같은 데이터가 불러와지는지 확인 #length(idx) - python 코드에서랑 같은 데이터가 불러와지는지 확인 |
- 소수점으로 분류되어서 round 함수사용하기
- idx : 70%
#4-2) diagnosis 변수를 1, 0 으로 변경
wdbc$diagnosis_sub <- as.factor(wdbc$diagnosis_sub) |
- diagnosis_sub : 를 factor 형으로 변환
#4-3) diagnosis 변수를 1, 0 으로 변경
head(wdbc[-idx[1:length(idx)],]) idx[1:length(idx)] trData <- wdbc[idx[1:length(idx)],] teData <- wdbc[-idx[1:length(idx)],] |
- trData : 트레인 데이터
- teData : 테스트 데이터
#### 의사결정 나무 ####
#1 필요한 패키지 로딩
library(rpart) library(caret) |
#2 rpart 활용한 분류분석 데이터 생성
data_lm <- rpart(diagnosis_sub~., data = trData) |
- data_lm : rpart 분류분석 데이터
#3 예측 tabl생성
rpart_lm <-predict(data_lm, newdata = teData, type = 'class') table(teData$diagnosis_sub, rpart_lm) |
.#4 정확도
teData$diagnosis_sub <- as.factor(teData$diagnosis_sub) confusionMatrix(rpart_lm, teData$diagnosis_sub) # Accuracy : 0.9181 |
.
.#5 시각화
rpart.plot(data_lm) |
.
#### SVM ####
#1 필요한 패키지 로딩
library(e1071) library(caret) library(dplyr) |
#2 linear 커널 사용 튜닝
result1 <- tune.svm(diagnosis_sub~., data=trData, gamma=2^(-5:0), cost = 2^(0:4), kernel="linear") |
#3 튜닝된 파라미터 확인
result1$best.parameters |
#4 SVM 실행
normal_svm1 <- svm(diagnosis_sub~., data=trData, gamma=0.0625, cost=1, kernel = "linear") |
#5 결과 확인
summary(normal_svm1) |
# Call: # svm(formula = diagnosis_sub ~ ., data = trData, gamma = 0.0625, # cost = 1, kernel = "linear") # # # Parameters: # SVM-Type: C-classification # SVM-Kernel: linear # cost: 1 # # Number of Support Vectors: 32 # # ( 16 16 ) # # # Number of Classes: 2 # # Levels: # 0 1 |
#6 sv index 확인
normal_svm1$index |
#7 SVM으로 예측
normal_svm1_predict <- predict(normal_svm1, teData) |
#8 테이블 확인
table(teData$diagnosis_sub, normal_svm1_predict) |
normal_svm1_predict 0 1 0 97 2 1 3 69 |
#9 정확도
confusionMatrix(normal_svm1_predict, teData$diagnosis_sub) |
#10 시각화
wdbc %>% ggplot(aes(x=radius_mean ,y=texture_mean,colour=diagnosis_sub)) + geom_point() + theme_minimal(base_family="NanumGothic") |
< Python >
데이터의 비어있는 값과 중복값이 있는지, diagnosis 에 담긴 benign 과 malignancy 의 빈도수가 얼마인지 확인
#1 필요한 모듈 임포트
import sklearn.datasets as d import pandas as pd import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt from sklearn import metrics from sklearn.model_selection import cross_val_score from SyncRNG import SyncRNG from sklearn.tree import DecisionTreeClassifier # 분류모델 구축-결정트리 from sklearn.tree import DecisionTreeRegressor,plot_tree from sklearn.tree import export_graphviz |
#2 데이터 로드
wdbccancer = pd.read_csv("wdbc_data.csv") wdbccancer |
id diagnosis ... symmetry_worst dimension_worst 0 87139402 B ... 0.2827 0.06771 1 8910251 B ... 0.2940 0.07587 2 905520 B ... 0.2998 0.07881 3 868871 B ... 0.2102 0.06784 4 9012568 B ... 0.2487 0.06766 .. ... ... ... ... ... 564 911320502 B ... 0.2235 0.06925 565 898677 B ... 0.2434 0.08488 566 873885 M ... 0.3175 0.09772 567 911201 B ... 0.2606 0.07810 568 9012795 M ... 0.2730 0.08666 [569 rows x 32 columns] |
#3 만들어진 wdbccancer의 결측값 확인
wdbccancer.isnull().sum() |
#4 문자형태인 타기 값을 숫자 형태로 변환
wdbccancer['diagnosis'].unique() # array(['B', 'M'], dtype=object) def func1(row): if 'M' in row : return 1 else : return 0 |
- M = 1 (악성종양,암), B = 0 으로 변환
#5 변환된 결과를 데이터프레임에 새로운 컬럼을 만들기
wdbccancer['diagnosis'] = wdbccancer['diagnosis'].apply(func1) wdbccancer.head() |
- 'diagnosis' 이라는 새로운 컬럼
#6 필요없는 컬럼 삭제
wdbc = wdbccancer.drop(columns=['id']) wdbc.head() |
#7 데이터 셋 7:3 으로 분할
v=list(range(1,len(wdbccancer)+1)) s=SyncRNG(seed=42) # s.shuffle(v)[:5] ord=s.shuffle(v) idx=ord[:round(len(wdbccancer)*0.7)] # idx[:5] |
#8 인덱스 수정-R이랑 같은 데이터 가져오기
for i in range(0,len(idx)): idx[i]=idx[i]-1 |
- R에서는 데이터프레임이 1부터 시작하기 때문에 python에서 0행과 R에서 1행이 같은 원리로 같은 인덱스 번호를 가진다면 -1을 해주어 같은 데이터를 가지고 오게 한다.
#9 학습데이터, 테스트데이터 생성
train=wdbc.loc[idx] # 70% train=train.sort_index(ascending=True) test=wdbc.drop(idx) # 30% train_x=train.drop(['diagnosis'],axis=1) train_y=train['diagnosis'] test_x=test.drop(['diagnosis'],axis=1) test_y=test['diagnosis'] |
#### 의사결정 나무 ####
#1 모델 생성
reg = DecisionTreeRegressor(max_depth=2).fit(train_x,train_y) |
- reg :
#2 예측
pred=reg.predict(test_x) p1=pred.round() p2=np.array(test_y) |
#3 정확도
import sklearn.metrics as metrics metrics.accuracy_score(p2,p1) # 0.9181286549707602 |
#4 변수중요도
for i,col in enumerate(train_x.columns): print(f'{col} 중요도 : {reg.feature_importances_[i]}') |
#5 시각화
fig = plt.Figure(facecolor="white") plot_tree(reg,feature_names=train_x.columns,filled=True) |
#### SVM ####
#1 필요한 모듈 임포트
from sklearn.svm import LinearSVC from sklearn.svm import SVC import sklearn.svm as svm import sklearn.metrics as mt from sklearn.model_selection import cross_val_score, cross_validate |
#2 데이터 로드
wdbccancer_svm = pd.read_csv("wdbc_data.csv") wdbccancer_svm |
#3 결측값 확인
wdbccancer_svm.isnull().sum() |
# 아이디는 유방암을 예측하는데 전혀 도움이 되지 않기 때문에 무시
# diagnosis M = 1 (악성종양,암), B = 0
#4 문자형태인 타기 값을 숫자 형태로 변환
wdbccancer_svm['diagnosis'].unique() # array(['B', 'M'], dtype=object) def func1(row): if 'M' in row : return 1 else : return 0 |
#5 변환된 결과를 데이터프레임에 '진단' 이라는 새로운 컬럼을 만들어 넣어준다
wdbccancer_svm['진단'] = wdbccancer_svm['diagnosis'].apply(func1) wdbccancer_svm.head() |
#6 필요없는 컬럼 삭제
wdbc = wdbccancer_svm.drop(columns=['id','diagnosis']) wdbc.head() |
#7 분류보델 구축 - 결정트리 & 훈련 검증용 데이터 분리 임포트
from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split |
#8 데이터 셋 7:3으로 분할
X = wdbc.drop(['진단'], axis = 1) # 목표변수 y = wdbc['진단'] # 설정변수 X_train,X_test,y_train,y_test = train_test_split (X,y, test_size = 0.3 , random_state = 1004) |
- test_size: 테스트 셋 구성의 비율
#9 kernel = linear 로 선형분리
svm_model = svm.SVC(kernel='linear', random_state=100) |
#9-1) 교차검증
scores = cross_val_score(svm_model,X,y,cv=5) scores pd.DataFrame(cross_validate(svm_model,X,y,cv=5)) print("교차검증 평균: ", scores.mean()) |
- 교차검증 평균 : 0.9508461419034312
#10 kernel = 'rbf'로 비선형분리 진행
svm_model2 = svm.SVC(kernel='rbf') |
#10-2) 교차검증
scores2 = cross_val_score(svm_model2, X, y, cv=5) scores2 pd.DataFrame(cross_validate(svm_model2, X, y, cv=5)) print('교차검증 평균: ', scores2.mean()) |
- 교차검증 평균: 0.9156652693681104
선형 분리에서 높은 평균 SCORE , 선형분리가 적합한 케이스
#11 시각화
import matplotlib.pyplot as plt plt.figure(figsize=(7,7)) X1=np.array(X) y1=np.array(y) plt.scatter(X1[:,0],X1[:,1],c = y1) plt.xlabel("radius_mean") plt.ylabel("texture_mean") plt.show() |
'portfolio' 카테고리의 다른 글
[ R ] R과 python을 활용한 데이터 분석 시각화 #3 (1) (0) | 2022.12.30 |
---|---|
[ python ] R과 python을 활용한 데이터 분석 시각화 #2 (2) (0) | 2022.12.29 |
[ R ] R과 python을 활용한 데이터 분석 시각화 #1 (0) | 2022.12.29 |
[ R ] Covid-19 (1) | 2022.12.05 |
[Python] Covid-19 (0) | 2022.11.14 |