합성곱
핵심 질문
다항식 곱셈에서 같은 차수로 모이는 계수들은 어떻게 계산할까?
교과서 설명
이 자료에서는 합성곱을 먼저 다항식 계수 조합으로 본다. 두 계수 배열 a, b를 곱해서 새 배열 c를 만들 때, c[k]는 차수가 k가 되는 모든 곱을 더한 값이다.
c[k]=(a∗b)[k]=i+j=k∑a[i]b[j]
같은 식을 j=k−i로 바꾸어 쓰면 다음과 같다.
c[k]=i∑a[i]b[k−i]
신호 처리에서는 이 계산을 “한 배열을 뒤집고 밀어 가며 겹침을 더한다”고 설명하기도 한다. 하지만 FFT와 다항식 곱셈을 연결할 때는 “i+j=k인 계수 조합을 모은다”는 관점이 더 직접적이다.
길이가 m인 배열과 길이가 n인 배열을 선형 합성곱하면 결과 길이는 m+n−1이다. 없는 칸은 0이라고 생각한다.
a[i]=0if i is outside a,b[j]=0if j is outside b
결과 길이가 m+n−1인 이유는 가능한 차수 합의 범위 때문이다. 가장 작은 합은 0+0=0이고, 가장 큰 합은
(m−1)+(n−1)=m+n−2
이다. 따라서 결과 인덱스는
0,1,2,…,m+n−2
이고, 칸의 개수는 m+n−1개다.
합성곱 공식의 유도
두 다항식을
A(x)=i∑a[i]xi,B(x)=j∑b[j]xj
라고 쓰자. 곱하면
A(x)B(x)=(i∑a[i]xi)(j∑b[j]xj)
이고, 분배법칙으로 모든 항을 곱하면
A(x)B(x)=i∑j∑a[i]b[j]xi+j
가 된다. 이제 결과 다항식을
C(x)=k∑c[k]xk
라고 쓰면, xk의 계수 c[k]는 i+j=k가 되는 모든 항에서 나온다. 따라서
c[k]=i+j=k∑a[i]b[j]
가 된다. 이것이 합성곱 공식이다.
직접 계산하면 모든 쌍 (i,j)를 확인해야 하므로 대략 mn번의 곱셈이 필요하다. 두 배열 길이가 모두 N 정도라면 O(N2) 계산이 된다. FFT를 쓰는 이유는 이 병목을 줄이기 위해서다.
또 하나 구분해야 할 말이 있다. 지금 정의한 것은 선형 합성곱이다. DFT 안에서 길이를 고정한 채 곱하면 결과가 끝에서 앞으로 말려 들어가는 순환 합성곱이 된다. 그래서 FFT로 선형 합성곱을 하려면 뒤에서 zero padding을 반드시 다룬다.
직관 비유
두 주사위를 던져 합이 k가 되는 경우를 모은다고 생각하자. 합이 3인 경우는 (1,2)와 (2,1)처럼 여러 조합이 있다. 합성곱도 차수의 합이 k가 되는 곱들을 모두 모아 더한다.
예제
(1+2x)(3+4x)=3+10x+8x2
가운데 계수 10은 1⋅4+2⋅3에서 나온다.
배열로 쓰면 같은 계산이다.
[1,2]∗[3,4]=[3,10,8]
각 칸은 다음처럼 채워진다.
c[0]c[1]c[2]=1⋅3=3=1⋅4+2⋅3=10=2⋅4=8
차수 조합표로 쓰면 다음과 같다.
k012i+j=k(0,0)(0,1),(1,0)(1,1)c[k]1⋅3=31⋅4+2⋅3=102⋅4=8
이 표에서 k는 결과 배열의 번호이자 다항식의 차수다. 같은 xk 앞에 모이는 곱을 모두 더하면 c[k]가 된다.
손풀이 체크
-
[2,1]∗[1,3]의 가운데 값은?
답 보기
2⋅3+1⋅1=7
-
길이 3 배열과 길이 4 배열의 선형 합성곱 결과 길이는?
답 보기
3+4−1=6
-
(1+x)(1+x+x2)의 계수 배열은?
답 보기
[1,2,2,1]
다음으로 이어지는 생각
그냥 계산하면 느리지만, DFT와 FFT를 이용하면 빠르게 만들 수 있다. 다음 장에서는 “느리다”와 “빠르다”를 계산량으로 비교한다.