NumPy ndarray의 /연산과 /=연산은 다르다

seokj·2023년 1월 21일
0
post-thumbnail

NumPy의 배열은 가변 시퀀스이다. 튜플같은 것과 다르게 제일 처음 선언된 이후에 자신이 가지고 있는 항목을 수정하거나 추가/삭제가 가능하다는 뜻이다.

시퀀스에 관한 자세한 내용은 여기를 확인하자.


참고자료
https://numpy.org/doc/stable/reference/generated/numpy.can_cast.html


보통 x = x / a연산과 x /= a연산은 같다고 생각할 수 있지만 /=연산이 구현되지 않았을 때 /연산을 통해 저 방식으로 계산될 수 있는 것 뿐이고 NumPy배열은 /=연산을 따로 구현해놓았기 때문에 다른 방법으로 계산된다. /연산은 두 피연산자를 건드리지 않고 새로운 객체를 만들어 반환하는 것이 파이썬에서 관용적으로 이뤄지고 있는 방식이기 때문에 /=를 /로 바꿔 계산하면 생성할 필요가 없는 객체를 계산과정에서 생성하기 때문에 비효율적이기 때문이다.

아래 코드에서는 /와 /=가 다른 결과를 보여준다.

첫 번째 코드에서는 반면 새로운 객체를 만들어서 arr에 대입하기 때문에 dtype이 바뀌고 값은 그대로 들어간다. (dtype을 출력해보면 np.float64라고 나온다.) dtype이 바뀐 것도 이상하고
두 번째 코드에서는 NumPy배열의 broadcasting에 의해 각 항목 1, 2, 3의 값이 3으로 나누어진 0.333..., 0.666..., 1. 이 구해지고 이를 dtype이 np.uint인 ndarray에 대입하려다 자료형이 안 맞아서 오류를 내는 것이다. 오류 메시지에 나오는 UFuncTypeError의 UFunc은 두 피연산자를 연산하여 합치는 과정에서 호출되는 함수이다. 이 함수는 casting rule을 인자로 받는데 어느정도 수준까지 형변환을 허용할 것인지 지정하는 역할을 한다. 'same_kind'가 /=의 기본값이며 값이 손실되지 않거나 같은 종류 (np.float32, np.float64는 같은 종류이다.)에 속하는 자료형끼리만 변환할 수 있다는 의미이다. 다른 종류의 casting_rule인 'no', 'equiv', 'safe', 'unsafe'에 대한 자세한 설명은 여기를 참고한다.

위 코드에서의 arr /= 3np.divide(arr, 3, out=arr, casting='same_kind')와 같다. 바꿔서 실행하면 같은 오류가 날 것이다. 이 때 casting의 인자로 unsafe를 전달해주면 정보가 손실되더라도 형변환을 허용하기 때문에 dtype이 바뀌지 않고 0.333..., 0.666..., 1.이 int형인 0, 0, 1으로 형변환되면서 inplace연산으로 수행된다.

profile
안녕하세요

0개의 댓글