※ 일본 포스팅을 번역한 것입니다. 오역 및 직역이 있으며 내용의 오류가 있는 경우 댓글로 알려주시면 수정하겠습니다.
책 Data Science from Scratch 챕터 2에서 나온 일부의 내용을 내가 필요할 때 보기위해 정리한 메모이다.
yield
yield에 대한 이미지는 이 포스팅에서 잘 다루고 있다. 그 다음 이 포스팅을 읽는다면 더욱 이해가 깊어질 것이다. 여기서 yield에 대해 한 문장으로 간략하게 말하자면, "return을 사용하면 그 행에서 처리가 끝나 값을 모두 return하게 되므로, 거대한 데이터를 이용해서 반복 작업을 할 경우, 반복할 때마다 메모리를 쓸모없이 낭비하게 된다. 이때, yield을 사용하면 편리하다"라고 할 수 있다.
def func():
a = 10
b = 20
c = a + b
yield c # 여기서 일단 정지
a = 100
b = 200
c = a + b
yield c # 여기서 일단 정지
a = 1000
b = 2000
c = a + b
yield c # 여기서 일단 정지
for x in func():
print (x)
#---- 결과 -----
# 30
# 300
# 3000
#---------------
partial
함수를 여러번 돌릴 때 함수의 일부를 사용하여 새로운 함수를 만들고 싶을 때 도움이 되는 것이 이 partial이다. 사용시에는 functools로 부터 import해야한다.
# 예를 들어, base를 power승(제곱)하는 함수를 만든다.
def exp(base, power):
return base ** power
이 함수를 사용하여 2의 x 제곱을 계산하는 함수를 만들고 싶은 경우, 아래와 같이 쓸 수 있다.
def two_to_the(power):
return exp(2, power)
그러나 partial를 사용하면 아래와 같이 더욱 간단하게 작성할 수 있다.
from functools import partial
two_to_the = partial(exp, 2) # 첫 번째 인수에는 사용하는 함수, 두 번째 인수에는 base를 지정
print two_to_the(3) # 8
참고하는 함수의 다른 인수를 지정하고 싶은 경우에는, 그 인수의 이름을 포함해서 지정한다.
square_of = partial(exp, power=2) # 이번에는 power를 지정
print square_of(3) # 9
이 partial는 매우 편리하므로 습관들이는 것이 좋을 것 같다.
Python의 기본적인 고차함수 (higher-order functions)
map, filterm reduce는 고차함수라고 불린다. 참고로 고차함수란 영어로는 "higher-order functions"로, "다른 함수를 인수로 받아들이는 함수"이다. 예를 들어 리스트의 각 요소에 공통 처리를 하도록 작성하고 싶은 경우 등, 처리를 알기 쉽게 간략히 기재하는 것이 가능하다.
map
map(x, y)는 x(i) for i in y이다.
def double(x):
return 2 * x
xs = [1, 2, 3, 4]
twice_xs = [double(x) for x in xs] # [2, 4, 6, 8]
twice_xs = map(double, xs) # same as above
list_doubler = partial(map, double) # *function* that doubles a list
twice_xs = list_doubler(xs) # [2, 4, 6, 8]
여러 개의 인수를 가진 리스트가 부여된 경우, 여러 개의 인수를 가진 함수에도 사용할 수 있게 된다.
def multiply(x, y):
return x * y
products = map(multiply, [1, 2], [4, 5]) # [1 * 4, 2 * 5] = [4, 10]
filter
filter(x, y)는 i for i in y if x(i)이다.
def is_even(x): # True if x is even, False if x is odd
return x % 2 == 0
x_evens = [x for x in xs if is_even(x)] # [2, 4]
x_evens = filter(is_even, xs) # same as above
list_evener = partial(filter, is_even) # *function* that filters a list
x_evens = list_evener(xs) # [2, 4]
reduce
여러 개의 요소를 하나로 정리하고 싶을 때 사용한다. 구체적으로는 배열의 맨 앞에서부터 2개의 요소를 뽑아내 처리를 하고, 다음은 그 결과와 다음의 요소와 함께 처리하는 것을 반복하는 경우가 있을 것이다.
python3에서 부터는 functools로 부터 import해야만 reduce를 사용할 수 있다.
from functools import reduce
def multiply(x, y): return x * y
x_product = reduce(multiply, xs) # = 1 * 2 * 3 * 4 = 24
list_product = partial(reduce, multiply) # *function* that reduces a list
x_product = list_product(xs) # 24
enumerate
루프 처리를 할 때 enumerate를 사용하면 요소의 인덱스와 요소의 양쪽을 동시에 취득할 수 있다. 예를 들어 documents이라는 리스트의 요소와 인덱스 양쪽에 do_something이라는 처리를 반복 실행하는 경우 다음과 같이 작성할 수 있다.
# not Pythonic
for i in range(len(documents)):
document = documents[i]
do_something(i, document)
그러나 위 코드는 python답지 않은 코딩으로 enumerate를 사용하면 (index, element)의 튜플을 만들게 되어 아래와 같이 작성할 수 있게 된다.
for i, document in enumerate(documents):
do_something(i, document)
만약 인덱스만을 취득하고 싶은 경우는 다음과 같이 작성할 수 있다.
for i in range(len(documents)): do_something(i) # not Pythonic
for i, _ in enumerate(documents): do_something(i) # Pythonic
참고로 eumerate와 zip은 비슷해보이지만 다음과 같이 출력 결과가 완전히 다르다.
a = [a1, a2, a3]
b = [b1, b2, b3]
# enumerate
for i, a_i in enumerate(a):
print(i, a_i)
#---- 결과 -----
# 0 a1
# 1 a2
# 2 a3
#---------------
# zip
for a_i, b_i in zip(a,b):
print(a_i, b_i)
#---- 결과 -----
# a1 b1
# a2 b2
# a3 b3
#---------------
참고자료
'IT > AI\ML' 카테고리의 다른 글
[python/tensorflow2.x] Tensorflow2.x버전 작성법(2) (0) | 2021.09.14 |
---|---|
[python/tensorflow2.x] Tensorflow2.x버전 작성법(1) (0) | 2021.09.11 |
[python/Tensorflow] TFRecord를 만들어서 최소한의 CIFAR-10데이터로 학습시키기 (0) | 2021.07.30 |
[논문] 새로운 활성화함수 "FReLU" 탄생과 해설 (0) | 2021.07.25 |
머신러닝에서의 IoU(Intersection over Union)란? (0) | 2021.07.19 |