■ KNN
■ knn 알고리즘은 무엇인가?
책134p
"K nearest neighbor 의 약자로 머신러닝의 지도학습에 분류에
해당하는 알고리즘이다"
새로 들어온 데이터가 기존 데이터의 그룹 중 어느 그룹에
속하는지를 찾을 때
거리가 가까운 데이터의 그룹을 자기 그룹으로 선택하는
아주 간단한 알고리즘이다"
k가 1이면 1번째로 가까운 이웃데이터를,
K가 3이면 3번째로 가까운 이웃데이터를 선택한다.
K의 개수는 의사결정을 해야하기 때문에 항상 홀수를 선택해야 함.
사례 |
|
인식 |
정지 영상 및 동영상에서 광학 글자 인식과 얼굴 인식을 포함하는 컴퓨터 비젼 응용 |
선호도 |
영화나 음악 추천에 대한 개인별 선호 예측 |
패턴 |
특정 단백질 및 질병 발견에 사용 가능한 유전자 데이터의 패턴 인식 |
"KNN 은 최근접 인적방법으로 골라내기 때문에 "학습단계"가 없다.
바로예측이다!
오히려 위치적 파악으로 결정내리기 때문에
인스턴스 학습 또는 암기학습 이라고 한다."
"거리를 계산하기 때문에 반드시 변수들의 데이터를 min/max 표준화를
해야한다"
- 예시 : (1200g, 5seeds)와 (2000g, 7seeds)를 KNN할 경우 1200과 2000의 차이의 거리가 너무 커서 seeds의 거리가 적용되지 않는다. 따라서 정규화 or 표준화작업이 필요하다.
거리 = √((2000−1200)^2+(7−5)^2) 에서 (7-5)^2은 유의미한 차이이나
g의 차이가 너무 커서 거리 계산에서 유의하지 않게 된다.
"적절한 k값을 사용자가 직접 알아내야 한다"
"seed값을 setting 해야 한다. knn 함수 안에 동점처리가 되었을 경우,
랜덤으로 둘 중에 하나를 선택하는 코드가 있다"
■ knn 알고리즘의 장단점
장점 |
단점 |
단순하고 효율적이다 |
모델을 생성하지 않아 특징과 클래스 간의 관계를 이해하는 능력이 제약된다 |
기저 데이터 분포에 대한 가정을 하지 않는다 |
적절한 k의 선택이 필요하다(하드코딩) |
훈련 단계가 빠르다 |
분류 단계가 느리다 |
|
명목 특징 및 누락 데이터를 위한 추가 처리가 필요하다 |
knn 알고리즘의 이름은 예시의 k-최근접 이웃 정보를 이용해
레이블이 없는 예시를 분류한다는 사실에서 붙여졌다.
적절한 k값을 사용자가 직접 알아내야 한다.
134p
예: wbcd_test_pred <- knn(train=wbcd_train, test=wbce_test,
c1=wbce_train_labels, k=21)
k값 |
테스트 데이터 정확도 |
1 |
75% |
2 |
79% |
: |
: |
: |
: |
명목형 데이터와 결측치에 대한 추가 처리작업이 필요한다.
더미코딩해서 숫자 0 또는 1로 변환한다.
예: 유방암 데이터
wisc_bc_data.csv
이 데이터의 id의 숫자는? 명목형 데이터(의미없는 숫자)
knn은 숫자만 처리한다.
숫자가 아닌 데이터는 "더미코딩"을 해줘야 한다.(p123)
■ knn으로 분류하기전에 전처리해야되는 사항
1. 명목형 데이터는 더미 코딩해서 숫자 0 또는 1로 변환한다
2. 변수간에 서로 단위가 다른 데이터이므로
표준화 |
서로 다른 값을 동일범위로 구성시키는 작업 |
|
정규화 |
0~100 으로 설정하여 데이터를 관찰하는 작업
|
min/max 정규화 또는 Z 표준화를 해야 한다.
*min/max함수는 데이터를 0~1사이로 변환시켜줌.(정규화)
function normalize()
*Z표준화는 평균0, 표준편차1 인 데이터의 분포로 구성하는 작업(표준화)
function Z_standard()
**표준화는 서로다른 데이터를 동일범위로 구성시키는 작업
*** knn 이 거리계산 작업이라 반드시 정규화,표준화가 필요하다
https://ratsgo.github.io/machine%20learning/2017/04/17/KNN/
참고사이트!
3. 데이터를 3가지로 나눈다.
전체 data가 10,000개
1) train data(6,000개)
2) validation data(2,000개) ---> 훈려데이터의 일부를
모델을 학습시키기 위해
쓰는 데이터
3) test data(2000개)----------> 실전 데이터
4. 라벨의 class가 양성, 악성 두가지면 두개의 비율이 비슷해야한다.
즉, 양성 50%, 악성 50%로 데이터의 갯수를 맞춰주고 학습시켜야한다.
파이썬 모듈중 SMOTE 가 있는데, 데이터를 알아서 늘려준다!
R에서의 함수 생성 방법
함수명<-function(인수 또는 입력값){
계산처리1
계산처리2
.....................
return (계산 결과 반환)
}
예제:
nomalize<-function(x){
return ((x-min(x))/ (max(x)-min(x)) )
}
nomalize(c(1,2,3,4,5))
[1] 0.00 0.25 0.50 0.75 1.00
> nomalize(c(10,20,30,40,50))
[1] 0.00 0.25 0.50 0.75 1.00
키, 몸무게, ........., 체질량 지수
177 78 정상
비만
복비
nomalize(c(55,64,77,81,90))
[1] 0.0000000 0.2571429 0.6285714 0.7428571 1.0000000
> nomalize(c(165,172,177,181,186))
[1] 0.0000000 0.3333333 0.5714286 0.7619048 1.0000000
문제180.
통계 표준화 함수 생성하시오
표준화(Z) = x -평균 /표준편차
z_standard<-function(x){
+ return ((x-mean(x))/ sd(x)
)
+ }
> nomalize(c(55,64,77,81,90))
[1] -1.3234328
-0.6761015 0.2589325 0.5466353
1.1939666
>
nomalize(c(165,172,177,181,186))
[1] -1.38176866
-0.51816325 0.09869776 0.59218657
1.20904758
정규화: 0과 1사이 값으로 만드는 것
표준화: 평균이 0, 표준편차가 1인 정규분포로 만드는 것
z_standard(c(55,64,77,81,90))
[1] -1.3234328 -0.6761015
0.2589325 0.5466353 1.1939666
> scale(c(55,64,77,81,90))
[,1]
[1,] -1.3234328
[2,] -0.6761015
[3,] 0.2589325
[4,] 0.5466353
[5,]
1.1939666
attr(,"scaled:center")
[1] 73.4
attr(,"scaled:scale")
[1] 13.90324
※ scale 함수가 정규화
문제181. knn 알고리즘 이해하기 위해 아래의 거리를 구하는
함수를 생성하시오
knn 알고리즘이 data 와 data 사이의 거리를 구하는 알고리즘을
구해서 가장 인접한 데이터를 값으로 취함
화면 캡처: 2019-02-22 오전 11:10
d<-function(zero,n3,n2){
sqrt( (zero-n2)^2 + (n3-zero)^2 + (n2-zero)^2 )}
d(0,3,2)
# c로 묶으면 행렬(백터)라서 안됨. 각각의 값이 되게 해야함
################################
a=c(0,3,2)
b=c(2,0,0)
distance<-function(a,b){
sqrt(sum((a-b)^2))}
distance(a,b)
[1] 4.123106
파란색: 사과
연두색: 배
맨 아래 N 에서 (4,4) 일 때 어떤 과일이냐??
참고!
data<-c('A','B','C','D','E','F')
x<-c(1,2,4,5,6,7)
y<-c(5,6,5,2,3,1)
group<-c(rep('apple',3), rep('pear',3) )
data.frame(data, x, y, group)
#data.table(data, x, y, group)
data.frame(data, x,
y, group)
data x y group
1 A 1 5 apple
2 B 2 6 apple
3 C 4 5 apple
4 D 5 2 pear
5 E 6 3 pear
6 F 7 1 pear
문제184.
아래의 그림에서 N과 가장 거리가 가까운 과일은 무엇인가?
data<-c('A','B','C','D','E','F')
x<-c(1,2,4,5,6,7)
y<-c(5,6,5,2,3,1)
group<-c(rep('apple',3), rep('pear',3) )
df<-data.frame(data, x, y, group)
str(df)
df<-data.frame(data,x,y,group,stringsAsFactors = FALSE)
#data.table(data, x, y, group)
df
df[1,]
nrow(df) # 행의 갯수
length(df) # 열의 갯수
for(i in 1:nrow(df) ) {
#nrow 는 전체건수 가져오는 메소드
row <- df[i,]
a[i]<- abs(row$x-4) + abs(row$y-4 )
df$
# do stuff with row
}
length(a)
for(i in 1:length(a)) {
if (a[i]==min(a) )
{print(i)
print(group[i]) }
}
[1]
3
[1] "apple"
================================================
fruits <- data.frame('데이터'=c('A','B','C','D','E','F'),
'x좌표'=c(1,2,4,5,6,7),
'y좌표'=c(5,6,5,2,3,1),
'그룹'=c(rep('A',3),rep('P',3)), stringsAsFactors = FALSE)
distance<-function(a,b){
return ( sqrt( sum( (a-b)^2) ) )
}
temp <- c()
for ( i in 1 : length(fruits$x좌표) ) {
temp <- append( temp, distance( c ( fruits$x좌표[i],fruits$y좌표[i] ) , c ( 4, 4 ) ) )
}
fruits$그룹[which(temp==min(temp))]
"A"
fruits$그룹[which(rank(temp) <= 3)]
"A" "P" "P"
문제188.
유방암 데이터의 양성(B)과 약성(M)의 건수가 각각 어떻게 되는지 확인하시오
> table(wisc$diagnosis)
B M
357 212
문제189.
유방암 데이터의 양성(B)와 악성(M)의 건수의 비율이 어떻게 되는지
확인하시오
prop.table(table(wisc$diagnosis))*100
B M
62.74165 37.25835
■ Knn 의 분류 실습 ( 유방암 데이터 악성과 양성 분류)
1.데이터 게시판에서 유방암 데이터를 내려받는다
wisc_bc_data.cv
wbcd <- read.csv("wisc_bc_data.csv",
stringsAsFactors=FALSE)
# header 필요없음
str(wbcd)
라벨 : B --> 양성
M --> 악성
table(wbcd$diagnosis)
B M
357 212
총 : 569 명중 1/3 이 악성이고 2/3 가 양성이다.
2. 라벨 컬럼을 팩터로 변환
wbcd$diagnosis <- factor(wbcd$diagnosis,
levels = c("B","M"),
labels=c("Benign","Maliganant") )
str(wbcd)
3. 양성과 악성의 비율이 어떻게 되는지 확인한다.
round( prop.table( table(wbcd$diagnosis) ), 1 ) * 100
4. 정규화 작업 (normalize 함수로 작업)
wbcd_n <- as.data.frame(lapply(wbcd[,3:32], normalize) )
#파이썬의 map과 같은 것!
* 정규화가 잘 되었는지 확인 ( 0 ~ 1 사이에 있는지)
summary(wbcd_n)
5. 훈련 데이터와 테스트(실험) 데이터를 나누는 작업
( 4/5 ) ( 1/5 )
" 훈련 데이터로 기계학습 시켜서 모델을 생성한후
실험 데이토로 검증하는 작업 "
nrow(wbcd_n)
569
wbcd_train <- wbcd_n[1:469, ]
wbcd_test <- wbcd_n[470:569, ]
wbcd_train_label <- wbcd[1:469,2]
wbcd_test_label <- wbcd[470:569,2]
wbcd_test_label
6. knn 알고리즘으로 기계학습 시켜서 모델을 생성한다.
library(class)
훈련데이터의 갯수 469 의 제곱근 21
result1 <- knn(train=wbcd_train, test=wbcd_test,
cl= wbcd_train_label, k = 21 )
result1
data.frame(wbcd[470:569,2], result1)
7. 이 모델의 정확도가 몇 % 인지 알아내시오 !
prop.table( table(ifelse(wbcd[470:569,2]==result1,"o","x" )))
o x
0.98 0.02
8. 이원 교차표를 이용해서 모델을 분석하시오 !
library(gmodels)
CrossTable(x= wbcd[470:569,2] , y = result1,
prop.chisq=FALSE )
Total Observations in Table: 100
| result1
wbcd[470:569, 2] | Benign | Maliganant | Row Total |
-----------------|------------|------------|------------|
Benign | 61 | 0 | 61 |
| 1.000 | 0.000 | 0.610 |
| 0.968 | 0.000 | |
| 0.610 | 0.000 | |
-----------------|------------|------------|------------|
Maliganant | 2 | 37 | 39 |
| 0.051 | 0.949 | 0.390 |
| 0.032 | 1.000 | |
| 0.020 | 0.370 | |
-----------------|------------|------------|------------|
Column Total | 63 | 37 | 100 |
| 0.630 | 0.370 | |
-----------------|------------|------------|------------|
화면 캡처: 2019-02-22 오후 4:51
우리가 제일 피해야 할 양성->악성판단이 5건이 나왔다
이걸 달리할수 있는 방법은 k값 조절뿐이다
k = 5, 정확도 : 98%
k = 19 , 정확도 : 96%
양성->악성 판단 4건
■ 유방암 데이터로 knn 알고리즘 돌려서 악성인지 양성인지 테스트
정확도: 98%
데이터를 표준화 또는 정규화 하는 작업
1. min/max 정규화 ---> 정확도 98%
2. Z - 표준화( 평균0, 표준편차1) ---> 정확도 ?
P = 관심범주 (=target 군)
N=대조군 (관심범주(target)가 아닌 군)
그래서 양성이 N 이다.
예측(predict)이 타게팅 이다.
화면 캡처: 2019-02-25 오전 10:24
p.137
모델성능 개선하기 위해서
1. 수치 특징을 재조정
2. k값 재조정
전통적으로 정규화normalization 가 knn분류에 사용되어 왔지만,
항상 특징을 재조정하기 위한 최적의 방법이 될 수 없다.
z-점수 표준화 값은 사전에 정의된 최솟값, 최댓값이 없기 때문에
극값이 중심 방향으로 축소되지 않는다.
종양이 걷잡을 수 없이 자라면서 악성 종양 때문에 매우
극단적인 이상치가 나타날지도 모른다고 의심할 수 있다.
그러므로 거리계산에서 이상치에 좀 더 큰 가중치를 두는 것이
합리적이다.
벡터를 표준화 하기 위해 R내장함수 scale()을 이용하고
스케일함수는 데이터프레임에 직접 적용할수 있으므로
lapply() 함수를 사용할 필요가 없다.
표준화 잘되었는지 확인하려면 summary()를 통해서
평균이 0 인지 확인.
문제190.
문제 189번에서는 min/max 정규화를 해서 정확도를 확인했는데
이번에는 z-표준화(scale 함수)를 해서 정확도를 확인하시오
(이원 교차표를 반드시 확인하시오)
앞서 사용한 min/max 방법에 비해
scale 방법이 FP(정상->악성 판단) 가 높아진걸 확인했다.
■ 현업에서 데이터 분석할 때 필요한 사항
1. 오라클 데이터베이스에 있는 데이터를 csv 로 내리지 않고
바로 오라클과 R을 연동한다든지
오라클과 파이썬을 연동해서 바로 분석할 수 있게 하는게 중요하다
2. 현업 담당자들이 바로 분석할 수 있도록 UI를 만들어
UI를 배포(샤이니 기술 요구)
문제191.
knn 알고리즘을 R 샤이니에 구현하시오
1) 지난시간까지 완성했던 샤이키 코드: 그래프 + 테이블 포멧
############## set this file location to working directory ##########################
packages <- 'rstudioapi'
if (length(setdiff(packages, rownames(installed.packages()))) > 0) {
install.packages(setdiff(packages, rownames(installed.packages())))
}
library('rstudioapi')
current_dir<-dirname(rstudioapi::getSourceEditorContext()$path)
setwd(current_dir)
package_in<-function(p_name,option=1){
packages <- p_name
if (length(setdiff(packages, rownames(installed.packages()))) > 0) {
install.packages(setdiff(packages, rownames(installed.packages())))
}
if (option==1){
library(p_name,character.only = TRUE)
}
}
###########################1. 패키지 설치##########################################
package_in('shinydashboard')
package_in('shiny')
package_in('ggplot2')
package_in('plotly')
package_in('lattice')
######################### 2. 화면 개발 ###########################################
sidebar <- dashboardSidebar(
sidebarMenu(
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",".xlsx",".txt",
"text/comma-separated-values,text/plain",
".csv")),
menuItem("테이블",
menuSubItem('Tableformat',tabName='tableformat') ),
menuItem("그래프",
menuSubItem('Barplot',tabName='barplot'),
menuSubItem('Piechart',tabName='piechart'),
menuSubItem('Lineplot',tabName='lineplot'),
menuSubItem('Scatterplot',tabName='scatterplot'),
menuSubItem('boxplot',tabName='boxplot')
)
)
)
body <- dashboardBody(
tabItems(
##### table_format
tabItem(tabName = "tableformat",
mainPanel(
DT::dataTableOutput("table")
)
),
##### bar plot
tabItem(tabName = "barplot",
sidebarPanel(
selectInput("in_sel_bar_yVar","y Variable:", choices = NULL),
selectInput("in_sel_bar_xVar","x Variable:", choices = NULL)
),
mainPanel(
plotOutput('plot_bar')
)
),
##### piechart
tabItem(tabName = "piechart",
sidebarPanel(
selectInput("in_sel_pie_xVar","x Variable:", choices = NULL)
),
mainPanel(
plotlyOutput('plot_pie')
)
),
##### line plot
tabItem(tabName = "lineplot",
sidebarPanel(
selectInput("in_sel_line_yVar","y Variable:", choices = NULL),
selectInput("in_sel_line_xVar","x Variable:", choices = NULL)
),
mainPanel(
plotlyOutput('plot_line')
)
),
##### scatter plot
tabItem(tabName = "scatterplot",
sidebarPanel(
selectInput("in_sel_scatter_yVar","y Variable:", choices = NULL),
selectInput("in_sel_scatter_xVar","x Variable:", choices = NULL)
),
mainPanel(
plotOutput('plot_scatter'),
textOutput('text_scatter')
)
),
##### scatter plot
tabItem(tabName = "boxplot",
sidebarPanel(
selectInput("in_sel_box_xVar","x Variable:", choices = NULL)
),
mainPanel(
plotOutput('plot_box')
)
)
)
)
ui<-dashboardPage(
dashboardHeader(title='my graph'),
sidebar,
body
)
######################3. 서버단 개발 ########################################
server <- function(input, output,session) {
options(warn = -1)
options(shiny.maxRequestSize = 30*1024^2)
dataload<-reactive({
req(input$file1)
file1 = input$file1
data1 = read.csv(file1$datapath)
updateSelectInput(session, "in_sel_bar_xVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_bar_yVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_pie_xVar", choices = data1[,1])
updateSelectInput(session, "in_sel_line_xVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_line_yVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_scatter_xVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_scatter_yVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_box_xVar", choices = colnames(data1))
return(data1)
})
####table_format
output$table <- DT::renderDataTable(DT::datatable({
req(input$file1)
file1 = input$file1
data1 = read.csv(file1$datapath)
}))
####nomal_bar
output$plot_bar <- renderPlot({
table_in<-dataload()
xdata<-as.factor(table_in[,input$in_sel_bar_xVar])
ydata<-as.factor(table_in[,input$in_sel_bar_yVar])
fdata=data.frame(x=xdata,y=ydata)
ggplot(fdata) +
geom_bar(aes_string(x='x',y='y',fill='x'),stat = "identity",show.legend=F)
})
output$plot_pie <- renderPlotly({
table_in<-dataload()
plot_ly(table_in, labels = ~colnames(table_in)[-1], values=~as.factor( table_in[table_in[,1] == input$in_sel_pie_xVar,-1] ),type='pie')
})
output$plot_line <- renderPlotly({
table_in<-dataload()
x <- list(title = input$in_sel_line_xVar)
y <- list(title = input$in_sel_line_yVar)
plot_ly(data = table_in,x=~table_in[,input$in_sel_line_xVar],y=~table_in[,input$in_sel_line_yVar],type='scatter',mode='dot')%>%
layout(xaxis = x, yaxis = y)
})
output$plot_scatter <- renderPlot({
table_in<-dataload()
xyplot(table_in[,input$in_sel_scatter_yVar]~table_in[,input$in_sel_scatter_xVar], grid=T,type=c('p','smooth'),col.line='darkorange',lwd=2, xlab=input$in_sel_scatter_xVar,ylab=input$in_sel_scatter_yVar)
})
output$text_scatter <- renderText({
table_in<-dataload()
paste("The correlation between the two is: ", cor(table_in[,input$in_sel_scatter_yVar],table_in[,input$in_sel_scatter_xVar]))
})
output$plot_box <- renderPlot({
table_in<-dataload()
bwplot(~table_in[,input$in_sel_box_xVar], data=table_in,xlab=input$in_sel_box_xVar)
})
}
######################### 4. 샤이니 실행 ###############################
shinyApp(ui = ui, server = server)
2) 머신러닝 탭을 샤이니에 붙이기 위한 기본 골격 코드
0. knn 패키지 추가
#Knn
package_in("class")
1. 사이드 메뉴에 아래의 내용 추가
sidebar <- dashboardSidebar(
menuSubItem('Knn',tabName = 'knn')
)
2. 바디에 아래의 내용 추가
body <- dashboardBody(
tabItem(tabName = "knn",
sidebarPanel(
uiOutput("dependents_delcol_knn"), # -->컬럼삭제 화면
uiOutput("dependents_selcol_knn"), # -->라벨컬럼 선택하는 화면
uiOutput("dependents_button_knn") #--> knn 알고리즘 수행하는
버튼화면
#uiOutput("check_view_plot_knn"),
),
mainPanel(verbatimTextOutput("submit_input_sample_knn")),
#↑컬럼삭제하면 나머지 컬럼들 표시
mainPanel(verbatimTextOutput("TestTableRender_knn"),
# ↑이원교차표 표시
style = "color:red; font-size:12px; font-style:italic;
overflow-y:scroll; max-height: 400px; background: ghostwhite;")
)
)
3. 서버에 아래의 내용 추가
server <- function(input, output,session) {
## knn UI input
output$dependents_delcol_knn <- renderUI({
data <- dataload()
if (is.null(data)) return(NULL)
# 필요없는 컬럼을 삭제하는 코드(유방암 데이터에서 id 지우듯이!)
checkboxGroupInput(inputId = 'in_che_delcol_knn',
label = "delete colmun:",
choices = colnames(data),
selected = 'null',
inline = FALSE
)
})
# knn 모델을 돌리게끔 action 버튼을 누르는 코드
output$dependents_button_knn <- renderUI({
data <- dataload()
if (is.null(data)) return(NULL)
actionButton("in_btn_submit_knn","Submit")
})
# 라벨이 어떤 컬럼인지 선택하는 코드
output$dependents_selcol_knn <- renderUI({
data <- dataload()
if (is.null(data)) return(NULL)
selectInput("in_sel_label_knn","Submit",choices = colnames(data))
})
#4. 서버에 UI output 에 아래의 내용추가
normalize <- function(x) {
return (( x - min(x)) / (max(x) -min(x)))
}
###############knn show, reactive
subinput_table_knn <- eventReactive(input$in_btn_submit_knn, {
req(input$file1)
file1 = input$file1
data = read.csv(file1$datapath,stringsAsFactors =FALSE)
data1<-as.data.frame(lapply(data[,-which(colnames(data)==input$in_sel_label_knn)],
#제껴라! # 라벨컬럼
normalize))
# min/max 를 이용한 normalize
train_index = as.integer(trunc(nrow(data1) *0.8)) #0.8은 임의정함. 바꿔도 노상관
train <- data1[1:as.integer(train_index), ] #숫자로 바꿔줘야 한다.(인식못함)
#[1:367]
test <- data1[as.integer(train_index+1):as.integer(nrow(data1)), ]
train_label <-data[1:as.integer(train_index),which(colnames(data)==input$in_sel_label_knn)]
#다시 라벨 집어넣어줌
test_label <- data[as.integer(train_index+1):as.integer(nrow(data1)),which(colnames(data)==input$in_sel_label_knn) ]
train_label <- factor(train_label )
#test_label <- factor(test_label)
result <- knn(train=train , test=test , cl=train_label, k= 21 ) # k값 조정가능 (k=전체로우row의 제곱근)
cross_table <- CrossTable(test_label , result, prop.chisq=FALSE ) #이원교차표
return(cross_table)
})
#output 이 2개다
output$TestTableRender_knn <- renderPrint({
subinput_table_knn() #이원교차표
})
output$submit_input_sample_knn <- renderPrint({
req(input$file1)
file1 = input$file1
data <- read.csv(file1$datapath)
data1 <- data[,!(colnames(data) %in% input$in_che_delcol_knn )]
return(head(data1,5)) #헤더수 조정!
})
}
######################### 4. 샤이니 실행 ###############################
shinyApp(ui = ui, server = server)
문제192(점심시간문제)
위에 샤이니 코드에는 k값 21을 직접 셋팅했지만
다른 데이터를 넣으면 21이 아니라 달라져야 하므로
k값이 책에 나온대로 입력 데이터 훈련 건수의 제곱근이 들어가게끔
코드를 수정하시오
############## set this file location to working directory ##########################
packages <- 'rstudioapi'
if (length(setdiff(packages, rownames(installed.packages()))) > 0) {
install.packages(setdiff(packages, rownames(installed.packages())))
}
library('rstudioapi')
current_dir<-dirname(rstudioapi::getSourceEditorContext()$path)
setwd('D:\\Rdata')
package_in<-function(p_name,option=1){
packages <- p_name
if (length(setdiff(packages, rownames(installed.packages()))) > 0) {
install.packages(setdiff(packages, rownames(installed.packages())))
}
if (option==1){
library(p_name,character.only = TRUE)
}
}
###########################1. 패키지 설치##########################################
# 그래프
package_in('shinydashboard')
package_in('shiny')
package_in('ggplot2')
package_in('plotly')
package_in('lattice')
#Knn
package_in("class")
package_in("gmodels")
######################### 2. 화면 개발 ###########################################
sidebar <- dashboardSidebar(
sidebarMenu(
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",".xlsx",".txt",
"text/comma-separated-values,text/plain",
".csv")),
menuItem("테이블",
menuSubItem('Tableformat',tabName='tableformat') ),
menuItem("그래프",
menuSubItem('Barplot',tabName='barplot'),
menuSubItem('Piechart',tabName='piechart'),
menuSubItem('Lineplot',tabName='lineplot'),
menuSubItem('Scatterplot',tabName='scatterplot'),
menuSubItem('boxplot',tabName='boxplot')
),
menuItem("머신러닝",
menuSubItem('Knn',tabName = 'knn')
)
)
)
body <- dashboardBody(
tabItems(
##### table_format
tabItem(tabName = "tableformat",
mainPanel(
DT::dataTableOutput("table")
)
),
##### bar plot
tabItem(tabName = "barplot",
sidebarPanel(
selectInput("in_sel_bar_yVar","y Variable:", choices = NULL),
selectInput("in_sel_bar_xVar","x Variable:", choices = NULL)
),
mainPanel(
plotOutput('plot_bar')
)
),
##### piechart
tabItem(tabName = "piechart",
sidebarPanel(
selectInput("in_sel_pie_xVar","x Variable:", choices = NULL)
),
mainPanel(
plotlyOutput('plot_pie')
)
),
##### line plot
tabItem(tabName = "lineplot",
sidebarPanel(
selectInput("in_sel_line_yVar","y Variable:", choices = NULL),
selectInput("in_sel_line_xVar","x Variable:", choices = NULL)
),
mainPanel(
plotlyOutput('plot_line')
)
),
##### scatter plot
tabItem(tabName = "scatterplot",
sidebarPanel(
selectInput("in_sel_scatter_yVar","y Variable:", choices = NULL),
selectInput("in_sel_scatter_xVar","x Variable:", choices = NULL)
),
mainPanel(
plotOutput('plot_scatter'),
textOutput('text_scatter')
)
),
##### scatter plot
tabItem(tabName = "boxplot",
sidebarPanel(
selectInput("in_sel_box_xVar","x Variable:", choices = NULL)
),
mainPanel(
plotOutput('plot_box')
)
),
#### knn
tabItem(tabName = "knn",
sidebarPanel(
uiOutput("dependents_delcol_knn", #컬럼 삭제하는 화면
style="overflow-y:scroll; max-height: 500px; background: ghostwhite;"), #화면 스크롤
uiOutput("dependents_selcol_knn"), #라벨 컬럼 선택하는 화면
uiOutput("dependents_button_knn") #knn 알고리즘 수행하는
#uiOutput("check_view_plot_knn"), #버튼 화면
), # 컬럼삭제하면 나머지 컬럼들 표시
mainPanel(verbatimTextOutput("submit_input_sample_knn"),
style="overflow-y:scroll: max-height: 500px; background: ghostwhite;"),
mainPanel(verbatimTextOutput("TestTableRender_knn"),
style = "color:red; font-size:12px; font-style:italic;
overflow-y:scroll; max-height: 400px; background: ghostwhite;")
)
)
)
ui<-dashboardPage(
dashboardHeader(title='my graph'),
sidebar,
body
)
######################3. 서버단 개발 ########################################
server <- function(input, output,session) {
options(warn = -1)
options(shiny.maxRequestSize = 30*1024^2)
dataload<-reactive({
req(input$file1)
file1 = input$file1
data1 = read.csv(file1$datapath)
updateSelectInput(session, "in_sel_bar_xVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_bar_yVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_pie_xVar", choices = data1[,1])
updateSelectInput(session, "in_sel_line_xVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_line_yVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_scatter_xVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_scatter_yVar", choices = colnames(data1))
updateSelectInput(session, "in_sel_box_xVar", choices = colnames(data1))
return(data1)
})
####table_format
output$table <- DT::renderDataTable(DT::datatable({
req(input$file1)
file1 = input$file1
data1 = read.csv(file1$datapath)
}))
####nomal_bar
output$plot_bar <- renderPlot({
table_in<-dataload()
xdata<-as.factor(table_in[,input$in_sel_bar_xVar])
ydata<-as.factor(table_in[,input$in_sel_bar_yVar])
fdata=data.frame(x=xdata,y=ydata)
ggplot(fdata) +
geom_bar(aes_string(x='x',y='y',fill='x'),stat = "identity",show.legend=F)
})
output$plot_pie <- renderPlotly({
table_in<-dataload()
plot_ly(table_in, labels = ~colnames(table_in)[-1], values=~as.factor( table_in[table_in[,1] == input$in_sel_pie_xVar,-1] ),type='pie')
})
output$plot_line <- renderPlotly({
table_in<-dataload()
x <- list(title = input$in_sel_line_xVar)
y <- list(title = input$in_sel_line_yVar)
plot_ly(data = table_in,x=~table_in[,input$in_sel_line_xVar],y=~table_in[,input$in_sel_line_yVar],type='scatter',mode='dot')%>%
layout(xaxis = x, yaxis = y)
})
output$plot_scatter <- renderPlot({
table_in<-dataload()
xyplot(table_in[,input$in_sel_scatter_yVar]~table_in[,input$in_sel_scatter_xVar], grid=T,type=c('p','smooth'),col.line='darkorange',lwd=2, xlab=input$in_sel_scatter_xVar,ylab=input$in_sel_scatter_yVar)
})
output$text_scatter <- renderText({
table_in<-dataload()
paste("The correlation between the two is: ", cor(table_in[,input$in_sel_scatter_yVar],table_in[,input$in_sel_scatter_xVar]))
})
output$plot_box <- renderPlot({
table_in<-dataload()
bwplot(~table_in[,input$in_sel_box_xVar], data=table_in,xlab=input$in_sel_box_xVar)
})
## knn UI input
output$dependents_delcol_knn <- renderUI({
data <- dataload()
if (is.null(data)) return(NULL)
checkboxGroupInput(inputId = 'in_che_delcol_knn',
label = "delete colmun:", #필요없는 컬럼을
choices = colnames(data), #삭제하는 코드
selected = 'null',
inline = FALSE
)
})
output$dependents_button_knn <- renderUI({
data <- dataload() #knn 모델을 돌리겠금
if (is.null(data)) return(NULL) #action 버튼을 누르는 코드
actionButton("in_btn_submit_knn","Submit")
})
output$dependents_selcol_knn <- renderUI({
data <- dataload() #라벨이 어떤 컬럼인지
if (is.null(data)) return(NULL) #선택하는 코드
selectInput("in_sel_label_knn","Submit",choices = colnames(data))
}) # diagnois 선택하는 컬럼스크롤
normalize <- function(x) {
return (( x - min(x)) / (max(x) -min(x)))
}
###############knn show, reactive롤
## 아래 과정을 거쳐서 이원교차표 도출
subinput_table_knn <- eventReactive(input$in_btn_submit_knn, {
req(input$file1)
file1 = input$file1
data = read.csv(file1$datapath,stringsAsFactors =FALSE)
data1<-as.data.frame(lapply(data[,-which(colnames(data)==input$in_sel_label_knn)],
#제껴라! # 라벨컬럼
# 유방암 데이터에서는 선택한 diagnosis
normalize))
# min/max 를 이용한 normalize
train_index = as.integer(trunc(nrow(data1) *0.8)) #0.8은 임의정함. 바꿔도 노상관
train <- data1[1:as.integer(train_index), ] #숫자로 바꿔줘야 한다.(인식못함)
#[1:367]
test <- data1[as.integer(train_index+1):as.integer(nrow(data1)), ]
train_label <-data[1:as.integer(train_index),which(colnames(data)==input$in_sel_label_knn)]
#다시 라벨 집어넣어줌
test_label <- data[as.integer(train_index+1):as.integer(nrow(data1)),which(colnames(data)==input$in_sel_label_knn) ]
train_label <- factor(train_label )
#test_label <- factor(test_label)
### k 값 훈련데이터의 제곱근--------
k<-sqrt(nrow(train))
k<-round(k)
result <- knn(train=train , test=test , cl=train_label, k ) # k값 조정가능 (k=전체로우row의 제곱근)
cross_table <- CrossTable(test_label , result, prop.chisq=FALSE ) #이원교차표
return(cross_table)
})
#output 이 2개다
output$TestTableRender_knn <- renderPrint({
subinput_table_knn() #이원교차표
})
output$submit_input_sample_knn <- renderPrint({
req(input$file1)
file1 = input$file1
data <- read.csv(file1$datapath)
data1 <- data[,!(colnames(data) %in% input$in_che_delcol_knn )]
# id 컬럼뺀 나머지를 담아서 data1 이라고 선언
return(head(data1,2))
# 각각의 컬럼을 2개씩 보여줌
# 이원교차표 위에 나타남
})
}
######################### 4. 샤이니 실행 ###############################
shinyApp(ui = ui, server = server)
문제193.
우리가 만든 knn 샤이니 화면에
붓꽃 데이터로 knn 분류를 잘 하는지 확인하시오
개고양이 처럼 데이터가 안섞여있다.
그럼 샤이니로 켰을 때 제대로 된 knn 결과를 얻을 수 없다.
셔플시켜보자.
■ data shuffle 시키고 내리기
setwd("d://data")
set.seed(11) #랜덤으로 셔플시킬 건데 자리마다 일정하게 시키려고.
iris <- read.csv("iris.csv", header=T)
iris_shuffle <- iris[sample(nrow(iris)), ] # sample(nrow(iris)) 하면 셔플된다.
write.csv(iris_shuffle,file="iris_shuffle.csv", row.names=FALSE)
# 셔플된걸 write.csv로 저장!
#row.names 안나오게!
#해당 경로 폴더 들어가면 새로 생겨있음
■ train 과 test 로 나누기
train_num<-round(0.7*nrow(skin_shuffle),0)
skin_train <- skin_shuffle[1:train_num,]
skin_test <-skin_shuffle[(train_num+1):nrow(skin_shuffle),]