특정 방식으로 정렬되지 않은 데이터 세트가 있지만 명확하게 표시되면 두 가지 뚜렷한 경향이 있습니다. 간단한 선형 회귀 분석은 두 계열 사이의 명확한 구분 때문에 실제로는 적합하지 않습니다. 두 개의 독립적 인 선형 추세선을 얻는 간단한 방법이 있습니까?
레코드를 위해 파이썬을 사용하고 있으며 기계 학습을 포함하여 프로그래밍 및 데이터 분석에 상당히 익숙하지만 절대적으로 필요한 경우 R로 건너 뛸 수 있습니다.
특정 방식으로 정렬되지 않은 데이터 세트가 있지만 명확하게 표시되면 두 가지 뚜렷한 경향이 있습니다. 간단한 선형 회귀 분석은 두 계열 사이의 명확한 구분 때문에 실제로는 적합하지 않습니다. 두 개의 독립적 인 선형 추세선을 얻는 간단한 방법이 있습니까?
레코드를 위해 파이썬을 사용하고 있으며 기계 학습을 포함하여 프로그래밍 및 데이터 분석에 상당히 익숙하지만 절대적으로 필요한 경우 R로 건너 뛸 수 있습니다.
답변:
문제를 해결하려면 데이터 세트에 대한 가정과 일치하는 확률 모델을 정의하는 것이 좋습니다. 귀하의 경우에는 선형 회귀 모델이 혼합되어 있어야합니다. 다른 데이터 포인트를 다른 혼합 성분과 연결하여 가우스 혼합 모델과 유사한 "회귀 기 혼합"모델을 작성할 수 있습니다.
시작하는 데 필요한 코드를 포함 시켰습니다. 이 코드는 두 회귀 분석기의 혼합물에 대해 EM 알고리즘을 구현합니다 (더 큰 혼합물로 확장하기가 비교적 쉬워야합니다). 이 코드는 임의의 데이터 세트에 대해 상당히 강력한 것으로 보입니다. 그러나 선형 회귀 분석과 달리 혼합 모형에는 볼록하지 않은 목표가 있으므로 실제 데이터 세트의 경우 다른 임의의 시작점으로 몇 번의 시행을 수행해야 할 수도 있습니다.
import numpy as np
import matplotlib.pyplot as plt
import scipy.linalg as lin
#generate some random data
N=100
x=np.random.rand(N,2)
x[:,1]=1
w=np.random.rand(2,2)
y=np.zeros(N)
n=int(np.random.rand()*N)
y[:n]=np.dot(x[:n,:],w[0,:])+np.random.normal(size=n)*.01
y[n:]=np.dot(x[n:,:],w[1,:])+np.random.normal(size=N-n)*.01
rx=np.ones( (100,2) )
r=np.arange(0,1,.01)
rx[:,0]=r
#plot the random dataset
plt.plot(x[:,0],y,'.b')
plt.plot(r,np.dot(rx,w[0,:]),':k',linewidth=2)
plt.plot(r,np.dot(rx,w[1,:]),':k',linewidth=2)
# regularization parameter for the regression weights
lam=.01
def em():
# mixture weights
rpi=np.zeros( (2) )+.5
# expected mixture weights for each data point
pi=np.zeros( (len(x),2) )+.5
#the regression weights
w1=np.random.rand(2)
w2=np.random.rand(2)
#precision term for the probability of the data under the regression function
eta=100
for _ in xrange(100):
if 0:
plt.plot(r,np.dot(rx,w1),'-r',alpha=.5)
plt.plot(r,np.dot(rx,w2),'-g',alpha=.5)
#compute lhood for each data point
err1=y-np.dot(x,w1)
err2=y-np.dot(x,w2)
prbs=np.zeros( (len(y),2) )
prbs[:,0]=-.5*eta*err1**2
prbs[:,1]=-.5*eta*err2**2
#compute expected mixture weights
pi=np.tile(rpi,(len(x),1))*np.exp(prbs)
pi/=np.tile(np.sum(pi,1),(2,1)).T
#max with respect to the mixture probabilities
rpi=np.sum(pi,0)
rpi/=np.sum(rpi)
#max with respect to the regression weights
pi1x=np.tile(pi[:,0],(2,1)).T*x
xp1=np.dot(pi1x.T,x)+np.eye(2)*lam/eta
yp1=np.dot(pi1x.T,y)
w1=lin.solve(xp1,yp1)
pi2x=np.tile(pi[:,1],(2,1)).T*x
xp2=np.dot(pi2x.T,x)+np.eye(2)*lam/eta
yp2=np.dot(pi[:,1]*y,x)
w2=lin.solve(xp2,yp2)
#max wrt the precision term
eta=np.sum(pi)/np.sum(-prbs/eta*pi)
#objective function - unstable as the pi's become concentrated on a single component
obj=np.sum(prbs*pi)-np.sum(pi[pi>1e-50]*np.log(pi[pi>1e-50]))+np.sum(pi*np.log(np.tile(rpi,(len(x),1))))+np.log(eta)*np.sum(pi)
print obj,eta,rpi,w1,w2
try:
if np.isnan(obj): break
if np.abs(obj-oldobj)<1e-2: break
except:
pass
oldobj=obj
return w1,w2
#run the em algorithm and plot the solution
rw1,rw2=em()
plt.plot(r,np.dot(rx,rw1),'-r')
plt.plot(r,np.dot(rx,rw2),'-g')
plt.show()
이 스레드의 다른 곳에서 user1149913은 강력한 조언 (EM 추정)을위한 훌륭한 조언 (확률 모델 정의)과 코드를 제공합니다. 두 가지 문제가 해결되어야합니다.
확률 모델에서 벗어남에 대처하는 방법 (2011-2012 데이터에서 매우 분명하고 기울기가 적은 점의 파동에서 다소 분명함).
EM 알고리즘 (또는 다른 알고리즘)의 올바른 시작 값을 식별하는 방법
# 2를 해결하려면 Hough 변환 사용을 고려하십시오 . 이것은 특징의 선형 스트레치를 찾기 위해 효율적으로 라돈 변환 으로 계산할 수있는 특징 탐지 알고리즘입니다 .
개념적으로 Hough 변환은 선 집합을 나타냅니다. 평면의 선은 기울기 와 고정 원점으로부터의 거리 로 매개 변수화 할 수 있습니다 . 이 좌표 시스템 의 점은 단일 선을 지정합니다. 원래 그림의 각 점은 해당 점을 통과하는 선의 연필을 결정합니다.이 연필 은 Hough 변환에서 곡선 으로 나타납니다 . 원래 플롯의 피처가 공통 선을 따라 떨어지거나 1에 가까워지면 Hough 변환에서 생성 된 곡선 모음이 해당 공통 선에 해당하는 공통 교차점을 갖는 경향이 있습니다. Hough 변환에서 가장 큰 강도의 점을 찾아서 원래 문제에 대한 좋은 솔루션을 읽을 수 있습니다.y x , y
이 데이터를 시작하기 위해 먼저 보조 재료 (축, 눈금 표시 및 레이블)를 잘라 내고 오른쪽 하단의 명백한 지점을 잘라내어 아래쪽 축을 따라 뿌렸습니다. (그 물건이 잘리지 않으면 절차는 여전히 잘 작동하지만 축, 프레임, 진드기의 선형 시퀀스, 선형 레이블 및 심지어 축을 아래쪽 축에 산발적으로 감지합니다)
img = Import["http://i.stack.imgur.com/SkEm3.png"]
i = ColorNegate[Binarize[img]]
crop2 = ImageCrop[ImageCrop[i, {694, 531}, {Left, Bottom}], {565, 467}, {Right, Top}]
(이 코드와 나머지 코드는 Mathematica에 있습니다.)
이 이미지의 각 점은 여기에서 볼 수있는 Hough 변환의 좁은 범위의 곡선에 해당합니다. 그들은 사인파입니다.
hough2 = Radon[crop2, Method -> "Hough"] // ImageAdjust
이것은 질문이 라인 클러스터링 문제 라는 시각적 의미를 나타냅니다 . 허프 변환은 포인트 클러스터링 문제로 줄여서 원하는 클러스터링 방법을 적용 할 수 있습니다.
이 경우 클러스터링이 매우 명확하여 Hough 변환의 간단한 사후 처리가 완료되었습니다. 변환에서 가장 큰 강도의 위치를 식별하기 위해 대비를 늘리고 약 1 %의 반경으로 변환을 흐리게했습니다. 이는 원본 이미지의 플롯 포인트 직경과 비슷합니다.
blur = ImageAdjust[Blur[ImageAdjust[hough2, {1, 0}], 8]]
결과를 임계 값으로 지정하면 중심이 가장 큰 강도의 점을 합리적으로 식별하는 두 개의 작은 얼룩으로 범위가 좁아졌습니다.
comp = MorphologicalComponents[blur, 0.777]) // Colorize
( 의 임계 값은 경험적으로 발견되었습니다. 두 영역 만 생성하고 두 영역 중 작은 영역은 가능한 한 작습니다.)
이미지의 왼쪽은 0도 (가로) 방향에 해당하며 왼쪽에서 오른쪽으로 보면 각도가 선형으로 180 도로 증가합니다. 보간, 나는 두 얼룩이 각각 19도 및 57.1 도의 중심에 있다고 계산합니다. 블롭의 수직 위치에서 절편을 읽을 수도 있습니다. 이 정보는 초기 적합치를 산출합니다.
width = ImageDimensions[blur][[1]];
slopes = Module[{x, y, z}, ComponentMeasurements[comp, "Centroid"] /.
Rule[x_, {y_, z_}] :> Round[((y - 1/2)/(width - 1)) 180., 0.1]
]
{19., 57.1}
비슷한 방식으로 이러한 기울기에 해당하는 절편을 계산하여 다음과 같은 결과를 얻을 수 있습니다.
(빨간색 선은 이전 그림의 작은 분홍색 점에 해당하고 파란색 선은 더 큰 아쿠아 얼룩에 해당합니다.)
대부분의 경우이 접근 방식은 첫 번째 문제를 자동으로 처리했습니다. 선형성의 편차는 가장 큰 강도의 점이 지워지지 만 일반적으로 많이 이동하지는 않습니다. 솔직하게 외곽에있는 점은 후프 변환 전체에서 낮은 수준의 노이즈에 영향을 미치며 후 처리 과정에서는 사라집니다.
이 시점에서 이러한 추정값을 EM 알고리즘 또는 가능성 최소화 기 (좋은 추정값이 주어지면 빠르게 수렴 됨)의 시작 값으로 제공 할 수 있습니다. 그러나 반복적으로 가중 된 최소 제곱 과 같은 강력한 회귀 추정기를 사용하는 것이 좋습니다 . 모든 지점에 회귀 가중치 를 제공 할 수 있습니다. 가중치가 낮 으면 점이 선에 닿지 않음을 나타냅니다. 원하는 경우이 가중치를 사용하여 각 점을 해당 선에 지정하십시오. 그런 다음 점을 분류 한 후 두 점 그룹에서 보통 최소 제곱 (또는 다른 회귀 절차)을 별도로 사용할 수 있습니다.
rotation
원래는 0으로 설정되었으므로 아무런 차이가 없었습니다.
이 질문은 다른 질문 과 관련이 있습니다. 실제로 이런 종류의 문제에 대한 학문적 연구를했습니다. 내 대답 "최소 제곱근"피팅을 확인하십시오. 자세한 내용은 최소값이 여러 개인 피팅 방법입니다 .
whuber의 Hough 변환 기반 접근 방식은 사용자가 제공 한 간단한 시나리오에 매우 적합한 솔루션입니다. 나는 다음과 같이보다 복잡한 데이터로 시나리오를 작업했습니다.
저의 공동 저자들과 저는 이것을 "데이터 연결"문제로 표시했습니다. 해결하려고 할 때 주된 문제는 일반적으로 기하 급수적 인 데이터 조합으로 인한 조합입니다.
우리는 반복적 인 기술로 N 곡선의 일반적인 문제에 접근하여 매우 좋은 결과를주는 " 데이터 연관 문제에 대한 가우시안 프로세스의 겹치는 혼합물 "출판물을 보유하고 있습니다 . 종이에 링크 된 Matlab 코드를 찾을 수 있습니다.
[업데이트] OMGP 기법의 Python 구현은 GPClust 라이브러리 에서 찾을 수 있습니다 .
볼록 최적화 문제를 해결하기 위해 문제를 완화 한 또 다른 논문이 있지만 아직 출판되지 않았습니다. 2 개의 곡선에만 적용되므로 데이터에서 완벽하게 작동합니다. 관심이 있으시면 알려주십시오.
user1149913은 훌륭한 답변 (+ 1)을 가지고 있지만 2011 년 말에 데이터 수집이 분리 된 것으로 보입니다. 따라서 데이터의 해당 부분을 잘라낸 다음 여전히 다른 임의의 항목으로 몇 번 실행해야합니다 당신이 무엇을 얻을 시작 계수.
일을하는 간단한 방법은 데이터를 눈으로 두 세트로 분리 한 다음 익숙한 선형 모델 기술을 사용하는 것입니다. R에서는 lm
함수가됩니다.
또는 두 줄을 눈으로 맞 춥니 다. R에서는 abline
이 작업을 수행 하는 데 사용 합니다.
데이터가 뒤죽박죽 났고, 이상 치가 있으며 끝이났습니다.