How to process sensor data

对sensor数据的预处理

import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
from scipy import stats
from sklearn import metrics

import tensorflow as tf
from tensorflow.keras import models
from tensorflow.keras import layers

1. 读取csv文件得到dataFrame

如果没有head需要加上列的名字

columns = ['user','activity','timestamp', 'x-axis', 'y-axis', 'z-axis']
def read_data(file_patch):
  train = pd.read_csv(file_patch, header = None, names = columns)
  train = train.dropna()
  return train

2. 对数据进行归一化处理

# mean and std
def feature_normalize(feature):
  mu = np.mean(feature, axis=0)
  sigma = np.std(feature, axis=0)
  return (feature - mu) / sigma

3. 形成训练测试数据集

# x1,y1,z1, x2, y2, z2

//窗口大小time_steps; 数据是叠加的每次移动的大小step
def create_segments_for_rnn(df, step, time_steps=200):
  X_train = []
  Y_train = []
  hot_test = []
  for i in range(0, df.shape[0] - time_steps, step):

    //获得几列数据中的从第几行到第几行,得到仍是dataframe,转换为narray
    xyz_data = df[['x-axis', 'y-axis', 'z-axis']][i:i+time_steps]
    X_train.append(np.array(xyz_data))

    //给数据加标签

    label = stats.mode(df['activity'][i: i + time_steps])[0][0]
    hot_test.append(label)
  #怎样找到 one-hot和字符串的对应关系?

   get_dummies对后面的字符串列表进行one-hot编码,编码的结果之和字符串的字母顺序相关和字符串的排列顺序无关,总是按字母序排列 如:list('abcf') 还是list('fbac')得到的a的编码总是[1.0, 0, 0, 0] bcf也是这样

每次到这里,都会花费好长时间:pd.Series(list('abcf')是

one-hot 编码的数据源:会表示成dataframe的Index: 如下面的list('abcf'): ['a', 'b', 'c', 'f'] 注意不是上面的列: a/b/c/f

one-hot编码需要的几位:表示为column

 ['a', 'b', 'c', 'f'] 对应的One-hot向量是:index[0,1,2,3] 对应的向量, 如下图所示

In [69]: pd.get_dummies(pd.Series(list('abcf')), dtype=float)
Out[69]: 
     a    b    c    f
0  1.0  0.0  0.0  0.0
1  0.0  1.0  0.0  0.0
2  0.0  0.0  1.0  0.0
3  0.0  0.0  0.0  1.0

In [70]: pd.get_dummies(pd.Series(list('fbac')), dtype=float)
Out[70]: 
     a    b    c    f
0  0.0  0.0  0.0  1.0
1  0.0  1.0  0.0  0.0
2  1.0  0.0  0.0  0.0
3  0.0  0.0  1.0  0.0

所以找到字符串和one-hot对应关系的方法也很简单:

得到所有的字符串列表,df['activity'].df['activity'].value_counts(),然后pd.get_dummies(hot_test)就能找到对应的关系

  Y_train = np.asarray(pd.get_dummies(hot_test), dtype = np.float32)
  return np.array(X_train), Y_train

3.1 scipy.stats.mode函数,寻找出现次数最多的成员

Python中的scipy.stats.mode函数,寻找出现次数最多的成员
from scipy.stats import mode
list = ['a', 'a', 'a', 'b', 'b', 'b', 'a']
print("# Print mode(list):", mode(list))
print("# list中最常见的成员为:{},出现了{}次。".format(mode(list)[0][0], mode(list)[1][0]))
 
# Print mode(list): ModeResult(mode=array(['a'], dtype='<U1'), count=array([4]))
# list中最常见的成员为:a,出现了4次。

3.2 one -hot编码

请注意one-hot的编码是行向量的的形式不是列的形式

In [77]: LABELS = ['Downstairs', 'Jogging', 'Walk', 'Sitting', 'Standing', 'Upstairs', 'Walk']

In [78]: pd.get_dummies(LABELS)
Out[78]: 
   Downstairs  Jogging  Sitting  Standing  Upstairs  Walk
0           1        0        0         0         0     0
1           0        1        0         0         0     0
2           0        0        0         0         0     1
3           0        0        1         0         0     0
4           0        0        0         1         0     0
5           0        0        0         0         1     0
6           0        0        0         0         0     1
 

shuffle data: 打乱训练数据顺序

def shuffle_data(X, Y): //索引取随机数
  np.random.seed(10)
  randomList = np.arange(X.shape[0])
  np.random.shuffle(randomList)
  return X[randomList], Y[randomList]

训练数据和验证数据分割

def split_data(X,Y,rate):
  X_train = X[int(X.shape[0]*rate):]
  Y_train = Y[int(Y.shape[0]*rate):]
  X_val = X[:int(X.shape[0]*rate)]
  Y_val = Y[:int(Y.shape[0]*rate)]
  return X_train, Y_train, X_val, Y_val

模型的构建

sensor的序列数据可以看成1通道的图像数据只是 x 不等于 y, input shape可描述为 (128, 3, 1), 这样就可以用图像处理用的Conv2D、DepthwiseConv2D,只是kernel的形状不是对称的。

有关DepthwiseConv2D和Conv2D的区别:DepthWiseConv2D是MobileNet提出的是为了减小模型的大小,但对1 channel而言两者大概是一致的。

当前的理解是Depth的depth_multiplier类似于Conv的 feature number

depthwise conv2D

model_dipth = models.Sequential()
model_dipth.add(layers.DepthwiseConv2D((4, 3), activation='relu', padding='same', depth_multiplier=8, input_shape=(128, 3, 1)))
model_dipth.add(layers.MaxPooling2D((3, 3)))
model_dipth.add(layers.Conv2D(16, (4, 1), padding='same', activation='relu'))
model_dipth.add(layers.MaxPooling2D((3, 1)))
model_dipth.add(layers.Flatten())
model_dipth.add(layers.Dense(16, activation='relu'))
model_dipth.add(layers.Dense(6, activation='softmax'))
model_dipth.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])
model_dipth.summary()

