-
Notifications
You must be signed in to change notification settings - Fork 1
/
3-FkNN.R
163 lines (124 loc) · 5.68 KB
/
3-FkNN.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#<>--------------------------------------------------<>
# Fuzzy K-Nearest Neighbors Algorithm
#
# date: 24.11.2017
# version:0.1
# author: Jodavid Ferreira; Anny Kerollayny; Raydonal Ospina
# e-mails: jdaf1@de.ufpe.com; akgr1@de.ufpe.br; raydonal@de.ufpe.br
#<>--------------------------------------------------<>
# Prerequisites
library(parallel)
#install.packages("parallel")
library(doSNOW)
library(doParallel)
#Cores
cores <- detectCores()-1
cores
#######################################################
#######################################################
#######################################################
fuzzy_kNN <- function(train, test, cl, viz = 1, m = 2) {
#train: training sample (data.frame);
#test: test sample (data.frame);
#cl: TRUE class vector;
#viz: number Neighbors;
#m: force parameter, used to determine the importance of the neighbor along with the weight;
#Condition that the number of training lines is equal to the size of the true response vector
if( dim( train )[1] != length( cl ) ) stop( "Training dimension is different from the vector of known outcomes!")
#<> -------------------------------------- <>
#<> -------------------------------------- <>
#### Euclidian distance
euclideanDist <- function(x1, x2) {
d <- (x1-x2)^2;
return(d);
}
#<> -------------------------------------- <>
#<> -------------------------------------- <>
#### Distance between test observation and training sample to find nearest neighbors
distNeighbors <- function(x1,vetx) {
saida2 <- 0
#Condition below for the training sample vector between with data.frame type
if( is.null( dim(x1) ) & length(x1)!=1) stop("Incorrect dimension of data. Input the training sample as data.frame type!")
for( i in 1:dim(vetx)[2] ){
saida <- euclideanDist( as.numeric(x1[i]) , vetx[,i])
saida2 <- saida2+saida;
}
return( sqrt(saida2) )
}
#<> -------------------------------------- <>
#### Distance with formula to calculate pertinence
distPert <- function(x1,x2) {
if(m<=1) stop( "m must be greater than 1!" )
if(x1==x2){ saida=0; saida } else{
saida <- abs(x1 - x2)
return(saida)
}
}
#<> ----------------------- <>
#<> ----------------------- <>
##Calculating the degrees of pertinence
bd_p_pert<-cbind(train,cl)
#pertinen_fin<-c()
pertinen_fin<- simplify2array(mclapply(1:dim(train)[1], function(j){
t=train[j,] #Observate to be calculated pertinence
t1<-cl[j] #Selecting Class of the j-observation
saida_Neighbors<-data.frame(distNeighbors(t,train),cl) #Calculating the distance between the observation and the other observations
saida_Neighbors<-saida_Neighbors[order(saida_Neighbors[,1]),] #Sorting through the distance column to pick up the nearest neighbors
grupos<-saida_Neighbors[1+(1:viz),2] #Selecting nearest neighbors
grup<-table(grupos) #viewing in a frequency table
# Calculation of pertinence for training sample
#Generating the first pertinences
u<-0
for(i in 1:length(levels(cl))){
if(names(grup[i])==t1){
u[i]<-0.51+(grup[i]/viz)*.49
}else{
u[i]<-(grup[i]/viz)*.49
}
}
#pertinen_fin<-
return(u)
},mc.cores = cores))
pertinen_fin <- t(pertinen_fin)
bd_p_pert<-cbind(bd_p_pert,pertinen_fin)
#<> ----------------------- <>
##Loop to set the groups of the test observations
#grupofin<-c()
grupofin <- foreach(j=1:dim(test)[1],.combine=c) %dopar% {
#simplify2array(mclapply(1:dim(test)[1],function(j) { #Loop for sample test
t=test[j,] #Observation to be classified
print(j);cat(j);
saida_Neighbors<-data.frame(distNeighbors(t,train),cl,train,pertinen_fin) #Calculating the distance between the observation and the other observations
saida_Neighbors<-saida_Neighbors[order(saida_Neighbors[,1]),] #Sorting through the distance column to pick up the nearest neighbors
grupos<-saida_Neighbors[1+(1:viz),-1] #Selecting the nearest neighbors
# Calculation of pertinence for test sample
##Defining the gi's
U<-c()
for(i in 1:length(levels(cl))){
coluna_i<-1+dim(train)[2]+i #The first one is of column cl, this is necessary because the column of pertinence is after the column cl + variables_variables
sai3=0;sai4=0;
for(l in 1:viz){
for(k in 1+(1:dim(train)[2])){
sai6<-(distPert(t[(k-1)],grupos[l,k]))^2;
sai5 <- ( 1 / (sqrt(sai6)^(2/(m-1))) );
if(sai5==Inf){sai5=.Machine$integer.max}
sai<-grupos[l,coluna_i] * sai5
sai2 <- ( 1 / (sqrt(sai6)^(2/(m-1))) );
if(sai2==Inf){.Machine$integer.max}
sai3<-sai3+sai;
sai4=sai4+sai2;
if(sai4==Inf) sai4=.Machine$integer.max;
}
}
U[i] = ifelse(sai3==0 & sai4==0 ,1,sai3/sai4);
}
#grupofin<-
return(U)
# },mc.cores=cores)) # fim do mcapply
}#Fim do foreach
return(t(grupofin))
}#finished function Fuzzy_kNN
##################################################################################################
##################################################################################################
#Byte Code Compilation
fuzzy_kNN <- compiler::cmpfun( fuzzy_kNN )