用该传感器判断是食指还是中指还是其他指头。. Q3 C* G0 k6 @& u. L2 S* c
/ c5 r$ z3 Y9 i% m对于我们的三个指头(5个也好)本质上是一种多分类网络问题,我们将输入信号划分成不同的分类。0 Y2 h2 j" D$ W/ R. L
小拇指
( E2 S) {. L3 y; T1 V大拇指2 e+ E' z1 N+ j% L8 ~5 ?+ I
中指(后来用了食指方便)
5 Q6 N m6 [0 z* l ^- E3 L5 l( }7 ]没有指头(空置)
* X. Z" T8 p" E$ E. P' Q: ?
! u: k, n b2 ^! n& h; r因此我们利用多分类神经网络来实现判断功能。3 u3 Y& |" m C& a) {; S1 ^
. i8 g7 `0 N1 Y& r# x4 f6 x$ |- 5 A/ q4 z3 ^# c' y& K
- int i = 0;- K% L, f! t8 G) h# S% B4 _
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)$ ^2 A& a7 p. n5 a. G' P4 ?' X! M& o
- {
. \. W0 H" m; l- [9 P& h$ B - maxim_max30102_read_fifo(&red,&ir);
3 c- n( x1 G, y( d - printf("%ld ",ir);# o. Z4 `" \! p1 {
- i++;& s. D) X. `0 ~$ O& E8 B' H
- if(i==128)" A3 K$ W9 A" x2 g& }/ D8 I
- {
/ n. M# u# n! O' u$ X2 R$ b - i=0;
# a. t" y3 V8 ?( \; A( d - printf("\n");1 y R G& x4 J5 r! X
- }
: E3 h. I0 K& @ - }
复制代码
" t: E; O( G0 D5 p* F" N信号的输入部分则和上期一样,100HZ的采样率,128的采样长度。3 H3 F9 f5 |, v9 E# K
* h2 Q5 }9 [ O9 {) B7 S9 L
: c4 D" v9 j% l( j/ z
6 X) m8 I- T* P4 A' {创建一个n-Class n分类神经网络。% |6 g9 i: z6 T: p" Y, B: k
% k* y5 M* A- ]+ ~& I. F2 T
; i9 Q8 B1 G, A5 k' c$ U2 X
+ }1 v! G; z' v
其他设置都和上期的保持一样,使用通用一轴传感器。
1 c8 A2 B% N4 x# A+ o; k. I: F* P4 J7 j1 f/ g* I% [: {; I
! \7 Q S7 X! }7 u$ s B( Z
' f. t/ Q! v4 a8 b' \但是信号输入的地方,我们利用串口导入各个类别的数据(这里是不同的指头)+ e8 T8 \, L% a' P# X1 G& i
/ t& t; m {: _; M- T u1 P
2 Z$ E7 N# \% F% {
* C6 E% _6 ^- ^1 Y K7 f6 K
需要注意的是,这里的标签即代表着我们的分类,不像之前那样子可以一个类别下面可以使用多组数据。
) Y3 n; t7 P: z/ r
0 `7 {, \6 ^4 B9 v
7 \' |9 i- Z7 p/ c' q6 K: Y
" L$ j3 m, r+ k8 y3 K
训练我们的模型,这里可以选择我们的分类(其实这里我觉得要是把某组数据能添加到某个分类就好了,这里让我研究一下)。: k P8 ^, k' X$ z4 G2 u
! b( ~1 C2 ]$ h _: j
. n9 X# Y2 T6 R+ Q z( f8 W
- g+ [- T7 g- f% y训练好我们的模型,这里可以关注各指标。
) D& O4 Y8 O6 l# a$ h4 L. \" \
. \; S2 A/ v I0 b) X接着就是验证我们的模型,验证的过程可以参考文章开头的视频。+ V. }6 g4 N8 P, H
- C5 j5 D! a( q' |4 D# Z+ g
/ S0 @! v( y2 b m* y) d& F1 T; ]7 X) j2 O# B
部署完我们的模型之后,查看生成的.ZIP文件,其中相比于异常识别多了一个knowledge的头文件。+ K \3 A) A5 I' X
) g7 m: b' M: P6 \6 y
! z1 S) ~: R6 c m9 q% s9 O6 W
, o9 L3 \3 @" ]; L, Z. M9 V
这里我们需要libneai.a以及两个.h文件; P# N" r) ~/ u
' y# K, t; ~6 [3 Z) K* X0 Q3 I" `. y
STM32中用机器学习实现正确率99.95%的心率异常检测!
! A# R" D# f# D4 t/ y; w1 ^( j9 X/ G1 q/ N3 L8 k
怎么导入文件请查看这篇文章。# S0 J% q' K8 M2 V
& f# g1 Z3 u" v, z2 }1 F% m
2 y: v' t% G6 _- |( ]- v$ @
, Z5 H' x) A8 U% y/ M: w
初始化函数中,我们需要导入一个数组,这个数组就定义在knowledge.h这个文件中。
: c: u8 U$ \% a/ b ~. a
I4 [) X! Q- @8 }% j
8 Y! B. a; n- J9 m* w
# o5 T) [) Z; N8 ~/ l- neai_classification_init(knowledge);
复制代码 ' i" g9 Q6 V! N4 E8 x& z
初始化的时候,需要以这个数组为参数。: V/ h3 x1 r9 k
4 a. y0 k) v# Z1 B+ f. H
之后我们在定时器中,采集到128个数据之后进行预测。
0 j5 K/ O* r j! j1 M
% t) u6 |% i1 M: N- float IRD[128];% X0 x1 N# p+ k4 Z' P' ?& P0 b+ l; e" g
- int i = 0;- t, l B8 N& W; @6 c/ U# y
- int LeranTime= 0;! R2 f3 V. v% a( u
- const char *id2class[CLASS_NUMBER + 1] = { // Buffer for mapping class id to class name4 d( e s: t' `% w$ ~* x+ v3 u: f
- "unknown",
I+ w4 b( ]6 _- R( x8 ] - "zhongzhi",' P+ ?$ E8 B. a- L7 |6 q+ R
- "Error"," |4 o% T" a s d; B/ V
- "xiaomuzhi2",1 l1 u3 L [" L" ?
- "damuzhi",
8 T. R; a( }/ m' v" |) A+ ^ - };
( O y6 \) Y! Z - float Output[4];" C% Y: ]) l( J2 s/ S7 y/ u
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
v4 C8 n, b3 S2 ]) Z - {
" ^' N+ A4 `( e3 ? - uint16_t yuce;$ F' _8 g8 Q, f4 `( y
- maxim_max30102_read_fifo(&red,&ir);& W/ H/ _( A& ^1 p5 [. C% A5 a
- IRD = ir;
7 c; z+ }; ^. Z6 s8 m Z# D7 Y- z! D - i++;
! C% N0 J4 g6 ]1 G - //printf("%d ",ir);
5 K+ X) I4 O1 ~6 ?7 k - if(i==128)
( N) W6 N$ k, L1 T9 L, M' K" T. A( N - {
/ M _# K8 Q9 [# L5 [* r; f/ d - 9 f* P0 k( C+ V. ~% h
& H2 E! x" Y- q; x& L- neai_classification(IRD,Output,&yuce);
/ k! s& n" `- u* y: w! D; F - " ]: d4 J" m# p/ [3 D& k: o) Y
- 2 F' U3 O9 H, z1 T; B" y
- printf("\n\n\n");4 ]/ T& f- E+ v! ?" a0 B
- printf("zhongzhi:%.2f\r\n",Output[0]);8 w; [& }( B0 ^# _8 l: r
- printf("Error:%.2f\r\n",Output[1]);6 B* W$ |1 Y' D W5 ?
- printf("xiaomuzhi:%.2f\r\n",Output[2]);: w8 F" A: D9 A0 l
- printf("damuzhi:%.2f\r\n",Output[3]);
5 k. W2 ]' N% C9 M. d9 ]2 K - LeranTime++;* Q/ Q2 p5 I! E
- i = 0;
8 R* f5 a) G8 t4 l" h/ u/ v0 ` - }# S- P! y* f* R: L
- }
复制代码
: c' Q6 h5 t, L$ t: {) A: _ h. r这里的 预测函数有三个参数,第一个参数是输入数组,第二参数是输出数组,输出数组中包含着对于各个分类的参数预测值,第三个参数输入一个指针,这个指针会指向预测最大值的索引。
* |- D2 m- I! E3 B( T; Z1 r2 e: ~. q" n
5 v; T4 U5 u3 X: R- w
, a2 S" F& a% y" ~6 }0 o# a8 v烧入我们的代码,可以看到,空置的时候,Error的预测值是最大的。
3 u: V% S D/ O" d/ k. x) q
$ K# B0 e. T' k( a
: M; u8 P6 c! Z. g2 G
& V" V) T8 B, [+ ~6 r$ }
当我们放上中指的时候,检测到中指的概率是最大的。$ n9 Z1 x! h" x3 k( q0 @
( M' C* L1 z9 Y7 ?. @
3 G3 ?! ]( C' j1 h! z `9 N' N
( s- J- s- C" \7 [2 B" L% ?+ z小拇指也是可以正常的检测。
1 S! m( g/ ]- _: I6 g8 Q7 W2 d, t9 j+ Y5 D4 T; I! w+ A
0 Z! _; E" B' R* X9 U, c
+ O- @$ j/ c2 H
转载自:电路小白
! I" C- L: V( B3 G( g$ ?4 |7 J: W如有侵权请联系删除; K. F8 h) W7 z8 Y* F# N
& A S2 z! e0 {/ g7 V. u+ q. L6 p6 x e. h
' G# O+ r+ ?$ K9 \
) L# J {+ h! @1 F% L |