Мое следующее решение основано на алгоритме RANSAC .Это метод для подгонки математической модели (например, линии) к данным с большим количеством выбросов.
RANSAC - это один конкретный метод из области устойчивая регрессия .
Мое решение ниже сначала соответствует RANSAC.Затем вы удаляете точки данных, близкие к этой строке, из своего набора данных (что соответствует сохранению выбросов), снова подбираете RANSAC, удаляете данные и т. Д., Пока не останется очень мало точек.
Такие подходы всегдаиметь параметры, которые зависят от данных (например, уровень шума или близость линий).В следующем решении MIN_SAMPLES
и residual_threshold
- это параметры, которые могут потребовать некоторой адаптации к структуре ваших данных:
import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
MIN_SAMPLES = 3
x = np.linspace(0, 2, 100)
xs, ys = [], []
# generate points for thee lines described by a and b,
# we also add some noise:
for a, b in [(1.0, 2), (0.5, 1), (1.2, -1)]:
xs.extend(x)
ys.extend(a * x + b + .1 * np.random.randn(len(x)))
xs = np.array(xs)
ys = np.array(ys)
plt.plot(xs, ys, "r.")
colors = "rgbky"
idx = 0
while len(xs) > MIN_SAMPLES:
# build design matrix for linear regressor
X = np.ones((len(xs), 2))
X[:, 1] = xs
ransac = linear_model.RANSACRegressor(
residual_threshold=.3, min_samples=MIN_SAMPLES
)
res = ransac.fit(X, ys)
# vector of boolean values, describes which points belong
# to the fitted line:
inlier_mask = ransac.inlier_mask_
# plot point cloud:
xinlier = xs[inlier_mask]
yinlier = ys[inlier_mask]
# circle through colors:
color = colors[idx % len(colors)]
idx += 1
plt.plot(xinlier, yinlier, color + "*")
# only keep the outliers:
xs = xs[~inlier_mask]
ys = ys[~inlier_mask]
plt.show()
На следующем графике точки, показанные в виде звезд, относятся к скоплениям, обнаруженным моимкод.Вы также видите несколько точек, изображенных в виде кружков, которые являются точками, остающимися после итераций.Несколько черных звезд образуют скопление, от которого можно избавиться, увеличив MIN_SAMPLES
и / или residual_threshold
.