Другое

Регулярные выражения для сопоставления шаблонов в массивах NumPy и PyTorch

Изучите нативные методы для сопоставления шаблонов, подобных регулярным выражениям, в массивах NumPy и PyTorch без преобразования в строки. Узнайте эффективные методы обнаружения числовых последовательностей с практическими примерами и советами по оптимизации производительности.

Как реализовать сопоставление шаблонов, похожее на регулярные выражения, для числовых последовательностей в массивах numpy или torch?

Существуют ли встроенные методы в чистом numpy или PyTorch для поиска конкретных последовательностей числовых значений, соответствующих определенным логическим шаблонам, аналогично регулярным выражениям, внутри массивов или строк матриц?

Я знаю, что могу преобразовать массив в строки и использовать традиционные регулярные выражения, но я ищу прямой подход, который работает с числовыми данными без преобразования. Какие существуют эффективные методы для сопоставления шаблонов в массивах numpy или тензорах PyTorch?

Сопоставление с образцом числовых последовательностей в стиле регулярных выражений в массивах NumPy и PyTorch

Сопоставление с образцом числовых последовательностей в стиле регулярных выражений в массивах NumPy и PyTorch можно реализовать с помощью нескольких встроенных подходов, которые не требуют преобразования числовых данных в строки. Хотя традиционные регулярные выражения работают с текстом, обе библиотеки предоставляют специализированные функции для сопоставления с образцом в числовых массивах.

Содержание

Подходы к сопоставлению с образцом в NumPy

Использование векторизованных функций регулярных выражений

В NumPy нет встроенных функций регулярных выражений для числовых массивов, но можно векторизовать модуль регулярных выражений Python для сопоставления с образцом числовых последовательностей при их преобразовании в строки. Однако это все равно включает преобразование в строки:

python
import numpy as np
import re

# Создание числового массива
data = np.array([101, 124, 979, 430, 1073, 146, 111, 650])
pattern = re.compile(r'1[0-9]{2}')  # Сопоставление чисел, начинающихся с 1, за которыми следуют 2 цифры

# Векторизованный подход с преобразованием в строки
vmatch = np.vectorize(lambda x: bool(pattern.match(str(x))))
matches = vmatch(data)

Использование fromregex NumPy для данных из файлов

Для числовых шаблонов, хранящихся в файлах, NumPy предоставляет функцию fromregex, которая может извлекать шаблоны непосредственно из текстовых файлов:

python
import numpy as np
from io import StringIO

# Текстовые данные с числовыми последовательностями
text = StringIO("101 124 979 430\n146 111 650 983")
pattern = r'(\d+)\s+(\d+)'  # Сопоставление двух цифр, за которыми следует пробел и еще цифры

# Создание структурированного массива из совпадений регулярных выражений
result = np.fromregex(text, pattern, [('first', 'i4'), ('second', 'i4')])

Использование математических операций для обнаружения шаблонов

Для чисто числового сопоставления с образцом без преобразования в строки можно использовать математические операции:

python
import numpy as np

# Поиск последовательностей, где значения увеличиваются на 10
def find_increasing_sequence(arr, step=10):
    diffs = np.diff(arr)
    return np.where(diffs == step)[0]

data = np.array([5, 15, 25, 30, 40, 50])
indices = find_increasing_sequence(data, step=10)  # Возвращает [0, 1, 4]

Сопоставление с образцом тензоров PyTorch

Использование функции torch.match

PyTorch предоставляет встроенную функцию torch.match для сопоставления с образцом в тензорах:

python
import torch

# Шаблонные и образцовые тензоры
template = torch.tensor([101., 124., 979., 430., 1073., 146., 111., 650.])
pattern1 = torch.tensor([430., 1073., 146.])

# Поиск совпадений шаблонов с точным сопоставлением
start_indices = torch.match(pattern1, template, mismatch_cnt=0, axis=0)
print(start_indices)  # Возвращает tensor([3])

Функция torch.match поддерживает:

  • Точное сопоставление (0 несоответствий)
  • Приблизительное сопоставление с указанной допустимостью несоответствий
  • Поиск шаблонов вдоль указанных осей

Сопоставление последовательностей с помощью пользовательских функций

Для более сложных числовых шаблонов можно реализовать пользовательские функции сопоставления:

python
import torch

def find_pattern_indices(data, pattern, tolerance=1e-6):
    """Поиск индексов, где шаблон встречается в тензоре данных"""
    pattern_len = len(pattern)
    data_len = len(data)
    
    if pattern_len > data_len:
        return torch.tensor([], dtype=torch.long)
    
    # Сдвиг окна по данным
    matches = []
    for i in range(data_len - pattern_len + 1):
        window = data[i:i+pattern_len]
        if torch.allclose(window, pattern, atol=tolerance):
            matches.append(i)
    
    return torch.tensor(matches, dtype=torch.long)

