查看: 6863|回复: 3

[原创] i.MX RT1060利用机器学习识别异常检测

[复制链接]

该用户从未签到

715

主题

6374

帖子

0

超级版主

Rank: 8Rank: 8

积分
25213
最后登录
2025-8-18
发表于 2020-11-5 15:06:19 | 显示全部楼层 |阅读模式
概述
异常检测是用于识别异常行为(与大多数数据点明显不同的数据点)。异常行为通常与某类问题,故障或异常事件(财务欺诈,传感器故障,运行状况问题,垃圾邮件检测)强相关。
在本文中将展示如何使用神经网络搜索处于固定位置的传感器中的异常移动。当然,这种方法可以应用于更复杂的问题,例如检测看不见的跌倒,机器声音异常,异常波动,或制造系统错误。在传感器数据中搜索异常行为是一种无监督学习的一类问题,面对的是无标注的数据,从中学习到数据的分布P(X)的算法。各种经典和深度机器学习算法都可以用于此问题。单类支持向量机(OC-SVM)和高斯混合模型(GMM)是常见的机器学习算法,已成功应用于异常检测问题。但是,它们在复杂的多维数据上的性能欠佳。
深度学习方法非常适合用于识别数据异常,尤其在较复杂和嘈杂的数据上显示出比SVM等常见机器学习技术更好的性能,其中自动编码器在检测异常中应用广泛。 自动编码器是学习预测其输入的前馈神经网络。 输入被简化为核心特征(编码),然后重新创建(解码),而实际输入与预测输出之间的误差称为重构误差。 自动编码器预测异常数据时会得到高于阈值的重构误差,以此来识别异常行为。
训练数据准备硬件平台:MIMXRT1060 EVKFRDM-STBC-AGM01 (如图1所示)
WeChat Image_20201027153941.jpg

Fig 1

