特定の方法で順序付けられていないデータのセットがありますが、明確にプロットすると2つの明確な傾向があります。ここでは、2つのシリーズが明確に区別されているため、単純な線形回帰は適切ではありません。2つの独立した線形トレンドラインを取得する簡単な方法はありますか?
記録のために、私はPythonを使用しており、機械学習を含むプログラミングとデータ分析にかなり満足していますが、絶対に必要な場合はRに飛び乗ります。
特定の方法で順序付けられていないデータのセットがありますが、明確にプロットすると2つの明確な傾向があります。ここでは、2つのシリーズが明確に区別されているため、単純な線形回帰は適切ではありません。2つの独立した線形トレンドラインを取得する簡単な方法はありますか?
記録のために、私はPythonを使用しており、機械学習を含むプログラミングとデータ分析にかなり満足していますが、絶対に必要な場合はRに飛び乗ります。
回答:
あなたの問題を解決するために、良いアプローチは、データセットに関する仮定と一致する確率モデルを定義することです。あなたの場合、おそらく線形回帰モデルの混合が必要です。あなたは、異なる混合物成分と異なるデータポイントを関連付けることにより、ガウス混合モデルと同様のモデル「説明変数の混合物」を作成することができます。
始めるためのコードを含めました。コード実装2つの回帰の混合物のための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推定)のための偉大なアドバイス(確率モデルを定義)およびコードを提供します。 次の2つの問題に対処する必要があります。
(2011-2012データで非常に明らかとあまり傾斜点の起伏に幾分明らかである)確率モデルからの逸脱に対処する方法。
どのようにEMアルゴリズム(または他のアルゴリズム)のための良い出発値を識別します。
アドレス#2に、使用することを検討してハフ変換。これは、特徴の線形ストレッチを見つけるために、ラドン変換として効率的に計算できる特徴検出アルゴリズムです。
ハフ変換で。元のプロットの特徴が共通の線に沿って、または1に十分近い場合、ハフ変換で生成される曲線のコレクションは、その共通の線に対応する共通の交差を持つ傾向があります。ハフ変換で最大強度のこれらの点を見つけることによって、我々は、元の問題に良い解決策を読み取ることができます。
これらのデータを開始するために、まず補助的なもの(軸、目盛り、ラベル)を切り取り、適切な測定のために右下の明らかに外れた点を切り取り、下の軸に沿って振りかけました。(そのようなものが切り取られていない場合でも、手順はうまく機能しますが、軸、フレーム、ティックの線形シーケンス、ラベルの線形シーケンス、さらには下軸に散発的に存在するポイントも検出します!)
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にあります。)
この画像の各ドットには、ここに表示されているハフ変換の狭い範囲の曲線に対応しています。それらは正弦波です:
hough2 = Radon[crop2, Method -> "Hough"] // ImageAdjust
これにより、問題がラインクラスタリング問題であるという意味が視覚的に明らかになります。ハフ変換はそれをポイントクラスタリング問題に還元し、任意のクラスタリング手法を適用できます。
この場合、クラスタリングは非常に明確であるため、ハフ変換の単純な後処理で十分です。変換で最大強度の位置を特定するために、コントラストを上げて、約1%の半径で変換をぼかしました。これは、元の画像のプロットポイントの直径に相当します。
blur = ImageAdjust[Blur[ImageAdjust[hough2, {1, 0}], 8]]
これらの推定フィットライン:結果を閾値と、その重心合理的に最大強度の点を識別する2つの小さなブロブにそれを狭く。
comp = MorphologicalComponents[blur, 0.777]) // Colorize
画像の左側は0度(水平)の方向に対応し、左から右に見ていくと、その角度は180度まで直線的に増加します。補間して、2つの塊がそれぞれ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
元々ゼロに設定されていたため、違いはありませんでしたへの参照を削除して修正しました。
この質問は別の質問にリンクしていました。私は実際にこの種の問題について学術研究を行いました。私の答え「最小平方根」フィッティングを確認してください?詳細については、複数の最小値を使用した近似方法。
whuberのハフ変換ベースのアプローチは、あなたが与えたものとして、単純なシナリオのための非常に良いソリューションです。次のような、より複雑なデータを使用したシナリオに取り組みました。
私の共著者と私はこれを「データの関連付け」の問題だと言いました。あなたはそれを解決しようとすると、主な問題は、可能なデータの組み合わせの指数関数的量による通常の組合せです。
「データ結合問題のためのガウス過程の混合の重複」という出版物があり、N曲線の一般的な問題に反復手法でアプローチし、非常に良い結果を出しました。論文にリンクされているMatlabコードを見つけることができます。
[更新] OMGP技術のA Pythonの実装を見つけることができGPClustライブラリ。
凸最適化問題を得るために問題を緩和した別の論文がありますが、まだ出版には受け入れられていません。それはあなたのデータを完璧に動作しますので、それは、2本の曲線に特異的です。興味があれば教えてください。
user1149913には優れた答え(+1)がありますが、2011年後半にデータコレクションがバラバラになったように見えるため、データのその部分を切り捨ててから、異なるランダムで数回実行する必要がありますあなたが得るものを見るために係数を開始します。
物事を行うための一つの簡単な方法は、その後、目で2つのセットにデータを分けるあなたが使用している線形どんなモデル技術を使用することです。Rでは、lm
関数になります。
または、目で2行合わせます。Rではabline
、これを行うために使用します。
データのごちゃ混ぜには、外れ値を持ち、そして最後に離れて落ち、まだ私は空想の方法は価値があるか分からないようで、目、2つのかなり明白ラインを持っています。