안녕하세요. 지난 포스팅의 넘파이 알고 쓰자 - 쌍곡선 함수(Hyperbolic functions)에서는 넘파이에서 제공하는 쌍곡함수에 대해서 소개하였습니다. 오늘은 더 간단한 넘파이에서 제공하는 덧셈, 곱셈, 뺄셈를 할 수 있는 다양한 함수들을 소개해드리도록 하겠습니다. 여기서는 기존파이썬에서 제공하는 함수와 얼마나 많은 시간 차이가 나는지도 알아보도록 하겠습니다. Show 1. numpy.prod(a, axis=None)가장 먼저 볼 함수는 곱셈 함수입니다. 기존의 파이썬과는 다르게 axis가 존재하여 원하는 축을 중심으로 계산을 수행하여 활용성이 좀 더 높은 것을 볼 수 있습니다. axis=None이라면 입력되는 넘파이 배열의 원소를 전부 곱하는 함수입니다.
위의 코드에서는 1~5까지의 넘파이 배열을 생성한 뒤 전부 곱하기 때문에 120을 반환하는 것을 볼 수 있습니다. 그렇다면 넘파이 배열이 엄청커진다면 얼마나 시간이 소요될까요? 간단한 실험을 위해서 아래의 함수를 구현합니다.
이제 배열의 개수를 늘려가면서 시간이 얼마나 소비되는 지 비교해보겠습니다.
보시면 for loop > math module > numpy module 순으로 시간이 오래걸리는 것을 관찰할 수 있습니다. 재밌는 점은 데이터가 100개 정도 있을 때는 넘파이 모듈이 for loop에 비해 0.23배 정도 더 느린것을 볼 수 있습니다. 하지만 데이터의 개수를 점점 많이 늘려감에 따라서 for loop와 math module의 시간은 비약적으로 증가하지만 numpy module의 경우 그리 많이 증가하지 않는 것도 관찰할 수 있습니다. 곱해야하는 데이터가 십만개인 경우 for loop에 비해 508.65배 정도 빠르고, math module에 비해 508.76배 정도 더 느립니다. 이를 통해 알 수 있는 것은 빅데이터와 같이 처리해야하는 데이터가 너무 많은 경우에는 넘파이 모듈을 이용하는 것이 시간적인 측면이나 코드의 간결성 측면에서나 더 좋다는 것입니다. 2. numpy.sum(a, axis=None)이 함수 역시 간단하기 때문에 걸리는 시간만 비교해보도록 하겠습니다.
이번에도 마찬가지로 데이터가 적을 때는 오히려 넘파이 모듈의 사용이 좋은 효율을 보이기는 어렵습니다. 하지만 데이터가 점점 많아짐에 따라서 계산하는 속도의 차이가 크지 않은 것을 볼 수 있습니다. 특히, 마지막의 경우에는 for loop에 비해 약 63배, math module에 비해 약 7배 정도 빠른 성능을 보인것을 관찰할 수 있습니다. 3.numpy.nanprod(a, axis=None), numpy.nansum(a, axis=None)이번에도 위에서 언급한 함수들과 동일한 기능을 하는 함수들입니다. 차이점은 np.prod, np.sum 같은 경우에는 np.nan이라는 값을 만나게 되면 np.nan 값을 반환하지만 이 함수들은 해당 값들은 제외하고 곱셈이나 덧셈을 하게 됩니다. 다루는 데이터에 np.nan 값을 처리하기 애매한 경우에 유용하게 사용할 수 있는 함수입니다.
4. numpy.cumprod(a, axis=None), numpy.cumsum(a, axis=None)이번에는 기능이 살짝 다른 함수들입니다. a 라는 넘파이 배열이 입력되면 이 함수는 누적곱과 누적합을 반환합니다. 예를 들어 배열이 [1, 2, 3]이 입력되는 경우 np.cumprod에서는 [1, 1 * 2, 1 * 2 * 3]을 반환하고, np.cumsum에서는 [1, 1 + 2, 1 + 2 + 3]을 반환하게 됩니다. 물론, axis를 지정해주면 해당 axis만 cumprod, cumsum을 수행하게 되겠죠. 바로 간단한 예제를 통해서 확인해보도록 하겠습니다.
5. numpy.nancumprod(a, axis=None), numpy.nancumsum(a, axis=None)그렇다면 넘파이 배열 a에 np.nan 값이 포함되어 있는 경우에는 어떻게 해야할까요? 물론 이를 위한 함수도 존재합니다.
그냥 cumprod, cumsum에서는 np.nan이 껴있기 때문에 해당 인덱스 이후로는 전부 nan을 반환합니다. 그에 반에 nancumprod, nancumsum 함수의 경우에는 해당 인덱스가 np.nan이라면 이전 인덱스의 결과를 그대로 복사해주게 됩니다. 6. numpy.diff(a, n=1, axis=-1)이 함수는 이산미분을 수행하는 함수입니다. 수학적으로 1차 이산미분은 out[i] = a[i + 1] - a[i]로 정의됩니다. 만약 1차보다 큰 고차 이산미분을 수행하게 되면 diff 함수를 recursive 하게 사용하여 계산하게 됩니다. 이는 쉽게 n을 1보다 큰 값으로 지정해주면 됩니다. 아래의 예제를 통해서 보도록 하겠습니다.
상단 그림에서 빨간색 원은 1차 미분입니다. 파란색 사각형이 0~5까지 1의 크기로 늘어나고 있기 때문에 1~5까지의 1차 미분값은 1이 됩니다. 초록색 십자형은 2차 미분입니다. 즉, 1차 미분을 한번 더 미분한것이라고 볼 수 있습니다. 1차 미분은 1~5까지는 값이 동일하기 때문에 1~4까지의 2차 미분값은 0입니다. 이때, 여기서 가장 눈여겨 볼 부분은 2차 미분이 음수에서 양수로 변화하는 x = 10인 부분입니다. 이 부분은 이미지 처리에서 zero-crossing이라고 해서 이미지의 가장자리(edge)를 추출해낼 수 있는 부분으로 간주하고 있기 때문에 이미지 처리를 공부하신다면 반드시 알아두어야할 개념입니다. |