Python Pros가 루프를 피하는 이유 : 벡터화 된 사고에 대한 부드러운 안내서


저자의 이미지 | 캔버
틀 소개
Python을 처음 사용하는 경우 일반적으로 데이터 모음을 처리해야 할 때마다 “for”루프를 사용합니다. 숫자 목록을 제곱해야합니까? 그들을 통해 루프. 필터링하거나 합산해야합니까? 다시 루프. 우리의 두뇌가 순차적으로 생각하고 작동하기 때문에 이것은 인간으로서 우리에게 더 직관적입니다 (한 번에 한 가지 덕분에).
그러나 이것이 컴퓨터가해야한다는 의미는 아닙니다. 그들은 무언가를 이용할 수 있습니다 벡터화 된 사고. 기본적으로 모든 요소를 통해 루핑을 수행하여 작업을 수행하는 대신 전체 목록을 Python Like에 제공합니다. “여기 목록이 있습니다. 한 번에 모든 작업을 수행하십시오.”
이 튜토리얼에서는 그것이 어떻게 작동하는지, 왜 중요한지에 대한 온화한 소개를 제공하며, 그것이 얼마나 유익 할 수 있는지 몇 가지 예를 다룰 것입니다. 그래서 시작합시다.
틀 벡터화 된 사고는 무엇이며 왜 중요한가?
앞에서 논의한 바와 같이, 벡터화 된 사고는 순차적으로 운영을 처리하는 대신 공동으로 수행하고자한다는 것을 의미합니다. 이 아이디어는 실제로 수학의 매트릭스 및 벡터 작업에서 영감을 얻었으며 코드를 훨씬 빠르고 읽을 수있게합니다. Numpy와 같은 라이브러리를 사용하면 파이썬에서 벡터화 된 사고를 구현할 수 있습니다.
예를 들어, 숫자 목록에 2를 곱 해야하는 경우 모든 요소에 액세스하고 작업을 하나씩 수행하는 대신 전체 목록에 동시에 곱하십시오. 이것은 Python의 오버 헤드를 많이 줄이는 것과 같은 주요 이점이 있습니다. Python 루프를 통해 반복 할 때마다 통역사는 유형 확인, 객체 관리 및 루프 메커니즘 처리와 같은 많은 작업을 수행해야합니다. 벡터화 된 접근법을 사용하면 대량으로 처리하여이를 줄입니다. 또한 훨씬 빠릅니다. 나중에 성능 영향에 대한 예제와 함께 볼 수 있습니다. 방금 이미지의 형태로 말한 내용을 시각화하여 내가 언급 한 내용에 대한 아이디어를 얻을 수 있습니다.
이제 그것이 무엇인지에 대한 아이디어를 얻었으므로 어떻게 구현할 수 있는지, 그것이 어떻게 유용 할 수 있는지 살펴 보겠습니다.
틀 간단한 예 : 온도 변환
다른 국가마다 사용되는 온도 규칙이 다릅니다. 예를 들어, 화씨 척도에 익숙하고 데이터가 섭씨로 제공되는 경우 두 가지 접근 방식을 사용하여이를 변환하는 방법은 다음과 같습니다.
// 루프 접근
celsius_temps = [0, 10, 20, 30, 40, 50]
fahrenheit_temps = []
for temp in celsius_temps:
fahrenheit = (temp * 9/5) + 32
fahrenheit_temps.append(fahrenheit)
print(fahrenheit_temps)
산출:
[32.0, 50.0, 68.0, 86.0, 104.0, 122.0]
// 벡터화 된 접근법
import numpy as np
celsius_temps = np.array([0, 10, 20, 30, 40, 50])
fahrenheit_temps = (celsius_temps * 9/5) + 32
print(fahrenheit_temps) # [32. 50. 68. 86. 104. 122.]
산출:
[ 32. 50. 68. 86. 104. 122.]
각 항목을 한 번에 하나씩 처리하는 대신 목록을 낭프 배열로 바꾸고 한 번에 모든 요소에 공식을 적용합니다. 둘 다 데이터를 처리하고 동일한 결과를 제공합니다. Numpy 코드가 더 간결한 것 외에도 지금 당장 시차를 알지 못할 수도 있습니다. 그러나 우리는 곧 그것을 다룰 것입니다.
틀 고급 예 : 여러 배열에서의 수학적 작업
여러 배열이 있고 이익을 계산 해야하는 다른 예를 들어 보겠습니다. 두 가지 접근 방식으로 수행 할 수있는 방법은 다음과 같습니다.
// 루프 접근
revenues = [1000, 1500, 800, 2000, 1200]
costs = [600, 900, 500, 1100, 700]
tax_rates = [0.15, 0.18, 0.12, 0.20, 0.16]
profits = []
for i in range(len(revenues)):
gross_profit = revenues[i] - costs[i]
net_profit = gross_profit * (1 - tax_rates[i])
profits.append(net_profit)
print(profits)
산출:
[340.0, 492.00000000000006, 264.0, 720.0, 420.0]
여기서는 각 항목에 대한 이익을 수동으로 계산합니다.
- 수익에서 비용을 빼기 (총 이익)
- 세금을 적용하십시오
- 새로운 목록에 결과를 추가하십시오
잘 작동하지만 많은 수동 인덱싱입니다.
// 벡터화 된 접근법
import numpy as np
revenues = np.array([1000, 1500, 800, 2000, 1200])
costs = np.array([600, 900, 500, 1100, 700])
tax_rates = np.array([0.15, 0.18, 0.12, 0.20, 0.16])
gross_profits = revenues - costs
net_profits = gross_profits * (1 - tax_rates)
print(net_profits)
산출:
[340. 492. 264. 720. 420.]
벡터 화 된 버전도 더 읽기 쉬우 며 3 개의 배열 모두에서 동시에 요소 별 작업을 수행합니다. 이제는 확실한 증거없이 “더 빠른”것을 계속 반복하고 싶지 않습니다. 그리고 당신은“Kanwal이 무엇에 대해 이야기하고 있습니까?”라고 생각하고있을 것입니다. 그러나 이제 구현하는 방법을 보았 으므로이 둘 사이의 성능 차이를 살펴 보겠습니다.
틀 성능 : 숫자는 거짓말을하지 않습니다
내가 말하는 차이점은 과대 광고 나 이론적 인 것이 아닙니다. 측정 가능하고 입증되었습니다. 얼마나 많은 개선을 기대할 수 있는지 이해하기 위해 실용적인 벤치 마크를 살펴 보겠습니다. 우리는 1,000,000 인스턴스의 매우 큰 데이터 세트를 생성하고 두 가지 접근 방식을 사용하여 각 요소에서 작업 \ (x^2 + 3x + 1 \)를 수행하고 시간을 비교합니다.
import numpy as np
import time
# Create a large dataset
size = 1000000
data = list(range(size))
np_data = np.array(data)
# Test loop-based approach
start_time = time.time()
result_loop = []
for x in data:
result_loop.append(x ** 2 + 3 * x + 1)
loop_time = time.time() - start_time
# Test vectorized approach
start_time = time.time()
result_vector = np_data ** 2 + 3 * np_data + 1
vector_time = time.time() - start_time
print(f"Loop time: {loop_time:.4f} seconds")
print(f"Vector time: {vector_time:.4f} seconds")
print(f"Speedup: {loop_time / vector_time:.1f}x faster")
산출:
Loop time: 0.4615 seconds
Vector time: 0.0086 seconds
Speedup: 53.9x faster
그것은 50 배 이상 더 빠릅니다 !!!
이것은 작은 최적화가 아니며 데이터 처리 작업 (큰 데이터 세트에 대해 이야기하고 있음)을 훨씬 더 실현 가능하게 만듭니다. 이 튜토리얼에 Numpy를 사용하고 있지만 Pandas는 Numpy 위에 구축 된 또 다른 라이브러리입니다. 당신도 그것을 사용할 수 있습니다.
틀 벡터화하지 않을 때
대부분의 경우에 작동한다고해서 접근 방식이라는 의미는 아닙니다. 프로그래밍에서 “최고의”접근 방식은 항상 당면한 문제에 달려 있습니다. 데이터 세트의 모든 요소에서 동일한 작업을 수행 할 때 벡터화가 좋습니다. 그러나 논리에 복잡한 조건부, 조기 종료 또는 이전 결과에 의존하는 작업이 포함 된 경우 루프 기반 접근 방식을 고수하십시오.
마찬가지로, 매우 작은 데이터 세트로 작업 할 때 벡터화 된 작업을 설정하는 오버 헤드가 이점을 능가 할 수 있습니다. 따라서 이해가되는 곳에 사용하고 그렇지 않은 곳에 강제로 사용하지 마십시오.
틀 마무리
Python과 계속 협력하면서 벡터화 기회를 찾기 위해 도전하십시오. `for` for` 루프에 도달 할 때, 잠시 멈추고 Numpy 또는 Pandas를 사용하여 동일한 작업을 표현하는 방법이 있는지 물어보십시오. 종종 그렇지 않은 경우가 많으며 결과는 더 빠를뿐만 아니라 더 우아하고 이해하기 쉬운 코드가 될 것입니다.
목표는 코드에서 모든 루프를 제거하는 것이 아닙니다. 사용하는 것입니다 작업을위한 올바른 도구.
Kanwal Mehreen 기계 학습 엔지니어이자 데이터 과학에 대한 열정과 AI의 의학 교차점을 가진 기술 작가입니다. 그녀는 eBook “Chatgpt의 생산성을 극대화하는 것”을 공동 저술했습니다. APAC의 Google Generation Scholar 2022로서 그녀는 다양성과 학업 우수성을 챔피언시킵니다. 그녀는 또한 Tech Scholar, Mitacs Globalink Research Scholar 및 Harvard Wecode Scholar의 Teradata 다양성으로 인정 받고 있습니다. Kanwal은 STEM 분야의 여성에게 힘을 실어주기 위해 펨코드를 설립 한 변화에 대한 열렬한 옹호자입니다.
Post Comment