DenseNet Classifier: Detecting Regions of Interest in Synthetic Signals#

This example demonstrates how to use DeepPeak’s DenseNet classifier to identify regions of interest (ROIs) in synthetic 1D signals containing Gaussian peaks.

We will: - Generate a dataset of noisy signals with random Gaussian peaks - Build and train a DenseNet classifier to detect ROIs - Visualize the training process and model predictions

Note

This example is fully reproducible and suitable for Sphinx-Gallery documentation.

Imports and reproducibility#

import numpy as np

from DeepPeak.machine_learning.classifier import WaveNet, BinaryIoU
from DeepPeak.signals import Kernel, SignalDatasetGenerator

np.random.seed(42)

Generate synthetic dataset#

NUM_PEAKS = 3
SEQUENCE_LENGTH = 200

generator = SignalDatasetGenerator(n_samples=100, sequence_length=SEQUENCE_LENGTH)

dataset = generator.generate(
    signal_type=Kernel.GAUSSIAN,
    n_peaks=(1, NUM_PEAKS),
    amplitude=(1, 20),
    position=(0.1, 0.9),
    width=(0.03, 0.05),
    noise_std=0.1,
    categorical_peak_count=False,
    compute_region_of_interest=True,
)

Visualize a few example signals and their regions of interest#

dataset.plot(number_of_samples=3)
classifier wavenet

Build and summarize the WaveNet classifier#

