Оптимизация Java-кода приводит к числовым неточностям и ошибкам

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

Это итерационный алгоритм, касающийся обновления матрицы, пикселей x кластеры матрицы членства U (сумма значений в строке должна быть 1,0), это правило обновления, которое я хочу оптимизировать:

alt text

, где x - это элемент матрицы X ( пикселей x объектов ), а v принадлежит матрице V ( кластеров x объектов ). И m - это параметр, который находится в диапазоне от 1,1 до бесконечности , а c - количество кластеров. Используемое расстояние является евклидовой нормой.

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

    int nClusters = V.length;
    double exp = (1.0 / (m - 1.0));
    for(int i = 0; i < X.length; i++)
    {
        int count = 0;
        for(int j = 0; j < nClusters; j++)
        {
             double distance = D[i][j];
             double denominator = D[i][nClusters];
             double numerator = Math.pow(distance, exp);
             U[i][j] = (float) (1f / (numerator * denominator));
        }
     }

Где я предварительно вычислил знаменатель в дополнительный столбец матрицы D , пока вычислял расстояния:

    for (int i = 0; i < X.length; i++)
    {
        for (int j = 0; j < V.length; j++)
        {
            double sum = 0;
            for (int k = 0; k < nDims; k++)
            {
                final double d = X[i][k] - V[j][k];
                sum += d * d;
            }

            D[i][j] = sum;
            D[i][B.length] += Math.pow(1 / D[i][j], exp);
        }
    }

При этом я обнаружил численные различия между «банальное» вычисление и второе, приводящее к разному числовому значению в U (не в первой итерации, но довольно скоро). Я полагаю, что проблема в том, что очень маленькие числа возводятся в степень до высоких значений (элементы U могут варьироваться от 0,0 до 1,0 и exp , для m = 1,1 , is 10 ) приводит к очень маленьким значениям, тогда как деление числителя и знаменателя и THEN возведение в степень результат кажется лучше в численном отношении. Проблема в том, что здесь требуется гораздо больше операций. 7633

Это первая строка матрицы D оптимизированным способом (обратите внимание, что последнее значение является предварительно вычисленным знаменателем):

414.3880 44469.38 17300.090 1197.7657 2.0796E-26

Это первая строка U не оптимизирована:

0.99997544 4.9366603E-21 6.216704E-17 2.4565863E-5

Это первая строка U оптимизирована:

0.3220644 1.5900239E-21 2.0023086E-17 7.912171E-6

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

Я что-то делаю не так? Есть ли возможное решение, как оптимизировать код и добиться его численной стабильности? Любые предложения или критика будут оценены. float floatValue [5] = {1.1F, 2.2F, 3.3F, 4.4F, 5.5F}; int i; if ((fp = fopen ("test", "wb")) == NULL) {printf ("Невозможно открыть ...

Я использовал приведенный ниже код для записи одномерного массива в файл:

FILE *fp;
float floatValue[5] = { 1.1F, 2.2F, 3.3F, 4.4F, 5.5F };
int i;

if((fp=fopen("test", "wb"))==NULL) {
    printf("Cannot open file.\n");
}

if(fwrite(floatValue, sizeof(float), 5, fp) != 5)
    printf("File write error.");
fclose(fp);

/* read the values */
if((fp=fopen("test", "rb"))==NULL) {
    printf("Cannot open file.\n");
}

if(fread(floatValue, sizeof(float), 5, fp) != 5) {
    if(feof(fp))
        printf("Premature end of file.");
    else
        printf("File read error.");
}
fclose(fp);

for(i=0; i<5; i++)
    printf("%f ", floatValue[i]);

У меня вопрос, хочу ли я писать и читать 2D-массив ??

6
задан EvilTeach 12 May 2012 в 16:35
поделиться