Detecting normal EKG pulses » Histórico » Versión 1
Federico Vera, 2018-06-10 00:42
1 | 1 | Federico Vera | # Application Example |
---|---|---|---|
2 | |||
3 | ## Detecting normal EKG pulses. |
||
4 | |||
5 | I will not enter into too much detail in this text in an attempt to _trick_ the |
||
6 | reader (you) into doing some research. But the basic idea is to train an MLP and |
||
7 | then use the results to try and deduce if a Pulse is normal or not (the same |
||
8 | approach can be used to detect specific pathologies). |
||
9 | |||
10 | This is **not** the usual approach which usually includes extracting features |
||
11 | like the a<sub>k</sub>s of the Fourier Transform, eigenvalues, and such. The |
||
12 | approach that will be described in this example is much simpler (albeit it has |
||
13 | a less accurate result... _or does it?_) |
||
14 | |||
15 | ## About the EKG |
||
16 | EKGs or ECGs (whichever you like) is basically a set of five (three, five or |
||
17 | six) different signals or _derivations_. Most of the bibliographic |
||
18 | information and cardiological knowledge is in the time domain, and |
||
19 | unfortunately most of the features usually extracted for NN training are |
||
20 | frequency based, which brings us to a little problem, no cardiologist wants to |
||
21 | apply something that he/she can't understand. |
||
22 | |||
23 | We can of course analyze an ECG in the time domain, and with a little tinkering |
||
24 | the results are actually quite encouraging. |
||
25 | |||
26 | ## Preprocessing |
||
27 | As you might know before throwing a signal at a NN and expecting great results |
||
28 | is usually coherent to to some filtering and transforming I'll keep the |
||
29 | filtering to a minimum, and mostly done in order to have nice function plots. |
||
30 | |||
31 | Let's start by getting a copy of [`mrft`] |
||
32 | and some EKG Data (for convenience there are some samples included in `mrft`), |
||
33 | in case you don't like them, you are free to search some, manufacture one, or |
||
34 | even use a synthesizer like [`Java ECG Generator`](http://www.mit.edu/~gari/CODE/ECGSYN/JAVA/APPLET2/ecgsyn/ecg-java/source.html). |
||
35 | |||
36 | ## Training |
||
37 | Open `mrft` select the menu `Examples`->`EKG (Synth)` this will populate the |
||
38 | tables the following way: |
||
39 | |||
40 | [[https://raw.githubusercontent.com/wiki/dktcoding/mrft/imgs/ekg/data.png|alt=Data]] |
||
41 | |||
42 | Go ahead and press `F5` (a training session should start and with some luck |
||
43 | converge to an _"acceptable"_ fit). |
||
44 | |||
45 | [[https://raw.githubusercontent.com/wiki/dktcoding/mrft/imgs/ekg/firstplot.png|alt=FirstPlot]] |
||
46 | |||
47 | There's something odd with the way this MLP is trained... do you see it? No? |
||
48 | |||
49 | (_Tip:_ in the lower plot both the training and validation errors stay very |
||
50 | close together! they should be diverging, or at the very least separate, remember over-fitting?) |
||
51 | This usually happens with synthetic data, since adjustment is **too perfect** |
||
52 | the training and validation datasets are basically one in the same. |
||
53 | |||
54 | ## Adding some noise |
||
55 | Noise is a bad thing that should be removed, why do we want to add it? well |
||
56 | the fact is that NN tend to work better with noisy data (not so noisy mind |
||
57 | you). |
||
58 | |||
59 | There are several ways to add noise, but for this we'll use a transformation, |
||
60 | so go to `Dataset -> Transform... -> Custom Function (All)`, something like |
||
61 | this should appear: |
||
62 | |||
63 | [[https://raw.githubusercontent.com/wiki/dktcoding/mrft/imgs/ekg/custransf.png|alt=FirstPlot]] |
||
64 | |||
65 | We'll leave the `x` value as it is, but in the `fx` text field write: |
||
66 | `gaussian2(fx, 0.1)` then click on apply, your data now must look |
||
67 | something like this: |
||
68 | |||
69 | [[https://raw.githubusercontent.com/wiki/dktcoding/mrft/imgs/ekg/secondplot.png|alt=SecondPlot]] |
||
70 | |||
71 | Try pressing `F5` now so it re trains... |
||
72 | |||
73 | Yes, I lied (not entirely) gaussian noise didn't change the validation error, |
||
74 | but I'll let you figure out why on your own (one clue: `Box–Muller`, the |
||
75 | rest is _simple_ math). For a bit more information about this see |
||
76 | `Adding noise` in [[Data manipulation]] |
||
77 | |||
78 | ## Selecting the right weights |
||
79 | As the NN trains itself the synaptic weights of the training epochs are saved |
||
80 | (not all of them), so now we must decide which of all the weights to use, |
||
81 | click on the error table (`Error Plots` panel), and when you start selecting |
||
82 | rows, you should see two things, one is that the red plot of the function plot |
||
83 | changes, and the second one is that a line (or guide) appears in the error |
||
84 | plot this indicates in the graph the moment of that particular weight. |
||
85 | |||
86 | [[https://raw.githubusercontent.com/wiki/dktcoding/mrft/imgs/ekg/guide.png|alt=Guide]] |
||
87 | |||
88 | Once you are satisfied with the results (i.e. choose the "best" weights |
||
89 | <sup id="a1">[1](#f1)</sup>) |
||
90 | |||
91 | ## Now what? |
||
92 | I don't actually have time to finish it today, but the gist is: we will use |
||
93 | that synaptic weight to predict values of an unknown EKG, and estimate how |
||
94 | similar is it with the training value (mse), with that, we'll choose the one |
||
95 | with the lowest mse (mean square error) is the one that we'll accept as |
||
96 | correct. |
||
97 | @TODO complete example |
||
98 | |||
99 | <b id="f1"><sup>1</sup></b> There are several criteria for choosing the "best" |
||
100 | as a rule of thumb pick the closest to the left with the lowest error, or the |
||
101 | point where the validation an training errors intersect. [↩](#a1) |