如何将多个时间序列数据呈现给 R 中的 SVM (ksvm)(或者,如何将二维输入数据呈现给 SVM)
Posted
技术标签:
【中文标题】如何将多个时间序列数据呈现给 R 中的 SVM (ksvm)(或者,如何将二维输入数据呈现给 SVM)【英文标题】:How to present multiple time-series data to an SVM (ksvm) in R (or, How to present two-dimensional input data to an SVM) 【发布时间】:2015-06-24 15:54:19 【问题描述】:我如何让ksvm 模型知道数据集中的前 100 个数字都是来自一个传感器的时间序列数据,而接下来的 100 个数字都是来自另一个传感器的时间序列数据,等等,六个不同的时间串联传感器输入?或者(也许更一般地),我如何将二维输入数据呈现给 SVM?
我需要二进制是/否预测模型的过程有六个非周期性时间序列输入,所有输入都具有相同的采样频率。一个事件触发数据收集的开始,在预定时间后,我需要一个是/否预测(最好包括正确概率输出)。应该产生“是”与“否”的时间序列输入的特征尚不清楚,但已知的是每个输入时间序列数据与最终结果之间应该存在某种相关性。所有输入上也存在明显的噪声。有意义的信息和噪声都以短持续时间的突发形式出现在输入上(对于给定的输入源,有意义的突发总是在相同的一般时间),但是很难识别哪些突发是有意义的,哪些是噪声;即,对于一个输入,突发发生在“正确”时间这一事实并不一定表示“是”输出;它可能只是噪音。要知道预测是否应该是“是”,模型需要以某种方式合并来自所有六个时间序列输入的信息。我收集了大约 900 个“否”结果和 100 个“是”结果的先前数据。
我对 R 和 SVM 都很陌生,但我想我想使用 SVM 模型 (kernlab's ksvm)。我无法弄清楚如何将输入数据呈现给它。我也不确定如何告诉 ksvm 数据是时间序列数据,或者这是否相关。我尝试使用 Rattle GUI 前端到 R 从 csv 文件中提取我的数据,但我无法弄清楚如何将所有六个输入的时间序列数据呈现到 ksvm 模型中。作为 csv 文件输入,似乎导入所有 1000 个样本的数据的唯一方法是组织输入数据,使所有样本数据(所有六个时间序列输入)都在 csv 文件的单行上,在 csv 文件的每一行上显示一个单独的已知结果文件的数据。但这样做时,第一个、第二个、第三个等数字是来自第一个传感器的时间序列数据的每个部分的事实在翻译中丢失了,以及第 101 个、第 102 个、第 103 个等的事实. 数字是来自第二个传感器的时间序列数据的每一部分,依此类推;对于 ksvm 模型,每个数据样本仅被视为与其邻居无关的孤立数字。如何将这些数据作为六个独立但相互关联的时间序列数组呈现给 ksvm?或者如何将二维数据数组呈现给 ksvm?
更新:
好的,我尝试了两种基本策略,但结果很糟糕(嗯,结果模型比盲目猜测要好,但不多)。
首先,不熟悉 R,我使用 Rattle GUI 前端到 R。我有一种感觉,这样做可能会限制我的选择。但无论如何,这就是我所做的......
已知结果文件示例(仅显示 4 个传感器而不是 6 个,仅显示 7 个时间样本而不是 100 个):
training168_yes.csv
Seconds Since 1/1/2000,sensor1,sensor2,sensor3,sensor4
454768042.4, 0, 0, 0, 0
454768042.6, 51, 60, 0, 172
454768043.3, 0, 0, 0, 0
454768043.7, 300, 0, 0, 37
454768044.0, 0, 0, 1518, 0
454768044.3, 0, 0, 0, 0
454768044.7, 335, 0, 0, 4273
training169_no.csv
Seconds Since 1/1/2000,sensor1,sensor2,sensor3,sensor4
454767904.5, 0, 0, 0, 0
454767904.8, 51, 0, 498, 0
454767905.0, 633, 0, 204, 55
454767905.3, 0, 0, 0, 512
454767905.6, 202, 655, 739, 656
454767905.8, 0, 0, 0, 0
454767906.0, 0, 934, 0, 7814
我知道将所有训练样本的数据导入 R/Rattle 的唯一方法是将所有结果文件合并到一个 .csv 文件中,每行一个样本结果。我只能想到两种方法,所以我都尝试了(我知道当我这样做时,我会隐藏潜在的重要信息,这就是这个 SO 问题的重点):
TRIAL #1:对于每个结果文件,将每个传感器的样本添加到一个数字中,消除所有时间信息:
result,sensor1,sensor2,sensor3,sensor4
no, 886, 1589, 1441, 9037
yes, 686, 60, 1518, 4482
no, 632, 1289, 1173, 9152
yes, 411, 67, 988, 5030
no, 772, 1703, 1351, 9008
yes, 490, 70, 1348, 4909
当我完成使用 Rattle 生成 SVM 后,Rattle 的日志选项卡为我提供了以下脚本,可用于在 RGui 中生成和训练 SVM:
library(rattle)
building <- TRUE
scoring <- ! building
library(colorspace)
crv$seed <- 42
crs$dataset <- read.csv("file:///C:/Users/mminich/Desktop/***/trainingSummary1.csv", na.strings=c(".", "NA", "", "?"), strip.white=TRUE, encoding="UTF-8")
set.seed(crv$seed)
crs$nobs <- nrow(crs$dataset) # 6 observations
crs$sample <- crs$train <- sample(nrow(crs$dataset), 0.67*crs$nobs) # 4 observations
crs$validate <- NULL
crs$test <- setdiff(setdiff(seq_len(nrow(crs$dataset)), crs$train), crs$validate) # 2 observations
# The following variable selections have been noted.
crs$input <- c("sensor1", "sensor2", "sensor3", "sensor4")
crs$numeric <- c("sensor1", "sensor2", "sensor3", "sensor4")
crs$categoric <- NULL
crs$target <- "result"
crs$risk <- NULL
crs$ident <- NULL
crs$ignore <- NULL
crs$weights <- NULL
require(kernlab, quietly=TRUE)
set.seed(crv$seed)
crs$ksvm <- ksvm(as.factor(result) ~ .,
data=crs$dataset[,c(crs$input, crs$target)],
kernel="polydot",
kpar=list("degree"=1),
prob.model=TRUE)
TRIAL #2:对于每个结果文件,将每次所有传感器的样本添加到一个数字中,从而消除有关单个传感器的任何信息:
result,time1, time2, time3, time4, time5, time6, time7
no, 0, 549, 892, 512, 2252, 0, 8748
yes, 0, 283, 0, 337, 1518, 0, 4608
no, 0, 555, 753, 518, 2501, 0, 8984
yes, 0, 278, 12, 349, 1438, 3, 4441
no, 0, 602, 901, 499, 2391, 0, 7989
yes, 0, 271, 3, 364, 1474, 1, 4599
我再次使用 Rattle 生成 SVM,Rattle 的日志选项卡为我提供了以下脚本:
library(rattle)
building <- TRUE
scoring <- ! building
library(colorspace)
crv$seed <- 42
crs$dataset <- read.csv("file:///C:/Users/mminich/Desktop/***/trainingSummary2.csv", na.strings=c(".", "NA", "", "?"), strip.white=TRUE, encoding="UTF-8")
set.seed(crv$seed)
crs$nobs <- nrow(crs$dataset) # 6 observations
crs$sample <- crs$train <- sample(nrow(crs$dataset), 0.67*crs$nobs) # 4 observations
crs$validate <- NULL
crs$test <- setdiff(setdiff(seq_len(nrow(crs$dataset)), crs$train), crs$validate) # 2 observations
# The following variable selections have been noted.
crs$input <- c("time1", "time2", "time3", "time4", "time5", "time6", "time7")
crs$numeric <- c("time1", "time2", "time3", "time4", "time5", "time6", "time7")
crs$categoric <- NULL
crs$target <- "result"
crs$risk <- NULL
crs$ident <- NULL
crs$ignore <- NULL
crs$weights <- NULL
require(kernlab, quietly=TRUE)
set.seed(crv$seed)
crs$ksvm <- ksvm(as.factor(result) ~ .,
data=crs$dataset[,c(crs$input, crs$target)],
kernel="polydot",
kpar=list("degree"=1),
prob.model=TRUE)
不幸的是,即使有近 1000 个训练数据集,这两个生成的模型都只给了我比随机机会得到的结果略好的结果。我很确定如果有办法避免破坏时间数据或不同传感器之间的区别,它会做得更好。我怎样才能做到这一点?顺便说一句,我不知道这是否重要,但所有传感器的传感器读数几乎是在同一时间获取的,但是一次读数和下一次读数之间的时间差通常从一次运行到下一个(即在“培训”文件之间),我无法控制。我认为这可能是安全的,可以忽略(即我认为按 1、2、3 等顺序对读数进行编号可能是安全的)。
【问题讨论】:
当我第一次开始发布 R 问题时,有人问我 "make a reproducible example"。这些技巧帮助我提出了更好的 R 问题,甚至回答了我自己的 R 问题。简而言之,如果您在问题中提供示例数据以及您认为应该工作的代码(或者尽可能接近使其工作的代码)以及预期的输出,那么我们都有一个很好的开始帮助您找到答案。 您研究过卡尔曼滤波器吗?它们旨在将两个容易出错的信号组合成一个更可靠的信号。 @BenjyKessler - 我不确定卡尔曼是否适用于我的情况?关于卡尔曼滤波器的***文章谈到了“固定滞后平滑器”,但在我的情况下,一个传感器与其他传感器的爆发之间的滞后是未知的,但已知(可能)存在。我希望 SVM 模型可以自动调整自身以检测滞后,如果它们很重要的话。无论如何,滞后会不时改变;我希望每次流程发生变化时,我都可以使用新的训练数据重新训练 SVM。如果我不知道滞后,卡尔曼还能提供帮助吗?另外,如果我有 6 个输入而不是 2 个输入会有帮助吗? @ChristopherBottoms - 感谢您的建议。我正在整理一个我已经尝试过的小例子,但结果令人沮丧。 @ChristopherBottoms,希望我的更新足以作为可重现的示例? 【参考方案1】:SVM 采用特征向量并使用它来构建分类器。您的特征向量可以是 6 维,每个来自不同的来源和时间,作为第七维。每个有信号的时间点都会产生另一个向量。创建 t
向量,Vt
,每个大小为 7,并将它们作为特征向量。用您的数据填充它们并将它们传递给ksvm
。通过添加t
作为特征向量中的另一个特征,您可以将在特定时间发生的所有数据相互关联,而且它还将帮助 SVM 了解它们是值的级数。
您可以选择Vt
的子集作为训练集。您必须使用正确分类的标签手动标记这些向量。
【讨论】:
我对R和统计学都不是很流利,所以我不知道如何解释S1,...,S6,t produces Vt, t=t0->tn Vt<-R^7
。您能否在答案中添加信息,逐点分解并解释每段的含义以及“产生”的含义,包括逗号后面的含义以及“->”和“
我换种说法,我也不是 R 专家。这应该是你的方法。也许其他了解 R 的人可以帮助您实现。
您是否在 R 中手动创建了 ksvm 对象(不使用 Rattle)?我无法弄清楚如何创建您所说的这些“特征向量”。我可以从其 .csv 文件中加载单个“观察”,该文件会生成一个 typeof() 为“list”的表,尽管当我打印它时,它似乎是一个矩阵(二维数组)。我是否只是创建这些二维对象的列表并将其作为“数据”提供给 ksvm?顺便说一句,我现在将时间戳从自 2000 年以来的秒数转换为自开始以来的秒数,因此第一行的时间戳为 0.000,依此类推。
嗯,实际上我以前从未使用过 R :) IIUC 你需要构建一个二维矩阵,其中每一行都是一个特征向量。
不是这样,但如果你有,你可能会得到更好的答案。以上是关于如何将多个时间序列数据呈现给 R 中的 SVM (ksvm)(或者,如何将二维输入数据呈现给 SVM)的主要内容,如果未能解决你的问题,请参考以下文章