Для циклов в R, которые занимают слишком много времени, чтобы закончить - PullRequest
0 голосов
/ 28 мая 2018

Я пытаюсь воспроизвести это уравнение в R для кластеризации ядра K-Means: enter image description here

Но цикл, который я создал, занимает слишком много времени, чтобы закончить, и я не знаю, какЧтобы улучшить его, вот пример части кода, которая создает проблему:

c=3
for (g in 1:c) { 
  ans = 0
  for (k in 1:nrow(iris)) {
    for (l in 1:nrow(iris)) {
      ans = ans + (iris[k,'cluster']==g) *(iris[l,'cluster']==g)*kernelmatrix[k,l]
      }
    }
  third[g] = ans
  }   

Это псевдокод, потому что это только часть полной функции, выражение (iris[l,'cluster']==g) эточтобы проверить, принадлежит ли элемент iris[l,'cluster'] к кластеру g, а kernelmatrix[k,l] - это элемент из nxn матрицы операций ядра.

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

РЕДАКТИРОВАТЬ: Вот код с частью ядра матрицы, но я думаю, что это не важно для кода (где вы все читаете данные, можетедумаю, что это любой набор данных, например, радужная оболочка, например:

## Euclidian Distance  
        # Remember: 
        #1.|| a || = sqrt(aDOTa), 
        #2. d(x,y) = || x - y || = sqrt((x-y)DOT(x-y))
        #3. aDOTb = sum(a*b)


        d<-function(x,y){
                aux=x-y
                dis=sqrt(sum(aux*aux))
                return(dis)
        }

        ##Radial Basis Function Kernel
        # Remember :
        # 1.K(x,x')=exp(-q||x-x'||^2) where ||x-x'|| is could be defined as the
        # euclidian distance and 'q' it's the gamma parameter
        rbf<-function(x,y,q=0.2){
                aux<-d(x,y)
                rbfd<-exp(-q*(aux)^2)
                return(rbfd)
        }
        #
        #calculating the kernel matrix
        kernelmatrix=matrix(0,nrow(data),nrow(data))
        for(i in 1:nrow(data)){
                for(j in 1:nrow(data)){
                        kernelmatrix[i,j]=rbf(data[i,1:(ncol(data)-1)],data[j,1:(ncol(data)-1)],q)
                }
        }

Ответы [ 3 ]

0 голосов
/ 29 мая 2018

Вы пытались использовать что-то вроде пакета Kernlab ?Многие авторы пакетов будут реализовывать такие вещи в C ++, поэтому производительность будет намного выше, чем урученных уравнений, даже после того, как вы векторизовали этот код (что является важным шагом, если вы хотите, чтобы он выполнялся разумно).

0 голосов
/ 30 мая 2018

Интерпретатор R действительно медленный.Кажется, не имеет большого значения, используете ли вы циклы или другие конструкции циклов.Поэтому постарайтесь свести к минимуму количество фактического кода R, а когда производительность станет проблематичной, рассмотрите возможность переписать код на языке C. Используйте R только в качестве «драйвера».

В вашем случае есть несколько очевидных проблем:

Ваши вычисления предположительно симметричны (если ваша функция ядра симметрична).Если вы воспользуетесь этим, вы будете в два раза быстрее.Внутренний цикл вообще не нужно запускать, если точка не находится в кластере.Вы суммируете только нули.

Вы делаете выбор k * k раз.Вытащите их, если петли, чтобы сделать их только k раз.Затем векторизуйте все операции.

И чтобы стать намного быстрее, попробуйте заменить все два внутренних цикла на матричную операцию (которая будет выполняться в C, а не на двух циклах интерпретатора R ...).Наивно, умножение.Но потом поймите, что вы просто делаете выбор.Так что вы хотите написать это сумма (kernelmatrix [selection, selection]), верно?

0 голосов
/ 29 мая 2018

Это может быть начало может быть:

data("iris")
iris <- as.data.frame(iris, stringsAsFactors = FALSE)
ans <- 1:nrow(iris)
third <- ans + as.numeric(iris[,'Sepal.Length']==5)*as.numeric(iris[,'Sepal.Length']==4)

Но это трудно без набора данных и определения матрицы ядра

...