1. 程式人生 > >手把手帶你實現 室內使用者移動預測(附python程式碼)

手把手帶你實現 室內使用者移動預測(附python程式碼)

介紹

大多數的時間序列資料主要用於交易生成預測。無論是預測產品的需求量還是銷售量,航空公司的乘客數量還是特定股票的收盤價,我們都可以利用時間序列技術來預測需求。

學習Python中有不明白推薦加入交流群

            號:960410445
            群裡有志同道合的小夥伴,互幫互助,
            群裡有不錯的視訊學習教程和PDF!

image

隨著生成的資料量呈指數級增長,嘗試新思想和演算法的機會也隨之增加。使用複雜的時間序列資料集仍然是一個待開發的領域。

這篇文章的目的就是介紹時間序列分類的新概念。我們將首先了解該概念的含義和在行業中的應用。我們不會只停留在理論部分,還會通過處理時間序列資料集並執行分類解決實際問題。一邊做一邊學有助於以實際的操作來理解概念。

目錄:

時間序列分類簡介1. ECG / EEG訊號分類2. 影象分類3. 運動感測器資料分類描述問題場景檢視資料集預處理建立分類模型

時間序列分類簡介

時間序列分類實際上已經存在了一段時間。但到目前為止,它主要用於實驗室研究,而不是行業應用。目前有很多正在進行的研究,新建立的資料集,許多新的演算法。當我第一次接觸到到時間序列分類概念時,最初的想法是:我們怎樣對時間序列進行分類以及時間序列分類資料是什麼樣的?我相信你一定也想知道。

可以想象,時間序列分類資料與常規分類問題不同,因為它的屬性是有序序列。讓我們來看看一些時間序列分類用例,瞭解它們之間的差異。

1. ECG / EEG訊號分類

心電圖(ECG, electrocardiogram),用於記錄心臟的電活動,並廣泛用於診斷各種心臟問題。使用外部電極捕獲這些ECG訊號。

例如,考慮以下訊號樣本,它代表一個心跳的電活動。左側影象表示正常心跳,而相鄰的影象表示心肌梗塞。

image

從電極捕獲的資料將是時間序列的形式,並且訊號可以分類為不同的類別。我們還可以對記錄大腦電活動的腦電訊號進行分類。

2. 影象分類

影象也可以是時間順序相關的。考慮以下的情況:

根據天氣條件,土壤肥力,水的可用性和其他外部因素,作物在特定的田地中生長。在該區域上持續每天拍攝圖片,持續5年,並標記在該區域上種植作物的名稱。該資料集中的影象是在固定的時間間隔拍攝的,並且具有特定的順序,這可能是對影象進行分類的重要因素。

3. 運動感測器資料分類

感測器生成高頻資料,可以識別其範圍內物體的移動。通過設定多個無線感測器並觀察感測器中訊號強度的變化,我們可以識別物體的運動方向。

你還知道哪些時間序列分類的應用嗎?歡迎大家在文末留言。

描述問題場景

我們將專注於 “室內使用者運動預測” 的問題。在該問題中,多個運動感測器被放置在不同的房間中,目標是從這些運動感測器捕獲的頻率資料中識別個體是否在房間之間移動。

兩個房間一共有四個運動感測器(A1,A2,A3,A4)。請看下面的影象,其中說明了感測器在每個房間中的位置。一共設定了 3 對類似的房間(group1,group2,group3)。

image

一個人可以沿著上圖所示的六個預定義路徑中的任意一個移動。路徑2, 3, 4或 6 是在房間內移動,路徑 1 或 5 在房間之間移動。

感測器的讀數可以識別人在某個時間點的位置。當人在房間內或在房間內移動時,感測器中的讀數會發生變化。改變化可用於標識人員的路徑。

現在問題已經表述清楚了,是時候開始編碼了!在下一節中,我們會檢視該問題的資料集,有助於使該問題更加清晰。資料集:室內使用者移動預測。

檢視資料集

資料集一共包含316個檔案:

  • 314 個 MovementAAL csv 檔案,包含環境中的運動感測器的讀數。

  • 一個 Target csv 檔案,包含每個 MovementAAL 檔案的目標變數。

  • 一個 Group Data csv 檔案,用於標識 MovementAAL 檔案屬於哪一個組。

  • Path csv 檔案包含目標採取的路徑。

首先看一下資料集。

1import pandas as pd2import numpy as np3%matplotlib inline4import matplotlib.pyplot as plt5from os import listdir
1from keras.preprocessing import sequence2import tensorflow as tf3from keras.models import Sequential4from keras.layers import Dense5from keras.layers import LSTM67from keras.optimizers import Adam8from keras.models import load_model9from keras.callbacks import ModelCheckpoint

在載入所有檔案之前先快速瀏覽一下要處理的資料。讀取移動資料的前兩個檔案:

1df1 = pd.read_csv('/MovementAAL/dataset/MovementAAL_RSS_1.csv')2df2 = pd.read_csv('/MovementAAL/dataset/MovementAAL_RSS_2.csv')
1df1.head()

image

1df2.head()

image

1df1.shape, df2.shape
1((27, 4), (26, 4))