软件工程:tensorflow_lite_adt (来自SDK_2.8.0_EVK-MIMXRT1060)
Note: 经测试,tensorflow_lite_adt 工程有bug,需要用以下代码替换原工程中的BOARD_InitPins(void)函数
  1. void BOARD_InitPins(void) {
  2.   CLOCK_EnableClock(kCLOCK_Iomuxc);           /* iomuxc clock (iomuxc_clk_enable): 0x03u */

  3.   IOMUXC_SetPinMux(
  4.       IOMUXC_GPIO_AD_B0_12_LPUART1_TX,        /* GPIO_AD_B0_12 is configured as LPUART1_TX */
  5.       0U);                                    /* Software Input On Field: Input Path is determined by functionality */
  6.   IOMUXC_SetPinMux(
  7.       IOMUXC_GPIO_AD_B0_13_LPUART1_RX,        /* GPIO_AD_B0_13 is configured as LPUART1_RX */
  8.       0U);                                    /* Software Input On Field: Input Path is determined by functionality */
  9.   IOMUXC_SetPinConfig(
  10.       IOMUXC_GPIO_AD_B0_12_LPUART1_TX,        /* GPIO_AD_B0_12 PAD functional properties : */
  11.       0x10B0u);                               /* Slew Rate Field: Slow Slew Rate
  12.                                                  Drive Strength Field: R0/6
  13.                                                  Speed Field: medium(100MHz)
  14.                                                  Open Drain Enable Field: Open Drain Disabled
  15.                                                  Pull / Keep Enable Field: Pull/Keeper Enabled
  16.                                                  Pull / Keep Select Field: Keeper
  17.                                                  Pull Up / Down Config. Field: 100K Ohm Pull Down
  18.                                                  Hyst. Enable Field: Hysteresis Disabled */
  19.   IOMUXC_SetPinConfig(
  20.       IOMUXC_GPIO_AD_B0_13_LPUART1_RX,        /* GPIO_AD_B0_13 PAD functional properties : */
  21.       0x10B0u);                               /* Slew Rate Field: Slow Slew Rate
  22.                                                  Drive Strength Field: R0/6
  23.                                                  Speed Field: medium(100MHz)
  24.                                                  Open Drain Enable Field: Open Drain Disabled
  25.                                                  Pull / Keep Enable Field: Pull/Keeper Enabled
  26.                                                  Pull / Keep Select Field: Keeper
  27.                                                  Pull Up / Down Config. Field: 100K Ohm Pull Down
  28.                                                  Hyst. Enable Field: Hysteresis Disabled */

  29.   /* GPIO_RST pin configuration. */
  30.   IOMUXC_SetPinMux(
  31.       IOMUXC_GPIO_AD_B1_05_GPIO1_IO21,        /* GPIO_AD_B0_09 is configured as GPIO1_IO09 */
  32.       0U);
  33.   IOMUXC_SetPinConfig(
  34.       IOMUXC_GPIO_AD_B1_05_GPIO1_IO21,        /* GPIO_AD_B0_11 PAD functional properties : */
  35.       0x10B0u);

  36.   IOMUXC_SetPinMux(
  37.       IOMUXC_GPIO_AD_B0_09_GPIO1_IO09,        /* GPIO_AD_B0_09 is configured as GPIO1_IO09 */
  38.       0U);
  39.   IOMUXC_SetPinConfig(
  40.       IOMUXC_GPIO_AD_B0_09_GPIO1_IO09,        /* GPIO_AD_B0_09 PAD functional properties : */
  41.       0xB0A9u);                               /* Slew Rate Field: Slow Slew Rate
  42.                                                  Drive Strength Field: R0/6
  43.                                                  Speed Field: medium(100MHz)
  44.                                                  Open Drain Enable Field: Open Drain Disabled
  45.                                                  Pull / Keep Enable Field: Pull/Keeper Enabled
  46.                                                  Pull / Keep Select Field: Keeper
  47.                                                  Pull Up / Down Config. Field: 100K Ohm Pull Down
  48.                                                  Hyst. Enable Field: Hysteresis Disabled */

  49.   IOMUXC_SetPinMux(
  50.       IOMUXC_GPIO_AD_B0_10_GPIO1_IO10,        /* GPIO_AD_B0_10 is configured as GPIO1_IO10 */
  51.       0U);
  52.   IOMUXC_SetPinConfig(
  53.       IOMUXC_GPIO_AD_B0_10_GPIO1_IO10,        /* GPIO_AD_B0_10 PAD functional properties : */
  54.       0xB0A9u);                               /* Slew Rate Field: Fast Slew Rate
  55.                                                  Drive Strength Field: R0/5
  56.                                                  Speed Field: medium(100MHz)
  57.                                                  Open Drain Enable Field: Open Drain Disabled
  58.                                                  Pull / Keep Enable Field: Pull/Keeper Enabled
  59.                                                  Pull / Keep Select Field: Pull
  60.                                                  Pull Up / Down Config. Field: 100K Ohm Pull Up
  61.                                                  Hyst. Enable Field: Hysteresis Disabled */

  62.   IOMUXC_SetPinMux(
  63.       IOMUXC_GPIO_AD_B0_11_GPIO1_IO11,        /* GPIO_AD_B0_11 is configured as GPIO1_IO11 */
  64.       0U);
  65.   IOMUXC_SetPinConfig(
  66.       IOMUXC_GPIO_AD_B0_11_GPIO1_IO11,        /* GPIO_AD_B0_11 PAD functional properties : */
  67.       0x10B0u);                               /* Slew Rate Field: Slow Slew Rate
  68.                                                  Drive Strength Field: R0/6
  69.                                                  Speed Field: medium(100MHz)
  70.                                                  Open Drain Enable Field: Open Drain Disabled
  71.                                                  Pull / Keep Enable Field: Pull/Keeper Enabled
  72.                                                  Pull / Keep Select Field: Keeper
  73.                                                  Pull Up / Down Config. Field: 100K Ohm Pull Down
  74.                                                  Hyst. Enable Field: Hysteresis Disabled */

  75.   IOMUXC_SetPinMux(
  76.       IOMUXC_GPIO_SD_B0_01_GPIO3_IO13,        /* GPIO_SD_B0_01 is configured as GPIO3_IO13 */
  77.       0U);

  78. }
