我有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
上发布了完整数组here(它对应于下面代码中的dataPoints
列表。)
现在,我最初需要找到此elbow point
曲线的L-shape
,我感谢this post。
现在,在下图中,红色矢量p
代表肘点。我想在向量x=(?,?)
上找到b
(黄色星)点,它对应于p
到b
的正交投影。
情节上的红点是我获得的红点(显然是错误的)。我得到了以下内容:
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
的投影由其起点和终点定义,即s
和x
(黄色星),则遵循那个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()
答案 0 :(得分:3)
如果您使用绘图直观地确定解决方案是否正确,则必须在每个轴上使用相同的比例绘制数据,即使用plt.axis('equal')
。如果轴没有相同的刻度,则曲线之间的角度会失真。
答案 1 :(得分:1)
首先,重点是〜(50,37)p
或s+p
?如果p
,那可能就是您的问题!如果p
变量的Y分量为正数,则在获得点积时,您将无法获得预期的结果。
假设该点为s+p
,如果有一点Post-It涂鸦是正确的,
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
未经测试!因人而异。希望这会有所帮助。