概述 异常检测是用于识别异常行为(与大多数数据点明显不同的数据点)。异常行为通常与某类问题,故障或异常事件(财务欺诈,传感器故障,运行状况问题,垃圾邮件检测)强相关。
在本文中将展示如何使用神经网络搜索处于固定位置的传感器中的异常移动。当然,这种方法可以应用于更复杂的问题,例如检测看不见的跌倒,机器声音异常,异常波动,或制造系统错误。在传感器数据中搜索异常行为是一种无监督学习的一类问题,面对的是无标注的数据,从中学习到数据的分布P(X)的算法。各种经典和深度机器学习算法都可以用于此问题。单类支持向量机(OC-SVM)和高斯混合模型(GMM)是常见的机器学习算法,已成功应用于异常检测问题。但是,它们在复杂的多维数据上的性能欠佳。
深度学习方法非常适合用于识别数据异常,尤其在较复杂和嘈杂的数据上显示出比SVM等常见机器学习技术更好的性能,其中自动编码器在检测异常中应用广泛。 自动编码器是学习预测其输入的前馈神经网络。 输入被简化为核心特征(编码),然后重新创建(解码),而实际输入与预测输出之间的误差称为重构误差。 自动编码器预测异常数据时会得到高于阈值的重构误差,以此来识别异常行为。 训练数据准备硬件平台:MIMXRT1060 EVK 和 FRDM-STBC-AGM01 (如图1所示)
Fig 1
软件工程:tensorflow_lite_adt (来自SDK_2.8.0_EVK-MIMXRT1060)Note: 经测试,tensorflow_lite_adt 工程有bug,需要用以下代码替换原工程中的BOARD_InitPins(void)函数 - void BOARD_InitPins(void) {
- CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 is configured as LPUART1_TX */
- 0U); /* Software Input On Field: Input Path is determined by functionality */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 is configured as LPUART1_RX */
- 0U); /* Software Input On Field: Input Path is determined by functionality */
- IOMUXC_SetPinConfig(
- IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 PAD functional properties : */
- 0x10B0u); /* Slew Rate Field: Slow Slew Rate
- Drive Strength Field: R0/6
- Speed Field: medium(100MHz)
- Open Drain Enable Field: Open Drain Disabled
- Pull / Keep Enable Field: Pull/Keeper Enabled
- Pull / Keep Select Field: Keeper
- Pull Up / Down Config. Field: 100K Ohm Pull Down
- Hyst. Enable Field: Hysteresis Disabled */
- IOMUXC_SetPinConfig(
- IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 PAD functional properties : */
- 0x10B0u); /* Slew Rate Field: Slow Slew Rate
- Drive Strength Field: R0/6
- Speed Field: medium(100MHz)
- Open Drain Enable Field: Open Drain Disabled
- Pull / Keep Enable Field: Pull/Keeper Enabled
- Pull / Keep Select Field: Keeper
- Pull Up / Down Config. Field: 100K Ohm Pull Down
- Hyst. Enable Field: Hysteresis Disabled */
- /* GPIO_RST pin configuration. */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_AD_B1_05_GPIO1_IO21, /* GPIO_AD_B0_09 is configured as GPIO1_IO09 */
- 0U);
- IOMUXC_SetPinConfig(
- IOMUXC_GPIO_AD_B1_05_GPIO1_IO21, /* GPIO_AD_B0_11 PAD functional properties : */
- 0x10B0u);
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 is configured as GPIO1_IO09 */
- 0U);
- IOMUXC_SetPinConfig(
- IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 PAD functional properties : */
- 0xB0A9u); /* Slew Rate Field: Slow Slew Rate
- Drive Strength Field: R0/6
- Speed Field: medium(100MHz)
- Open Drain Enable Field: Open Drain Disabled
- Pull / Keep Enable Field: Pull/Keeper Enabled
- Pull / Keep Select Field: Keeper
- Pull Up / Down Config. Field: 100K Ohm Pull Down
- Hyst. Enable Field: Hysteresis Disabled */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_AD_B0_10_GPIO1_IO10, /* GPIO_AD_B0_10 is configured as GPIO1_IO10 */
- 0U);
- IOMUXC_SetPinConfig(
- IOMUXC_GPIO_AD_B0_10_GPIO1_IO10, /* GPIO_AD_B0_10 PAD functional properties : */
- 0xB0A9u); /* Slew Rate Field: Fast Slew Rate
- Drive Strength Field: R0/5
- Speed Field: medium(100MHz)
- Open Drain Enable Field: Open Drain Disabled
- Pull / Keep Enable Field: Pull/Keeper Enabled
- Pull / Keep Select Field: Pull
- Pull Up / Down Config. Field: 100K Ohm Pull Up
- Hyst. Enable Field: Hysteresis Disabled */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_AD_B0_11_GPIO1_IO11, /* GPIO_AD_B0_11 is configured as GPIO1_IO11 */
- 0U);
- IOMUXC_SetPinConfig(
- IOMUXC_GPIO_AD_B0_11_GPIO1_IO11, /* GPIO_AD_B0_11 PAD functional properties : */
- 0x10B0u); /* Slew Rate Field: Slow Slew Rate
- Drive Strength Field: R0/6
- Speed Field: medium(100MHz)
- Open Drain Enable Field: Open Drain Disabled
- Pull / Keep Enable Field: Pull/Keeper Enabled
- Pull / Keep Select Field: Keeper
- Pull Up / Down Config. Field: 100K Ohm Pull Down
- Hyst. Enable Field: Hysteresis Disabled */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_SD_B0_01_GPIO3_IO13, /* GPIO_SD_B0_01 is configured as GPIO3_IO13 */
- 0U);
- }
复制代码在 FRDM-STBC-AGM01 里有陀螺仪(FXAS21002),加速度器和磁感器(FXOS8700CQ)传感器芯片,而我们需要利用它们获得3轴加速度计和陀螺仪读数,并将连续多次的读取值经预处理后,展平为2D向量(如图2所示)输入到模型中,在本应用中,将连续5组的3轴加速度计和陀螺仪读数的差值展平为[1,30]的向量作为神经网路的输入。
Fig 2 打开tensorflow_lite_adt 工程,在adt.cpp文件中,修改宏定义DATA_COLLECT如下,随后烧录工程代码并运行,打开串口终端即能接收3轴加速度计和陀螺仪的读数,还有修改用宏定义SAMPLE_NUM可以用来决定要收集的传感器读数的个数,本次实验我们选择默认值:1000。
#define DATA_COLLECT true //false
数据预处理原始数据通常在被送到模型之前要进行预处理(如数据过滤,数据统计或进行傅立叶变换等)。为了确保模型检测异常移动性能不受传感器具体位置的干扰(如加速度计受重力影响),保存好串口终端接收到的SAMPLE_NUM组3轴加速度计和陀螺仪的读数后,计算两个连续读数之间的差,并将加速度传感器数据除以10以保持和陀螺仪数据在同一数量级上,具体代码如下: - ## Preprocess data
- def preprocess_data(data):
- #data = (FLAGS.scale_range/3*(data - data.mean())/data.std()).clip(-1,1)
- data = data.diff()[5:]
- data[['ax','ay','az']] /= 10
- #data = (data + 1)/2
- return data
- chanels = ['wx', 'wy', 'wz', 'ax', 'ay', 'az']
- patch_size = 5
- # load input data
- data = pd.read_csv('new_input_data.txt', delimiter = ',', dtype = np.int, header=None,names=chanels)
- data = preprocess_data(data)
- # prepare patches
- samples_nb = int(np.floor(data.shape[0] / float(patch_size))) * patch_size
- patch = np.reshape(data[chanels][:samples_nb].values, (-1,len(chanels)*patch_size))
- # split into train and test set
- train_set, test_set = train_test_split(patch, test_size=0.1, random_state=42)
- # split into train and valiation set
- train_set, valiation_set = train_test_split(train_set, test_size=0.2, random_state=42)
- x_train, x_validate, x_test = train_set.astype(np.float32), valiation_set.astype(np.float32), test_set.astype(np.float32)
- }
复制代码 模型创建使用tensorflow 创建自动编码器模型,模型由Encoder 网络(编码器)和Decoder 网络(解码器)两部分组成,且都由全连接层网络搭建,其中Encoder 网络(编码器)有两层全连接层网络,而Decoder 网络(解码器)则有三层,当然,小伙伴可以在小编的代码基础上自定义层数,神经网络节点数,激活函数,优化器等,模型创建代码如下: - # create autoencoder model
- lr = 1e-3
- encoding_dim = 30
- tf.keras.backend.clear_session()
- class Autoencoder(keras.Model):
- def __init__(self):
- super(Autoencoder, self).__init__()
- # Encoders
- self.encoder = Sequential([
- layers.Dense(15, activation=tf.nn.relu),
- layers.Dense(4, activation=tf.nn.relu),
- ])
- # Decoders
- self.decoder = Sequential([
- layers.Dense(4, activation=tf.nn.relu),
- layers.Dense(16, activation=tf.nn.relu),
- layers.Dense(encoding_dim, activation=tf.nn.relu),
- ])
- def call(self, inputs, training=None):
- # [b, 30] => [b, 4]
- h = self.encoder(inputs)
- # [b, 4] => [b, 30]
- x_hat = self.decoder(h)
- return x_hat
- model = Autoencoder()
- model.build(input_shape=(None, encoding_dim))
- optimizer = tf.optimizers.Adam(lr=lr)
- model.compile(optimizer=optimizer,
- loss='mean_squared_error',
- metrics=['accuracy'])
- model.summary()
复制代码 模型训练数据和模型都准备完毕后,就可以训练了,小伙伴也可以自定义nb_epoch,batch_num值来设置训练过程。
模型训练代码如下: - # set training parameters
- nb_epoch = 1000
- batch_num = 20
- history = model.fit(x_train,x_train,
- epochs=nb_epoch,
- batch_size=batch_num,
- shuffle=True,
- validation_data=(x_validate,x_validate),
- verbose=1)
复制代码 模型评估模型训练完成,我们需要验证其在test数据集的性能表现来依此评估重构误差的范围,并绘出线型图来直观的展示重构误差。 - import matplotlib.pyplot as plt
- # evaluate
- predictions = model.predict(x_test)
- error = np.mean(np.square(predictions - x_test), 1)
- # Threshold
- threshold = 3 * np.mean(error)
-
- x = np.arange(predictions.shape[0])
- x_dense = np.arange(0,predictions.shape[0],0.02)
- y = np.interp(x_dense, x, error)
- y_a = np.ma.masked_less(y, threshold)
- fig, ax = plt.subplots(figsize=(10,10))
- ax.plot(x_dense, y, linestyle='-',color='g')
- ax.plot(x_dense, y_a, linestyle='--',color='r')
- ax.set_xticks(np.arange(0,100,10))
- ax.grid(which='major', axis='x', linestyle='--')
- ax.set_title('Vizualize the Vibration amplitude ',fontsize=18)
复制代码Fig 3 从图中可以看出,重构误差最大值处在在3.0附近上下,所以我们设置的重构误差阈值threshold :4.7008是可行的。 模型部署在模型训练完成后,将模型保存为tflite文件,接着用xxd命令将tflite文件转化为C文件(指令如下),最后打开C文件,用其内容替换原先tensorflow_lite_adt工程中的adt_model.h内容即可。 - # Save the file as a C source file
- xxd -i model_integer_only_quantization.tflite > model_quantized.cc
复制代码Note: 上述的数据预处理,模型创建和评估代码参考位于~\SDK_2.8.0_EVK-MIMXRT1060\middleware\eiq\tensorflow-lite\examples\adt\adt_train\adt_train.py文件 测试模型部署完成后,修改宏定义DATA_COLLEC
#define DATA_COLLECT false
进行测试,可以看到在板子在移动时,会导致重构误差暴增而超过阈值,而在板子重新停止移动后,重构误差很快会重新降到阈值之下。 Fig 4 参考 :Anomaly Detection i.MX RT application using TensorFlow Lite
|