复制代码
FRDM-STBC-AGM01 里有陀螺仪(FXAS21002),加速度器和磁感器(FXOS8700CQ)传感器芯片,而我们需要利用它们获得3轴加速度计和陀螺仪读数,并将连续多次的读取值经预处理后,展平为2D向量(如图2所示)输入到模型中,在本应用中,将连续5组的3轴加速度计和陀螺仪读数的差值展平为[1,30]的向量作为神经网路的输入。
7748584-27b4564b12410cee.png
Fig 2
打开tensorflow_lite_adt 工程,在adt.cpp文件中,修改宏定义DATA_COLLECT如下,随后烧录工程代码并运行,打开串口终端即能接收3轴加速度计和陀螺仪的读数,还有修改用宏定义SAMPLE_NUM可以用来决定要收集的传感器读数的个数,本次实验我们选择默认值:1000。
#define DATA_COLLECT true //false

数据预处理
原始数据通常在被送到模型之前要进行预处理(如数据过滤,数据统计或进行傅立叶变换等)。为了确保模型检测异常移动性能不受传感器具体位置的干扰(如加速度计受重力影响),保存好串口终端接收到的SAMPLE_NUM组3轴加速度计和陀螺仪的读数后,计算两个连续读数之间的差,并将加速度传感器数据除以10以保持和陀螺仪数据在同一数量级上,具体代码如下:
  1. ## Preprocess data
  2. def preprocess_data(data):
  3.     #data = (FLAGS.scale_range/3*(data - data.mean())/data.std()).clip(-1,1)
  4.     data = data.diff()[5:]
  5.     data[['ax','ay','az']] /= 10
  6.     #data = (data + 1)/2
  7.     return data


  8. chanels = ['wx', 'wy', 'wz', 'ax', 'ay', 'az']
  9. patch_size = 5

  10. # load input data
  11. data = pd.read_csv('new_input_data.txt', delimiter = ',', dtype = np.int, header=None,names=chanels)
  12. data = preprocess_data(data)

  13. # prepare patches   
  14. samples_nb = int(np.floor(data.shape[0] / float(patch_size))) * patch_size
  15. patch = np.reshape(data[chanels][:samples_nb].values, (-1,len(chanels)*patch_size))

  16. # split into train and test set
  17. train_set, test_set = train_test_split(patch, test_size=0.1, random_state=42)
  18. # split into train and valiation set
  19. train_set, valiation_set = train_test_split(train_set, test_size=0.2, random_state=42)

  20. x_train, x_validate, x_test = train_set.astype(np.float32), valiation_set.astype(np.float32), test_set.astype(np.float32)
  21. }
复制代码
模型创建
使用tensorflow 创建自动编码器模型,模型由Encoder 网络(编码器)和Decoder 网络(解码器)两部分组成,且都由全连接层网络搭建,其中Encoder 网络(编码器)有两层全连接层网络,而Decoder 网络(解码器)则有三层,当然,小伙伴可以在小编的代码基础上自定义层数,神经网络节点数,激活函数,优化器等,模型创建代码如下:
  1. # create autoencoder model
  2. lr = 1e-3  
  3. encoding_dim = 30

  4. tf.keras.backend.clear_session()

  5. class Autoencoder(keras.Model):

  6.     def __init__(self):
  7.         super(Autoencoder, self).__init__()

  8.         # Encoders
  9.         self.encoder = Sequential([
  10.             layers.Dense(15, activation=tf.nn.relu),
  11.             layers.Dense(4, activation=tf.nn.relu),
  12.         ])

  13.         # Decoders
  14.         self.decoder = Sequential([
  15.             layers.Dense(4, activation=tf.nn.relu),
  16.             layers.Dense(16, activation=tf.nn.relu),
  17.             layers.Dense(encoding_dim, activation=tf.nn.relu),
  18.         ])


  19.     def call(self, inputs, training=None):
  20.         # [b, 30] => [b, 4]
  21.         h = self.encoder(inputs)
  22.         # [b, 4] => [b, 30]
  23.         x_hat = self.decoder(h)
  24.         return x_hat

  25. model = Autoencoder()
  26. model.build(input_shape=(None, encoding_dim))

  27. optimizer = tf.optimizers.Adam(lr=lr)

  28. model.compile(optimizer=optimizer,
  29.               loss='mean_squared_error',
  30.               metrics=['accuracy'])

  31. model.summary()
