Skip to content

Commit 3a7ea9c

Browse files
committed
mlKnn added
1 parent 946e696 commit 3a7ea9c

5 files changed

Lines changed: 125 additions & 3 deletions

File tree

NAMESPACE

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export(mlearning)
1616
export(mlLda)
1717
export(mlQda)
1818
export(mlRforest)
19+
export(mlKnn)
1920
export(mlLvq)
2021
export(mlNnet)
2122
export(mlSvm)
@@ -63,6 +64,7 @@ S3method(print, summary.lvq)
6364
S3method(mlLda, default)
6465
S3method(mlQda, default)
6566
S3method(mlRforest, default)
67+
S3method(mlKnn, default)
6668
S3method(mlLvq, default)
6769
S3method(mlNnet, default)
6870
S3method(mlSvm, default)
@@ -72,6 +74,7 @@ S3method(mlNaiveBayes, default)
7274
S3method(mlLda, formula)
7375
S3method(mlQda, formula)
7476
S3method(mlRforest, formula)
77+
S3method(mlKnn, formula)
7578
S3method(mlLvq, formula)
7679
S3method(mlNnet, formula)
7780
S3method(mlSvm, formula)
@@ -81,6 +84,7 @@ S3method(mlNaiveBayes, formula)
8184
S3method(predict, mlLda)
8285
S3method(predict, mlQda)
8386
S3method(predict, mlRforest)
87+
S3method(predict, mlKnn)
8488
S3method(predict, mlLvq)
8589
S3method(predict, mlNnet)
8690
S3method(predict, mlSvm)

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# mlearning 1.1.0
22

3-
- mlKnn() is implemented for K-nearest neigbour.
3+
- mlKnn() is implemented for K-nearest neigbours.
44

55
- Several adjustments were required for compatibility with R 4.2.0 (it is not allowed any more to use vectors \> 1 with \|\| and &&).
66

