【TensorFlow】 基于LSTM的行为识别

简介

本文基于LSTM来完成用户行为识别。数据集来源:https://archive.ics.uci.edu/ml/machine-learning-databases/00240/

此数据集一共有6种行为状态:

  1. 行走;
  2. 站立;
  3. 躺下;
  4. 坐下;
  5. 上楼;
  6. 下楼;

以上6种行为数据是通过传感器进行采集的。

.\data\UCI HAR Dataset\train\Inertial Signals

实现

本次实验实现的是6分类任务。

import tensorflow as tf
import numpy as np


# 模型好坏主要由数据决定,数据决定模型上限,模型决定逼近这个上限,记录仪上的数据
def load_X(X_signals_paths):
    X_signals = []

    for signal_type_path in X_signals_paths:
        file = open(signal_type_path, 'r')
        X_signals.append(
            [np.array(serie, dtype=np.float32) for serie in
             [row.replace('  ', ' ').strip().split(' ') for row in file]])
        file.close()

    return np.transpose(np.array(X_signals), (1, 2, 0))


def load_y(y_path):
    file = open(y_path, 'r')
    y_ = np.array([elem for elem in [row.replace('  ', ' ').strip().split(' ') for row in file]], dtype=np.int32)
    file.close()
    return y_ - 1


class Config(object):
    def __init__(self, X_train, X_test):
        self.train_count = len(X_train)  # 训练记录
        self.test_data_count = len(X_test)
        self.n_steps = len(X_train[0])  # 步长,128步

        self.learning_rate = 0.0025
        self.lambda_loss_amount = 0.0015  # 正则化惩罚粒度
        self.training_epochs = 300
        self.batch_size = 1500

        self.n_inputs = len(X_train[0][0])  # 每个step收集9个,数据收集维度
        self.n_hidden = 32  # 隐层神经元个数
        self.n_classes = 6  # 输出6个类别
        self.W = {'hidden': tf.Variable(tf.random_normal([self.n_inputs, self.n_hidden])),  # 输入到隐层
                  'output': tf.Variable(tf.random_normal([self.n_hidden, self.n_classes]))}  # 隐层到输出

        self.biases = {'hidden': tf.Variable(tf.random_normal([self.n_hidden], mean=1.0)),
                       'output': tf.Variable(tf.random_normal([self.n_classes]))}


# 构造LSTM网络
def LSTM_Network(_X, config):
    # 数据转换,使其满足LSTM网络要求
    _X = tf.transpose(_X, [1, 0, 2])  # 把0 1 2调换成1 0 2,调换第一维度和第二维度
    _X = tf.reshape(_X, [-1, config.n_inputs])

    _X = tf.nn.relu(tf.matmul(_X, config.W['hidden']) + config.biases['hidden'])  # 9个神经元变为32

    _X = tf.split(_X, config.n_steps, 0)  # 把每一步放到RNN对应的位置

    # 两层LSTM堆叠在一起
    lstm_cell_1 = tf.contrib.rnn.BasicLSTMCell(config.n_hidden, forget_bias=1.0, state_is_tuple=True)
    lstm_cell_2 = tf.contrib.rnn.BasicLSTMCell(config.n_hidden, forget_bias=1.0, state_is_tuple=True)
    lstm_cells = tf.contrib.rnn.MultiRNNCell([lstm_cell_1, lstm_cell_2], state_is_tuple=True)

    outputs, states = tf.contrib.rnn.static_rnn(lstm_cells, _X, dtype=tf.float32)  # outputs:最终结果; states:中间结果
    print(np.array(outputs).shape)  # 查看outputs,128个输出结果

    lstm_last_output = outputs[-1]  # 取最终结果

    return tf.matmul(lstm_last_output, config.W['output']) + config.biases['output']  # 分类


def one_hot(y_):
    y_ = y_.reshape(len(y_))
    n_values = int(np.max(y_)) + 1
    return np.eye(n_values)[np.array(y_, dtype=np.int32)]


