Сравнение расстояний между массивами?


Как сравнить сходство между двумя массивами? Скажем, у меня есть:

Base Array: [.5,0,0,0,.25,0,0,.25,0,0,0,0]

Array 1: [1,0,0,0,1,0,0,1,0,0,0,0]
Array 2: [0,0,1,0,0,0,1,0,0,1,0,0]
Array 3: [1,0,0,0,0,0,0,0,0,0,0,0]

Что касается приведенных выше массивов, то ответом должен быть массив 1. Ответ-массив 1, потому что элементы массива "ближе" по структуре к элементам массива базового массива. Отличаясь от массива 3, .25 ближе к 1, чем 0. Другой пример:

Base Array: [.75,0,0,0,0,0,0,0,.25,0,0,0]

Array 1: [1,0,0,0,1,0,0,1,0,0,0,0]
Array 2: [0,0,1,0,0,0,1,0,0,1,0,0]
Array 3: [1,0,0,0,0,0,0,0,0,0,0,0]

Который в этом случае массив 3 должен быть ответом.

Однако, используя мой текущий algo (который я дам позже), ответ становится массивом 3. Вот что я использую:

for (int i = 0; i < basearray.Length; i++)
{
  temp = (basearray[i] - arrayX[i]);
  dist += temp * temp;
}

Итак, я думаю, что с моим Альго что-то не так? Или, может быть, мне нужно использовать "другой" вид алгоритма, а не расстояние (так как по существу,.25 ближе к 0, чем 1, но то, что я хочу, это иначе).

Спасибо!

Обновление:

Я нашел ответ! Спасибо всем за помощь. Вот оно:

float[] pbaseArrX = new float[3];
float[] pcompArrX = new float[3];

float dist1 = 0, dist2 = 0;

for (int i = 0; i < baseArrX.Count; i++)
{
  pbaseArrX[i] = baseArrX[i] / (baseArrX[0] + baseArrX[1] + baseArrX[2]);
}

//Do the following for both compArr1 and compArr2;
for (int i = 0; i < compArrX.Count; i++)
{
  pcompArrX[i] = pcompArrX[i] / (pcompArrX[0] + pcompArrX[1] + pcompArr[2]);
}

//Get distance for both
for (int i = 0; i < pcompArrX.Count; i++)
{
  distX = distX + ((pcompArrX[i] - pbaseArrX[i])^2);
}

//Then just use conditional to determine which is 'closer'
4 2

4 ответа:

Похоже, что вы хотите сравнить массивы как лучи (только направление), но вы сравниваете их как векторы (направление и величина). Я бы предложил сравнить массивы скосинусным подобием , который является просто Косинусом угла между векторами и, следовательно, сравнением только их направлений. Для представленных массивов косинусное сходство между базовым массивом и массивом 1 составляет 0,94, а с массивом 2-0,82, что соответствует вашим ожиданиям.

Массив 3-Правильный ответ. Алгоритм, который вы используете, дает вам правильный результат.

В принципе, для меня массив 3 больше похож на базовый массив, чем Array1. Что это за образец, который вы ищете? Вы говорите, что Array1 должен быть результатом... почему?

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

Если вы хотите, чтобы результат был Array1 затем:

  • Определите, почему Array1 должен быть результатом логических терминов.
  • перевести, почему Array1 должен быть результатом в математическую формулировку
  • реализовать эту формулировку

Проблема здесь в том, что ваше понятие "сходства" не имеет четкого определения. В зависимости от случая использования данных существует бесконечно много способов определения сходства. Оставляя ваш массив в стороне, есть простой пример для этого:

    Очки и бинокль похожи, потому что вы используете их оба, чтобы смотреть на вещи.
  • очки и велосипед похожи, потому что оба состоят из двух кругов, связанных друг с другом
  • очки и трава похожи, потому что оба начинаются с "G" и заканчиваются "S"
Как вы можете видеть, если вы не определяете точно, что вам нужно, все может быть похоже на что угодно. Люди хороши, чтобы использовать правильный вид сходства для правильной задачи, но компьютер не сможет этого сделать, если вы не скажете ему явно, что вы хотите.

Оставляя этот пункт в стороне, есть один общий случай подобия, который довольно часто используется для последовательных данных в интеллектуальном анализе данных. Это называется косинусным расстоянием, и это не так. отличается от того, что вы используете. Это называется косинусным расстоянием. Вот алгоритм:

for (int i = 0; i < basearray.Length; i++)
{
  temp += (basearray[i] * arrayX[i]);
  f_base += (basearray[i] * basearray[i]);
  f_array += (array[i] * array[i]);
}
dist = 1 - (temp / sqrt( f_base * f_array ));
Это в основном просто вычисление "угла" между обоими массивами, изображенными в виде точек в n-мерном пространстве. Прекрасно работает в большинстве случаев и может быть легко адаптирована к другим потребностям (когда требуются другие виды сходства).

Математически каждый массив является точкой, а мера расстояния называется нормой . Вы используете версию евклидовой нормы, которая является нашей стандартной мерой пространственного расстояния в трех измерениях. Это просто не хватает квадратного корня, потому что все, что вас интересует, какой из них ближе, в отличие от измерения фактического расстояния, так что это все равно будет работать для вас.

В вашем примере третий массив определенно ближе всего по Евклидову расстоянию, потому что ваш базовый массив-это чертовски ближе к нулевому массиву, чем ваш первый массив. У них может быть" похожая структура", но вы смотрите на это неправильно. Ваша мера расстояния интересуется числовым расстоянием, и 0 (в массиве 3) намного ближе к 0.25, чем 1 (в массиве 1).

Если вы смотрите на "структуру", это означает, что вы думаете, что 0 намного более значимо, чем любое другое число. то есть вы хотите вознаградить соответствующий массив за то, что он имеет ненулевые значения в одном и том же месте, а не численно близок до 0.

Я не уверен, какую норму вы хотите для этого, и, честно говоря, это создает у меня впечатление, что мы упускаем то, что вам нужно достичь в конце дня - это немного трудно сделать предложения о том, что мы знаем до сих пор.