R/mlearning.R

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,3 +1312,104 @@ na.action = na.exclude, threshold = 0.001, eps = 0, ...) {
13121312
# algorithm = "Weka naive Bayes classifier",
13131313
# class = c("mlNaiveBayesWeka", "mlearning", "Weka_classifier"))
13141314
#}
1315+
1316+
mlKnn <- function(train, ...)
1317+
UseMethod("mlKnn")
1318+
1319+
mlKnn.formula <- function(formula, data, k.nn = 5, ..., subset, na.action) {
1320+
mlearning(formula, data = data, method = "mlKnn", model.args =
1321+
list(formula = formula, data = substitute(data),
1322+
subset = substitute(subset)), call = match.call(), k.nn = k.nn, ...,
1323+
subset = subset, na.action = substitute(na.action))
1324+
}
1325+
1326+
mlKnn.default <- function(train, response, k.nn = 5, ...) {
1327+
if (!is.factor(response))
1328+
stop("only factor response (classification) accepted for mlKnn")
1329+
1330+
dots <- list(...)
1331+
.args. <- dots$.args.
1332+
dots$.args. <- NULL
1333+
dots$k.nn <- k.nn
1334+
if (!length(.args.))
1335+
.args. <- list(levels = levels(response),
1336+
n = c(intial = NROW(train), final = NROW(train)),
1337+
type = "classification", na.action = "na.pass",
1338+
mlearning.call = match.call(), method = "mlKnn")
1339+
1340+
# matrix of numeric values
1341+
if (any(sapply(train, is.factor))) {
1342+
warning("force conversion from factor to numeric; may be not optimal or suitable")
1343+
train <- sapply(train, as.numeric)
1344+
}
1345+
1346+
# Create an object similar to the one obtained with ipred::ipredknn
1347+
res <- list(learn = list(y = response, X = train))
1348+
res$k <- k.nn
1349+
class(res) <- "simpleKnn"
1350+
1351+
# Return a mlearning object
1352+
structure(res, formula = .args.$formula, train = train,
1353+
response = response, levels = .args.$levels, n = .args.$n, args = dots,
1354+
optim = .args.$optim, numeric.only = TRUE, type = .args.$type,
1355+
pred.type = c(class = "class", prob = "prob"), summary = NULL,
1356+
na.action = .args.$na.action,
1357+
mlearning.call = .args.$mlearning.call, method = .args.$method,
1358+
algorithm = "k-nearest neighbours",
1359+
class = c("mlKnn", "mlearning", class(res)))
1360+
}
1361+
1362+
#summary.mlKnn <- function(object, ...)
1363+
# structure(cbind(Class = object$cl, as.data.frame(object$x)),
1364+
# class = c("summary.mlKnn", "data.frame"))
1365+
1366+
#print.summary.mlKnn <- function(x, ...) {
1367+
# cat("Train dataset:\n")
1368+
# print(as.data.frame(x))
1369+
# invisible(x)
1370+
#}
1371+
1372+
predict.mlKnn <- function(object, newdata,
1373+
type = c("class", "prob", "both"),
1374+
method = c("direct", "cv"), na.action = na.exclude, ...) {
1375+
if (!inherits(object, "mlKnn"))
1376+
stop("'object' must be a 'mlKnn' object")
1377+
1378+
# If method == "cv", delegate to cvpredict()
1379+
method <- as.character(method)[1]
1380+
if (method == "cv") {
1381+
if (!missing(newdata))
1382+
stop("cannot handle new data with method = 'cv'")
1383+
return(cvpredict(object = object, type = type, na.action = na.action, ...))
1384+
}
1385+
1386+
# Recalculate newdata according to formula...
1387+
if (missing(newdata))
1388+
newdata <- object$learn$X # Use train
1389+
# Use model.frame but eliminate dependent variable, not required
1390+
# (second item in the formula)
1391+
newdata <- model.frame(formula = attr(object, "formula")[-2],
1392+
data = newdata, na.action = na.pass)[, names(object$learn$X)]
1393+
# Only numerical predictors
1394+
newdata <- sapply(as.data.frame(newdata), as.numeric)
1395+
1396+
# Determine how many data and perform na.action
1397+
n <- NROW(newdata)
1398+
newdata <- match.fun(na.action)(newdata)
1399+
ndrop <- attr(newdata, "na.action")
1400+
1401+
if (inherits(object, "simpleKnn")) {
1402+
res <- class::knn(object$learn$X, newdata, object$learn$y, k = object$k,
1403+
prob = TRUE)
1404+
} else {# ipred::ipredknn
1405+
res <- ipred::predict.ipredknn(object, newdata, type = "class")
1406+
}
1407+
type <- as.character(type[1])
1408+
if (type == "prob") {
1409+
return(attr(res, "prob"))
1410+
} else if (type == "class") {
1411+
attr(res, "prob") <- NULL
1412+
}
1413+
1414+
.expandFactor(res, n, ndrop)
1415+
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<!-- badges: end -->
88

9-
{mlearning} rovides a unified interface to various machine learning algorithms. Confusion matrices are provided too.
9+
{mlearning} provides a unified interface to various machine learning algorithms. Confusion matrices are provided too.
1010

1111
## Installation
1212

man/mlearning.Rd

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
\alias{mlNnet.default}
2626
\alias{mlNnet.formula}
2727
\alias{predict.mlNnet}
28+
\alias{mlKnn}
29+
\alias{mlKnn.default}
30+
\alias{mlKnn.formula}
31+
\alias{predict.mlKnn}
2832
\alias{mlLvq}
2933
\alias{mlLvq.default}
3034
\alias{mlLvq.formula}
@@ -91,6 +95,12 @@ mlNnet(train, ...)
9195
\method{predict}{mlNnet}(object, newdata, type = c("class", "membership", "both", "raw"),
9296
method = c("direct", "cv"), na.action = na.exclude,...)
9397

98+
mlKnn(train, ...)
99+
\method{mlKnn}{default}(train, response, k.nn = 5, ...)
100+
\method{mlKnn}{formula}(formula, data, k.nn = 5, ..., subset, na.action)
101+
\method{predict}{mlKnn}(object, newdata, type = c("class", "prob", "both"),
102+
method = c("direct", "cv"), na.action = na.exclude,...)
103+
94104
mlLvq(train, ...)
95105
\method{mlLvq}{default}(train, response, k.nn = 5, size, prior, algorithm = "olvq1", ...)
96106
\method{mlLvq}{formula}(formula, data, k.nn = 5, size, prior, algorithm = "olvq1", ...,
@@ -193,7 +203,7 @@ train(object, ...)
193203
computed. }
194204
\item{decay}{ parameter for weight decay. Default 0. }
195205
\item{maxit}{ maximum number of iterations. Default 1000. }
196-
\item{k.nn}{ k used for k-NN test of correct classification. Default is 5. }
206+
\item{k.nn}{ k used for k-NN number of neighbour considered. Default is 5. }
197207
\item{algorithm}{ an algorithm among 'olvq1' (default, the optimized lvq1),
198208
'lvq1', 'lvq2', or 'lvq3'. }
199209
\item{scale}{ are all the variables scaled? If a vector is provided, it is
@@ -356,6 +366,13 @@ plot(na.omit(airquality)$Ozone, predict(ozone.nnet, type = "raw"))
356366
abline(a = 0, b = 1)
357367

358368

369+
## Supervised classification using k-nearest neighbours
370+
summary(res <- mlKnn(Species ~ ., data = irisTrain))
371+
predict(res) # This object only returns class
372+
confusion(res) # Self-consistency
373+
confusion(predict(res, newdata = irisTest), irisTest$Species) # Test set perfs
374+
375+
359376
## Supervised classification using learning vector quantization
360377
summary(res <- mlLvq(Species ~ ., data = irisTrain))
361378
predict(res) # This object only returns class

0 commit comments

Comments
 (0)