if __name__ == '__main__':

    # 指定九种不同输入信号,即9个文件的文件名前缀
    INPUT_SIGNAL_TYPES = [
        'body_acc_x_',
        'body_acc_y_',
        'body_acc_z_',
        'body_gyro_x_',
        'body_gyro_y_',
        'body_gyro_z_',
        'total_acc_x_',
        'total_acc_y_',
        'total_acc_z_'
    ]

    # 六种行为标签,行走 站立 躺下 坐下 上楼 下楼
    LABELS = [
        'WALKING',
        'WALKING_UPSTAIRS',
        'WALKING_DOWNSTAIRS',
        'SITTING',
        'STANDING',
        'LAYING'
    ]

    # 指定数据路径
    DATA_PATH = 'data/'
    DATASET_PATH = DATA_PATH + 'UCI HAR Dataset/'
    print('\n' + 'Dataset is now located at:' + DATASET_PATH)
    TRAIN = 'train/'
    TEST = 'test/'

    X_train_signals_paths = [
        DATASET_PATH + TRAIN + 'Inertial Signals/' + signal + 'train.txt' for signal in INPUT_SIGNAL_TYPES
    ]
    X_test_signals_paths = [DATASET_PATH + TEST + 'Inertial Signals/' + signal + 'test.txt' for signal in
                            INPUT_SIGNAL_TYPES]
    X_train = load_X(X_train_signals_paths)
    X_test = load_X(X_test_signals_paths)
    print('X_train:', X_train.shape)  # 7352条数据,每个数据128窗口序列,每个序列记录9个不同指标
    print('X_test:', X_test.shape)
    y_train_path = DATASET_PATH + TRAIN + 'y_train.txt'
    y_test_path = DATASET_PATH + TEST + 'y_test.txt'
    y_train = one_hot(load_y(y_train_path))
    y_test = one_hot(load_y(y_test_path))
    print('y_train:', y_train.shape)  # 7352条数据,6个类别
    print('y_test:', y_test.shape)

    config = Config(X_train, X_test)
    print("Some useful info to get an insight on dataset's shape and normalisation:")
    print("features shape, labels shape, each features mean, each features standard deviation")
    print(X_test.shape, y_test.shape,
          np.mean(X_test), np.std(X_test))
    print('the dataset is therefore properly normalised, as expected.')

    X = tf.placeholder(tf.float32, [None, config.n_steps, config.n_inputs])
    Y = tf.placeholder(tf.float32, [None, config.n_classes])

    pred_Y = LSTM_Network(X, config)  # 最终预测结果

    # l2正则惩罚,tf.trainable_variables()(仅可以查看可训练的变量)
    l2 = config.lambda_loss_amount * \
         sum(tf.nn.l2_loss(tf_var) for tf_var in tf.trainable_variables())

    # 损失值
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=pred_Y)) + l2
    optimizer = tf.train.AdamOptimizer(learning_rate=config.learning_rate).minimize(cost)

    correct_pred = tf.equal(tf.argmax(pred_Y, 1), tf.argmax(Y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_pred, dtype=tf.float32))

    # tf.InteractiveSession():可以先构建一个session然后再定义操作(operation)
    # tf.Session():需要在会话构建之前定义好全部的操作(operation)然后再构建会话
    # tf.ConfigProto():获取到 operations 和 Tensor 被指派到哪个设备(几号CPU或几号GPU)上运行
    # log_device_placement=False:不会在终端打印出各项操作是在哪个设备上运行
    sess = tf.InteractiveSession(config=tf.ConfigProto(log_device_placement=False))
    init = tf.global_variables_initializer()
    sess.run(init)

    best_accuracy = 0.0

    for i in range(config.training_epochs):
        # zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表
        for start, end in zip(range(0, config.train_count, config.batch_size),
                              range(config.batch_size, config.train_count + 1, config.batch_size)):
            sess.run(optimizer, feed_dict={X: X_train[start:end],
                                           Y: y_train[start:end]})

        # 也可对迭代过程进行可视化展示
        pred_out, accuracy_out, loss_out = sess.run([pred_Y, accuracy, cost], feed_dict={X: X_test, Y: y_test})
        print('traing iter: {},'.format(i) + 'test accuracy: {},'.format(accuracy_out) + 'loss:{}'.format(loss_out))
        best_accuracy = max(best_accuracy, accuracy_out)

        print('')
        print('final test accuracy: {}'.format(accuracy_out))
        print("best epoch's test accuracy: {}".format(best_accuracy))
        print('')

