У меня есть наборы точек x, y, z в трехмерном пространстве и еще одна переменная с именем charge
, которая представляет количество заряда, отложенного в определенной координате x, y, z. Я хотел бы сделать взвешенный (взвешенный по количеству заряда, накопленного в детекторе, который просто соответствует более высокому весу для большего заряда) для этих данных, чтобы они проходили через заданную точку, вершину.
Теперь, когда я делал это для 2D, я пробовал всевозможные методы (приводя вершину к началу координат и выполняя такое же преобразование для всех других точек и заставляя подгонку проходить через начало координат, придавая вершине действительно большой вес), но ни один из них не был так хорош, как ответ, данный Хайме здесь: Как сделать полиномиальную подгонку с фиксированными точками
Он использует метод множителей Лагранжа, с которым я смутно знаком по студенческому курсу Advanced Multi variable, но не более того, и не похоже, что преобразование этого кода будет таким же простым, как простое добавление координаты z. (Обратите внимание, что хотя код не учитывает сумму депонированного платежа, он все же дал мне наилучшие результаты). Мне было интересно, есть ли версия того же алгоритма, но в 3D. Я также связался с автором ответа в Gmail, но не получил от него ответа.
Вот еще немного информации о моих данных и о том, что я пытаюсь сделать в 2D: Как взвесить точки на точечной диаграмме для подбора?
Вот мой код для этого таким образом, что я заставляю вершину находиться в начале координат, а затем подбираю настройку данных fit_intercept=False
. В настоящее время я использую этот метод для 2D-данных, так как не уверен, есть ли 3D-версия для множителей Лагранжа, но есть способы линейной регрессии сделать это в 3D, например, здесь: Подгонка линии в 3D:
import numpy as np
import sklearn.linear_model
def plot_best_fit(image_array, vertexX, vertexY):
weights = np.array(image_array)
x = np.where(weights>0)[1]
y = np.where(weights>0)[0]
size = len(image_array) * len(image_array[0])
y = np.zeros((len(image_array), len(image_array[0])))
for i in range(len(np.where(weights>0)[0])):
y[np.where(weights>0)[0][i]][np.where(weights>0)[1][i]] = np.where(weights>0)[0][i]
y = y.reshape(size)
x = np.array(range(len(image_array)) * len(image_array[0]))
weights = weights.reshape((size))
for i in range(len(x)):
x[i] -= vertexX
y[i] -= vertexY
model = sklearn.linear_model.LinearRegression(fit_intercept=False)
model.fit(x.reshape((-1, 1)),y,sample_weight=weights)
line_x = np.linspace(0, 512, 100).reshape((-1,1))
pred = model.predict(line_x)
m, b = np.polyfit(np.linspace(0, 512, 100), np.array(pred), 1)
angle = math.atan(m) * 180/math.pi
return line_x, pred, angle, b, m
image_array
— это массив numpy, а vertexX
и vertexY
— это координаты x и y вершины соответственно. Вот мои данные: https://uploadfiles.io/bbhxo. Я не могу создать игрушечные данные, так как нет простого способа воспроизвести эти данные, они были получены с помощью Geant4, моделирующего нейтрино, взаимодействующее с ядром аргона. Я не хочу избавляться от сложности данных. И это конкретное событие оказывается тем, для которого мой код не работает, я не уверен, смогу ли я сгенерировать данные специально, чтобы мой код не работал с ним.
fit_intercept=False
. - person Andrew Guy   schedule 13.08.2018