首先我的数据并没有做任何任何的处理,本来我是打算加一个直流滤波的,首先是效果不太好,其次是我都用上机器学习了我为什么还要自己处理数据?机器学习本事的目的就是节约我们的脑子,利用机器来提取特征,而不是我们自己去提取特征(直流偏置本身也是一种特征),就算我的信号有其他的误差,我们可以处理一下提高分辨度,但是!对于机器而言,这些本身就是他的特征,我们只需要告诉机器,哪些特征是对的,哪些特征是错的!; c: |# q: i; Z) t
/ ]6 n/ r/ e$ {! k' v: F& F
训练模型方面,我们使用MAX30102每10ms采样一次,每128次采样作为一组数据上传。
! g; _6 _. p8 x+ H4 G* z; w9 _, `
- int i = 0;/ C$ {3 n# U9 {7 k) }5 [8 @& r
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim). |( g* g: I6 z( _* e' }' I
- {
* O k( }- ]: j. X z - maxim_max30102_read_fifo(&red,&ir);- b3 c: R( I5 `& [* f
- printf("%ld ",ir);5 R. Z ]$ u8 _! w+ b! k9 q' F
- i++;& |5 h' Q R3 ?4 v# ~# r- x1 n
- if(i==128)
/ o, S6 v/ D# E7 U, W/ S - {
( w$ \8 u. ]/ j& W. z - i=0;9 Z/ I4 ?0 g e) s, v. `9 F
- printf("\n");
B# H+ v& O- \0 G8 D' n+ q3 S9 P - }( p6 u5 r0 L$ ?( t& a! E2 N
- }
复制代码
1 Y+ l9 q/ o& I9 @6 S" \9 L- {这里我们不对数据进行任何处理,因为既然我们选择了机器学习就是为了节省我们对于数据的处理,节省对于特征的提取。 ]/ l* @3 U2 l
: Y8 `4 R4 ]3 h, F* A& Q1 F
模型训练
4 b# r* V/ Y5 \% U我们打开NanoEdge AI Studio,这次的项目我们选择异常检测。
) t* ^1 t" i' v8 F; u; {* C
& n5 j4 q4 |( p% k! {
4 Y9 U- ]) y; y" c2 m2 H4 G) _' [9 n, g
: @$ }+ b8 p7 _/ `
/ M7 y) [, s. I* a, A& n
5 r' B/ f5 @0 m0 y3 C: q传感器选择通用传感器,轴数为1,芯片型号选择自己所需要的芯片型号。5 A" k5 ]5 x8 @* g$ d8 G7 } {
; H- K0 @9 e0 s! c! X
! U; a. c% M0 v6 R
: ?% P3 s! I$ @7 s/ z. z6 F
Regualr signals 常规数据
/ d ]" C; ]+ V4 T' p( Q. ^Abnormal signals 异常数据- O& B# W$ X! I8 o! t5 f) d* E. u
. J8 `) ~9 }# R9 S+ Q- @3 b4 R; R我们通过串口(USB)分别导入正常的信号和异常的信号。4 f) @2 |2 _6 B
5 S5 B L9 F/ |" @
# Q: p* ~4 T- G6 o0 U6 Y9 h0 Z, J5 L
* N: w2 ^" V0 p9 B9 Z
( z% A% z6 k( j1 r* D1 f/ p: `% y& r# y% u
数据集尽可能多且广泛并且经典。0 F9 R5 a! v: n9 u6 \7 U D
8 N9 E+ {2 ?6 _9 C% O+ ~ U* p, _
" |2 a) r! H% ]/ y; h3 \
# L0 F. g9 }. K- K我们总共导入了两百组信号,这些信号包含了大拇指,中指以及稍微靠前的位置和稍微靠后的位置,保证数据集的范围足够的广泛。' c5 H8 l8 j2 i7 R3 w
. e& R/ Y) e+ K/ q# ~: C
" S* e0 F. g0 i+ g4 j; `/ f0 P
' [4 q' X6 n. r& ~. l# w异常信号就非常简单,我们放在那里空置信号,晃动信号这里我放在那里测了总共三百多组(打游戏打忘记了)。& z1 {$ g y. P5 [
/ A% k" ]) u( Q1 Z/ D4 `然后利用这两组信号进行训练。
5 `/ R8 H- [. X: W9 l) a0 b- l; x& c- M* E
5 W8 e+ ~- q7 h5 B# }# G$ d7 g8 u1 ~; F/ p; F r8 m7 J6 h3 [
我们将异常信号和正常信号全部选上,之后进行训练。' p& Z3 a2 T* T4 m5 d2 ^
! I7 Q( ^0 z. i" L& Q
* N- H: h( _" w$ ^ ~- Y/ W0 [1 X/ O7 B$ w5 w W8 Q
之后查看训练详情,等待模型训练完成。% R3 j* Z9 `7 l$ B! H3 {. q
$ A: w. T) H( T' u6 v* D4 u7 |, J
/ q) b, C) r8 d3 i" B" z# D4 O0 `$ N& Y
可以看到,训练完的模型无论是准确率还是RAM大小Flash大小,都相当的合适,接下来我们测试一下我们的模型。- ]0 g7 m G' B6 n. s5 C6 @1 A
; C5 n- o! m. j5 e5 ]
+ C' t' y$ t4 `+ ?2 `
/ n- Z% `" F* b' v7 c) _$ `
这边可以查看训练过程中的模型。2 m3 R0 I8 \7 A' c; f% i8 ~! ?
, Y/ b3 x* C6 `+ Y4 l: A5 K1 b4 E+ C
# Q& L9 n1 A* g+ }( p: S
4 N" o9 j1 i @
验证我们的模型。5 Z, C! z) {$ `6 E0 b2 `: o
1 _. T" \ }% K; p0 E0 X5 v0 ?* c/ T
* b* F: ~# U: c5 q. I
C. [$ q# W9 p1 W7 _5 U6 N这里需要注意的是,我们第一次导入数据会先进行训练,异常检测需要有一个学习环节。; E3 y% R( F. ~ e
& J0 V9 M7 }) _& m- ^) k官方的手册中推荐了至少十组正常数据进行学习。
( m& n8 ?, m: [9 X
A. D u6 r; Y* ^- W1 w
1 Y* a, ^0 R& Q& t' ]
4 `1 w& `8 N3 }4 L
我录了21组正常数据进行学习。1 `0 O3 J" M; I6 u. o" D1 d9 m
. U3 A0 G3 P4 Q: t然后就可以对模型进行验证。
( k* f" \6 j4 B. v; D. U7 w" z- K# k( S: }2 A' `# O @7 }
4 @. }! p$ k- I( a( _
: W. k7 e# E4 g" }0 I V
( W5 [1 A, f$ b部署我们的模型,其中需要他的.a文件和.h文件。! R1 x2 w' p j/ C7 u' M
6 q# n- i. r& @8 X6 z4 I
" g/ j( i5 ]0 E6 [0 h
n# |$ Y; m$ p$ C8 }. a
这里我们需要使用CubeIDE来编程。因为这里的.a文件是静态文件,静态文件使用keil编程有点麻烦,需要安装GCC编译器,STM32CubeIDE集成好了可以编译.a文件。
* a9 P2 T0 l6 }
- m6 [4 A; ~* y" {
4 S. G( \* |" X) g/ Z
' m3 @" r6 i8 M
在属性中添加静态库的路径。
# L! @3 f2 H1 s* S7 Z! S+ F: _2 W& {. Y
0 S: I; H6 k. F( ?; X
' Y/ m* A- J) ?" E6 V5 {
在库中添加路径,我们的.a文件是libneai.a,这里需要省略lib和后缀.a
4 k* f+ A6 F: m8 q2 C
9 o8 m+ x! d+ P3 P, ~. v
5 d5 z: }2 }% N
! {6 v8 q% k9 r, g; o) I导入NanoEdgeAI的库函数。4 a; f0 s1 D3 ]9 V1 n* l! @# o( s2 M$ |
& L7 i, H3 T1 P$ K* {
- J8 M& |+ c* v! m$ ]' d
N9 i; b9 n v( o+ }& x可以看到这里有三个函数,初始化函数,学习函数以及预测函数。
r% [6 I; }9 L7 z% O
K: X% x" P, t0 b9 A
1 V% Q9 Q7 h% @! g& j, r; G定义一个枚举变量用来存放标志位。
- ^2 h5 F) C" X- MyState = neai_anomalydetection_init();//初始化
复制代码
+ @; g7 g; Z- i# x8 }2 E初始化我们的模型。
$ T! T. g- i, W" l- K. F6 a- float IRD[128];2 P0 F$ n5 ?2 b; u
- int i = 0;: a/ B) Z8 p) h/ b. a& W
- int LeranTime= 0;" f9 m& _& S6 {6 U2 C( N O
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)" Q$ b! R' F" o: W8 y
- {# u4 O4 [) k+ y% N. t1 u+ b
- uint8_t yuce;
$ Q0 p7 m( w% E& X5 `/ n - maxim_max30102_read_fifo(&red,&ir);
; k* x/ ^' d1 [1 M: h - IRD[i] = ir;: o' T( O* q4 Z1 N
- i++;3 j5 s8 N; X% A
- & c8 [: z- n* u$ a" [7 u% N1 |
- if(i==128)6 M5 a- R5 X& J" A! i7 e7 g9 S3 X
- {
3 n# Y# m7 }1 b2 ^" q6 T - if(LeranTime<10)% _+ Z/ t+ u2 w7 }$ ^: P O
- {, {- I% i5 i/ d6 n
- HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);//LED翻转
" f# t- `* I0 z3 s6 l% J) g4 f - neai_anomalydetection_learn(IRD);
$ Z! x2 p4 J' y. {5 D, S - }
0 }) Y& D/ X7 v G' Q8 J - else
$ z& U' O& }+ f( a - {
2 E- z/ J- B' w% @) L. V/ j/ q7 t - neai_anomalydetection_detect(IRD, &yuce);; F* E* S2 `# O: }
- if(yuce>80)
) s8 t3 z1 [0 z) e: \ - {2 P& w [- u9 |8 T( B; u
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 1);0 o, s8 l) `" \3 }# B
- }: c8 N/ U. B. c
- else
2 e0 h |( u/ ^. j" | - {) x' A' L& c# y$ Z6 H$ l+ |
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, 0);1 `1 _8 i/ y* J- I
- }6 s! ^! F8 x( L% L0 E
- }
- v9 N+ o2 S" R3 p* Q - LeranTime++;
6 T" g Y, ]! K. z8 G4 Q) E4 R$ m4 V, e2 i - i = 0;. j1 C- g2 a8 S7 X
- }
; L2 z( t- [* T( T - }
复制代码
4 h: u: z* \) L3 M9 j
7 y5 x/ D# N' N# o9 \我们在定时器回调函数中调用,上电之后前十次为学习阶段,之后对测量值进行预测,当预期值>80即认为状态正常,则灯灭。- a+ p- I( x" m& _$ U" q- R2 R
如果预期值<80则报警灯想起。- E! N7 i* r Q
5 q" B1 ~% \4 |
& u2 d' R% U# J& B, S: Z' j
; K" F/ C% U7 X1 |1 u转载自:电路小白$ g! @$ E. e( \" M- M
如有侵权请联系删除
2 t8 N7 ~; T/ y/ y1 J5 V$ w" u& d0 W* o# D0 Q
7 k/ O; _/ K) h% ^
Z2 \8 R, f* p* J. q/ B
|