|
|
|
|
|
|
|
|
import numpy as np |
|
|
import pandas as pd |
|
|
|
|
|
def generate_series(length=20000, num_channels=6, anomaly_rate=0.005, rng=None): |
|
|
if rng is None: |
|
|
rng = np.random.default_rng(0) |
|
|
t = np.arange(length) |
|
|
data = [] |
|
|
labels = np.zeros(length, dtype=int) |
|
|
for c in range(num_channels): |
|
|
freq = rng.uniform(0.01, 0.1) |
|
|
phase = rng.uniform(0, 2 * np.pi) |
|
|
amp = rng.uniform(0.5, 2.0) |
|
|
signal = amp * np.sin(2 * np.pi * freq * t + phase) |
|
|
noise = rng.normal(0, 0.2, size=length) |
|
|
data.append(signal + noise) |
|
|
data = np.stack(data, axis=1) |
|
|
num_anom = int(length * anomaly_rate) |
|
|
for _ in range(num_anom): |
|
|
center = rng.integers(50, length - 50) |
|
|
width = rng.integers(5, 25) |
|
|
channels = rng.choice(num_channels, size=max(1, num_channels//2), replace=False) |
|
|
for ch in channels: |
|
|
amplitude = rng.uniform(3, 6) |
|
|
window = np.arange(center - width//2, center + width//2) |
|
|
window = window[(window >= 0) & (window < length)] |
|
|
data[window, ch] += amplitude * np.exp(-((window - center) ** 2) / (2 * (width/2)**2)) |
|
|
labels[max(center - width//2,0): min(center + width//2, length)] = 1 |
|
|
return data, labels |
|
|
|