본문 바로가기

반응형

분류 전체보기

(369)
Smooth L1 Loss vs Huber Loss 일반적인 회귀 (regression) 훈련에는 예측값과 실제값 차이의 절댓값인 L1 loss나 예측값과 실제값 차이의 제곱인 L2 loss를 목적 함수로 사용하게 됩니다. 잘 알려져 있다시피 L2 loss는 모든 구간에서 안정적으로 미분이 가능하지만 제곱이 들어가는만큼 아웃라이어 (이상치)에 민감하게 반응하고, L1 loss는 아웃라이어에 L2 loss 대비 강건한 대신 미분이 불가능한 지점이 존재하고 평균 대신 중앙값 (median)을 추정하는 만큼 부정확한 요소가 존재합니다. 따라서 L1, L2 loss을 합친 Smooth L1 loss나 Huber loss가 제안되었습니다. Huber loss, Smooth L1 loss 모두 L1과 L2의 장점 만을 합치고자 제안된 목적 함수로 공통적으로 예측값과..
LightGBM feature importance Feature Selection - XGBoost Feature Selection - Random Forest (1) Feature Selection - Random Forest (2) 최근 XGBoost, LightGBM, Random Forest, Factorization Machine 등 여러 알고리즘을 이용해 회귀 모델을 구성한 적이 있습니다. MAE, R2 등의 정확도는 비슷했지만 feature importance를 측정하니 LightGBM 모델에 대해서만 feature importance가 다른 양상을 나타냈습니다. Figure 1을 보면 LightGBM 모델의 경우 feature importance 합이 1이 되지도 않고 A부터 H까지의 feature가 균등한 importance를 가지고 있..
Numba (2) - 타입 컨테이너, 루프 퓨전 Numba (1) Numba 타입 컨테이너 Numba에서 가장 중요한 권장 사항은 최적의 컴파일을 제공하는 "nopython" 모드를 사용하는 것일 겁니다. (오브젝트 모드 (object mode)는 최소한의 최적화만 진행하게 됩니다) 이는 @jit 데코레이터에 "nopython=True" 옵션을 주거나 @njit 데코레이터를 사용하면 되는데요, 하지만 지난 포스트에서 살펴봤듯이 이 모드는 제한이 많아 컴파일이 성공하려면 Numba가 작상한 함수 내의 모든 변수 타입을 추론할 수 있어야 합니다. Numba는 튜플, 문자열, 이넘, 정수, 실수 등의 간단한 스칼라 타입과 넘파이 배열 데이터 타입을 지원하지만 대표적으로 리스트, 딕셔너리 아규먼트에 대해서는 동작하지 않습니다. 이는 파이썬 리스트나 딕셔너리는..
파이썬 코드 C언어로 컴파일하기 (3) - 사이썬과 넘파이 파이썬 코드 C언어로 컴파일하기 (1) 파이썬 코드 C언어로 컴파일하기 (2) 이 포스트에서 살펴봤듯이 파이선의 리스트 객체는 실제 데이터가 아니라 데이터가 저장된 주소를 담고 있기에 리스트 객체가 가리키는 객체는 메모리의 어디든 존재할 수 있습니다. 따라서 역참조에 따른 부가비용이 발생합니다. 하지만 배열 객체는 기본 타입을 연속적인 RAM 블록에 저장하므로 주소 계산이 빠르고 파이썬에서는 array 모듈로 기본 타입에 대한 1차원 저장소를 제공합니다. 넘파이의 array 모듈을 사용하면 다차원 배열을 지원하죠. 따라서 파이썬에서 다음 주소를 요청하지 않고 연속적인 메모리 공간에 놓인 배열 객체를 이용해 오프셋을 이용해 다음 메모리 주소를 직접 계산하도록 접근한다면 파이썬 가상 머신을 호출할 필요가 없..
파이썬 코드 C언어로 컴파일하기 (2) 파이썬 코드 C언어로 컴파일하기 (1) 지난 포스트에서 calculate_z 함수를 사이썬으로 빌드하여 속도 개선을 얻었지만 calculate_z 함수 내용을 아예 건드리지 않고 그대로 빌드했습니다. 그렇다면 무엇을 어떻게 변경하면 추가적인 속도 개선을 얻을 수 있을까요? C언어와 파이썬의 여러 차이점 중 하나는 C언어는 변수의 타입을 미리 지정하는 정적언어인데 반해 파이썬은 변수가 어떤 타입이라도 참조할 수 있고 코드 어디에서든 참조하는 객체의 타입을 변경할 수 있는 동적언어라는 점입니다. 따라서 순수 파이썬으로 작성된 코드는 동적언어라는 특징 때문에 가상 머신에서 다음 연산에 사용할 기본적인 데이터 타입을 알 수 없으므로 기계어 수준의 최적화를 수행하기 어렵습니다. 실행 속도 대신 개발 속도를 선택한..
파이썬 코드 C언어로 컴파일하기 (1) 코드를 빠르게 하는 가장 쉬운 방법은 처리해야할 작업의 양, 데이터를 간소화하고 프로파일링을 통해 병목이 발생하는 구문을 최적화하는 것입니다. 특히, C 언어를 이용한 더 낮은 수준 (low level)으로 코드를 기계어로 컴파일하면 간단하게 큰 속도 향상을 얻을 수 있습니다. 특히, 같은 연산을 무수히 반복하는 루프를 포함하는 수학적인 코드에서는 임시 객체를 사용할 확률이 높기에 컴파일을 통해 큰 이득을 얻을 수 있습니다. 다만, 정규 표현식, 문자열 연산, 데이터베이스 등의 외부 라이브러리를 호출하는 코드는 속도 개선을 기대하기 어렵고 numpy 또한 벡터 연산을 집중해서 호출하고 임시 객체를 많이 생성하지 않아 컴파일이 별로 도움이 되지는 않습니다. (이미 C기반으로 최적화가 되어있기도 하고요) L..
행렬과 벡터 연산 (6) - numexpr 모듈 이용하기 행렬과 벡터 연산 (1) - 확산 방정식 예제 행렬과 벡터 연산 (2) - 확산 방정식 순수 파이썬 구현 행렬과 벡터 연산 (3) - 파이썬 리스트와 numpy 연산 속도 차이 행렬과 벡터 연산 (4) - numpy 배열을 이용한 확산 방정식 행렬과 벡터 연산 (5) - numpy 배열 메모리 최적화 지난 포스트를 거치면서 1) 메모리의 지역성, CPU 벡터 연산 활용을 지원하는 numpy 배열을 이용하고 2) 제자리 연산, numpy 함수 개량 등을 통해 확산 방정식의 속도를 크게 개선했습니다. 제자리 연산을 통해 메모리 재활용을 할 수 있어 캐시 미스를 줄일 수 있었지만 제자리 연산은 한 번에 하나의 연산에만 적용할 수 있는 단점이 있습니다. 예를 들어 A*B+C를 계산한다고 했을 때, 먼저 A*B ..
행렬과 벡터 연산 (5) - numpy 배열 메모리 최적화 행렬과 벡터 연산 (1) - 확산 방정식 예제 행렬과 벡터 연산 (2) - 확산 방정식 순수 파이썬 구현 행렬과 벡터 연산 (3) - 파이썬 리스트와 numpy 연산 속도 차이 행렬과 벡터 연산 (4) - numpy 배열을 이용한 확산 방정식 그렇다면 numpy 배열로 메모리 할당 횟수 (캐시 미스)를 줄인 이후에 메모리 할당 부분은 어떻게 최적화할 수 있을까요? 필요한 데이터를 캐시에서 찾지 못하면 메모리 할당은 단순히 메모리를 찾아보는 대시니 필요한 크기만큼의 데이터를 운영체제에 요청하게 됩니다. 캐시를 채우는 과정은 하드웨어적으로 최적화된 것에 반해 운영체제에 무언가를 요청할 때 발생하는 오버헤드는 (특히 메모리 할당) 커널과 통신해야 하므로 매우 큽니다. 제자리 연산 (in-place operat..

반응형