咱们接触的大多数时间序列数据主要涉及产生预测的交易。不管是预测产品的需求仍是销售额,航空公司的乘客数量或特定股票的收盘价,咱们都习惯于利用久经考验的时间序列技术来预测需求。php
但随着生成的数据量呈指数增加,尝试新想法和算法的机会也随之增长。使用复杂的时间序列数据集仍然是一个利基领域,扩展你的保留曲目以包含新想法老是有帮助的。python
这就是本文的目的,向你介绍时间序列分类的新概念。咱们将首先了解这个主题的含义以及它在行业中的应用。可是不会只停留在理论部分——咱们将经过处理时间序列数据集并执行二进制时间序列分类来解决问题。边学边应用——这将有助于你以实际的方式理解这个概念。算法
时间序列分类介绍数据库
时间序列分类实际上已经存在了一段时间。但到目前为止,它主要限于研究实验室,而没有进行行业应用。可是有不少研究正在进行,正在建立新的数据集并提出了许多新的算法。网络
能够想象,时间序列分类数据与常规分类问题不一样,由于属性具备有序序列。 让咱们来看看一些时间序列分类用例,以了解这种差别。app
1.对心电图(ECG/EEG)信号进行分类post
心电图或心电图记录心脏的电活动,普遍用于诊断各类心脏问题。使用外部电极捕获这些心电图信号。性能
例如,考虑如下信号样本,它表明一个心跳的电活动。左侧的图像表示正常心跳,而与其相邻的图像表示心肌梗塞。学习
从电极捕获的数据将是时间序列形式,而且信号能够分类为不一样的类别。咱们还能够对记录大脑电活动的脑电信号进行分类。测试
在学习的道路上确定会遇到困难,没有好的学习资料怎么去学习呢? 若是你感受学不会?莫慌,推荐你加群 前面923中间414后面804 ,群里有志同道合的小伙伴 互帮互助,还能够拿到许多视频教程!
2.图像分类
图像也能够是顺序的时间相关格式。请考虑如下情形:
根据天气条件、土壤肥力、水的可用性和其余外部因素,农做物在特定的田地中生长。这块田地被监测拍摄了5年,并标记在该字段上种植的做物的名称。 你知道为何要这么作吗?数据集中的图像是在固定的时间间隔以后拍摄的,而且具备定义的序列,这多是对图像进行分类的重要因素。
3.对运动传感器数据进行分类
传感器生成高频数据,能够识别其范围内物体的移动。经过设置多个无线传感器并观察传感器中信号强度的变化,能够识别物体的运动方向。
设置问题陈述
咱们将致力于“室内用户运动预测”问题。在该挑战中,多个运动传感器被放置在不一样的房间中,而且目标是基于从这些运动传感器捕获的频率数据来识别个体是否已经移动穿过房间。
两个房间有四个运动传感器(A1,A2,A3,A4)。请看下面的图像,其中说明了传感器在每一个房间中的位置。这两个房间的设置是在3对不一样的房间(group1,group2,group3)中建立的。
一我的能够沿着上图中所示的六个预约义路径进行任何移动。若是一我的走在路径2,3,4或6上,他会在单个房间内移动。另外一方面,若是一我的沿着路径1或路径5行进,咱们能够说该人在两个房间之间移动。
传感器读数可用于识别人在给定时间点的位置。当人在房间或房间内移动时,传感器中的读数会发生变化。此更改可用于标识人员的路径。
既然这个问题陈述已经清楚了,如今是时候开始编码了!
读取和理解数据
咱们的数据集有316个文件
· 314个MovementAAL csv文件,包含放置在环境中的运动传感器的读数
· Target csv文件,其中包含每一个MovementAAL文件的目标变量
· 一个组数据csv文件,用于标识哪一个MovementAAL文件属于哪一个安装组
· Path csv文件,包含对象所采用的路径
咱们来看看数据集。咱们将从导入必要的数据库库开始。
import pandas as pd import numpy as np %matplotlib inline import matplotlib.pyplot as plt from os import listdir from keras.preprocessing import sequence import tensorflow as tf from keras.models import Sequential from keras.layers import Dense from keras.layers import LSTM from keras.optimizers import Adam from keras.models import load_model from keras.callbacks import ModelCheckpoint
在加载全部文件以前,让咱们快速了解一下要处理的数据。从移动数据中读取前两个文件:
df1 = pd.read_csv(‘/MovementAAL/dataset/MovementAAL_RSS_1.csv') df2 = pd.read_csv('/MovementAAL/dataset/MovementAAL_RSS_2.csv') df1.head
df2.head
df1.shape, df2.shape
((27, 4), (26, 4))
这些文件包含来自四个传感器的标准化数据——A1,A2,A3,A4。csv文件的长度(行数)不一样,由于对应于每一个csv的数据的持续时间不一样。为简化起见,咱们假设每秒都会收集传感器数据。第一次读数持续27秒(因此是27行),而另外一次读数持续26秒(因此是26行)。
在构建模型以前,咱们必须处理这些不一样的长度。如今,咱们将使用如下代码块读取传感器中的值并将其存储在列表中:
path = 'MovementAAL/dataset/MovementAAL_RSS_' sequences = list for i in range(1,315): file_path = path + str(i) + '.csv' print(file_path) df = pd.read_csv(file_path, header=0) values = df.values sequences.append(values) targets = pd.read_csv('MovementAAL/dataset/MovementAAL_target.csv') targets = targets.values[:,1]
咱们如今有一个列表“序列”,其中包含来自运动传感器的数据和“目标”,其中包含csv文件的标签。当咱们打印序列[0]时,从第一个csv文件中获取传感器的值:
sequences[0]
如前所述,数据集是在三对不一样的房间中收集的——所以有三组。此信息可用于将数据集划分为训练集、测试集和验证集。咱们如今将加载DatasetGroup csv文件:
groups= pd.read_csv('MovementAAL/groups/MovementAAL_DatasetGroup.csv', header=0) groups = groups.values[:,1]
咱们将前两组的数据用于培训目的,第三组用于测试。
预处理步骤
因为时间序列数据的长度不一样,咱们没法直接在此数据集上构建模型。那么怎样才能决定一个系列的理想长度呢?咱们能够经过多种方式处理它,这里有一些想法:
· 用零填充较短的序列,使全部序列的长度相等。在这种状况下,咱们将向模型提供不正确的数据。
· 查找序列的最大长度,并使用最后一行中的数据填充序列。
· 肯定数据集中序列的最小长度,并将全部其余序列截断为该长度。可是,这将致使数据的巨大损失。
· 取全部长度的平均值,截断较长的系列,并填充比平均长度短的序列。
让咱们找出最小长度、最大长度和平均长度:
len_sequences =
for one_seq in sequences:
len_sequences.append(len(one_seq))
pd.Series(len_sequences).describe
count 314.000000
mean 42.028662
std 16.185303
min 19.000000
25% 26.000000
50% 41.000000
75% 56.000000
max 129.000000
dtype: float64
大多数文件的长度在40到60之间。只有3个文件的长度超过100。所以,采用最小或最大长度没有多大意义。第90个四分位数为60,这被视为数据序列的长度。咱们来编代码:
#Padding the sequence with the values in last row to max length
to_pad = 129
new_seq =
for one_seq in sequences:
len_one_seq = len(one_seq)
last_val = one_seq[-1]
n = to_pad - len_one_seq
to_concat = np.repeat(one_seq[-1], n).reshape(4, n).transpose
new_one_seq = np.concatenate([one_seq, to_concat])
new_seq.append(new_one_seq)
final_seq = np.stack(new_seq)
#truncate the sequence to length 60
from keras.preprocessing import sequence
seq_len = 60
final_seq=sequence.pad_sequences(final_seq, maxlen=seq_len, padding='post', dtype='float', truncating='post')
既然数据集已准备好,咱们将根据组将其分开。准备训练、验证和测试集:
train = [final_seq[i] for i in range(len(groups)) if (groups[i]==2)]
validation = [final_seq[i] for i in range(len(groups)) if groups[i]==1]
test = [final_seq[i] for i in range(len(groups)) if groups[i]==3]
train_target = [targets[i] for i in range(len(groups)) if (groups[i]==2)]
validation_target = [targets[i] for i in range(len(groups)) if groups[i]==1]
test_target = [targets[i] for i in range(len(groups)) if groups[i]==3]
train = np.array(train)
validation = np.array(validation)
test = np.array(test)
train_target = np.array(train_target)
train_target = (train_target+1)/2
validation_target = np.array(validation_target)
validation_target = (validation_target+1)/2
test_target = np.array(test_target)
test_target = (test_target+1)/2
构建时间序列分类模型
咱们准备了用于LSTM(长短时间记忆)模型的数据。咱们处理了可变长度序列并建立了训练、验证和测试集。构建一个单层LSTM网络。
model = Sequential
model.add(LSTM(256, input_shape=(seq_len, 4)))
model.add(Dense(1, activation='sigmoid'))
model.summary
咱们如今将训练模型并监控验证的准确性:
adam = Adam(lr=0.001)
chk = ModelCheckpoint('best_model.pkl', monitor='val_acc', save_best_only=True, mode='max', verbose=1)
model.compile(loss='binary_crossentropy', optimizer=adam, metrics=['accuracy'])
model.fit(train, train_target, epochs=200, batch_size=128, callbacks=[chk], validation_data=(validation,validation_target))
#loading the model and checking accuracy on the test data
model = load_model('best_model.pkl')
from sklearn.metrics import accuracy_score
test_preds = model.predict_classes(test)
accuracy_score(test_target, test_preds)
这里的准确度得分为0.78846153846153844。这是一个很是有前景的开始,但咱们确定能够经过使用超参数,改变学习速度和/或时代数来改善LSTM模型的性能。
总结
预处理步骤是全部部分中最复杂的。然而,它也是最重要的一个(不然整个时间序列数据将会失败)。在处理此类挑战时,向模型提供正确的数据一样重要。