Окружность Python, подходящая к точкам данных, менее чувствительна к случайному шуму

У меня есть набор измеренных радиусов (t+эпсилон+ошибка) под равноудаленными углами. Модель представляет собой круг радиуса (R) с центром в (r, альфа) с добавленным небольшим шумом и некоторыми случайными значениями ошибки, которые намного больше, чем шум.

Задача состоит в том, чтобы найти центр модели круга (r, Alpha) и радиус круга (R). Но он не должен быть слишком чувствительным к случайной ошибке (в приведенных ниже точках данных 7 и 14).

Некоторые радиусы могут отсутствовать, поэтому простое среднее здесь не сработает.

Я пробовал оптимизацию методом наименьших квадратов, но она существенно реагирует на ошибку.

Есть ли способ оптимизировать наименьшие дельты, но не наименьшие квадраты дельты в Python?

Model:
n=36
R=100
r=10
Alpha=2*Pi/6

Data points:
[95.85, 92.66, 94.14, 90.56, 88.08, 87.63, 88.12, 152.92, 90.75, 90.73, 93.93, 92.66, 92.67, 97.24, 65.40, 97.67, 103.66, 104.43, 105.25, 106.17, 105.01, 108.52, 109.33, 108.17, 107.10, 106.93, 111.25, 109.99, 107.23, 107.18, 108.30, 101.81, 99.47, 97.97, 96.05, 95.29]


person Oscar    schedule 16.02.2014    source источник
comment
Вы просто хотите выбросить выбросы?   -  person Slater Victoroff    schedule 16.02.2014
comment
@SlaterTyranus да, я хочу, чтобы они не влияли на мой подогнанный круг   -  person Oscar    schedule 16.02.2014


Ответы (2)


Отвечая на ваш последний вопрос

Есть ли способ оптимизировать наименьшие дельты, но не наименьшие квадраты дельты в Python?

Да, выберите метод оптимизации (например, симплекс с уклоном, реализованный в scipy.optimize.fmin) и используйте сумму абсолютных отклонений в качестве оценочной функции. Ваш набор данных невелик, я полагаю, что любой метод оптимизации общего назначения быстро сойдется. (В случае нелинейной аппроксимации методом наименьших квадратов также можно использовать алгоритм оптимизации общего назначения, но чаще используется алгоритм Левенберга-Марквардта, который минимизирует суммы квадратов.)

Если вас интересует, имеет ли теоретическое обоснование минимизация абсолютных отклонений вместо квадратов, см. раздел Численные рецепты, глава Надежная оценка.

С практической точки зрения сумма абсолютных отклонений может не иметь однозначного минимума. В тривиальном случае двух точек, скажем, (0,5) и (1,9) и постоянной функции y=a любое значение a между 5 и 9 дает ту же сумму (4). Нет такой проблемы, когда отклонения возводятся в квадрат.

Если минимизация абсолютных отклонений не сработает, вы можете рассмотреть эвристическую процедуру для выявления и удаления выбросов. Например, RANSAC или ROUT.

person marcin    schedule 17.02.2014

Кажется, что ваша главная проблема здесь будет заключаться в удалении выбросов. Есть несколько способов сделать это, но для вашего приложения лучше всего, вероятно, просто удалить элементы на основе их расстояния от медианы (поскольку медиана гораздо менее чувствительна к выбросам, чем среднее значение).

Если вы используете numpy, это будет выглядеть так:

def remove_outliers(data_points, margin=1.5):
    nd = np.abs(data_points - np.median(data_points))
    s = nd/np.median(nd)
    return data_points[s<margin]

После чего следует запустить метод наименьших квадратов.

Если вы не используете numpy, вы можете сделать что-то подобное с собственными списками Python:

def median(points):
    return sorted(points)[len(points)/2] # evaluates to an int in python2

def remove_outliers(data_points, margin=1.5):
    m = median(data_points)
    centered_points = [abs(point - m) for point in data_points]
    centered_median = median(centered_points)
    ratios = [datum/centered_median for datum in centered_points]
    return [point for i, point in enumerate(data_points) if ratios[i]>margin]

Если вы хотите просто не подсчитывать выбросы так сильно, вы можете просто вычислить среднее значение вашего набора данных, что является просто линейным эквивалентом оптимизации методом наименьших квадратов.

Если вы ищете что-то получше, я могу предложить пропустить ваши данные через какой-нибудь low передать фильтр, но я не думаю, что это действительно нужно здесь.

Фильтр нижних частот, вероятно, был бы лучшим, что вы можете сделать следующим образом: (Обратите внимание, альфа — это число, с которым вам придется возиться, чтобы получить желаемый результат.)

def low_pass(data, alpha):
    new_data = [data[0]]
    for i in range(1, len(data)):
        new_data.append(alpha * data[i] + (1 - alpha) * new_data[i-1])
    return new_data

В этот момент ваша оптимизация методом наименьших квадратов должна работать нормально.

person Slater Victoroff    schedule 16.02.2014
comment
Спасибо за ответ. Проблема в том, что размер выбросов не определен, поэтому я ищу код, который будет работать как оптимизация методом наименьших квадратов, но не для квадратов, чтобы минимизировать вклад выбросов в общий результат. - person Oscar; 16.02.2014
comment
@Oscar Приведенный выше код не предполагает какого-либо размера выбросов, это просто отклонение от стандарта. - person Slater Victoroff; 16.02.2014
comment
Первый код дает только целочисленные массивы, один элемент которых можно преобразовать в индекс. Второй удаляет 83% точек данных. Есть ли способ оптимизировать наименьшие дельты, а не квадраты? - person Oscar; 16.02.2014
comment
Обновил проблему. Некоторые радиусы могут отсутствовать, тогда среднее не сработает. Я думал о преобразовании Фурье и рассматривал радиусы как синусоиду, но это сложно для моего уровня новичка. - person Oscar; 16.02.2014
comment
@Oscar Вы можете изменить точную отсечку в соответствии с вашей проблемой, но я могу опубликовать пример подхода с фильтром нижних частот. Преобразование Фурье здесь не имеет смысла. - person Slater Victoroff; 16.02.2014