心电信号时间序列异常检测(Python)

191 篇文章 1 订阅
152 篇文章 5 订阅
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


from tensorflow.keras import layers, losses
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Model


import warnings
warnings.filterwarnings('ignore')
df = pd.read_csv('http://storage.googleapis.com/download.tensorflow.org/data/ecg.csv', header=None)
df.head()

Note: The dataset has 140 columns which represents the ECG readings and a labels column which has been encoded to 0 or 1 showing whether the ECG is abnormal or normal.

#separate the data and labels so that it will be easy for understanding
data = df.iloc[:,:-1].values
labels = df.iloc[:,-1].values
labels
array([1., 1., 1., ..., 0., 0., 0.])
train_data, test_data, train_labels, test_labels = train_test_split(data, labels, test_size = 0.2, random_state = 21)

Normalizing the data to the range [0-1]

#Now lets Normalize the data
#First we will calculate the maximum and minimum value from the training set 
min = tf.reduce_min(train_data)
max = tf.reduce_max(train_data)


#Now we will use the formula (data - min)/(max - min)
train_data = (train_data - min)/(max - min)
test_data = (test_data - min)/(max - min)


#I have converted the data into float
train_data = tf.cast(train_data, dtype=tf.float32)
test_data = tf.cast(test_data, dtype=tf.float32)
#The labels are either 0 or 1, so I will convert them into boolean(true or false) 
train_labels = train_labels.astype(bool)
test_labels = test_labels.astype(bool)


#Now let's separate the data for normal ECG from that of abnormal ones
#Normal ECG data
n_train_data = train_data[train_labels]
n_test_data = test_data[test_labels]


#Abnormal ECG data
an_train_data = train_data[~train_labels]
an_test_data = test_data[~test_labels]


print(n_train_data)
tf.Tensor(
[[0.57030463 0.46561658 0.29058117 ... 0.48504233 0.4233502  0.47598344]
 [0.48320588 0.28246963 0.16471253 ... 0.567567   0.4677294  0.2692329 ]
 [0.48144642 0.35151404 0.25972766 ... 0.5479421  0.5077544  0.54298663]
 ...
 [0.41039047 0.24164985 0.13120876 ... 0.5277313  0.5654091  0.5023885 ]
 [0.5397748  0.4140786  0.28101394 ... 0.51266515 0.43706053 0.4426865 ]
 [0.29639772 0.15988176 0.18883787 ... 0.53766966 0.545786   0.40826708]], shape=(2359, 140), dtype=float32)
#Lets plot a normal ECG
plt.plot(np.arange(140), n_train_data[0])
plt.grid()
plt.title('Normal ECG')
plt.show()

#Lets plot one from abnormal ECG
plt.plot(np.arange(140), an_train_data[0])
plt.grid()
plt.title('Abnormal ECG')
plt.show()

Autoencoders

#Now let's define the model!
#Here I have used the Model Subclassing API (but we can also use the Sequential API)
#The model has 2 parts : 1. Encoder and 2. Decoder
 
class detector(Model):
  def __init__(self):
    super(detector, self).__init__()
    self.encoder = tf.keras.Sequential([
                                        layers.Dense(32, activation='relu'),
                                        layers.Dense(16, activation='relu'),
                                        layers.Dense(8, activation='relu')
    ])
    self.decoder = tf.keras.Sequential([
                                        layers.Dense(16, activation='relu'),
                                        layers.Dense(32, activation='relu'),
                                        layers.Dense(140, activation='sigmoid')
    ])


  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded
#Let's compile and train the model!!
autoencoder = detector()
autoencoder.compile(optimizer='adam', loss='mae')
autoencoder.fit(n_train_data, n_train_data, epochs = 20, batch_size=512, validation_data=(n_test_data, n_test_data))
#Now let's define a function in order to plot the original ECG and reconstructed ones and also show the error
def plot(data, n):
  enc_img = autoencoder.encoder(data)
  dec_img = autoencoder.decoder(enc_img)
  plt.plot(data[n], 'b')
  plt.plot(dec_img[n], 'r')
  plt.fill_between(np.arange(140), data[n], dec_img[n], color = 'lightcoral')
  plt.legend(labels=['Input', 'Reconstruction', 'Error'])
  plt.show()


plot(n_test_data, 0)
plot(an_test_data, 0)

reconstructed = autoencoder(n_train_data)
train_loss = losses.mae(reconstructed, n_train_data)
t = np.mean(train_loss) + np.std(train_loss)


def prediction(model, data, threshold):
  rec = model(data)
  loss = losses.mae(rec, data)
  return tf.math.less(loss, threshold)
