Сравнивая расстояние между массивами? - PullRequest
2 голосов
/ 17 июня 2011

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

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]

Что касается приведенных выше массивов, ответ должен быть Array 1. Ответ - Array 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]

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

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

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

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

Спасибо!

UPDATE:

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

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 ]

5 голосов
/ 17 июня 2011

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

4 голосов
/ 17 июня 2011

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

  • Очки и бинокль похожи, потому что вы используете их оба, чтобы смотреть на вещи.
  • Очки и велосипед являютсяпохоже, потому что оба состоят из двух окружностей, связанных друг с другом
  • Очки и трава похожи, потому что оба начинаются с "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-мерном пространстве.Прекрасно работает в большинстве случаев и может быть легко адаптирован к другим потребностям (когда необходимы другие виды сходства).

4 голосов
/ 17 июня 2011

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

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

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

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

  • Определите, ПОЧЕМУ Массив1 должен быть результатом логических терминов.
  • Перевести, ПОЧЕМУ Array1 должен быть результатом математической формулировки
  • Реализация этой формулировки
2 голосов
/ 17 июня 2011

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

В вашем примере третий массив определенно ближе всего к евклидовурасстояние, потому что ваш базовый массив намного ближе к нулевому массиву, чем ваш первый массив.Они могут иметь «похожую структуру», но вы смотрите на нее неправильно.Ваша мера расстояния интересует числовое расстояние, и 0 (в массиве 3) намного ближе к 0,25, чем 1 (в массиве 1).

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

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

...