运行结果:

Dataset is now located at:data/UCI HAR Dataset/
X_train: (7352, 128, 9)
X_test: (2947, 128, 9)
y_train: (7352, 6)
y_test: (2947, 6)
Some useful info to get an insight on dataset's shape and normalisation:
features shape, labels shape, each features mean, each features standard deviation
(2947, 128, 9) (2947, 6) 0.09913992 0.39567086
the dataset is therefore properly normalised, as expected.
WARNING:tensorflow:From D:/WorkSpace/ai/csdn/lab-lstm-activity-recognition/lstm.py:58: BasicLSTMCell.__init__ (from tensorflow.python.ops.rnn_cell_impl) is deprecated and will be removed in a future version.
Instructions for updating:
This class is deprecated, please use tf.nn.rnn_cell.LSTMCell, which supports all the feature this cell currently has. Please replace the existing code with tf.nn.rnn_cell.LSTMCell(name='basic_lstm_cell').
(128,)
WARNING:tensorflow:From D:/WorkSpace/ai/csdn/lab-lstm-activity-recognition/lstm.py:141: softmax_cross_entropy_with_logits (from tensorflow.python.ops.nn_ops) is deprecated and will be removed in a future version.
Instructions for updating:

Future major versions of TensorFlow will allow gradients to flow
into the labels input on backprop by default.

See `tf.nn.softmax_cross_entropy_with_logits_v2`.

2019-12-16 19:45:10.908801: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
traing iter: 0,test accuracy: 0.4801492989063263,loss:1.9456521272659302

final test accuracy: 0.4801492989063263
best epoch's test accuracy: 0.4801492989063263

traing iter: 1,test accuracy: 0.5334238409996033,loss:1.6313532590866089

final test accuracy: 0.5334238409996033
best epoch's test accuracy: 0.5334238409996033

traing iter: 2,test accuracy: 0.6128265857696533,loss:1.4844205379486084

final test accuracy: 0.6128265857696533
best epoch's test accuracy: 0.6128265857696533

无题感悟

明天对于我们是未知的,明天会来什么我们也不知道,我们只能做好今天、珍惜当下。

身体是革命的本钱,没有好身体什么都是零,祝福我们、我们在乎的人、爱我们的人都健康。

愿,明天更好!共勉!2019.12.16 19:50 于国通四楼

  • 6
    点赞
  • 95
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
要基于 TensorFlow 实现 LSTM,需要使用 TensorFlow 的 RNN 模块。以下是一个简单的 Java 代码片段,演示如何使用 TensorFlowLSTMCell 类构建 LSTM 模型: ``` import org.tensorflow.*; import org.tensorflow.data.*; import org.tensorflow.framework.optimizers.*; import org.tensorflow.op.*; import org.tensorflow.types.*; int inputSize = 10; int numUnits = 32; int batchSize = 16; int sequenceLength = 20; // 创建 LSTM 单元 LSTMCell lstmCell = LSTMCell.create(numUnits); // 创建输入占位符 Placeholder<Float> inputs = Placeholder.create(Shape.of(batchSize, sequenceLength, inputSize), DataType.FLOAT); // 初始化 LSTM 状态 Tensor<Float> zeroState = lstmCell.zeroState(batchSize, DataType.FLOAT); StateTuple<Float, Float> state = StateTuple.create(zeroState, zeroState); // 遍历序列并运行 LSTM for (int i = 0; i < sequenceLength; i++) { // 提取当前时间步的输入 Operand<Float> inputStep = tf.slice(inputs, tf.constant(new int[]{0, i, 0}), tf.constant(new int[]{batchSize, 1, inputSize})); // 运行 LSTM 单元 LSTMCell.LSTMCellOutput output = lstmCell.apply(inputStep, state); // 更新状态 state = output.state(); } // 提取最终的 LSTM 状态 Operand<Float> finalState = state.c(); // 创建会话并运行图 try (Session session = new Session()) { // ... } ``` 这只是 LSTM 的一个简单实现,实际应用中需要根据具体需求进行修改和优化。同时,需要注意 TensorFlow 的版本和依赖库的兼容性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值