print(t)
0.030792654
pred = prediction(autoencoder, n_test_data, t)
#Lets see some more result visually !!
plot(n_test_data, 0)
plot(n_test_data, 1)
plot(n_test_data, 3)

Accuracy

threshold = np.mean(train_loss) + 2*np.std(train_loss)
preds = tf.math.less(train_loss, threshold)
tf.math.count_nonzero(preds)
<tf.Tensor: shape=(), dtype=int64, numpy=2232>
preds.shape
TensorShape([2359])
acc = 2240/2359*100
print("Accuracy = ", acc, "%")
Accuracy =  94.95548961424333 %
知乎学术咨询:https://www.zhihu.com/consult/people/792359672131756032?isMe=1

担任《Mechanical System and Signal Processing》等审稿专家,擅长领域:信号滤波/降噪,机器学习/深度学习,时间序列预分析/预测,设备故障诊断/缺陷检测/异常检测。

分割线

EMG信号降噪方法(MATLAB)

包括概率自适应模板减法PATS,经验模态分解方法EMD,二阶扩展卡尔曼平滑方法EKS2,平稳小波变换方法SWT,自适应模板减法+高通滤波方法,高通滤波方法,自适应模板减法,模板减法

完整代码可通过知乎学术咨询获得:

https://www.zhihu.com/consult/people/792359672131756032?isMe=1

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个使用PyTorch实现基于Transformer进行一维心电信号时间序列分类的代码示例: ```python import torch import torch.nn as nn import torch.optim as optim import numpy as np # 定义Transformer模型 class TransformerModel(nn.Module): def __init__(self, input_size, hidden_size, num_layers, num_heads, dropout): super(TransformerModel, self).__init__() self.pos_encoder = PositionalEncoding(hidden_size, dropout) self.transformer_encoder = nn.TransformerEncoder(nn.TransformerEncoderLayer(hidden_size, num_heads, hidden_size, dropout), num_layers) self.fc = nn.Linear(hidden_size, output_size) def forward(self, src): src = self.pos_encoder(src) output = self.transformer_encoder(src) output = output.mean(dim=1) # 对序列维度求平均 output = self.fc(output) return output # 定义位置编码层 class PositionalEncoding(nn.Module): def __init__(self, d_model, dropout=0.1, max_len=5000): super(PositionalEncoding, self).__init__() self.dropout = nn.Dropout(p=dropout) pe = torch.zeros(max_len, d_model) position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) pe = pe.unsqueeze(0).transpose(0, 1) self.register_buffer('pe', pe) def forward(self, x): x = x + self.pe[:x.size(0), :] return self.dropout(x) # 加载数据 data = np.load('data.npy') # 数据格式为 (num_samples, seq_len, input_size) labels = np.load('labels.npy') # 标签格式为 (num_samples,) # 划分训练集和测试集 train_data = data[:800] train_labels = labels[:800] test_data = data[800:] test_labels = labels[800:] # 转换为PyTorch的Tensor格式 train_data = torch.from_numpy(train_data).float() train_labels = torch.from_numpy(train_labels).long() test_data = torch.from_numpy(test_data).float() test_labels = torch.from_numpy(test_labels).long() # 定义模型参数 input_size = 1 # 输入特征维度 output_size = 5 # 输出类别数 hidden_size = 64 # 模型隐藏层维度 num_layers = 4 # 模型层数 num_heads = 8 # 注意力头数 dropout = 0.1 # Dropout概率 # 定义模型、损失函数和优化器 model = TransformerModel(input_size, hidden_size, num_layers, num_heads, dropout) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 训练模型 num_epochs = 10 batch_size = 32 for epoch in range(num_epochs): for i in range(0, len(train_data), batch_size): batch_data = train_data[i:i+batch_size] batch_labels = train_labels[i:i+batch_size] optimizer.zero_grad() outputs = model(batch_data) loss = criterion(outputs, batch_labels) loss.backward() optimizer.step() print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item())) # 测试模型 with torch.no_grad(): correct = 0 total = 0 for i in range(0, len(test_data), batch_size): batch_data = test_data[i:i+batch_size] batch_labels = test_labels[i:i+batch_size] outputs = model(batch_data) _, predicted = torch.max(outputs.data, 1) total += batch_labels.size(0) correct += (predicted == batch_labels).sum().item() print('Test Accuracy: {:.2f}%'.format(100 * correct / total)) ``` 以上代码中,使用了PyTorch实现了一个基于Transformer的模型,并使用交叉熵损失函数和Adam优化器进行训练。在训练过程中,使用了批量梯度下降的方法进行优化,同时使用了测试集对模型进行测试和评估。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哥廷根数学学派

码字不易,且行且珍惜

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值