# Пример использования
data = torch.tensor([1.0, 2.0, 3.0, 2.0, 3.0, 4.0, 5.0])
pattern = torch.tensor([2.0, 3.0, 4.0])
indices = find_pattern_indices(data, pattern)
print(indices)  # Возвращает tensor([3])

Использование torch.nn.utils.rnn для операций с последовательностями

Для сопоставления с образцом на основе последовательностей могут быть полезны утилиты RNN PyTorch:

python
import torch
import torch.nn.utils.rnn as rnn_utils

# Создание заполненных последовательностей из шаблонов переменной длины
sequences = [
    torch.tensor([1.0, 2.0, 3.0]),
    torch.tensor([2.0, 3.0]),
    torch.tensor([3.0, 4.0, 5.0, 6.0])
]

padded = rnn_utils.pad_sequence(sequences, batch_first=True, padding_value=0)
print(padded)

Продвинутые техники сопоставления с образцом

Обнаружение шаблонов на основе свертки

Для обнаружения конкретных числовых последовательностей в многомерных массивах:

python
import torch
import torch.nn.functional as F

def find_pattern_2d(data_tensor, pattern_tensor):
    """Использование свертки для поиска 2D-шаблонов в тензоре"""
    # Изменение формы для свертки
    data_reshaped = data_tensor.unsqueeze(0).unsqueeze(0)  # Добавление размерностей пакета и канала
    pattern_reshaped = pattern_tensor.unsqueeze(0).unsqueeze(0)
    
    # Использование взаимной корреляции для поиска совпадений
    correlation = F.conv2d(data_reshaped, pattern_reshaped)
    matches = (correlation == pattern_tensor.numel()).squeeze()
    
    return matches

# Пример
data = torch.tensor([
    [1, 2, 3, 4],
    [2, 3, 4, 5],
    [3, 4, 5, 6]
])
pattern = torch.tensor([[2, 3], [3, 4]])
matches = find_pattern_2d(data, pattern)
print(matches)  # Показывает позиции, где встречается шаблон

Статистическое сопоставление с образцом

Для шаблонов, основанных на статистических свойствах, а не на точных значениях:

python
import numpy as np

def find_statistical_pattern(data, window_size=3, threshold=0.8):
    """Поиск окон с похожими статистическими свойствами"""
    means = []
    stds = []
    
    # Расчет статистики скользящего окна
    for i in range(len(data) - window_size + 1):
        window = data[i:i+window_size]
        means.append(np.mean(window))
        stds.append(np.std(window))
    
    # Поиск похожих шаблонов
    means = np.array(means)
    stds = np.array(stds)
    
    # Сравнение каждого окна с другими
    similarity_matrix = np.zeros((len(means), len(means)))
    for i in range(len(means)):
        for j in range(len(means)):
            if i != j:
                mean_diff = abs(means[i] - means[j]) / (abs(means[i]) + abs(means[j]) + 1e-8)
                std_diff = abs(stds[i] - stds[j]) / (abs(stds[i]) + abs(stds[j]) + 1e-8)
                similarity = 1 - (mean_diff + std_diff) / 2
                similarity_matrix[i, j] = similarity
    
    # Поиск высокопохожих шаблонов
    return np.where(similarity_matrix > threshold)

Рекомендации по производительности

Советы по производительности для NumPy

  • Векторизация: Всегда отдавайте предпочтение векторизованным операциям вместо циклов Python
  • Представления памяти: Используйте представления памяти для больших массивов, чтобы избежать копирования
  • Типы данных: Используйте подходящие типы данных (например, np.float32 вместо np.float64 для точности, не требующей полной 64-битной)

Советы по производительности для PyTorch

  • Ускорение GPU: Перемещайте тензоры на GPU для масштабного сопоставления с образцом
  • Пакетная обработка: Обрабатывайте несколько шаблонов одновременно
  • Отслеживание градиентов: Отключайте градиенты при использовании сопоставления с образцом для вывода
python
# Эффективное сопоставление с образцом на основе GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
data = data.to(device)
pattern = pattern.to(device)

with torch.no_grad():  # Отключение градиентов для вывода
    results = torch.match(pattern, data, mismatch_cnt=0, axis=0)

Практические примеры

Пример 1: Обнаружение шаблонов цен на акции

python
import torch
import numpy as np

def detect_candlestick_patterns(prices, volume=None):
    """Обнаружение распространенных свечных шаблонов в данных о ценах"""
    prices = torch.tensor(prices, dtype=torch.float32)
    
    # Шаблон Доджи (открытие ≈ закрытие)
    doji_indices = []
    for i in range(1, len(prices) - 1):
        if abs(prices[i] - prices[i-1]) < 0.01 * prices[i]:
            doji_indices.append(i)
    
    # Шаблон поглощения
    engulfing_indices = []
    for i in range(1, len(prices) - 1):
        current_body = abs(prices[i] - prices[i-1])
        previous_body = abs(prices[i-1] - prices[i-2])
        if current_body > 1.5 * previous_body:
            engulfing_indices.append(i)
    
    return {
        'doji': torch.tensor(doji_indices),
        'engulfing': torch.tensor(engulfing_indices)
    }

# Пример использования
stock_prices = [100.1, 100.2, 100.05, 100.3, 100.8, 101.2, 101.15]
patterns = detect_candlestick_patterns(stock_prices)
print(f"Шаблоны Доджи на индексах: {patterns['doji']}")
print(f"Шаблоны поглощения на индексах: {patterns['engulfing']}")

Пример 2: Обнаружение шаблонов в аудиосигнале

python
import torch
import numpy as np

def find_audio_silences(audio_data, threshold=0.01, min_duration=100):
    """Поиск тихих сегментов в аудиоданных"""
    audio_tensor = torch.tensor(audio_data, dtype=torch.float32)
    amplitude = torch.abs(audio_tensor)
    
    # Поиск тихих регионов
    is_silent = amplitude < threshold
    
    # Группировка последовательных тихих выборок
    changes = torch.diff(is_silent.int(), prepend=torch.tensor([0]))
    silence_starts = torch.where(changes == 1)[0]
    silence_ends = torch.where(changes == -1)[0]
    
    # Фильтрация по минимальной длительности
    valid_silences = []
    for start, end in zip(silence_starts, silence_ends):
        if (end - start) >= min_duration:
            valid_silences.append((start, end))
    
    return valid_silences

# Пример использования
audio_signal = np.random.normal(0, 0.5, 10000)  # Случайный аудиосигнал
# Добавление некоторых тихих регионов
audio_signal[1000:1200] = 0.001
audio_signal[5000:5100] = 0.001

silences = find_audio_silences(audio_signal)
print(f"Найдено {len(silences)} тихих регионов")
for start, end in silences:
    print(f"Тишина с {start} по {end} выборок")

Пример 3: Обнаружение аномалий во временных рядах

python
import torch
import numpy as np

def detect_anomalies(data, window_size=10, threshold=3.0):
    """Обнаружение аномалий с использованием скользящего z-оценки"""
    data_tensor = torch.tensor(data, dtype=torch.float32)
    
    anomalies = []
    for i in range(window_size, len(data_tensor)):
        window = data_tensor[i-window_size:i]
        mean = torch.mean(window)
        std = torch.std(window)
        
        if std > 0:
            z_score = (data_tensor[i] - mean) / std
            if abs(z_score) > threshold:
                anomalies.append(i)
    
    return torch.tensor(anomalies)

# Пример использования
time_series = np.concatenate([
    np.random.normal(100, 5, 1000),  # Нормальные данные
    np.random.normal(200, 10, 50),   # Аномальные данные
    np.random.normal(100, 5, 1000)   # Возврат к норме
])

anomalies = detect_anomalies(time_series)
print(f"Обнаруженные аномалии на индексах: {anomalies}")

Источники

  1. Документация NumPy fromregex
  2. Stack Overflow: Сопоставление шаблонов регулярных выражений в массивах NumPy
  3. GitHub Issue PyTorch: Сопоставление с образцом
  4. Stack Overflow: Создание тензоров с конкретными шаблонами
  5. Stack Overflow: numpy.where на массиве строк с использованием регулярных выражений
  6. Stack Overflow: Логика регулярных выражений в массиве numpy/torch
  7. Документация PyTorch torch.match
  8. W3Resource NumPy fromregex

Заключение

Сопоставление с образцом числовых последовательностей в стиле регулярных выражений в массивах NumPy и PyTorch можно реализовать с помощью нескольких встроенных подходов:

  • NumPy: Несмотря на отсутствие прямой поддержки регулярных выражений для числовых данных, можно использовать векторизованные операции, математические сравнения или функцию fromregex для данных на основе файлов
  • PyTorch: Предоставляет встроенную функцию torch.match для сопоставления с образцом с необязательной допустимостью несоответствий, а также пользовательские реализации с использованием свертки и статистических методов
  • Производительность: Обе библиотеки поддерживают ускорение GPU для масштабного сопоставления с образцом при использовании PyTorch
  • Гибкость: Математические операции обеспечивают больший контроль, чем традиционные регулярные выражения для числовых шаблонов, позволяя допускать сопоставление на основе допусков и обнаружение статистических шаблонов

В большинстве случаев функция torch.match PyTorch предоставляет наиболее прямой встроенный подход к числовому сопоставлению с образцом, в то время как пользователи NumPy могут реализовывать эффективные пользовательские решения с использованием векторизованных операций и математических сравнений.

Авторы
Проверено модерацией
Модерация