首先我的数据并没有做任何任何的处理,本来我是打算加一个直流滤波的,首先是效果不太好,其次是我都用上机器学习了我为什么还要自己处理数据?机器学习本事的目的就是节约我们的脑子,利用机器来提取特征,而不是我们自己去提取特征(直流偏置本身也是一种特征),就算我的信号有其他的误差,我们可以处理一下提高分辨度,但是!对于机器而言,这些本身就是他的特征,我们只需要告诉机器,哪些特征是对的,哪些特征是错的!+ Y9 d9 i7 V1 @; @) R/ m
9 \8 M" V1 C. b- ~2 A' f
训练模型方面,我们使用MAX30102每10ms采样一次,每128次采样作为一组数据上传。/ ? J0 p5 J* A$ |! ]* x. J' d
" i0 q, t4 ]) ^6 K0 [6 B
- int i = 0;
6 E4 G8 } p+ v: {- ] T3 j - void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
+ }: W% ~3 e" U1 g& J+ m& H - {
2 I. p% C+ V; L( X+ e - maxim_max30102_read_fifo(&red,&ir);
" \. Z0 n+ d2 j. h - printf("%ld ",ir);
! h, p) h$ Q& h1 s7 G( v/ b x - i++;
8 |; o L Z. l* N - if(i==128)
0 N' r/ m" p6 L9 ? - {
: g# H n. P$ E. C) p4 w2 t: G% V - i=0;
3 O3 J( F: L4 S# G; J - printf("\n");
$ |4 U& g4 v( ]6 \& ~- K" l4 V - }
5 w, v+ E$ T, J - }
复制代码
/ ^3 Q: P" c# o# r这里我们不对数据进行任何处理,因为既然我们选择了机器学习就是为了节省我们对于数据的处理,节省对于特征的提取。
% S0 `* O0 m" S/ P
, Z6 \3 K* ^# H2 p模型训练
1 e0 V' t$ f/ S) x8 N* h我们打开NanoEdge AI Studio,这次的项目我们选择异常检测。
) X7 Q! i9 D7 I: U( C8 u8 [1 t" ]
$ ~8 T) w/ y Q3 _) P0 o+ L
0 a7 S6 }- U; d8 c* {
& I: A7 |9 G3 m1 ~' D' d2 C/ @, W; t2 B/ K# A( w
传感器选择通用传感器,轴数为1,芯片型号选择自己所需要的芯片型号。
5 Z; _2 ]- O4 \1 r2 i2 Z& O! X9 B' a5 W0 I( A) `! S& r
1 u# M2 A/ d4 h& U( ?6 R4 d: H
$ o' U2 h2 f8 F/ a& c; Z) a+ x, W; y
Regualr signals 常规数据
3 z% Z* v- T; c/ s. S# J' uAbnormal signals 异常数据6 s! F, L4 R5 `! x; L- v# i0 W
* `% Z& B* _+ C8 X3 t7 D0 Z
我们通过串口(USB)分别导入正常的信号和异常的信号。
, v* F' P) U$ M, h- Y+ k4 l [5 H2 ^1 Z0 U8 R0 x& J W5 l3 `
* m, L% h- t0 G+ H% l
6 z3 W, z- V) Q$ I$ H6 }& S
, Y ]% ?+ H9 v/ M; A7 J+ R# P9 l( r$ U2 f L- d- k' h- K
数据集尽可能多且广泛并且经典。8 S: q* `- d' [1 g
4 E+ Z( L- b4 [ q- A) a
4 u/ S1 H, y) ^9 S |0 r5 _. ]
# X$ E0 b- l9 L/ u% L; D我们总共导入了两百组信号,这些信号包含了大拇指,中指以及稍微靠前的位置和稍微靠后的位置,保证数据集的范围足够的广泛。
. f7 v2 C% g# v
/ S' Y! u/ [# J a* i8 r2 l# c& T
) o5 ? g/ f1 g4 A7 l6 [+ C
9 y9 t+ ?8 t0 T/ F: N N0 e异常信号就非常简单,我们放在那里空置信号,晃动信号这里我放在那里测了总共三百多组(打游戏打忘记了)。
3 ]+ J/ ]* [) N) |8 A2 ~4 k5 _8 y2 e u |) a
然后利用这两组信号进行训练。
- G" ^" ?" s- d* ]8 ~0 C9 p, R* [% k+ R! {) m
2 S& z2 V. @% w1 v; X9 }- A3 F2 d3 G# j& e, [9 e
我们将异常信号和正常信号全部选上,之后进行训练。
9 t& F& T. X8 @4 _. _0 F6 n/ ?
" ~% I: B s/ I. x1 B9 W
" F8 B) w0 m4 Y8 j# S
5 Q4 f2 O* K4 o. H: P之后查看训练详情,等待模型训练完成。) Y) e9 j+ ]* P2 E" D5 F
4 k( v) l3 S) f
& B" f/ {4 F" m$ Y( c4 u# z
! J8 v# E: W: ^) k. \. \' ~' V6 {, ?可以看到,训练完的模型无论是准确率还是RAM大小Flash大小,都相当的合适,接下来我们测试一下我们的模型。# N0 w# B3 N$ a% W+ r1 ~* [) M
3 l8 K2 } T$ f2 h" ~# _
: X, [; S1 L j
: O3 D- y ?9 e. O这边可以查看训练过程中的模型。
4 F D$ P! D6 Q3 R
7 _6 { u; \" S) ~& ]
, i) f! m6 _% ]) T
4 Y: R# z6 ]0 [. D4 p
验证我们的模型。" f2 r' I9 r/ [! \. {
# t' a: c9 w1 w# {/ e9 y: K4 \
) k% N. q5 n& F
, w3 J& v& a8 g! E
这里需要注意的是,我们第一次导入数据会先进行训练,异常检测需要有一个学习环节。) l. D0 p2 F$ `/ _: _& y
" F+ ]1 p0 z6 k1 G' v9 \
官方的手册中推荐了至少十组正常数据进行学习。( ?* |: _$ I" ]/ U
% R6 p+ _; b* d, V3 I. H$ Q0 ^
5 y8 z' D, k! @% l% \* l g
/ G2 a, z! @5 X6 V; s% M/ s o我录了21组正常数据进行学习。
' l6 p5 ~: G1 c" a% ~ J# B3 z9 z! T
然后就可以对模型进行验证。
. @/ c. B$ m! B7 ^6 J
! _' U" [* ]- z8 g. ~1 r( K4 |1 M, ~
) R1 B# E! Q) a- k& r
% L& U. g! z' ?* c. k @
" K! p7 e3 _* f. \% x0 M部署我们的模型,其中需要他的.a文件和.h文件。
6 {4 X( u7 `7 k. W# T9 Q
) m3 P; P8 q; X5 u
8 S; Q5 x, A4 l
* B, r e" ?; D% {7 F这里我们需要使用CubeIDE来编程。因为这里的.a文件是静态文件,静态文件使用keil编程有点麻烦,需要安装GCC编译器,STM32CubeIDE集成好了可以编译.a文件。
: w7 q, [" I: F5 E1 M
5 z/ \( ?6 Y( V) I
3 q4 P. L% _7 |' ?/ ^
. x) a1 r) }5 R6 D( `. d. ~& S
在属性中添加静态库的路径。. r" {7 k1 W$ R% C/ }
1 g, [3 c5 g# y0 E& ~; t
2 b# y: g8 {+ K9 }$ L2 f+ @3 P6 m9 w
在库中添加路径,我们的.a文件是libneai.a,这里需要省略lib和后缀.a
7 Q* v- x: d9 W9 J) C& k4 m# p$ l# u, S0 B" D
0 v# F5 x& f8 G: G g c; {# w% u
: C) {2 E/ R2 F导入NanoEdgeAI的库函数。7 k0 a2 Z1 k* L
+ A/ M4 E5 `% R z8 G: O
+ n8 r; p5 M+ {$ Z6 r
- W* o1 w9 b& h- n) _可以看到这里有三个函数,初始化函数,学习函数以及预测函数。
6 Z! h' j9 x- P; n6 q& `4 v$ }. _& ]) c- K- I
9 [* u0 x/ O" T2 F ^
定义一个枚举变量用来存放标志位。
- {- g/ C& f7 k3 z$ H- MyState = neai_anomalydetection_init();//初始化
复制代码 - u' u. _# N5 t5 e. O
初始化我们的模型。9 h7 h, @. i; M
- float IRD[128];
) k' e5 S, ^, I! V" I* U/ M$ _ - int i = 0;
/ c ? `$ I# Z$ v6 q( l; c, I" s0 T - int LeranTime= 0;& V; Z0 C! D/ s. M
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
. N- a; U+ n$ k! z' D - {: H& G/ p# Z! W- Y$ r6 _
- uint8_t yuce;
4 Q' C' D% n0 M2 w7 D% A, M - maxim_max30102_read_fifo(&red,&ir);
" `" I$ X$ A0 [$ b# V9 @ - IRD[i] = ir;. [2 U; f/ Q2 W) }; [; x
- i++;
$ e& V% ]! i: m, N - 0 _* D, Z- o, r0 \9 g
- if(i==128)) V" O. h! x3 R3 n1 U; A6 g1 }
- {
M& q% q# X* N# V ]+ Q& w) H0 P - if(LeranTime<10)
1 ]- a P( e+ _" V* ~ j: K ~ - {
) C6 }+ o2 w1 `3 \( C( D - HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);//LED翻转: W8 v2 T7 B' _9 z X6 `% t" ^
- neai_anomalydetection_learn(IRD);4 w7 w# U" ?# v, c" z) h4 Y S
- }
' F+ e' [- U& Z5 R: [ - else% i) Q9 i, m' L4 R8 f1 `/ z
- {
+ T5 n( }1 f9 C" U% s$ a - neai_anomalydetection_detect(IRD, &yuce);
5 J1 S- L) P' A% @2 S - if(yuce>80)+ I( a; r1 g2 Z* I8 p% i, j& |
- {0 S: i$ [% _# N4 V* q# u6 ]
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 1);
+ H$ o/ I. t( i8 D9 D$ B; U" f - }
. F" n: ]2 A7 e+ `" v& n' }% \ - else6 K% U6 T: {9 ~- q
- {
% n* P' I$ M5 u8 A - HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 0);/ A. A, D* u3 m9 m
- }
8 N2 |" K9 `2 M7 i# \& T, ` - }
+ q1 F% M( P% p8 n( }0 }. Z - LeranTime++;% {, b1 d4 e6 Y0 p( M
- i = 0;
* J Y* i5 f9 ]1 x3 [ - }" k _9 J' E) Y) d* K
- }
复制代码 0 `) l% h) F, A8 v
% W! q+ R6 f" v G* j我们在定时器回调函数中调用,上电之后前十次为学习阶段,之后对测量值进行预测,当预期值>80即认为状态正常,则灯灭。
" f- J# Z e* r- u" @ b" b8 e如果预期值<80则报警灯想起。
0 u" J( G& U) y% {- z( F! N& a, \4 p" F- h, E
* g6 m+ z4 V8 A* A$ g. ?
6 d+ ^6 B1 \( x2 t转载自:电路小白
1 P: R8 R7 K1 E如有侵权请联系删除" O% Y! J4 h9 r) b" }
; `. I) ^) O* w$ H7 {3 C& F" Q+ [5 Y- }: {) d
" A" P4 {4 Q' K4 q% K/ q |