Почему E увеличивается в каждой итерации алгоритма отображения Саммона? - PullRequest
0 голосов
/ 21 июня 2019

Я пытаюсь реализовать алгоритм нелинейного уменьшения размерности, известный как Sammon Mapping, в функции с именем sammon. Это должно принять как вход: (а) данные Х уменьшают в виде матрицы n × p (n наблюдений по p признакам); (б) максимальное число итераций для шага 3; (c) порог ошибки ε для этапа 3; а также (d) скорость обучения α для этапа 4.

Он должен генерировать в качестве выходного вектора n × 2 с окончательным двумерным макетом.

Алгоритм может быть реализован с градиентным спуском с использованием следующих шагов: 1. Начните со случайного двумерного расположения точек Y (Y - матрица n × 2). 2. Вычислить напряжение E Y. 3. Если E <ε или если достигнуто максимальное число итераций, остановитесь. 4. Для каждого yi из Y найдите следующий вектор yi (t + 1), основанный на текущем yi (t). 5. Перейдите к шагу 2. </p>

           def sammon(X, max_iter,lr):

            x = X
            y = np.random.normal(1,5,[x.shape[0],2])

            safe_div = lambda x: 0.0001 if x<=0.00000001 else x

            diss_x = euclidean_distances(X, X)

            for n_iter in range(max_iter):

                diss_y = euclidean_distances(y, y)

                e0 = 1/(diss_x.sum()/2)
                e1 = (diss_y - diss_x)**2
                e2 = diss_x

                E = e0 * (e1/np.where(e2<=0.00000001 , 0.0001,e2 )).sum()/2

                print('E = ',E)

                for i in range(y.shape[0]):

                    delta0 = np.zeros(y.shape[1])
                    delta1 = np.zeros(y.shape[1])

                    for j in range(y.shape[0]):
                        if i == j :
                            continue

                        diff_xy = (diss_x[i,j] - diss_y[i,j])
                        mult_xy = (diss_x[i,j] * diss_y[i,j])

                        delta0 = delta0 +(diff_xy/np.where(mult_xy<=0.00000001,                 
                        0.0001 , mult_xy))*(y[i]-y[j])

                delta1_0 = 1 + diff_xy/safe_div(diss_y[i,j])

                delta1_1 = (y[i]-y[j])**2/safe_div(diss_y[i,j])

                delta1 = delta1 + ((1/safe_div(mult_xy)) * (diff_xy - delta1_1 
                * delta1_0))

            delta = delta0/np.absolute(delta1)
            y[i] = y[i] - lr * delta

когда я пытался применить его к данным радужной оболочки от Sklearn, на каждой итерации E напряжение возрастало. Мне просто интересно, что пропущено? E Предположим, уменьшилось. но, к сожалению, я получаю такой результат, который неверен.

        sammon(X, 5, 0.03)
        E =  21.771582459972667
        E =  23.312512407210253
        E =  24.968563833599646
        E =  26.748792128398676
        E =  28.663238408887047 
...