复制代码
模型训练
数据和模型都准备完毕后,就可以训练了,小伙伴也可以自定义nb_epoch,batch_num值来设置训练过程。
模型训练代码如下:
  1. # set training parameters
  2. nb_epoch = 1000
  3. batch_num = 20

  4. history = model.fit(x_train,x_train,
  5.                     epochs=nb_epoch,
  6.                     batch_size=batch_num,
  7.                     shuffle=True,
  8.                     validation_data=(x_validate,x_validate),
  9.                     verbose=1)
复制代码
模型评估
模型训练完成,我们需要验证其在test数据集的性能表现来依此评估重构误差的范围,并绘出线型图来直观的展示重构误差。
  1. import matplotlib.pyplot as plt

  2. # evaluate
  3. predictions = model.predict(x_test)

  4. error = np.mean(np.square(predictions - x_test), 1)
  5. # Threshold
  6. threshold = 3 * np.mean(error)

  7.             
  8. x = np.arange(predictions.shape[0])
  9. x_dense = np.arange(0,predictions.shape[0],0.02)
  10. y = np.interp(x_dense, x, error)
  11. y_a = np.ma.masked_less(y, threshold)


  12. fig, ax = plt.subplots(figsize=(10,10))
  13. ax.plot(x_dense, y, linestyle='-',color='g')
  14. ax.plot(x_dense, y_a, linestyle='--',color='r')
  15. ax.set_xticks(np.arange(0,100,10))
  16. ax.grid(which='major', axis='x', linestyle='--')
  17. ax.set_title('Vizualize the Vibration amplitude ',fontsize=18)
复制代码
7748584-74aab22e8cd906d0.png
Fig 3
从图中可以看出,重构误差最大值处在在3.0附近上下,所以我们设置的重构误差阈值threshold :4.7008是可行的。
模型部署
在模型训练完成后,将模型保存为tflite文件,接着用xxd命令将tflite文件转化为C文件(指令如下),最后打开C文件,用其内容替换原先tensorflow_lite_adt工程中的adt_model.h内容即可。
  1. # Save the file as a C source file
  2. 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
进行测试,可以看到在板子在移动时,会导致重构误差暴增而超过阈值,而在板子重新停止移动后,重构误差很快会重新降到阈值之下。
7748584-8565d09e588c2d92.png
Fig 4
参考 :Anomaly Detection i.MX RT application using TensorFlow Lite

回复

使用道具 举报

  • TA的每日心情
    开心
    2022-5-25 16:03
  • 签到天数: 11 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    8

    主题

    720

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    3419
    最后登录
    2025-8-8
    发表于 2020-11-5 18:36:53 | 显示全部楼层
    这个用的是什么语言开发?
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 12:32
  • 签到天数: 1720 天

    连续签到: 13 天

    [LV.Master]伴坛终老

    23

    主题

    1万

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    15916
    最后登录
    2025-8-19
    发表于 2020-12-31 22:41:15 | 显示全部楼层
    乐天乐 发表于 2020-11-5 18:36
    这个用的是什么语言开发?

    python语言
    跟着日天混,三天饱九顿!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2023-8-29 13:54
  • 签到天数: 4 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    0

    主题

    5

    帖子

    0

    新手上路

    Rank: 1

    积分
    41
    最后登录
    2023-8-29
    发表于 2023-8-28 10:27:41 | 显示全部楼层
    您好,最后的参考链接失效了,请问有新的链接么
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-8-20 03:48 , Processed in 0.098518 second(s), 23 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表