首先我的数据并没有做任何任何的处理,本来我是打算加一个直流滤波的,首先是效果不太好,其次是我都用上机器学习了我为什么还要自己处理数据?机器学习本事的目的就是节约我们的脑子,利用机器来提取特征,而不是我们自己去提取特征(直流偏置本身也是一种特征),就算我的信号有其他的误差,我们可以处理一下提高分辨度,但是!对于机器而言,这些本身就是他的特征,我们只需要告诉机器,哪些特征是对的,哪些特征是错的!
" [3 H2 x# _3 g1 J9 }" s7 U
% V' x, A* z2 E( m训练模型方面,我们使用MAX30102每10ms采样一次,每128次采样作为一组数据上传。4 z- }* G/ k( B( t$ G W; U2 P$ ?+ i
/ X# W) n. u8 T( ~5 Y8 O- int i = 0;; s% b- }: R8 d8 r
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)- P5 R: n2 h' Q3 J3 B
- {
% _6 i/ _/ T. j ]4 J' m& v* ` - maxim_max30102_read_fifo(&red,&ir);( ?& k& J2 U" L, }* x
- printf("%ld ",ir);
. T. P) @0 A9 v. {4 K - i++;4 A# U: R1 V) \$ a8 u2 ?& [
- if(i==128)& h7 l' t& ?9 w) ]4 I. H. ?# Y. {
- {1 r( M. T) f2 F, G. J
- i=0;
- y1 V9 G2 H( u& \ - printf("\n");2 O' }* ?9 S4 e2 Y5 \8 j' x g
- }1 w' D4 ]' ]' X, h
- }
复制代码
b% t1 w# V/ G这里我们不对数据进行任何处理,因为既然我们选择了机器学习就是为了节省我们对于数据的处理,节省对于特征的提取。
0 p5 L" T' m+ N: _0 p8 y8 v3 [
Z5 M0 _+ G5 ?+ e模型训练
' z7 I6 S: |2 y0 i2 h5 n9 T我们打开NanoEdge AI Studio,这次的项目我们选择异常检测。
! s, @. H# S0 ]1 r W
9 L/ t3 r, u9 s* Q
' a+ C9 F% s: E0 a; C" R) f3 K* \7 h+ F
+ q, @2 W* o) W5 T, e% i
) x# Y4 X) k5 c3 ~+ j传感器选择通用传感器,轴数为1,芯片型号选择自己所需要的芯片型号。! k; r7 d2 r; _' _- }, F1 ]) L3 {
1 E" l9 E5 Y3 M& x$ K& G" ~
% ?3 S3 ]$ I* B E
+ e; Y% a. _: w8 p" |
Regualr signals 常规数据
7 S& j* y Q( ~Abnormal signals 异常数据; V7 D/ Y8 Q0 X, i7 S$ w
. d# J* t/ J' l
我们通过串口(USB)分别导入正常的信号和异常的信号。
) v& `- ]' Q/ w4 d1 B/ r
0 W* i5 Z8 f3 }6 a
! H& Z m' e- Z) i, T' k; Y
7 k4 t( ?# Z+ k$ o" S! I, A
1 p# h0 ^. T# D, \4 d e0 U) {& x
3 X9 W8 y: a @: X, I数据集尽可能多且广泛并且经典。) _7 Q& ]! n/ |5 w
) C( v" T/ y1 t/ ^
5 _- g* q; ~0 J7 d. G
5 Z; V# k: Z& N7 j1 K! F% k我们总共导入了两百组信号,这些信号包含了大拇指,中指以及稍微靠前的位置和稍微靠后的位置,保证数据集的范围足够的广泛。
3 F- l+ u4 y4 E, }9 e/ C( G# x3 C0 e* t) A# I' w
5 N( k9 {' b+ f- O8 @. \' A- ~$ Y/ G8 F% {
异常信号就非常简单,我们放在那里空置信号,晃动信号这里我放在那里测了总共三百多组(打游戏打忘记了)。
7 g5 z+ i* a* c4 p! i; U5 N
$ _7 j4 C5 ?' V# B& `然后利用这两组信号进行训练。
; |3 O0 F9 M/ w6 A- M( B
8 j5 r4 ~ L' A8 b
1 s) ], C8 M! Y- u8 G% |8 C) i& V
" D8 |8 o# A# S# s$ A
我们将异常信号和正常信号全部选上,之后进行训练。; ~. S/ w) z; r) S1 I
3 X r, ~, g1 |2 z, @9 `
% Q' D7 g4 u1 @
: I% l8 ^! K+ U% ?
之后查看训练详情,等待模型训练完成。# F5 ?; X% k+ t" X0 \9 D
0 q! d' {% m2 p4 Z3 |
+ A- l5 Z& f2 z C2 O1 r) H$ T
7 Q6 T9 x% E- }! I9 |2 j3 f* U可以看到,训练完的模型无论是准确率还是RAM大小Flash大小,都相当的合适,接下来我们测试一下我们的模型。$ T: b# Q" x; ?- d+ D8 n
; o+ {# `4 p2 |: a+ \
: X" J) z, Q% R) N0 B+ O
) ]1 L% a5 ^$ y2 Q这边可以查看训练过程中的模型。
& i6 T6 M% ^2 f. k( ~7 w, N2 x
: h' A2 j( M ]" R
; v: v) U% F5 _. G
* M/ X, u% ~# x. {0 l验证我们的模型。& |* a% [5 W* w0 }
( |6 x! J# S- K+ Z& `* j2 Y
0 V- n. a0 O+ k3 @8 G+ z( w
/ {3 l1 h& |2 F1 J# z6 l/ m
这里需要注意的是,我们第一次导入数据会先进行训练,异常检测需要有一个学习环节。6 @( ]4 P. M8 c$ X0 F* F
* B1 u; d% D" v官方的手册中推荐了至少十组正常数据进行学习。! ^7 u( R' r' [/ b+ E
8 @& n F. P( f' `' L3 O5 N; r+ O5 p9 X
* \5 ^. q8 C0 {' }& Q
( A: S! p) a% F我录了21组正常数据进行学习。
4 H# Z' e K6 T. {2 c7 m
T% H% N# S9 J- s' i2 i) w然后就可以对模型进行验证。) L0 I. B' f! i3 ~1 ~
/ n7 ^1 Y4 d6 x& f3 x$ H# ]* N
! r% y" {6 y* B1 p$ X" H9 [$ S
g# X; R: v. x& O7 I) {
( ~+ b1 M8 \0 j# o/ Y部署我们的模型,其中需要他的.a文件和.h文件。
; Q8 B [- o* w0 W- G' O. N
! R* }" T' \4 k
! \* z8 c# {; x+ \) x7 G
3 q# ~! A' m$ E3 J* F, K2 a8 q0 E这里我们需要使用CubeIDE来编程。因为这里的.a文件是静态文件,静态文件使用keil编程有点麻烦,需要安装GCC编译器,STM32CubeIDE集成好了可以编译.a文件。3 c3 s& e$ I! r4 N$ i
& T8 g* ?, u( ^0 g
1 B9 D" d, a% s! t/ q: a3 v1 K$ A! `) `; j
在属性中添加静态库的路径。9 d8 ^ D7 u. V& |# G/ L
; V3 f s6 g, _9 J
+ M- g9 S: U {. z. f- a
) e) P5 i0 T2 n' {$ q8 S4 J在库中添加路径,我们的.a文件是libneai.a,这里需要省略lib和后缀.a% W$ c& q+ G4 x; h! S
! G) V( R6 |8 G9 V* G
( Z* [' F6 o r0 [4 p: x0 Z' g. {$ \' Q
导入NanoEdgeAI的库函数。
! E- E6 m( V7 N+ Y! _2 H* y+ \ l- ~. U; ~1 v; Q
. t: Z d# N/ ~0 _7 q; |
& F3 R" H+ ~! e& W: N" T. X- D可以看到这里有三个函数,初始化函数,学习函数以及预测函数。" l9 ?7 z4 w: b1 e
) D. y0 e0 j* G; R! e, {
; {% E5 z9 k8 ]2 H" X
定义一个枚举变量用来存放标志位。
U1 x+ O* C1 n2 n9 K% t8 G2 |4 f- MyState = neai_anomalydetection_init();//初始化
复制代码
8 d" z: q" R- n/ e5 T- d初始化我们的模型。# W4 m2 ^4 G- W/ P+ R
- float IRD[128];- }2 l/ W2 z" w4 s k7 r
- int i = 0;
8 M) l. S! z) n0 ]0 i - int LeranTime= 0;
/ S" S; |* x2 q! L8 @! A% ^ ? - void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
2 M+ E: u, B1 l* s' I - {: v1 ~% y; D- q4 ^# y
- uint8_t yuce;$ y' F9 ? W8 l, @- U6 ?
- maxim_max30102_read_fifo(&red,&ir);
$ }3 L9 d# k- E7 O* [ - IRD[i] = ir;# A D O; N$ B/ L4 J
- i++;4 h1 Z+ p5 r* B% X) k# {
- ( |" I, l0 ~" j: L! T4 z" A
- if(i==128)) p/ B1 J7 ]- t+ T/ X
- {, a, z; `8 K' ^+ _8 r- h+ x# E( j
- if(LeranTime<10)
. Y5 H$ r0 A8 U - {# N! J2 L9 J! x; g" C- P& N
- HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);//LED翻转9 n) y& d' k% ]+ |5 |/ o+ t5 _
- neai_anomalydetection_learn(IRD);- K1 f3 a: H7 ]' f/ a/ T5 `
- }2 v; [5 B% g# }8 L5 a& C
- else3 o; b, i) ]. U
- {! @, ?: r4 w9 A. _' a% V" {2 V8 D
- neai_anomalydetection_detect(IRD, &yuce);9 }' `" A" U6 F& C$ `
- if(yuce>80)- E- ~ c! E; c# Q/ R
- {* T6 b# R% P: W C7 o6 n
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 1);2 s7 z" \7 D( y$ }# X' |! Y# w
- }
0 b* D9 ^* l7 j - else
9 o! ~( v- j- |, f( t; e - {
! Y3 Q5 ]1 _$ a7 H5 e# u - HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 0);$ ~; r+ G# f- I4 @! K9 Q( E
- }
$ v4 t0 `( t6 h7 X# g& J - }+ j. P& o: b1 k/ M
- LeranTime++;3 X1 b4 X* D+ w8 {3 a
- i = 0;3 q, X/ j: d* j8 A# u# c6 l) L
- }
5 v% b7 n# n6 C - }
复制代码
9 O1 `* M* Q' K! ~& R9 i; e9 i& `5 ?; j' }! @* l
我们在定时器回调函数中调用,上电之后前十次为学习阶段,之后对测量值进行预测,当预期值>80即认为状态正常,则灯灭。5 {% u6 U; }3 O6 B
如果预期值<80则报警灯想起。
' ^: l& Q$ W3 L2 R3 y
+ ^( }+ P, `* o% }* c' C5 v* M: M5 f" s/ h" [0 F( X
; f( R+ n& a/ I转载自:电路小白
: ? U4 p8 [, o' T; }如有侵权请联系删除8 i, r: K/ e5 z# w9 c, r
; y( v k; H0 p8 e' A1 g# D8 Q; [+ d6 a* o3 |5 F) Z& a* N
8 A7 d. v( \1 @8 m0 D% W$ o, \5 t
|