Оцените стандартное и среднее значение для большого набора данных изображения с помощью метода Велфорда с использованием pytorch - PullRequest
1 голос
/ 26 мая 2020

Я пытаюсь оценить стандартное и среднее значение для большого набора данных изображения с помощью алгоритма Велфорда. Насколько я понимаю, этот алгоритм более надежен, чем метод, который накапливает сумму и квадрат суммы значений. Однако я столкнулся с некоторыми проблемами. Во-первых, я протестировал алгоритм на небольшом случайном наборе данных (6 изображений), и среднее и стандартное значения, оцененные методом Велфорда, не совсем совпадают со средним и стандартным значениями, рассчитанными с использованием всего набора данных одновременно. Разница очень мала, но я не уверен, что делаю что-то не так.

import torch 
torch.set_printoptions(precision=10) 
class ImgRunningStats:

        def __init__(self):
            self.n = torch.zeros(1, dtype=torch.long)
            self.old_m = torch.zeros(3, dtype=torch.float64)
            self.new_m = torch.zeros(3, dtype=torch.float64)
            self.old_s = torch.zeros(3, dtype=torch.float64)
            self.new_s = torch.zeros(3, dtype=torch.float64)

        def push(self, x):
            self.n += 1

            if self.n == 1:
                self.old_m = self.new_m = x
                self.old_s = 0
            else:
                self.new_m = self.old_m + (x - self.old_m) / self.n
                self.new_s = self.old_s + (x - self.old_m) * (x - self.new_m)

                self.old_m = self.new_m
                self.old_s = self.new_s

        def mean(self):
            return self.new_m if self.n else 0.0

        def var(self):
            return self.new_s / (self.n - 1) if self.n > 1 else 0.0

        def std(self):
            return torch.sqrt(self.var())



    rs= ImgRunningStats()

    test_img_0 = torch.rand([2,3,250,250]) test_img_1 = torch.rand([2,3,250,250]) test_img_2 = torch.rand([2,3,250,250])

    images = [test_img_0, test_img_1, test_img_2]

    test_img = torch.cat([test_img_0, test_img_1, test_img_2], dim=0)

    print('mean full: ', test_img.mean(dim=[0,2,3])) print('std full: ', test_img.std(dim=[0,2,3], unbiased=True))


    for img in images:
        pixels = img.view(-1, img.shape[1])
        for px in pixels:
            rs.push(px)


    print(f'Mean Welford: {rs.mean()}, Std Welford: {rs.std()}')

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

Можно ли распараллелить этот алгоритм?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...