728x90
반응형
1. 개요
주어진 스칼라 값들의 분포로부터 새로운 값이 들어왔을 때 이것이 몇 분위의 값을 갖는지 알고 싶을 때가 있다.
예를들어, [1,......,1000] 이라는 값이 있다면 50.5라는 값은 여기서 몇 분위의 값인지 알고 싶은 것이다.
scikt-learn에는 sklearn.preprocessing.QuantileTransformer라는 기능은 이를 위한 기능을 제공하지만 버전이 업그레이드 됨에 따라 문제가 생기기 쉽다.
이를 방지하기 위해 numpy array 기능으로 만든 것을 만들어봤다.
2. 코드
class quantiletransformer:
'''
numpy array를 활용해서 주어진 값에 대한 quantile transformation을 하는 기능
fit : 주어진 훈련 데이터에 대해 균등한 분포로 quantile값을 추출함.
이후 해당 분포의 최소값과 최대값 샘플을 1개 씩 추출함.
샘플들 간에는 중복값은 존재하지 않게 만듬.
'''
import numpy as np
def __init__(self,n_subsample=1000,decimals=3):
self.n_subsample=n_subsample
self.reference_values=np.array([])
self.quantiles=np.linspace(0,1,n_subsample) # quantile을 생성함 0.001,.....0.999,1.000
self.decimals=decimals # 참조값의 소수 몇 번째 자리까지 인정할지를 결정함.
def fit(self,x):
'''
x : 1차원 벡터 numpy array
0부터 1까지 quantile을 균등하게 나눈 후에 이에 해당하는 값들을 reference_values에 저장함.
'''
self.reference_values=np.round(np.quantile(x,self.quantiles),decimals=self.decimals) # 이미 정렬된 값임
def predict(self,x):
'''
주어진 값이 원래 분포에서 quantile값이 얼마였는지 유추하는 기능
x : 1차원 벡터 numpy array
'''
# 대략적인 값의 구간 산출
q=np.searchsorted(a=self.reference_values, v=x, side='right')
right_wh=np.clip(q+1,0,self.n_subsample)
left_wh=np.clip(q-1,0,self.n_subsample-1)
left_score=self.reference_values[left_wh]
right_score=self.reference_values[right_wh]
coef=np.clip((x-left_score)/(right_score-left_score),0.0,1.0)
# quantile값 조정
mq=np.clip((q-1+coef)/self.n_subsample,0.0,1.0)
return mq
3. 테스트
import numpy as np
qtf=quantiletransformer(n_subsample=500)
random_values=[
np.random.randn(500)*0.01,
np.random.randn(500)*0.05+1,
np.random.randn(500)*10+2
]
random_values=np.concatenate(random_values,axis=None)
# fitting
qtf.fit(x=random_values)
# 1개 값 예측
print(qtf.predict(x=20))
# 여러 개 값 예측
print(qtf.predict(x=np.array([1,2,3,20,-8]))
# 저장된 reference값 확인
print(qtf.reference_values[:100])
# 상응하는 quantile값 확인
print(qtf.quantiles[:100])
# 저장하기
import dill
path='/path/to/save.dill'
with open(path,'wb') as f:
dill.dump(qtf,f)
f.close()
# 새로운 터미널 열고 다시 진행
import dill
import numpy as np #<-numpy array는 다시 로딩해줘야함.
path='/path/to/save.dill'
with open(path,'rb') as f:
qtf2=dill.load(f)
f.close()
# 1개 값 예측
print(qtf.predict(x=20))
# 여러 개 값 예측
print(qtf.predict(x=np.array([1,2,3,20,-8]))
# 저장된 reference값 확인
print(qtf.reference_values[:100])
# 상응하는 quantile값 확인
print(qtf.quantiles[:100])
728x90
반응형