基於手機傳感器數據使用 CNN 識別用戶行為的 Tensroflow 實現


傳感器數據集

這個項目使用了 WISDM (Wireless Sensor Data Mining) Lab 實驗室公開的 Actitracker 的數據集。 WISDM 公開了兩個數據集,一個是在實驗室環境采集的;另一個是在真實使用場景中采集的,這里使用的是實驗室環境采集的數據。

  • 測試記錄:1,098,207 條
  • 測試人數:36 人
  • 采樣頻率:20 Hz
  • 行為類型:6 種
    • 走路
    • 慢跑
    • 上樓梯
    • 下樓梯
    • 站立
  • 傳感器類型:加速度
  • 測試場景:手機放在衣兜里面

數據分析

從 實驗室采集數據下載地址 下載數據集壓縮包,解壓后可以看到下面這些文件:

  • readme.txt
  • WISDM_ar_v1.1_raw_about.txt
  • WISDM_ar_v1.1_trans_about.txt
  • WISDM_ar_v1.1_raw.txt
  • WISDM_ar_v1.1_transformed.arff

我們需要的是包含 RAW 數據的 WISDM_ar_v1.1_raw.txt 文件,其他的是轉換后的或者說明文件。文件的每一行數據包含了測試id,行為類型,時間,加速度x,加速度y和加速度z。

這是一個不平衡的數據集,各個行為類型的數據比例不同,官方的描述文件中也提到:

  • Walking: 424,400 (38.6%)
  • Jogging: 342,177 (31.2%)
  • Upstairs: 122,869 (11.2%)
  • Downstairs: 100,427 (9.1%)
  • Sitting: 59,939 (5.5%)
  • Standing: 48,395 (4.4%)

 

創建、訓練並測試模型

模型可以分為數據輸入模型,訓練模型創建和測試評估模型。

數據輸入類型可以分為數據集加載,數據標准化,創建輸入數據。

加載數據集

  文件的數據保存在 WISDM_ar_v1.1_raw.txt中,可以用pandas里面的函數,read_csv()進行讀取。

def read_data(file_path):
    column_names = ['user-id', 'activity', 'timestamp', 'x-axis', 'y-axis', 'z-axis']
    data = pd.read_csv(file_path, header=None, names=column_names)
    return data

 

數據標准化

  對變量的標准差標准化:標准差標准化是將某變量中的觀察值減去該變量的平均數,然后除以該變量的標准差。即

       x’ik = (xik -mean )/sk

    經過標准差標准化后,各變量將有約一半觀察值的數值小於0,另一半觀察值的數值大於0,變量的平均數為0,標准差為1。經標准化的數據都是沒有單位的純數量。對變量進行的標准差標准化可以消除量綱(單位)影響和變量自身變異的影響。但有人認為經過這種標准化后,原來數值較大的的觀察值對分類結果的影響仍然占明顯的優勢,應該進一步消除大小因子的影響。盡管如此,它還是當前用得最多的數據標准化方法。

# 數據標准化
def feature_normalize(dataset):
    mu = np.mean(dataset, axis=0)
    sigma = np.std(dataset, axis=0)
    return (dataset - mu) / sigma

 

創建輸入數據

創建輸入數據,每一組數據包含x,y,z三個軸的90條連續記錄,用‘stats.mode’方法獲取這90條記錄中出現次數最多的行為作為該組行為的標簽,

def segment_signal(data, window_size=90):
    segments = np.empty((0, window_size, 3))
    labels = np.empty((0))
    print len(data['timestamp'])
    count = 0
    for (start, end) in windows(data['timestamp'], window_size):
        print count
        count += 1
        x = data["x-axis"][start:end]
        y = data["y-axis"][start:end]
        z = data["z-axis"][start:end]
        if (len(dataset['timestamp'][start:end]) == window_size):
            segments = np.vstack([segments, np.dstack([x, y, z])])
            labels = np.append(labels, stats.mode(data["activity"][start:end])[0][0])
    return segments, labels

 

 

訓練模型創建(cnn的結構如下):

 

  • 輸入:1*90大小的向量,3通道.(每天軸為一個通道,90為連續的90條記錄)
  • 第一層卷積:1*10大小的卷積核60個。
  • 第一層max-pooling:20*1的核。
  • 第二層卷積:1*6卷積核10個。
  • 第一層全連接:有1000個隱藏的神經元,采用tanh的激活函數
  • Softmax層:歸一化。

 訓練過程采用的是梯度下降算法。

卷積函數和池化函數的定義:

def depthwise_conv2d(x, W):
    return tf.nn.depthwise_conv2d(x, W, [1, 1, 1, 1], padding='VALID')

# 為輸入數據的每個 channel 執行一維卷積,並輸出到 ReLU 激活函數
def apply_depthwise_conv(x, kernel_size, num_channels, depth):
    weights = weight_variable([1, kernel_size, num_channels, depth])
    biases = bias_variable([depth * num_channels])
    return tf.nn.relu(tf.add(depthwise_conv2d(x, weights), biases))

# 在卷積層輸出進行一維 max pooling
def apply_max_pool(x, kernel_size, stride_size):
    return tf.nn.max_pool(x, ksize=[1, 1, kernel_size, 1],
                          strides=[1, 1, stride_size, 1], padding='VALID')

卷積網絡的建立:

# 下面是使用 Tensorflow 創建神經網絡的過程。
X = tf.placeholder(tf.float32, shape=[None,input_height,input_width,num_channels])
Y = tf.placeholder(tf.float32, shape=[None,num_labels])

c = apply_depthwise_conv(X,kernel_size,num_channels,depth)
p = apply_max_pool(c,20,2)
c = apply_depthwise_conv(p,6,depth*num_channels,depth//10)

shape = c.get_shape().as_list()
c_flat = tf.reshape(c, [-1, shape[1] * shape[2] * shape[3]])

f_weights_l1 = weight_variable([shape[1] * shape[2] * depth * num_channels * (depth//10), num_hidden])
f_biases_l1 = bias_variable([num_hidden])
f = tf.nn.tanh(tf.add(tf.matmul(c_flat, f_weights_l1),f_biases_l1))

out_weights = weight_variable([num_hidden, num_labels])
out_biases = bias_variable([num_labels])
y_ = tf.nn.softmax(tf.matmul(f, out_weights) + out_biases)

損失函數集訓練函數

loss = -tf.reduce_sum(Y * tf.log(y_))
optimizer = tf.train.GradientDescentOptimizer(learning_rate = learning_rate).minimize(loss)

 

 

測試評估模型

測試評估函數

correct_prediction = tf.equal(tf.argmax(y_,1), tf.argmax(Y,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

 

我們將所有的數據進行7/3分,7用於對模型進行訓練,3用於對模型精度進行測試,其結果如下:

Precision 0.888409996548

Recall 0.884568153909

f1_score 0.880684696544

可以看成在在只迭代了8次的情況之下,等到了0.88的精度,效果非常好。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM