HOWTO · Python

Python의 교차 상관

이 기사에서는 Python에서 상호 상관을 처리하는 여러 가지 방법에 대해 설명합니다.

이 페이지의 내용

교차 상관은 한 수열을 다른 수열에 대해 이동시키면서 두 실수 숫자 수열을 비교합니다. 각 상대 위치마다 점수를 계산하므로 패턴이 어디에서 맞는지 알아볼 수 있습니다. 기본 점수는 곱의 합이며, 자동으로 정규화된 상관 계수가 되는 것은 아닙니다.

교차 상관이 측정하는 것

실수 수열 x와 y의 교차 상관은 각 시차에서 겹치는 값끼리 곱한 다음 그 곱을 모두 더합니다. 높은 양수 점수는 해당 시차에서 값들의 부호와 패턴이 대체로 일치함을 뜻하고, 음수 점수는 서로 반대임을 나타냅니다. 점수는 수열의 크기와 서로 겹치는 값의 개수에도 영향을 받습니다.

full 모드는 겹치는 쌍이 하나라도 있는 모든 시차를 포함합니다. x의 길이가 N이고 y의 길이가 M이면 점수는 N + M - 1개입니다. valid 모드는 더 짧은 수열이 더 긴 수열 안에 완전히 들어가는 시차만 남깁니다. same 모드는 첫 번째 입력을 중심으로 하고 그 입력과 같은 길이의 결과를 반환합니다. 길이가 짝수일 때 정확한 중심 정렬 규칙은 라이브러리에 따라 다릅니다. 이 모드들은 비교할 시차를 선택하며 정규화 여부를 정하지는 않습니다.

순수 Python으로 교차 상관 계산하기

직접 구현하면 겹치는 구간과 시차 규칙을 명확하게 확인할 수 있습니다. 실수 수열 x와 y를 입력으로 받는 다음 코드는 겹치는 값의 곱을 정규화하지 않고 합산합니다. 실수 입력에서 시차 순서와 결과는 NumPy의 correlate(x, y, mode="full") 규칙과 일치합니다.

다음 예제를 실행하세요.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

x = [1, 2, 3]
y = [4, 5]

scores = []
for lag in range(-len(y) + 1, len(x)):
    score = sum(
        x[index + lag] * y[index]
        for index in range(len(y))
        if 0 <= index + lag < len(x)
    )
    scores.append(score)

print(scores)
[5, 14, 23, 12]

결과에는 시차별 점수가 하나씩 있으며, -(len(y) - 1)부터 len(x) - 1까지 순서대로 나옵니다. 각 점수에는 인덱스 쌍 중 서로 겹치는 항만 포함됩니다. 이 간단한 방법은 작은 입력에 사용하거나 계산 원리를 이해하는 데 유용하지만, 중첩 반복의 작업량은 두 수열 길이의 곱에 비례해 늘어납니다.

NumPy로 교차 상관 계산하기

python -m pip install numpy 명령으로 NumPy를 설치합니다. numpy.correlate는 1차원 실수 숫자 배열을 처리하며 full, same, valid 모드를 제공합니다. 기본값은 valid이므로 특정 시차 집합이 필요하면 모드를 지정하세요.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

import numpy as np

x = np.array([1, 2, 3])
y = np.array([4, 5])

scores = np.correlate(x, y, mode="full")
print(scores.tolist())
[5, 14, 23, 12]

이 실수 입력에서는 순수 Python 예제와 전체 모드의 시차 순서 및 정규화되지 않은 곱의 합이 같습니다. 복소수 데이터에서 NumPy는 두 번째 입력을 켤레 복소수로 바꾸지만, 앞의 순수 Python 코드는 그렇게 하지 않습니다. 따라서 두 결과가 일치한다는 설명은 실수 입력에만 적용됩니다. 일반 Python 형태가 편리할 때만 배열을 리스트로 바꾸세요. 이후 수치 연산을 계속할 때는 대개 NumPy 배열이 더 편리합니다. 이 비교에서는 입력이 1차원 실수여야 합니다.

SciPy로 교차 상관 계산하기

python -m pip install scipy 명령으로 SciPy를 설치합니다. SciPy에는 NumPy도 필요합니다. scipy.signal.correlate는 같은 세 가지 출력 모드를 제공하며 SciPy의 다른 신호 처리 도구와 함께 사용하기 좋습니다. correlation_lags는 결과의 각 위치에 해당하는 시차를 반환하므로 인덱스를 직접 계산할 필요가 없습니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

import numpy as np
from scipy.signal import correlate, correlation_lags

x = np.array([1, 2, 3])
y = np.array([4, 5])

scores = correlate(x, y, mode="full", method="auto")
lags = correlation_lags(len(x), len(y), mode="full")
print(scores.tolist())
print(lags.tolist())
[5, 14, 23, 12]
[-1, 0, 1, 2]

기본적으로 SciPy의 method 옵션은 계산 전략을 선택하며, 요청한 상관 계산의 정의를 바꾸지는 않습니다. 라이브러리별 결과를 비교할 때는 실수 입력과 모드를 동일하게 유지하세요. NumPy와 마찬가지로 SciPy는 복소수 데이터에서 두 번째 입력을 켤레 복소수로 바꿉니다. 순수 Python 코드는 그렇게 하지 않습니다. 이 예제는 1차원 실수 배열을 사용합니다.

시차 해석과 방법 선택

실수 x를 첫 번째 인수로, 실수 y를 두 번째 인수로 넣으면 NumPy와 SciPy는 전체 모드의 시차를 -(len(y) - 1)부터 len(x) - 1까지 순서대로 반환합니다. 이 규칙에서 양의 시차는 y를 x의 더 뒤쪽 구간과 비교합니다. 최대점으로 시간 지연을 해석하기 전에 라이브러리의 인수 순서와 시차 규칙을 확인하세요. 입력 순서를 바꾸면 시차의 방향이 반대가 됩니다.

패키지 의존성이 없는 기준 계산이 필요하거나 수열이 짧다면 순수 Python을 선택하세요. 수치 코드에서 간결한 배열 연산이 필요하면 NumPy를 사용하세요. 명시적인 시차 값이나 다른 신호 처리 함수도 필요하면 SciPy가 적합합니다. 표본 간격이 일정하다면 시차 인덱스에 표본 간격을 곱해 시간으로 변환할 수 있습니다. 정규화된 계수가 필요하면 정규화 방식을 별도로 정의하고 서로 겹치는 표본 수를 반영하세요. 원시 교차 상관 점수는 겹치는 길이나 수열의 크기가 다를 때 바로 비교할 수 없습니다.

교차 상관과 Pandas 상관 계수

pandas.Series.corr는 정렬된 관측값을 대상으로 쌍별 상관 계수 하나를 계산합니다. 한 수열을 다른 수열에 대해 이동시키거나 시차마다 점수를 반환하지 않으므로 교차 상관 함수가 아닙니다. 여러 시차를 비교하려면 NumPy 또는 SciPy를 사용하세요. Pandas 데이터를 사용한다면 선택한 구현에 배열을 전달하기 전에 데이터를 명시적으로 정렬하고 숫자 값을 추출하세요. 인덱스가 맞지 않거나 결측값이 있을 때는 이를 어떻게 처리할지 정해야 합니다.