conv2D


model_dipth = models.Sequential()
model_dipth.add(layers.Conv2D(16, (4, 3), activation='relu', padding='same', input_shape=(128, 3, 1)))
model_dipth.add(layers.MaxPooling2D((3, 3)))
model_dipth.add(layers.Conv2D(32, (4, 1), padding='same', activation='relu'))
model_dipth.add(layers.MaxPooling2D((3, 1)))
model_dipth.add(layers.Flatten())
model_dipth.add(layers.Dropout(0.5))
model_dipth.add(layers.Dense(16, activation='relu'))
model_dipth.add(layers.Dense(6, activation='softmax'))

1DCNN

  model = Sequential()
  model.add(Conv1D(30, 10, activation='relu', input_shape=(shape[1], shape[2])))
  #model.add(Conv1D(30, 10, activation='relu'))
  model.add(MaxPooling1D(3))
  #model.add(Conv1D(48, 10, activation='relu'))
  model.add(Conv1D(48, 10, activation='relu'))
  #model.add(GlobalAveragePooling1D())
  model.add(Flatten())
  model.add(Dropout(0.5))
  model.add(Dense(num_classes, activation='softmax'))
  print(model.summary())

  • filters: 整数,输出空间的维度 (即卷积中滤波器的输出数量)。
  • kernel_size: 一个整数,或者单个整数表示的元组或列表, 指明 1D 卷积窗口的长度。
  • strides: 一个整数,或者单个整数表示的元组或列表, 指明卷积的步长

从实际的结果看还是1DCnn的效果最好且如果卷积后直接flatten而不进行maxpool效果是稳定的(放着手机不动推断的结果不变),其他推断的结果是来回变化的,具体原因是训练的数据集的问题还是模型的问题?后面还要仔细分析

 

损失函数的选择

categorical_crossentropy VS. sparse_categorical_crossentropy

原以为损失函数随便选个就行,看tensorflow给的一个例子是sparse_categorical_crossentropy, 也使用sparse_categorical_crossentropy,在fit时出现如下错误:

InvalidArgumentError:  Incompatible shapes: [32,6] vs. [32]
     [[node metrics_6/accuracy/Equal (defined at <ipython-input-80-987e0310275c>:1) ]] [Op:__inference_keras_scratch_graph_4523]
使用PyCharm也没debug到原因,后来想到原来没有问题的 loss function, 发现使用categorical_crossentropy没有问题

https://jovianlin.io/cat-crossentropy-vs-sparse-cat-crossentropy/

给的解释是

  • If your targets are one-hot encoded, use categorical_crossentropy.
  • But if your targets are integers, use sparse_categorical_crossentropy.
    • Examples of integer encodings (for the sake of completion):
      • 1
      • 2
      • 3

怎样保存得到训练、验证数据不是每次都生成

每次生成训练的数据时间很长,而要多次进行模型的选择和训练?把得到数据写到文件,下次直接从文件读出,大大节省了时间,有空仔细研究下Memory

from joblib import Memory
mem=Memory(".cache")
# x1,y1,z1, x2, y2, z2
@mem.cache()
def create_segments_for_rnn(df, step, time_steps=200):
  X_train = []
  Y_train = []
  hot_test = []
  for i in range(0, df.shape[0] - time_steps, step):
    xyz_data = df[['x-axis', 'y-axis', 'z-axis']][i:i+time_steps]
    X_train.append(np.array(xyz_data))

    label = stats.mode(df['activity'][i: i + time_steps])[0][0]
    hot_test.append(label)
  #怎样找到 one-hot和字符串的对应关系?
  Y_train = np.asarray(pd.get_dummies(hot_test), dtype = np.float32)
  return np.array(X_train), Y_train

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值