Предположим, кто-то хотел использовать numpy
для векторизации вычитаний массива.В качестве примера рассмотрим следующую настройку (код ниже): Я вычисляю евклидово расстояние между некоторыми (x, y) точками с данным центроидом.Причина этого вопроса в том, что приведенный ниже пример кода работает точно для 2-х измерений (x
и y
), но я бы хотел обобщить и адаптировать эту операцию к N-измерениям в целях адаптации моего Алгоритм k-средних .Приведенный ниже код предназначен только для вычисления ошибки с учетом указанного центроида.
import numpy as np
np.random.seed(10) ## for reproducibility
x = np.random.normal(40, 10, 10)
y = np.random.normal(50, 10, 10)
data = np.array([x, y])
centroids = np.array([[25, 75], [45, 55], [20, 80], [40, 60]])
k = len(centroids)
print("\nDATA:\n{}\n\n{} CENTROIDS:\n{}\n".format(data, k, centroids))
partials = np.array([[(data[i] - centroid[i])**2 for i in range(len(data))] for centroid in centroids])
res = np.sqrt(np.sum(partials))
print("\nPARTIAL DISTANCES:\n{}\n\nTOTAL DISTANCE:\n{}\n".format(partials, res))
Запуск приведенного выше кода приводит к следующему выводу:
DATA:
[[53.31586504 47.15278974 24.54599708 39.9161615 46.21335974 32.79914439
42.65511586 41.08548526 40.04291431 38.25399789]
[54.3302619 62.03037374 40.34934329 60.28274078 52.2863013 54.45137613
38.63397788 51.35136878 64.84537002 39.20195114]]
4 CENTROIDS:
[[25 75]
[45 55]
[20 80]
[40 60]]
PARTIAL DISTANCES:
[[[8.01788213e+02 4.90746093e+02 2.06118652e-01 2.22491874e+02
4.50006631e+02 6.08266533e+01 3.11703116e+02 2.58742836e+02
2.26289271e+02 1.75668460e+02]
[4.27238073e+02 1.68211205e+02 1.20066801e+03 2.16597719e+02
5.15912109e+02 4.22245943e+02 1.32248756e+03 5.59257758e+02
1.03116510e+02 1.28150030e+03]]
[[6.91536114e+01 4.63450368e+00 4.18366235e+02 2.58454139e+01
1.47224186e+00 1.48860878e+02 5.49848164e+00 1.53234257e+01
2.45726985e+01 4.55085444e+01]
[4.48549123e-01 4.94261549e+01 2.14641742e+02 2.79073501e+01
7.36416063e+00 3.00988153e-01 2.67846680e+02 1.33125097e+01
9.69313108e+01 2.49578348e+02]]
[[1.10994686e+03 7.37273991e+02 2.06660894e+01 3.96653489e+02
6.87140229e+02 1.63818097e+02 5.13254274e+02 4.44597689e+02
4.01718414e+02 3.33208439e+02]
[6.58935454e+02 3.22907468e+02 1.57217458e+03 3.88770311e+02
7.68049096e+02 6.52732182e+02 1.71114779e+03 8.20744071e+02
2.29662810e+02 1.66448079e+03]]
[[1.77312262e+02 5.11624011e+01 2.38826206e+02 7.02889396e-03
3.86058392e+01 5.18523215e+01 7.04964021e+00 1.17827824e+00
1.84163795e-03 3.04852335e+00]
[3.21459301e+01 4.12241752e+00 3.86148309e+02 7.99423486e-02
5.95011476e+01 3.07872269e+01 4.56506901e+02 7.47988219e+01
2.34776106e+01 4.32558836e+02]]]
TOTAL DISTANCE:
163.00230640508593
Я использую вложенный двойной цикл forв этом коде.Я заметил, что numpy.subtract
не имеет axis
kwarg.Я думал, что смогу numpy.tile
центроидам выполнить вычитание, но это кажется неэффективным для больших N, особенно если для сходимости требуется много итераций.Есть ли другой способ векторизации этой операции?