用该传感器判断是食指还是中指还是其他指头。
* G7 j, x$ L0 h7 `+ `9 ?9 E+ _6 J9 h
对于我们的三个指头(5个也好)本质上是一种多分类网络问题,我们将输入信号划分成不同的分类。1 \. Q' C" g8 w, J# u. ]8 `
小拇指7 |$ u& g/ D( I; A8 J. {& i# e
大拇指7 G0 F# a& Y* \# c5 H) e
中指(后来用了食指方便)
: j5 s' \0 O- ?4 w4 z( H: J8 k7 F没有指头(空置)
! i9 N6 s, L! |9 f, t" a; y# W
0 w; y4 | p" a, t9 e! D1 j7 T因此我们利用多分类神经网络来实现判断功能。6 X0 i& u5 j. x* j* K( m+ x
* ?* q; A4 b1 S; P% s4 p4 a; e
- " s2 H& ~9 b, T3 l. H# `
- int i = 0;# N/ p& r+ k& V+ `! |7 d
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
& W6 q6 T) p2 e. B* d" n/ m6 y - {
' J3 s7 Q5 b8 X0 f7 C2 O: a6 z' s - maxim_max30102_read_fifo(&red,&ir);
m9 j" y# F" V3 a - printf("%ld ",ir);+ T/ M! e. d; s8 r
- i++;
0 P! \( r9 f$ } a - if(i==128)
@+ r, C; |+ j' U) b/ E- X6 J - {
; J& Z$ N2 E* l6 H - i=0;# H4 c4 |0 e0 ]6 v
- printf("\n");
2 Q4 ^- T4 l2 p1 h - }& `5 D. E4 l9 F
- }
复制代码
6 p5 J: v; Z% j4 I' g信号的输入部分则和上期一样,100HZ的采样率,128的采样长度。& z# D; B( B3 \$ n
+ J$ z( z- l' N. h* u2 r# N
0 |! B9 K7 w5 L. Q0 q
! G" n1 w5 G+ M" e
创建一个n-Class n分类神经网络。# r+ _( f3 L/ l: k5 }
' c& K5 b" q$ ?
& M- M- B' |1 k, O( ]/ O% B) |# `& w2 Q
其他设置都和上期的保持一样,使用通用一轴传感器。
- Y0 |& V4 Y Q" P5 i L* \0 {+ w# Z+ G5 B/ ?' k; h4 K
% c Q* `5 u2 q: O; A+ C F) A, _+ M
6 P# r8 {* H. }) S" R* ^7 r但是信号输入的地方,我们利用串口导入各个类别的数据(这里是不同的指头)
8 n F: j: X2 z; g* n4 p3 M6 O$ D5 j5 y0 ^& t: H ~
# {# R, c! l( w1 N$ W. s; k
+ q+ a" ~3 n! o需要注意的是,这里的标签即代表着我们的分类,不像之前那样子可以一个类别下面可以使用多组数据。
$ t7 g$ O! ?7 R
& D4 t- h9 v# o! C. f) E: X9 P/ H
2 L8 e; j* l9 g9 G+ G/ i
5 s1 B( f& ~' d' g8 k$ l6 J- Z训练我们的模型,这里可以选择我们的分类(其实这里我觉得要是把某组数据能添加到某个分类就好了,这里让我研究一下)。& w1 \( {, _ Q8 y* `% |$ \
6 A$ B4 E" }/ b1 a% G
, [7 R7 _2 `" c5 T" }" _6 H9 x% g+ g! a- V! T
训练好我们的模型,这里可以关注各指标。7 v. f0 A) l2 b+ E! T0 f
1 f- G- p+ q9 X! K) Z+ F
接着就是验证我们的模型,验证的过程可以参考文章开头的视频。, M+ k x- q$ z* r" g
6 F# a. h8 P& j, @ g
7 L+ E$ p& @$ o& N' A7 D( Z
1 }, l9 e* b7 O/ U& s. J6 m% ^部署完我们的模型之后,查看生成的.ZIP文件,其中相比于异常识别多了一个knowledge的头文件。
' ^, Q+ e. B; m& p8 Q/ L) n o, V P3 k" a- j
* d, A. g/ p' S9 ~7 e1 ~( {: ^9 e! @: b, G, u$ x) e! x
这里我们需要libneai.a以及两个.h文件% }( l {' h. X5 A; u+ P) C5 d
' h& n) J4 \1 h- h: L
STM32中用机器学习实现正确率99.95%的心率异常检测!
, e9 S9 l% j0 T9 c |
& A2 C6 p$ T% o8 Z5 c5 E8 p( T" }怎么导入文件请查看这篇文章。+ p1 L& a& @ Z/ ]
F/ r( F, Z' f" r
& i: d* u5 }: {
6 [. Z- ]2 _/ q O初始化函数中,我们需要导入一个数组,这个数组就定义在knowledge.h这个文件中。, `9 I, I K! h) w- z; Z
% F4 H" o6 j( s$ ?- p0 }
! d% s) ]" @8 z
$ C0 B5 j- Z, b5 i& t- neai_classification_init(knowledge);
复制代码 9 ~0 y# N/ l G1 a' Q
初始化的时候,需要以这个数组为参数。
C5 Y9 C) \. L; F3 s1 G1 y* S! D
之后我们在定时器中,采集到128个数据之后进行预测。0 G0 c; t5 I ^) {+ }4 p
" Z2 f8 i$ p: {# H. A- float IRD[128];+ j! w4 y. O% n L M$ s; ]+ `
- int i = 0;
: z" ^2 W! ^& O+ h - int LeranTime= 0;
% q$ X% T- B. U: {. ~: s+ z+ u - const char *id2class[CLASS_NUMBER + 1] = { // Buffer for mapping class id to class name
9 w' Z" k" t2 i$ y1 H - "unknown",
9 k8 A# i# i O2 t4 D! w+ S - "zhongzhi",. {$ l. R8 Q$ Z8 J5 b! w8 J8 R d
- "Error",
1 S& _( ^, T; ?/ O8 E2 O - "xiaomuzhi2",0 {3 V! v9 W" {
- "damuzhi",
8 C$ Q0 P$ ~% D1 } - };
( N5 R* p3 z5 u, A% K; I: L; s - float Output[4];9 ^) r4 \) ]7 N# o$ [* Y
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim), f7 S. @* y8 ?& P* ?) V
- {
, y7 U" t" B3 J8 Q3 r' \. P - uint16_t yuce;
# `9 C, d" Y& k) X% j3 F" l - maxim_max30102_read_fifo(&red,&ir);
" S( M q$ ]. J, g: T! j) E. z2 y - IRD = ir;
& T# L% l4 G% s; S7 y/ x l- _ - i++;
/ P: j# N' Q1 o4 ~1 n* z; T - //printf("%d ",ir);
& r( E% v; q+ Z9 o- a1 s - if(i==128)
( q% s& O* d' G- e! R( ^! H6 M- H, A! m - {
) N! [, G% I; w: @ I ? - 5 }" [1 j" C1 P4 s8 v; P- b
- ; P6 T5 q9 p! w; F2 q) B7 A
- neai_classification(IRD,Output,&yuce);
) b- }5 G& L7 _( t, V
. P6 f# }- F! t- z
4 `* B, }7 N* o; C0 l- printf("\n\n\n");
1 C* X4 m+ X+ F - printf("zhongzhi:%.2f\r\n",Output[0]);9 @3 B$ N0 g8 G" V9 y
- printf("Error:%.2f\r\n",Output[1]);
7 r. c3 ]+ ~" H% ^% w- o - printf("xiaomuzhi:%.2f\r\n",Output[2]);( p5 o7 B1 e1 B- F3 r$ C$ z
- printf("damuzhi:%.2f\r\n",Output[3]);
5 O# U% v8 K9 k) q2 e" F - LeranTime++;
+ c% ?: u l& q% w) g0 f) h - i = 0;6 b3 b2 O/ C' |" o# [0 w% ` z" c
- }6 h7 Z0 I7 F* A# a
- }
复制代码
' E2 k5 i$ o0 u9 L+ @* m+ q( J这里的 预测函数有三个参数,第一个参数是输入数组,第二参数是输出数组,输出数组中包含着对于各个分类的参数预测值,第三个参数输入一个指针,这个指针会指向预测最大值的索引。
9 I% B" V) `& l
7 O* i" @- a8 y/ d1 l
2 g% y; i: ~1 C4 X+ ?, L9 F: T. w* A
/ N, Z7 O, d! e( Y9 |
烧入我们的代码,可以看到,空置的时候,Error的预测值是最大的。# O I" }4 N& v: o' v& v
0 v6 z- Q$ ?, U) P: A
P( @- P- Z4 ]% g6 Z' n2 F. u
6 y2 A) S# t8 r1 k' e$ K当我们放上中指的时候,检测到中指的概率是最大的。1 k! w, v8 f7 m' x; A+ \
0 z* [9 h# z$ _7 l; f
0 I/ D8 z3 F; ~ H( v* f/ @, \( z' J* B& V- o, o$ d
小拇指也是可以正常的检测。1 W: Q* {) o. v: }& s, o, _9 @" i
3 I1 |0 K Z5 y) w1 Q9 U3 S
% u. K |7 z. K* m
6 u$ ^4 K2 K( ~. A, [: I! q转载自:电路小白7 j% o/ x# r( P) T0 r6 w8 i6 p
如有侵权请联系删除
/ {9 C' n+ @( C, {/ Y t7 ]/ T( g7 Y/ j: \. k; l8 o1 G
; O; E2 {9 b V, g2 [9 _$ t
) J/ a1 q1 A1 Z8 e* K1 W
9 a: {/ U4 v/ | |