dense_net = WaveNet(
    sequence_length=SEQUENCE_LENGTH,
    num_filters=64,
    num_dilation_layers=6,
    kernel_size=3,
    optimizer="adam",
    loss="binary_crossentropy",
    metrics=["accuracy", BinaryIoU(threshold=0.5)],
)
dense_net.build()
dense_net.summary()
Model: "WaveNetDetector"
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
┃ Layer (type)        ┃ Output Shape      ┃    Param # ┃ Connected to      ┃
┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
│ input (InputLayer)  │ (None, 200, 1)    │          0 │ -                 │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ input_projection    │ (None, 200, 64)   │        128 │ input[0][0]       │
│ (Conv1D)            │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dilated_conv_0      │ (None, 200, 64)   │     12,352 │ input_projection… │
│ (Conv1D)            │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ res_0 (Conv1D)      │ (None, 200, 64)   │      4,160 │ dilated_conv_0[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ residual_add_0      │ (None, 200, 64)   │          0 │ input_projection… │
│ (Add)               │                   │            │ res_0[0][0]       │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dilated_conv_1      │ (None, 200, 64)   │     12,352 │ residual_add_0[0… │
│ (Conv1D)            │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ res_1 (Conv1D)      │ (None, 200, 64)   │      4,160 │ dilated_conv_1[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ residual_add_1      │ (None, 200, 64)   │          0 │ residual_add_0[0… │
│ (Add)               │                   │            │ res_1[0][0]       │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dilated_conv_2      │ (None, 200, 64)   │     12,352 │ residual_add_1[0… │
│ (Conv1D)            │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ res_2 (Conv1D)      │ (None, 200, 64)   │      4,160 │ dilated_conv_2[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ residual_add_2      │ (None, 200, 64)   │          0 │ residual_add_1[0… │
│ (Add)               │                   │            │ res_2[0][0]       │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dilated_conv_3      │ (None, 200, 64)   │     12,352 │ residual_add_2[0… │
│ (Conv1D)            │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ res_3 (Conv1D)      │ (None, 200, 64)   │      4,160 │ dilated_conv_3[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ residual_add_3      │ (None, 200, 64)   │          0 │ residual_add_2[0… │
│ (Add)               │                   │            │ res_3[0][0]       │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dilated_conv_4      │ (None, 200, 64)   │     12,352 │ residual_add_3[0… │
│ (Conv1D)            │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ res_4 (Conv1D)      │ (None, 200, 64)   │      4,160 │ dilated_conv_4[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ residual_add_4      │ (None, 200, 64)   │          0 │ residual_add_3[0… │
│ (Add)               │                   │            │ res_4[0][0]       │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dilated_conv_5      │ (None, 200, 64)   │     12,352 │ residual_add_4[0… │
│ (Conv1D)            │                   │            │                   │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ res_5 (Conv1D)      │ (None, 200, 64)   │      4,160 │ dilated_conv_5[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ residual_add_5      │ (None, 200, 64)   │          0 │ residual_add_4[0… │
│ (Add)               │                   │            │ res_5[0][0]       │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ skip_0 (Conv1D)     │ (None, 200, 64)   │      4,160 │ residual_add_0[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ skip_1 (Conv1D)     │ (None, 200, 64)   │      4,160 │ residual_add_1[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ skip_2 (Conv1D)     │ (None, 200, 64)   │      4,160 │ residual_add_2[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ skip_3 (Conv1D)     │ (None, 200, 64)   │      4,160 │ residual_add_3[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ skip_4 (Conv1D)     │ (None, 200, 64)   │      4,160 │ residual_add_4[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ skip_5 (Conv1D)     │ (None, 200, 64)   │      4,160 │ residual_add_5[0… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ skip_add (Add)      │ (None, 200, 64)   │          0 │ skip_0[0][0],     │
│                     │                   │            │ skip_1[0][0],     │
│                     │                   │            │ skip_2[0][0],     │
│                     │                   │            │ skip_3[0][0],     │
│                     │                   │            │ skip_4[0][0],     │
│                     │                   │            │ skip_5[0][0]      │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ post_relu (ReLU)    │ (None, 200, 64)   │          0 │ skip_add[0][0]    │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ output (Conv1D)     │ (None, 200, 1)    │         65 │ post_relu[0][0]   │
└─────────────────────┴───────────────────┴────────────┴───────────────────┘
 Total params: 124,225 (485.25 KB)
 Trainable params: 124,225 (485.25 KB)
 Non-trainable params: 0 (0.00 B)

Train the classifier#

history = dense_net.fit(
    dataset.signals,
    dataset.region_of_interest,
    validation_split=0.2,
    epochs=20,
    batch_size=64,
)
Epoch 1/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 4s 4s/step - BinaryIoU: 0.0637 - accuracy: 0.2576 - loss: 2.6198
2/2 ━━━━━━━━━━━━━━━━━━━━ 5s 509ms/step - BinaryIoU: 0.0707 - accuracy: 0.3804 - loss: 2.2031 - val_BinaryIoU: 0.0000e+00 - val_accuracy: 0.9613 - val_loss: 0.5487
Epoch 2/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 102ms/step - BinaryIoU: 0.0000e+00 - accuracy: 0.9472 - loss: 0.7395
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step - BinaryIoU: 0.0000e+00 - accuracy: 0.9496 - loss: 0.7084 - val_BinaryIoU: 0.0000e+00 - val_accuracy: 0.9613 - val_loss: 0.5057
Epoch 3/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 102ms/step - BinaryIoU: 0.0000e+00 - accuracy: 0.9490 - loss: 0.7025
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 86ms/step - BinaryIoU: 0.0000e+00 - accuracy: 0.9496 - loss: 0.6781 - val_BinaryIoU: 0.0000e+00 - val_accuracy: 0.9613 - val_loss: 0.3129
Epoch 4/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 102ms/step - BinaryIoU: 0.0000e+00 - accuracy: 0.9507 - loss: 0.4260
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step - BinaryIoU: 0.0787 - accuracy: 0.9510 - loss: 0.3949 - val_BinaryIoU: 0.2988 - val_accuracy: 0.9290 - val_loss: 0.2618
Epoch 5/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 101ms/step - BinaryIoU: 0.2955 - accuracy: 0.9074 - loss: 0.3475
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 86ms/step - BinaryIoU: 0.2967 - accuracy: 0.9076 - loss: 0.3439 - val_BinaryIoU: 0.3852 - val_accuracy: 0.9625 - val_loss: 0.1375
Epoch 6/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 100ms/step - BinaryIoU: 0.3680 - accuracy: 0.9454 - loss: 0.1807
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 85ms/step - BinaryIoU: 0.3202 - accuracy: 0.9460 - loss: 0.1857 - val_BinaryIoU: 0.0000e+00 - val_accuracy: 0.9613 - val_loss: 0.1559
Epoch 7/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 101ms/step - BinaryIoU: 0.0000e+00 - accuracy: 0.9491 - loss: 0.2195
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 85ms/step - BinaryIoU: 0.0000e+00 - accuracy: 0.9496 - loss: 0.2145 - val_BinaryIoU: 0.3114 - val_accuracy: 0.9712 - val_loss: 0.0827
Epoch 8/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 99ms/step - BinaryIoU: 0.2759 - accuracy: 0.9573 - loss: 0.1092
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step - BinaryIoU: 0.3110 - accuracy: 0.9544 - loss: 0.1143 - val_BinaryIoU: 0.4036 - val_accuracy: 0.9583 - val_loss: 0.1018
Epoch 9/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 101ms/step - BinaryIoU: 0.3727 - accuracy: 0.9411 - loss: 0.1307
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step - BinaryIoU: 0.3692 - accuracy: 0.9424 - loss: 0.1272 - val_BinaryIoU: 0.0194 - val_accuracy: 0.9620 - val_loss: 0.0861
Epoch 10/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 100ms/step - BinaryIoU: 0.0154 - accuracy: 0.9500 - loss: 0.1122
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 85ms/step - BinaryIoU: 0.0123 - accuracy: 0.9497 - loss: 0.1166 - val_BinaryIoU: 0.0323 - val_accuracy: 0.9625 - val_loss: 0.0886
Epoch 11/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 101ms/step - BinaryIoU: 0.0125 - accuracy: 0.9506 - loss: 0.1135
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 86ms/step - BinaryIoU: 0.0927 - accuracy: 0.9517 - loss: 0.1112 - val_BinaryIoU: 0.4093 - val_accuracy: 0.9683 - val_loss: 0.0854
Epoch 12/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 102ms/step - BinaryIoU: 0.4290 - accuracy: 0.9573 - loss: 0.1014
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 86ms/step - BinaryIoU: 0.4180 - accuracy: 0.9556 - loss: 0.1048 - val_BinaryIoU: 0.4018 - val_accuracy: 0.9673 - val_loss: 0.0862
Epoch 13/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 100ms/step - BinaryIoU: 0.4335 - accuracy: 0.9567 - loss: 0.1028
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 85ms/step - BinaryIoU: 0.4117 - accuracy: 0.9567 - loss: 0.1030 - val_BinaryIoU: 0.1928 - val_accuracy: 0.9665 - val_loss: 0.0822
Epoch 14/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 102ms/step - BinaryIoU: 0.1924 - accuracy: 0.9554 - loss: 0.0966
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 86ms/step - BinaryIoU: 0.2011 - accuracy: 0.9561 - loss: 0.0980 - val_BinaryIoU: 0.2229 - val_accuracy: 0.9677 - val_loss: 0.0767
Epoch 15/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 102ms/step - BinaryIoU: 0.2332 - accuracy: 0.9563 - loss: 0.0922
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step - BinaryIoU: 0.2689 - accuracy: 0.9584 - loss: 0.0899 - val_BinaryIoU: 0.4279 - val_accuracy: 0.9712 - val_loss: 0.0738
Epoch 16/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 100ms/step - BinaryIoU: 0.4325 - accuracy: 0.9596 - loss: 0.0901
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 86ms/step - BinaryIoU: 0.4331 - accuracy: 0.9600 - loss: 0.0902 - val_BinaryIoU: 0.4301 - val_accuracy: 0.9735 - val_loss: 0.0674
Epoch 17/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 102ms/step - BinaryIoU: 0.4203 - accuracy: 0.9616 - loss: 0.0858
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step - BinaryIoU: 0.4069 - accuracy: 0.9622 - loss: 0.0846 - val_BinaryIoU: 0.2609 - val_accuracy: 0.9703 - val_loss: 0.0635
Epoch 18/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 99ms/step - BinaryIoU: 0.2849 - accuracy: 0.9600 - loss: 0.0849
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step - BinaryIoU: 0.2808 - accuracy: 0.9609 - loss: 0.0840 - val_BinaryIoU: 0.4152 - val_accuracy: 0.9750 - val_loss: 0.0592
Epoch 19/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 101ms/step - BinaryIoU: 0.3758 - accuracy: 0.9637 - loss: 0.0812
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 86ms/step - BinaryIoU: 0.3868 - accuracy: 0.9641 - loss: 0.0804 - val_BinaryIoU: 0.5269 - val_accuracy: 0.9780 - val_loss: 0.0593
Epoch 20/20

1/2 ━━━━━━━━━━━━━━━━━━━━ 0s 101ms/step - BinaryIoU: 0.4596 - accuracy: 0.9639 - loss: 0.0826
2/2 ━━━━━━━━━━━━━━━━━━━━ 0s 86ms/step - BinaryIoU: 0.4753 - accuracy: 0.9655 - loss: 0.0806 - val_BinaryIoU: 0.4972 - val_accuracy: 0.9775 - val_loss: 0.0575

Plot training history#

dense_net.plot_model_history()
BinaryIoU, accuracy, loss, val_BinaryIoU, val_accuracy, val_loss

Predict and visualize on a test signal#

dense_net.plot_prediction(signal=dataset.signals[0:1, :], threshold=0.4)
Predicted Region of Interest
<Figure size 1200x500 with 1 Axes>

Total running time of the script: (0 minutes 10.587 seconds)

Gallery generated by Sphinx-Gallery