Создание объектов Spark из JPEG и использование spark_apply () в непереведенной функции - PullRequest
0 голосов
/ 18 марта 2020

Как правило, когда кто-то хочет использовать sparklyr для пользовательской функции ( т.е. ** непереведенных функций), они помещают их в spark_apply(). Однако я встречал только примеры, когда один локальный фрейм данных либо copy_to(), либо spark_read_csv() для удаленного источника данных, а затем использовал spark_apply() для него. Пример, только для иллюстративных целей:

library(sparklyr)
sc <- spark_connect(master = "local")

n_sim = 100
iris_samps <- iris %>% dplyr::filter(Species == "virginica") %>%
  sapply(rep.int, times=n_sim) %>% cbind(replicate = rep(1:n_sim, each = 50)) %>% 
  data.frame() %>%
  dplyr::group_by(replicate) %>%
  dplyr::sample_n(50, replace = TRUE)

iris_samps_tbl <- copy_to(sc, iris_samps)

iris_samps_tbl %>% 
  spark_apply(function(x) {mean(x$Petal_Length)}, 
    group_by = "replicate") %>%
  ggplot(aes(x = result)) + geom_histogram(bins = 20) + ggtitle("Histogram of 100 Bootstrapped Means using sparklyr")

Похоже, что было бы возможно использовать это для любого диапазона непереведенных функций, поступающих из пакетов CRAN или Bioconductor, если только данные находятся в объекте Spark.

У меня возникла специфическая проблема c для .jpeg изображений, когда я прочитал, что SparkR может загрузить сжатое изображение (.jpeg, .png, et c. ) в необработанное представление изображения с помощью ImageIO в Java библиотеке - вполне возможно, что sparklyr также может сделать это.

RsimMosaic::composeMosaicFromImageRandom(inputImage, outputImage, pathToTilesLibrary) функция принимает введите изображение и путь к плиткам, использованным для создания фотографии mosai c и выведите изображение ( пример здесь ).

Если эта функция сделала только одно изображение, и я знал, как превратить его в искровой объект, я мог бы представить, что команда будет выглядеть так: composeMosaicFromImageRandom(inputImage, outputImage, spark_obj). Тем не менее, эта функция берет путь к 30000 изображений.

Как можно создать 30 000 объектов Spark на пути к этим плиткам (.jpegs) и затем использовать эту функцию?

Если базовый код действительно нужно изменить, я использовал jimhester/lookup для предоставления исходного кода:

function (originalImageFileName, outputImageFileName, imagesToUseInMosaic, 
        useGradients = FALSE, removeTiles = TRUE, fracLibSizeThreshold = 0.7, 
        repFracSize = 0.25, verbose = TRUE) 
{
        if (verbose) {
                cat(paste("\n ------------------------------------------------ \n"))
                cat(paste("    R Simple Mosaic composer - random version   \n"))
                cat(paste(" ------------------------------------------------ \n\n"))
        }
        if (verbose) {
                cat(paste("    Creating the library... \n"))
        }
        libForMosaicFull <- createLibraryIndexDataFrame(imagesToUseInMosaic, 
                saveLibraryIndex = F, useGradients = useGradients)
        libForMosaic <- libForMosaicFull
        filenameArray <- list.files(imagesToUseInMosaic, full.names = TRUE)
        originalImage <- jpeg::readJPEG(filenameArray[1])
        xTileSize <- dim(originalImage[, , 1])[1]
        yTileSize <- dim(originalImage[, , 1])[2]
        if (verbose) {
                cat(paste("    -- Tiles in the Library : ", length(libForMosaic[, 
                        1]), "\n"))
                cat(paste("    -- Tile dimensions : ", xTileSize, " x ", 
                        yTileSize, "\n"))
        }
        if (verbose) {
                cat(paste("\n"))
                cat(paste("    Reading the original image... \n"))
        }
        originalImage <- jpeg::readJPEG(originalImageFileName)
        xOrigImgSize <- dim(originalImage[, , 1])[1]
        yOrigImgSize <- dim(originalImage[, , 1])[2]
        if (verbose) {
                cat(paste("    -- Original image dimensions : ", xOrigImgSize, 
                        " x ", yOrigImgSize, "\n"))
                cat(paste("    -- Output image dimensions : ", ((xOrigImgSize - 
                        2) * xTileSize), " x ", ((yOrigImgSize - 2) * yTileSize), 
                        "\n"))
        }
        if (verbose) {
                cat(paste("\n"))
                cat(paste("    Computing the mosaic... \n"))
        }
        outputImage <- array(dim = c(((xOrigImgSize - 2) * xTileSize), 
                ((yOrigImgSize - 2) * yTileSize), 3))
        removedList <- c()
        l <- 1
        pCoord <- matrix(nrow = ((xOrigImgSize - 2) * (yOrigImgSize - 
                2)), ncol = 2)
        for (i in 2:(xOrigImgSize - 1)) {
                for (j in 2:(yOrigImgSize - 1)) {
                        pCoord[l, 1] <- i
                        pCoord[l, 2] <- j
                        l <- l + 1
                }
        }
        npixels <- length(pCoord[, 1])
        for (i in 1:npixels) {
                idx <- round(runif(1, 1, length(pCoord[, 1])))
                pixelRGBandNeigArray <- computeStatisticalQuantitiesPixel(pCoord[idx, 
                        1], pCoord[idx, 2], originalImage, useGradients)
                tileFilename <- getCloseMatch(pixelRGBandNeigArray, 
                        libForMosaic)
                startI <- (pCoord[idx, 1] - 2) * xTileSize + 1
                startJ <- (pCoord[idx, 2] - 2) * yTileSize + 1
                outputImage[startI:(startI + xTileSize - 1), startJ:(startJ + 
                        yTileSize - 1), ] <- jpeg::readJPEG(tileFilename)
                if (removeTiles) {
                        libForMosaic <- removeTile(tileFilename, libForMosaic)
                        removedList <- c(removedList, tileFilename)
                        if (length(libForMosaic[, 1]) < (fracLibSizeThreshold * 
                                length(libForMosaicFull[, 1]))) {
                                idxs <- runif(round(0.25 * length(libForMosaicFull[, 
                                        1])), 1, length(removedList))
                                for (ii in 1:length(idxs)) {
                                        libForMosaic <- addBackTile(removedList[idxs[ii]], 
                                                libForMosaic, libForMosaicFull)
                                }
                                removedList <- removedList[-idxs]
                        }
                }
                if (length(pCoord[, 1]) > 2) {
                        pCoord <- pCoord[-idx, ]
                }
        }
        if (verbose) {
                cat(paste("\n"))
                cat(paste("    Done!\n\n"))
        }
        jpeg::writeJPEG(outputImage, outputImageFileName)
}

Обратите внимание: Моя первая попытка чтобы ускорить этот код, нужно было 1) использовать profvis, чтобы найти узкие места ( т.е. для циклов for) 2) использовать пакет foreach для циклов for. Это привело к более медленному коду, который предполагал, что я распараллеливался на слишком низком уровне. Как я понимаю, sparklyr больше относится к распределению вычислений, чем к распараллеливанию, поэтому, возможно, это сработает.

...