這些檔案包含了四個感測器的標準化資料 —— A1,A2,A3,A4。csv 檔案的長度(行數)不同,是因為對應的持續時間不同。為方便起見,我們假設每秒都會收集到感測器資料。第一次變化持續時間為27秒(27行),而另一次變化為26秒(26行)。

在建立模型之前,我們必須處理這種不同的長度。以下的程式碼用於讀取和儲存感測器的值:

1path = 'MovementAAL/dataset/MovementAAL_RSS_'2sequences = list()3for i in range(1,315):4    file_path = path + str(i) + '.csv'5    print(file_path)6    df = pd.read_csv(file_path, header=0)7    values = df.values8    sequences.append(values)
1targets = pd.read_csv('MovementAAL/dataset/MovementAAL_target.csv')2targets = targets.values[:,1]

現在有一個名為 'sequences' 的列表,包含了運動感測器的資料和目標——csv檔案的標籤。sequences[0] 中的資料就是第一個csv檔案中獲取感測器的值:

1sequences[0]

image

如上所述,資料集是在三對不同的房間中收集的,所以有三組資料。正好可以將資料集劃分為訓練集,測試集和驗證集。現在載入 DatasetGroup csv 檔案:

1groups = pd.read_csv('MovementAAL/groups/MovementAAL_DatasetGroup.csv', header=0)2groups = groups.values[:,1]

前兩組的資料用於訓練 ,第三組用於測試。

預處理

由於時間序列資料的長度不同,我們不能直接在資料集上建立模型。那麼怎樣確定合適的長度呢?我們可以通過多種方發處理。這裡有一些簡單的想法(歡迎在評論區提出批評和建議):

  • 用零填充較短的序列使所有序列的長度相等。這種方式下,我們向模型提供了不正確的資料

  • 找到序列的最大長度,使用它最後一行中的資料填充

  • 確定資料集中序列的最小長度,將其他所有的序列截斷為該長度。這將損失大量的資料

  • 取所有長度的平均值,截斷較長的序列,填充較短的序列

獲取最小,最大和平均序列長度:

1len_sequences = []2for one_seq in sequences:3    len_sequences.append(len(one_seq))4pd.Series(len_sequences).describe()
1count    314.0000002mean      42.0286623std       16.1853034min       19.000000525%       26.000000650%       41.000000775%       56.0000008max      129.0000009dtype: float64

大多數檔案的長度在 40 到 60 之間。只有 3 個檔案的長度超過 100。因此,採用最小或最大的長度沒有太大意義。第 90 個四分位數是 60,可以將它作為所有序列的長度。程式碼:

 1### 用最長序列的最後一行的資料填充較短的序列 2to_pad = 129 3new_seq = [] 4for one_seq in sequences: 5    len_one_seq = len(one_seq) 6    last_val = one_seq[-1] 7    n = to_pad - len_one_seq 8 9    to_concat = np.repeat(one_seq[-1], n).reshape(4, n).transpose()10    new_one_seq = np.concatenate([one_seq, to_concat])11    new_seq.append(new_one_seq)12final_seq = np.stack(new_seq)1314# 截斷較長的序列15from keras.preprocessing import sequence16seq_len = 6017final_seq=sequence.pad_sequences(final_seq, maxlen=seq_len, padding='post', dtype='float', truncating='post')

然後根據分組將資料集分開,準備訓練集,驗證集和測試集:

1train = [final_seq[i] for i in range(len(groups)) if (groups[i]==2)]2validation = [final_seq[i] for i in range(len(groups)) if groups[i]==1]3test = [final_seq[i] for i in range(len(groups)) if groups[i]==3]45train_target = [targets[i] for i in range(len(groups)) if (groups[i]==2)]6validation_target = [targets[i] for i in range(len(groups)) if groups[i]==1]7test_target = [targets[i] for i in range(len(groups)) if groups[i]==3]
 1train = np.array(train) 2validation = np.array(validation) 3test = np.array(test) 4 5train_target = np.array(train_target) 6train_target = (train_target+1)/2 7 8validation_target = np.array(validation_target) 9validation_target = (validation_target+1)/21011test_target = np.array(test_target)12test_target = (test_target+1)/2

建立分類模型

我們已經準備了用於 LSTM(長短期記憶)模型的資料,處理了不同長度的序列並建立了訓練集,驗證集和測試集。接下來就要建立一個單層 LSTM 網路。

1model = Sequential()2model.add(LSTM(256, input_shape=(seq_len, 4)))3model.add(Dense(1, activation='sigmoid'))
1model.summary()

image

訓練模型並驗證準確率:

1adam = Adam(lr=0.001)2chk = ModelCheckpoint('best_model.pkl', monitor='val_acc', save_best_only=True, mode='max', verbose=1)3model.compile(loss='binary_crossentropy', optimizer=adam, metrics=['accuracy'])4model.fit(train, train_target, epochs=200, batch_size=128, callbacks=[chk], validation_data=(validation,validation_target))
1# 載入模型,用測試集驗證準確性2model = load_model('best_model.pkl')34from sklearn.metrics import accuracy_score5test_preds = model.predict_classes(test)6accuracy_score(test_target, test_preds)

最後準確度得分為0.78846153846153844。這是一個相當良好的開端,但我們還可以通過使用超引數,改變學習速率或迭代次數改善 LSTM 模型的效能。