7

350 のドキュメント スコアがあり、それらをプロットすると、次のような形状になります。

docScores = [(0, 68.62998962), (1, 60.21374512), (2, 54.72480392), 
             (3, 50.71389389), (4, 49.39723969), ...,  
             (345, 28.3756237), (346, 28.37126923), 
             (347, 28.36397934), (348, 28.35762787), (349, 28.34219933)]

ここに完全な配列を投稿しました(以下のコードのリストにpastebin対応しています)。dataPoints

得点分布

さて、もともとelbow pointこの曲線の を見つける必要がありましたが、この記事L-shapeのおかげで見つかりました。

次のプロットでは、赤いベクトルpはエルボ ポイントを表します。の正射影に対応するベクトルx=(?,?)上の点 (黄色い星)を見つけたいと思います。bpb

ここに画像の説明を入力

プロットの赤い点は私が得たものです (明らかに間違っています)。次のようにして取得します。

b_hat = b / np.linalg.norm(b)    #unit vector of b
proj_p_onto_b = p.dot(b_hat)*b_hat
red_point = proj_p_onto_b + s

pここで、への射影がb開始点と終了点、つまりsx(黄色の星)によって定義される場合、 proj_p_onto_b = x - s、したがってx = proj_p_onto_b + s?

私はここで間違いを犯しましたか?

編集: @cxw への回答として、エルボ ポイントを計算するためのコードを次に示します。

def findElbowPoint(self, rawDocScores):
    dataPoints = zip(range(0, len(rawDocScores)), rawDocScores)
    s = np.array(dataPoints[0])
    l = np.array(dataPoints[len(dataPoints)-1])
    b_vect = l-s
    b_hat = b_vect/np.linalg.norm(b_vect)
    distances = []
    for scoreVec in dataPoints[1:]:
        p = np.array(scoreVec) - s
        proj = p.dot(b_hat)*b_hat
        d = abs(np.linalg.norm(p - proj)) # orthgonal distance between b and the L-curve
        distances.append((scoreVec[0], scoreVec[1], proj, d))

    elbow_x = max(distances, key=itemgetter(3))[0]
    elbow_y = max(distances, key=itemgetter(3))[1]
    proj = max(distances, key=itemgetter(3))[2]
    max_distance = max(distances, key=itemgetter(3))[3]

    red_point = proj + s

編集:プロットのコードは次のとおりです:

>>> l_curve_x_values = [x[0] for x in docScores]
>>> l_curve_y_values = [x[1] for x in docScores]
>>> b_line_x_values = [x[0] for x in docScores]
>>> b_line_y_values = np.linspace(s[1], l[1], len(docScores))
>>> p_line_x_values = l_curve_x_values[:elbow_x]
>>> p_line_y_values = np.linspace(s[1], elbow_y, elbow_x)
>>> plt.plot(l_curve_x_values, l_curve_y_values, b_line_x_values, b_line_y_values, p_line_x_values, p_line_y_values)
>>> red_point = proj + s
>>> plt.plot(red_point[0], red_point[1], 'ro')
>>> plt.show()
4

2 に答える 2

4

プロットを使用して解が正しいかどうかを視覚的に判断する場合は、各軸で同じスケールを使用してデータをプロットする必要があります。つまり、 を使用しますplt.axis('equal')。軸のスケールが等しくない場合、線間の角度はプロットで歪んでいます。

于 2016-10-06T14:02:54.353 に答える
1

まずポイントは ~(50, 37)ps+p? の場合p、それがあなたの問題かもしれません。変数の Y コンポーネントpが正の場合、内積を行ったときに期待する結果が得られません。

その点がs+pだとすると、ちょっとした付箋の落書きが正しければ、

p_len = np.linalg.norm(p)
p_hat = p / p_len
red_len = p_hat.dot(b_hat) * p_len   # red_len = |x-s|
    # because p_hat . b_hat = 1 * 1 * cos(angle) = |x-s| / |p|
red_point = s + red_len * b_hat

未検証!YMMV。お役に立てれば。

于 2016-10-06T12:12:43.370 に答える