도라에몽주머니

[ML] numpy 모듈으로 푸리에 변환 구현 본문

Study/ML

[ML] numpy 모듈으로 푸리에 변환 구현

에몽쓰 2024. 9. 27. 16:39

지난번 작성한 푸리에 변환에 관해 이번에는 코드를 작성해보며 이해하려 한다.

안봤으면 보고오시소・・・

https://geniemon0104.tistory.com/124

 

[ML] 푸리에 변환(Fourier Transform) 이란?

이번 안건에서 푸리에 변환과 관련한 내용을 접하게 되어, 다음에 또 푸리에 변환을 활용하게 될 때 참고로 사용하기 위해 정리해두고자 한다. 수학적인 증명방법이나 풀이보다는 왜 푸리에 변

geniemon0104.tistory.com

 

numpy 공식 문서

아래는 numpy 공식 문서이다. 학부때는 그냥 잘 모르겠으면 누가 적어놓은거 복붙하거나 따라 작성할 때도 많았던 것 같은데, 확실히 직장에 오니까 공식 문서의 중요성을 실감중이다... 일본이라 더 공식 문서를 읽는걸 강조하는걸지도...

https://numpy.org/doc/stable/reference/routines.fft.html#

 

Discrete Fourier Transform (numpy.fft) — NumPy v2.1 Manual

Discrete Fourier Transform (numpy.fft) The SciPy module scipy.fft is a more comprehensive superset of numpy.fft, which includes only a basic set of routines. Standard FFTs Real FFTs Hermitian FFTs Helper routines Background information Fourier analysis is

numpy.org

 

코드 작성

대충 코드 작성 흐름에 맞춰 순서를 적어뒀으니 따라서 실행하면 된다! 참고로 나는 주피터노트북 환경으로 셀을 하나하나 출력해보며 했지만 그냥 파이썬 스크립트 파일로 작성해도 되긴한다.

예제 코드는 아래 블로그를 참고했다. 정말 어디 교수님이신지,, 설명이 너무 좋아서 꽤나 감탄함...

https://m.blog.naver.com/choi_s_h/222128863344

 

[P059] 파이썬의 고속푸리에 변환-3, FFT (Fast Fourier Transform of Python, FFT-3)

   파이썬의 numpy 팩키지에서 제공하는 fft.fft( ) 함수와 fft.fftfreq( )의 두 함수를 사용하...

blog.naver.com

 

1. 필요한 모듈을 불러오기

이번에는 푸리에 변환에 사용할 numpy 모듈이랑 그래프 작성용 pyplot만 불러와도 된다.

import numpy as np
import matplotlib.pyplot as plt

 

2. 신호 생성하기

이번에 작성할 주파수 데이터는 샘플링 시간이 0.001초이고, 각 신호 주파수가 10, 20, 30, 40Hz, 진폭은 2.0, 1.0, 0.5, 1.5 로 설정했다. 왜 아래와 같은 코드가 되는지는 위 링크에 들어가보면 정말 자세하게 설명해주신다..ㅎㅎ

  • np.linspace : 수평축의 너비를 만들거나 1차원 배열을 만드는 등의 작업에 사용되는 함수
time = np.linspace(0, 1, 1000) # 샘플링 시간 간격을 0.001초로 설정

s1 = 2*np.sin(20 * np.pi * time) # 10Hz、2.0의 진폭
s2 = np.sin(40 * np.pi * time) # 20Hz、1.0의 진폭
s3 = 0.5*np.sin(60 * np.pi * time) # 30Hz、0.5의 진폭
s4 = 1.5*np.sin(80 * np.pi * time) # 40Hz、1.5의 진폭

s = s1 + s2 + s3 + s4 # 신호 합성

 

3. 푸리에 변환과 그래프 작성

https://blog.naver.com/choi_s_h/222128246691

 

[P058] 파이썬의 고속푸리에 변환-2, FFT (Fast Fourier Transform of Python, FFT-2)

   앞의 포스트에서 고속푸리에 변환(FFT)을 위해 파이썬의 fft.fft( ) 함수를 이용하여 계산...

blog.naver.com

이 파트는 위 글을 참고해서 작성했다,, 정말 아름다운 글이야,,,

numpy 모듈을 사용해 푸리에 변환을 한 값은 복소수가 된다. np.fft.fft()의 결과값으로 복소수 값을 구할 수 있는데, 이 결과값은 주파수 영역에서 어떤 주파수의 상대적인 크기가 큰지를 알려주는 정보이다.

즉, np.fft.fft() 로 얻은 복소수 값의 크기를 알아야 된다는 말인데, numpy 모듈의 abs를 사용해 복소수의 크기를 계산한다.

strength = np.fft.fft(s)
strength = np.abs(strength) # 복소수의 크기 계산
freq = np.fft.fftfreq(1000, 0.001) # 그래프 작성에서 필요한 주파수 축 계산

plt.plot(freq, strength)
plt.show()

 

위 코드블럭을 실행하면 아래의 그래프를 얻을 수 있다. 왜 대칭인 모양의 그래프가 나왔는지 궁금할텐데, 그냥 우리가 사용하는 fft 모듈의 특성상 좌우대칭으로 출력해준다...ㅎㅎ

좌우 대칭이어서 양수부분만 봐도 상관 없으니 양수부분에서 의미있는 부분인 0~50까지를 잘라서 확인해보자.

x축은 주파수, y축은 진폭을 의미

 

plt.xlim(0, 50, 10) # x축을 0~50까지 10 간격으로 출력
plt.ylim(0, 1200, 200) # y축을 0~1200까지 200 간격으로 출력
plt.grid()
plt.plot(freq, strength)
plt.show()

 

위의 코드블럭을 실행하면 아래와 같은 그래프를 얻을 수 있다. 참고로, 지금은 푸리에 변환 그래프를 꺾은선그래프로 표현하고 있지만 바 그래프로도 표현할 수 있다.

 

그래프를 보면 초기에 설정한대로 각 신호 주파수(10, 20, 30, 40Hz) 와 진폭(2.0, 1.0, 0.5, 1.5) 이 잘 나타나는 것을 확인할 수 있다. 즉, 푸리에 변환이 잘 계산되었다는 것이다👏👏

현실에서 분석하게 될 주파수 데이터는 이것보다 훨씬 복잡하고 다양한 성분이 섞여있겠지만 이러한 단순한 푸리에 변환 예제를 풀어보면서 푸리에 변환의 개념에 대해 이해할 수 있었다.