用该传感器判断是食指还是中指还是其他指头。4 ^1 f% U# o0 x: i* o$ o' F
. T2 E. A9 v& Z
对于我们的三个指头(5个也好)本质上是一种多分类网络问题,我们将输入信号划分成不同的分类。
# [) k5 c7 k9 H Z5 t7 t% I小拇指2 b* X7 r! s* O
大拇指# J$ o% P" P- i [& |
中指(后来用了食指方便)8 q, P& n6 O0 l. O+ x: {/ C
没有指头(空置)% I0 ?& m: S$ D: Z
/ E8 X2 x* [4 g$ y因此我们利用多分类神经网络来实现判断功能。# x- K# e" d+ E! a/ u# b
7 q! q! k" u l+ J7 [. h/ _! q) e
& v. ~7 J$ ~, c7 G3 P- int i = 0;. C z8 U1 O0 I9 b) h
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)$ q% w* P( N! \) m8 I
- {
7 N2 \) z0 |% Q1 i u% R8 X - maxim_max30102_read_fifo(&red,&ir);( y4 F7 _1 D8 X4 M
- printf("%ld ",ir);
. m4 H3 T R6 y/ C: \9 u9 b7 K - i++;; E- A' K- ` }" f; \4 E6 Q c4 r
- if(i==128)
- n2 E+ d0 T% p+ ?% g2 R - {
5 R# L4 o. F- ]3 [7 V. A - i=0; s! B9 g7 s. G. V
- printf("\n");
$ N/ ]: x1 Q0 J3 g- |0 G5 U - }& Z1 f) V1 N0 O- Q
- }
复制代码 8 r, N5 r/ `' `$ U8 H! K5 f
信号的输入部分则和上期一样,100HZ的采样率,128的采样长度。7 n% E1 R, x# ~# l/ [ V+ L& f7 S
" A% S4 \! l& c5 u% f$ L
p& y7 I! c, [$ v5 k2 N- j- _
5 |/ n3 C) D, \! f. ~) k
创建一个n-Class n分类神经网络。
! d3 l. u1 R; P& L+ \+ [* a2 g5 N
4 }+ \2 f; F9 q4 A' f3 V
& P, d7 L5 H# x: b- j$ B
其他设置都和上期的保持一样,使用通用一轴传感器。, B1 I, {( M) y; L7 v& p
, i! [2 F- k8 N
, F3 D' u4 q5 x+ a. s
2 N1 q% h Y* @3 @0 m, p但是信号输入的地方,我们利用串口导入各个类别的数据(这里是不同的指头)
; [* c' g( X6 M! k; @) N; S* |. a0 r M& e* }& N1 p2 k$ M% T
; n& `: I N% W8 H q# w( C
$ e; M- @1 D b# B* w, o7 F, \& v( F
需要注意的是,这里的标签即代表着我们的分类,不像之前那样子可以一个类别下面可以使用多组数据。2 H" D3 O8 i2 d3 H9 o$ e
4 b: X: g5 o: M6 s. t
1 B* q& {8 q$ d9 k$ u8 y' ?
5 D' J x) K4 E' h训练我们的模型,这里可以选择我们的分类(其实这里我觉得要是把某组数据能添加到某个分类就好了,这里让我研究一下)。
" S1 D* P+ P, G" P% s
) H/ Q- K4 `8 |4 B. f( R2 @* M- ?0 _
. S* ^' s4 ?) h1 y' a, x% x5 V3 T) x/ U* L
训练好我们的模型,这里可以关注各指标。; \* |3 m9 a' u) r; c" E1 {
$ `! L8 M( [5 A6 t4 j9 a
接着就是验证我们的模型,验证的过程可以参考文章开头的视频。3 B# W2 Q% O. b. K! r
- t. H; M O! r9 U3 A4 v
$ S C& q+ I5 F8 \2 i! Q" a0 l* q
7 `5 d, @" b- d% f9 ]/ [
部署完我们的模型之后,查看生成的.ZIP文件,其中相比于异常识别多了一个knowledge的头文件。
J& \$ i6 l9 ^# ~9 W3 r8 a6 J, f' |2 ^& a
! N8 ~% [; S, z2 A6 b4 t
7 G7 a" h1 w, t( I* G8 n& D
这里我们需要libneai.a以及两个.h文件+ i6 N* d& k" n! G. t" y h5 G
0 g8 E' ]: d5 L; x
STM32中用机器学习实现正确率99.95%的心率异常检测!
" {( _8 {- }) w6 d7 Q0 c& c( o' g$ ~# P/ D0 \
怎么导入文件请查看这篇文章。0 h( L. ~6 S; T
# Y: B; A7 A) ?" {! R4 R
; Q- d1 N2 D* Z/ b9 x
! f9 p. v( S2 z' O6 D! I, w& @初始化函数中,我们需要导入一个数组,这个数组就定义在knowledge.h这个文件中。
* i: G/ ?/ B( {; \3 @1 a
1 _6 f1 |& C( H5 q' ^9 T6 a
) \) C2 ?& ?7 L
6 ]9 x* j: I+ E6 n' I' b4 a, Y- neai_classification_init(knowledge);
复制代码 / u2 T9 B. s6 A/ T9 e' P
初始化的时候,需要以这个数组为参数。6 c p6 j4 f% G: c5 F
4 T$ [' m6 k5 s
之后我们在定时器中,采集到128个数据之后进行预测。
$ s8 D# q/ X& C& o
* J, h( |) k* h) |* ^/ d: L* r/ P- float IRD[128];, E9 b7 }& ^8 m: C- J
- int i = 0;
( d; N' k$ h7 ^& J# W& | - int LeranTime= 0;
* D4 \* M" ?( J" S - const char *id2class[CLASS_NUMBER + 1] = { // Buffer for mapping class id to class name
6 y. f9 L4 x- N' _) n - "unknown",; C; ^2 f- P3 G* g' W, w
- "zhongzhi",1 F3 M0 T5 t R9 v
- "Error",* B9 {; B6 E' a4 C
- "xiaomuzhi2",8 b8 C- \( C% G6 q4 E( ]/ H Q* d
- "damuzhi",
# Z& Y% x) r# @; v8 G T+ e - };
+ ~; V+ K u$ k) Q" T - float Output[4];1 f: ?! ?6 y/ M; W1 M0 u2 [
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
8 [# g3 F7 y5 ?% F3 _+ z - {
* h, p$ s& u/ @1 t1 ] `# N( { - uint16_t yuce;
$ ^/ K! \5 }1 q! ?) @# C; S/ m ^ - maxim_max30102_read_fifo(&red,&ir);
& c1 O" t/ Q4 R% L) V - IRD = ir;* I" @ }" B: T0 u+ l
- i++;0 `/ G* A7 p7 k; x
- //printf("%d ",ir);5 z% B& V2 H, @
- if(i==128)
" J" S% T$ Y; n s - {
2 z: @; }, v6 p9 w8 ~8 ^
0 ]# S+ R; Z2 B3 N7 M; b- . t1 ~: y5 i. l1 M
- neai_classification(IRD,Output,&yuce);8 { S8 l- K. _5 _; o
- 3 M! n' E$ {1 q7 I
- 6 s4 ~6 o3 M" m* j
- printf("\n\n\n");
0 }0 y Z5 _9 u$ s# E" T2 v( y - printf("zhongzhi:%.2f\r\n",Output[0]);
* z6 x8 F# D* v' H0 K" |, d - printf("Error:%.2f\r\n",Output[1]);: U" F/ L- I& k l$ P
- printf("xiaomuzhi:%.2f\r\n",Output[2]);
3 g9 R7 f6 C2 `3 |- M4 e - printf("damuzhi:%.2f\r\n",Output[3]);
3 O/ S# Q* a( P8 b% K4 r) u# @: e - LeranTime++;
0 Y- e) n; {9 v( q7 L* T - i = 0;
5 t- |5 S% f$ I7 r: x1 o2 e$ @; K, | - }; M. J ]) p' J7 o8 v7 K6 N
- }
复制代码
: D# D4 ]' |/ O这里的 预测函数有三个参数,第一个参数是输入数组,第二参数是输出数组,输出数组中包含着对于各个分类的参数预测值,第三个参数输入一个指针,这个指针会指向预测最大值的索引。0 d# v- l( }% I: @1 z4 t& i7 Y
' I4 P# P) f9 k- ]* e/ z+ Q {
9 O4 s- ~/ x/ e7 `
! \" m: C) p4 T烧入我们的代码,可以看到,空置的时候,Error的预测值是最大的。0 f- h1 U2 V0 u8 h( P! }
0 b4 B% X3 j" \8 ^: p& F
0 u8 N/ p- Q& A4 f1 j; t3 Y0 M# n1 i( w3 h$ L' R; Z' u, P" Q" T1 s
当我们放上中指的时候,检测到中指的概率是最大的。6 T- R& s9 i7 W& q
! R ?2 q# C! ~, F% o# M
6 c9 @# [5 h6 Q- b9 F) A
/ X E2 I) l$ y小拇指也是可以正常的检测。, O+ _( R9 N; {) l7 X2 B" d
* [$ _- O" o `: j* c% t: W6 ^
- @, _7 J/ z6 P9 U: S( E3 S# _( B6 p. y
转载自:电路小白
) C6 Q# r i! _如有侵权请联系删除; y( T7 C5 p3 z$ \7 ^5 u7 ~4 O$ C
" `3 x w& J7 R+ B% X) R! x0 W9 W4 o( F/ E [6 Q
% ?4 V) s/ w3 m# B
4 F8 Y) r, x' }" E% H/ T3 H |