Diff of /README.md [000000] .. [22f4a9]

Switch to unified view

a b/README.md
1
# Deep Learning for ECG Analysis: Benchmarks and Insights from PTB-XL
2
This repository is accompanying our article [Deep Learning for ECG Analysis: Benchmarks
3
and Insights from PTB-XL](https://doi.org/10.1109/jbhi.2020.3022989), which builds on the [PTB-XL dataset](https://www.nature.com/articles/s41597-020-0495-6). 
4
It allows to reproduce the ECG benchmarking experiments described in the paper and to benchmark
5
user-provided models within our framework. We also maintain a leaderboard for the described PTB-XL dataset
6
on this page, so feel free to submit your results as PRs.
7
8
Please acknowledge our work by citing the corresponding articles listed in **References** below.
9
10
11
## Setup
12
13
### Install dependencies
14
Install the dependencies (wfdb, pytorch, torchvision, cudatoolkit, fastai, fastprogress) by creating a conda environment:
15
16
    conda env create -f ecg_env.yml
17
    conda activate ecg_env
18
19
### Get data
20
Download and prepare the datasets (PTB-XL and ICBEB) via the follwing bash-script:
21
22
    ./get_datasets.sh
23
24
This script first downloads [PTB-XL from PhysioNet](https://physionet.org/content/ptb-xl/) and stores it in `data/ptbxl/`. 
25
Afterwards all training data from the [ICBEB challenge 2018](http://2018.icbeb.org/Challenge.html) is downloaded and temporally stored in `tmp_data/`. 
26
After downloading and unzipping `code/utils/convert_ICBEB.py` is called which stores the data in appropriate format in `data/ICBEB/`. 
27
28
## Reproduce results from the paper
29
30
Change directory: `cd code` and then call
31
32
    python reproduce_results.py
33
34
This will perform all experiments for all models used in the paper. 
35
Depending on the executing environment, this will take up to several hours. 
36
Once finished, all trained models, predictions and results are stored in `output/`, 
37
where for each experiment a sub-folder is created each with `data/`, `models/` and `results/` sub-sub-folders. 
38
39
### Download models and results
40
41
We also provide a [compressed zip-archive](https://datacloud.hhi.fraunhofer.de/s/gLkjQL94d7FXBbS) containing the `output` folder corresponding to our runs including trained models and predictions from our runs mentioned in the leaderboard below. 
42
43
## Benchmarking user-provided models
44
For creating custom benchmarking results our recommendation is as follows:
45
46
1. create your model `code/models/your_model.py` which implements a standard classifier interface with `fit(X_train, y_train, X_val, y_val)` and `predict(X)`
47
2. create a config file `code/configs/your_configs.py` with name, type and parameters (if needed)
48
3. add your modeltype and model import to the cases in `perform`-function of `code/experiments/scp_experiment.py` (already added for demonstration purpose!)
49
4. add your model-config to `models` and perform your experiment as below (adjusted code of `code/reproduce_results.py`):
50
51
```python
52
from experiments.scp_experiment import SCP_Experiment
53
from configs.your_custom_configs import your_custom_config
54
55
datafolder = '../data/ptbxl/'
56
outputfolder = '../output/'
57
58
models = [your_custom_config]
59
60
e = SCP_Experiment('your_custom_experiment', 'diagnostic', datafolder, outputfolder, models)
61
e.prepare()
62
e.perform()
63
e.evaluate()
64
```
65
66
### Notes on e.evaluate()
67
Altough we recommend to use our framework, custom evaluation of custom models is still possible via calling `code.utils.utils.evaluate_experiment(y_true, y_pred, thresholds)` 
68
manually with classwise thresholds. 
69
70
For `e.evaluate()`: If the name of the experiment is `exp_ICBEB` classifier thresholds are needed. 
71
In any other case `evaluate_experiment(y_true, y_pred)` will return a dictionary with `macro_auc` and `Fmax` (both metrics are **without any explicitly needed thresholds**). 
72
In case of `exp_ICBEB` we offer two functions for computing thresholds (located in `code/utils/utils.py`):
73
74
1. `thresholds = utils.find_optimal_cutoff_thresholds(y_train, y_train_pred)`
75
2. `thresholds = utils.find_optimal_cutoff_thresholds_for_Gbeta(y_train, y_train_pred)`
76
77
In addition to `macro_auc` and `Fmax` `evaluate_experiment(y_true, y_pred, thresholds)` will return `F_beta_macro` and `G_beta_macro` as proposed in the physionet-challenge.
78
79
### Notes on bootstrapping
80
Since bootstrapping results might take a while (even in parallel as in our code), we offer a flag for evaluation `e.evaluate(bootstrap_eval=False)` which just performs one single whole sample evaluation. 
81
82
**If you want to bootstrap your results:** In each respective experiment-folder `output/exp_*/` the bootstrapping ids for training, 
83
testing and validation is stored as numpy-arrays containing lists of ids. Otherwise create manually with `utils.get_appropriate_bootstrap_samples(y_train, n_bootstraping_samples)`. For sequential evaluation of those ids, the code might look like:
84
85
```python
86
if experiment_name == 'exp_ICBEB':
87
    thresholds = utils.find_optimal_cutoff_thresholds(y_train, y_train_pred)
88
else:
89
    thresholds = None
90
91
train_bootstrap_samples = np.array(utils.get_appropriate_bootstrap_samples(y_train, n_bootstraping_samples))
92
tr_df = pd.concat([utils.evaluate_experiment(y_train[ids], y_train_pred[ids], thresholds) for ids in train_bootstrap_samples])
93
94
tr_df.quantile(0.05), tr_df.mean(), tr_df.quantile(0.95)
95
```
96
97
### Notes on Finetuning
98
In [this jupyter notebook](https://github.com/helme/ecg_ptbxl_benchmarking/blob/master/code/Finetuning-Example.ipynb) we provide a basic example of how to finetune our provided models on your custom dataset.
99
100
101
102
## Leaderboard
103
104
We encourage other authors to share their results on this dataset by submitting a PR. The evaluation proceeds as described in the manuscripts: 
105
The reported scores are test set scores (fold 10) as output of the above evaluation procedure and should **not be used for hyperparameter tuning or model selection**. In the provided code, we use folds 1-8 for training, fold 9 as validation set and fold 10 as test set. We encourage to submit also the prediction results (`preds`, `targs`, `classes` saved as numpy arrays `preds_x.npy` and `targs_x.npy` and `classes_x.npy`) to ensure full reproducibility and to make source code and/or pretrained models available.
106
107
 ### 1. PTB-XL: all statements 
108
 
109
| Model | AUC ↓ | paper/source | code | 
110
|---:|:---|:---|:---| 
111
| inception1d | 0.925(08) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
112
| xresnet1d101 | 0.925(07) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
113
| resnet1d_wang | 0.919(08) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
114
| fcn_wang | 0.918(08) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
115
| lstm_bidir | 0.914(08) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
116
| lstm | 0.907(08) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
117
| Wavelet+NN | 0.849(13) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
118
119
 ### 2. PTB-XL: diagnostic statements 
120
 
121
| Model | AUC ↓ | paper/source | code | 
122
|---:|:---|:---|:---| 
123
| xresnet1d101 | 0.937(08) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
124
| resnet1d_wang | 0.936(08) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
125
| lstm_bidir | 0.932(07) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
126
| inception1d | 0.931(09) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
127
| lstm | 0.927(08) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
128
| fcn_wang | 0.926(10) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
129
| Wavelet+NN | 0.855(15) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
130
131
 ### 3. PTB-XL: Diagnostic subclasses 
132
 
133
| Model | AUC ↓ | paper/source | code | 
134
|---:|:---|:---|:---| 
135
| inception1d | 0.930(10) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
136
| xresnet1d101 | 0.929(14) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
137
| lstm | 0.928(10) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
138
| resnet1d_wang | 0.928(10) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
139
| fcn_wang | 0.927(11) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
140
| lstm_bidir | 0.923(12) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
141
| Wavelet+NN | 0.859(16) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
142
143
 ### 4. PTB-XL: Diagnostic superclasses 
144
 
145
| Model | AUC ↓ | paper/source | code | 
146
|---:|:---|:---|:---| 
147
| resnet1d_wang | 0.930(05) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
148
| xresnet1d101 | 0.928(05) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
149
| lstm | 0.927(05) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
150
| fcn_wang | 0.925(06) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
151
| inception1d | 0.921(06) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
152
| lstm_bidir | 0.921(06) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
153
| Wavelet+NN | 0.874(07) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
154
155
 ### 5. PTB-XL: Form statements 
156
 
157
| Model | AUC ↓ | paper/source | code | 
158
|---:|:---|:---|:---| 
159
| inception1d | 0.899(22) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
160
| xresnet1d101 | 0.896(12) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
161
| resnet1d_wang | 0.880(15) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
162
| lstm_bidir | 0.876(15) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
163
| fcn_wang | 0.869(12) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
164
| lstm | 0.851(15) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
165
| Wavelet+NN | 0.757(29) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
166
167
 ### 6. PTB-XL: Rhythm statements 
168
 
169
| Model | AUC ↓ | paper/source | code | 
170
|---:|:---|:---|:---| 
171
| xresnet1d101 | 0.957(19) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
172
| inception1d | 0.953(13) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
173
| lstm | 0.953(09) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
174
| lstm_bidir | 0.949(11) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
175
| resnet1d_wang | 0.946(10) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
176
| fcn_wang | 0.931(08) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
177
| Wavelet+NN | 0.890(24) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
178
179
180
### 7. ICBEB: All statements
181
182
| Model | AUC ↓ |  F_beta=2 | G_beta=2 | paper/source | code | 
183
|---:|:---|:---|:---|:---|:---| 
184
| xresnet1d101 | 0.974(05) | 0.819(30) | 0.602(37) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
185
| resnet1d_wang | 0.969(06) | 0.803(31) | 0.586(37) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
186
| lstm | 0.964(06) | 0.790(31) | 0.561(37) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
187
| inception1d | 0.963(09) | 0.807(30) | 0.594(41) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
188
| lstm_bidir | 0.959(11) | 0.796(31) | 0.573(36) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
189
| fcn_wang | 0.957(08) | 0.787(31) | 0.563(37) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
190
| Wavelet+NN | 0.905(14) | 0.665(34) | 0.405(36) | [our work](https://doi.org/10.1109/jbhi.2020.3022989) | [this repo](https://github.com/helme/ecg_ptbxl_benchmarking/)| 
191
192
# References
193
Please acknowledge our work by citing our journal paper
194
195
    @article{Strodthoff:2020Deep,
196
    doi = {10.1109/jbhi.2020.3022989},
197
    url = {https://doi.org/10.1109/jbhi.2020.3022989},
198
    year = {2021},
199
    volume={25},
200
    number={5},
201
    pages={1519-1528},
202
    publisher = {Institute of Electrical and Electronics Engineers ({IEEE})},
203
    author = {Nils Strodthoff and Patrick Wagner and Tobias Schaeffter and Wojciech Samek},
204
    title = {Deep Learning for {ECG} Analysis: Benchmarks and Insights from {PTB}-{XL}},
205
    journal = {{IEEE} Journal of Biomedical and Health Informatics}
206
    }
207
    
208
For the PTB-XL dataset, please cite
209
210
    @article{Wagner:2020PTBXL,
211
    doi = {10.1038/s41597-020-0495-6},
212
    url = {https://doi.org/10.1038/s41597-020-0495-6},
213
    year = {2020},
214
    publisher = {Springer Science and Business Media {LLC}},
215
    volume = {7},
216
    number = {1},
217
    pages = {154},
218
    author = {Patrick Wagner and Nils Strodthoff and Ralf-Dieter Bousseljot and Dieter Kreiseler and Fatima I. Lunze and Wojciech Samek and Tobias Schaeffter},
219
    title = {{PTB}-{XL},  a large publicly available electrocardiography dataset},
220
    journal = {Scientific Data}
221
    }
222
223
    @misc{Wagner2020:ptbxlphysionet,
224
    title={{PTB-XL, a large publicly available electrocardiography dataset}},
225
    author={Patrick Wagner and Nils Strodthoff and Ralf-Dieter Bousseljot and Wojciech Samek and Tobias Schaeffter},
226
    doi={10.13026/qgmg-0d46},
227
    year={2020},
228
    journal={PhysioNet}
229
    }
230
231
    @article{Goldberger2020:physionet,
232
    author = {Ary L. Goldberger  and Luis A. N. Amaral  and Leon Glass  and Jeffrey M. Hausdorff  and Plamen Ch. Ivanov  and Roger G. Mark  and Joseph E. Mietus  and George B. Moody  and Chung-Kang Peng  and H. Eugene Stanley },
233
    title = {{PhysioBank, PhysioToolkit, and PhysioNet}},
234
    journal = {Circulation},
235
    volume = {101},
236
    number = {23},
237
    pages = {e215-e220},
238
    year = {2000},
239
    doi = {10.1161/01.CIR.101.23.e215}
240
    }
241
    
242
If you use the [ICBEB challenge 2018 dataset](http://2018.icbeb.org/Challenge.html) please acknowledge
243
244
    @article{liu2018:icbeb,
245
    doi = {10.1166/jmihi.2018.2442},
246
    year = {2018},
247
    month = sep,
248
    publisher = {American Scientific Publishers},
249
    volume = {8},
250
    number = {7},
251
    pages = {1368--1373},
252
    author = {Feifei Liu and Chengyu Liu and Lina Zhao and Xiangyu Zhang and Xiaoling Wu and Xiaoyan Xu and Yulin Liu and Caiyun Ma and Shoushui Wei and Zhiqiang He and Jianqing Li and Eddie Ng Yin Kwee},
253
    title = {{An Open Access Database for Evaluating the Algorithms of Electrocardiogram Rhythm and Morphology Abnormality Detection}},
254
    journal = {Journal of Medical Imaging and Health Informatics}
255
    }