• 基于手机传感器数据使用 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的精度,效果非常好。

  • 相关阅读:
    怎样打印日志
    log4j(一)
    idea没有subversion问题
    tomcat启动报异常(一)
    HashSet
    spring容器初始化bean和销毁bean之前进行一些操作的定义方法
    MyBatis中$和#的区别
    基本数据类型与引用数据类型
    Access restriction: The method 'CharacterEncoder.encode(byte[])' is not API...
    Object源码
  • 原文地址:https://www.cnblogs.com/yuqt/p/6169303.html
Copyright © 2020-2023  润新知