I adapted the problem from the following link http://kdd.ics.uci.edu/databases/synthetic_control/synthetic_control.data.html. The goal is to classify the time series into 1 of 6 types of time series.
This dataset contains 600 examples of control charts synthetically generated by the process in Alcock and Manolopoulos (1999). There are six different classes of control charts:
The following image shows ten examples from each class:
NNS (>= 3.9.1)require(devtools); install_github('OVVO-Financial/NNS', ref = "NNS-Beta-Version")
require(NNS)
require(plyr)
require(data.table)
Scan from URL and convert into matrix with each observation as a column.
tsdata <- scan(url("http://kdd.ics.uci.edu/databases/synthetic_control/synthetic_control.data"))
tsdata <- matrix(tsdata, ncol=60, byrow = TRUE)
dim(tsdata)
## [1] 600 60
tsdata matrix with labelsThe following were put into columns of the matrix tsdata:
There are 60 observations per time series, as features or columns
We have the classification ID, per time series class it belongs to. The classes are organized as follows:
1-100 Normal
101-200 Cyclic
201-300 Increasing trend
301-400 Decreasing trend
401-500 Upward shift
501-600 Downward shiftThis leaves us with a matrix of 600 rows and 61 columns.
series = cbind(tsdata ,class.id = rep(1:6, each = 100))
dim(series)
## [1] 600 61
train and test setsThere are 600 time series, we will randomly remove 20% of the time series for an out of sample experiment.
set.seed(123)
test.index = sample(1:600, 120, replace = FALSE)
test.index
## [1] 173 473 245 528 561 28 314 530 327 270 565 268 399 337 61 527 144
## [18] 25 191 555 516 402 371 574 378 408 313 341 166 85 549 514 393 452
## [35] 14 591 428 122 179 130 80 232 231 206 571 78 596 258 147 599 26
## [52] 243 438 67 307 113 70 410 486 203 360 52 207 148 437 240 433 434
## [69] 423 234 400 333 375 1 251 116 200 321 184 58 127 347 217 575 54
## [86] 224 507 459 454 90 547 529 175 509 163 95 395 48 235 257 300 167
## [103] 244 475 535 441 567 301 541 73 513 537 30 462 351 544 266 461 283
## [120] 195
Checking our dimensions to ensure 120 time series have been removed.
training.ts.set = series[-test.index, ]
dim(training.ts.set)
## [1] 480 61
test.ts.set = series[test.index, ]
dim(test.ts.set)
## [1] 120 61
# Distribution of test set classifications
hist(series[ , "class.id"][test.index])
NNS.reg to find the most similarThe following settings in NNS.reg(..., order = "max", n.best = 1, ...) are very similar to a KNN = 1 (with the NNS general case exhibiting significant weighting differences and less sensitivity to the curse of dimensionality). We set up the following independent variables for training IVs.train, the dependent variable DV which is the class.id from our earlier training set training.ts.set, and our independent variables for testing IVs.test.
IVs.train = training.ts.set[ , colnames(training.ts.set) != "class.id"]
DV = training.ts.set[ , "class.id"]
IVs.test = test.ts.set[ , colnames(test.ts.set) != "class.id"]
Using these variables in our NNS.reg we store our Point.est as predictions
predictions = NNS.reg(IVs.train, DV, point.est = IVs.test, order = "max", n.best = 1, plot = FALSE, residual.plot = FALSE)$Point.est
Finally, a check of our accuracy yields:
mean(round(predictions) == test.ts.set[ , "class.id"])
## [1] 0.9833333
Let’s try 100 different seeds and visualize the results.
results=numeric()
for(i in 1:100){
set.seed(123+i)
test.index = sample(1:600, 120, replace = FALSE)
training.ts.set = series[-test.index, ]
test.ts.set = series[test.index, ]
IVs.train = training.ts.set[,colnames(training.ts.set) != "class.id"]
DV = training.ts.set[, "class.id"]
IVs.test = test.ts.set[,colnames(test.ts.set) != "class.id"]
predictions = NNS.reg(IVs.train, DV, point.est = IVs.test, order = "max", n.best = 1, plot = FALSE, residual.plot = FALSE)$Point.est
results[i] = mean(round(predictions) == test.ts.set[ , "class.id"])
}
hist(results)
mean(results); sd(results)
## [1] 0.9861667
## [1] 0.00999579
Comments
By reducing the
orderparameter in theNNS.regfunction, we can encode the time series with its regression points, which are clusters, thus permitting larger time-series analysis. This is an active area of development. Also, partial time-series matching is another area of active development.If you found this presentation interesting or useful, please feel free to reach out via e-mail: ovvo.financial.systems@gmail.com
Thanks for your interest!