■ 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),]