Пример #1
0
    def testBackwardGrayscaleAnalysisMode(self, datatype, nchs, nrows, ncols,
                                          mus):
        rtol, atol = 1e-3, 1e-6
        omgs = OrthonormalMatrixGenerationSystem(dtype=datatype,
                                                 partial_difference=False)

        # Parameters
        nSamples = 8
        nChsTotal = sum(nchs)
        nAngles = int((nChsTotal - 2) * nChsTotal / 8)
        angles = torch.randn(nAngles, dtype=datatype)
        # nSamples x nRows x nCols x nChsTotal
        X = torch.randn(nSamples,
                        nrows,
                        ncols,
                        nChsTotal,
                        dtype=datatype,
                        requires_grad=True)
        dLdZ = torch.randn(nSamples, nrows, ncols, nChsTotal, dtype=datatype)

        # Expected values
        ps, pa = nchs
        UnT = omgs(angles, mus).T
        # dLdX = dZdX x dLdZ
        expctddLdX = dLdZ.clone()
        Ya = dLdZ[:, :, :, ps:].view(nSamples * nrows * ncols, pa).T  # pa * n
        Za = UnT @ Ya
        expctddLdX[:, :, :, ps:] = Za.T.view(nSamples, nrows, ncols, pa)
        # dLdWi = <dLdZ,(dVdWi)X>
        expctddLdW_U = torch.zeros(nAngles, dtype=datatype)
        omgs.partial_difference = True
        for iAngle in range(nAngles):
            dUn = omgs(angles, mus, index_pd_angle=iAngle)
            Xa = X[:, :, :, ps:].view(-1, pa).T
            Za = dUn @ Xa  # pa x n
            expctddLdW_U[iAngle] = torch.sum(Ya * Za)

        # Instantiation of target class
        layer = NsoltIntermediateRotation2dLayer(number_of_channels=nchs,
                                                 mode='Analysis',
                                                 name='Vn')
        layer.orthTransUn.angles.data = angles
        layer.orthTransUn.mus = mus

        # Actual values
        torch.autograd.set_detect_anomaly(True)
        Z = layer.forward(X)
        layer.zero_grad()
        Z.backward(dLdZ)
        actualdLdX = X.grad
        actualdLdW_U = layer.orthTransUn.angles.grad

        # Evaluation
        self.assertEqual(actualdLdX.dtype, datatype)
        self.assertEqual(actualdLdW_U.dtype, datatype)
        self.assertTrue(
            torch.allclose(actualdLdX, expctddLdX, rtol=rtol, atol=atol))
        self.assertTrue(
            torch.allclose(actualdLdW_U, expctddLdW_U, rtol=rtol, atol=atol))
        self.assertTrue(Z.requires_grad)
Пример #2
0
    def testPartialDifference8x8RandAngPdAng13(self, datatype):
        rtol, atol = 1e-1, 1e-3

        # Expcted values
        pdAng = 13
        delta = 1e-3
        angs0 = 2 * math.pi * torch.rand(28)
        angs1 = angs0.clone()
        angs2 = angs0.clone()
        angs1[pdAng] = angs0[pdAng] - delta / 2
        angs2[pdAng] = angs0[pdAng] + delta / 2

        # Instantiation of target class
        omgs = OrthonormalMatrixGenerationSystem(dtype=datatype,
                                                 partial_difference=False)
        expctdM = (omgs(angles=angs2, mus=1) -
                   omgs(angles=angs1, mus=1)) / delta

        # Instantiation of target class
        omgs.partial_difference = True
        actualM = omgs(angles=angs0, mus=1, index_pd_angle=pdAng)

        # Evaluation
        self.assertTrue(torch.allclose(actualM, expctdM, rtol=rtol, atol=atol))
    def testBackwardWithRandomAnglesNoDcLeackage(self, datatype, nchs, stride,
                                                 nrows, ncols, mus):
        rtol, atol = 1e-2, 1e-5
        omgs = OrthonormalMatrixGenerationSystem(dtype=datatype,
                                                 partial_difference=False)

        # Parameters
        nSamples = 8
        nDecs = stride[0] * stride[1]  # math.prod(stride)
        nChsTotal = sum(nchs)
        nAnglesH = int((nChsTotal - 2) * nChsTotal / 8)
        anglesW = torch.randn(nAnglesH, dtype=datatype)
        anglesU = torch.randn(nAnglesH, dtype=datatype)
        # nSamples x nRows x nCols x nChs
        X = torch.randn(nSamples,
                        nrows,
                        ncols,
                        nChsTotal,
                        dtype=datatype,
                        requires_grad=True)
        dLdZ = torch.randn(nSamples, nrows, ncols, nDecs, dtype=datatype)

        # Expected values
        ps, pa = nchs
        anglesWNoDcLeak = anglesW.clone()
        anglesWNoDcLeak[:ps - 1] = torch.zeros(ps - 1, dtype=datatype)
        musW, musU = mus * torch.ones(ps, dtype=datatype), mus * torch.ones(
            pa, dtype=datatype)
        musW[0] = 1
        W0 = omgs(anglesWNoDcLeak, musW)
        U0 = omgs(anglesU, musU)
        # dLdX = dZdX x dLdZ
        ms, ma = int(math.ceil(nDecs / 2.)), int(math.floor(nDecs / 2.))
        Ys = dLdZ[:, :, :, :ms].view(nSamples * nrows * ncols, ms).T  # ms x n
        Ya = dLdZ[:, :, :, ms:].view(nSamples * nrows * ncols, ma).T  # ma x n
        Y = torch.cat(
            (
                W0[:, :ms] @ Ys,  # ps x ms @ ms x n
                U0[:, :ma] @ Ya),
            dim=0)  # pa x ma @ ma x n
        expctddLdX = Y.T.view(nSamples, nrows, ncols,
                              nChsTotal)  # n x (ps+pa) -> N x R x C X P
        # dLdWi = <dLdZ,(dVdWi)X>
        expctddLdW_W = torch.zeros(nAnglesH, dtype=datatype)
        expctddLdW_U = torch.zeros(nAnglesH, dtype=datatype)
        omgs.partial_difference = True
        for iAngle in range(nAnglesH):
            dW0_T = omgs(anglesWNoDcLeak, musW, index_pd_angle=iAngle).T
            dU0_T = omgs(anglesU, musU, index_pd_angle=iAngle).T
            Xs = X[:, :, :, :ps].view(-1, ps).T
            Xa = X[:, :, :, ps:].view(-1, pa).T
            Zs = dW0_T[:ms, :] @ Xs  # ms x n
            Za = dU0_T[:ma, :] @ Xa  # ma x n
            expctddLdW_W[iAngle] = torch.sum(Ys[:ms, :] * Zs)
            expctddLdW_U[iAngle] = torch.sum(Ya[:ma, :] * Za)

        # Instantiation of target class
        layer = NsoltFinalRotation2dLayer(number_of_channels=nchs,
                                          decimation_factor=stride,
                                          no_dc_leakage=True,
                                          name='V0~')
        layer.orthTransW0T.angles.data = anglesW
        layer.orthTransW0T.mus = mus
        layer.orthTransU0T.angles.data = anglesU
        layer.orthTransU0T.mus = mus

        # Actual values
        torch.autograd.set_detect_anomaly(True)
        Z = layer.forward(X)
        layer.zero_grad()
        Z.backward(dLdZ)
        actualdLdX = X.grad
        actualdLdW_W = layer.orthTransW0T.angles.grad
        actualdLdW_U = layer.orthTransU0T.angles.grad

        # Evaluation
        self.assertEqual(actualdLdX.dtype, datatype)
        self.assertEqual(actualdLdW_W.dtype, datatype)
        self.assertEqual(actualdLdW_U.dtype, datatype)
        self.assertTrue(
            torch.allclose(actualdLdX, expctddLdX, rtol=rtol, atol=atol))
        self.assertTrue(
            torch.allclose(actualdLdW_W, expctddLdW_W, rtol=rtol, atol=atol))
        self.assertTrue(
            torch.allclose(actualdLdW_U, expctddLdW_U, rtol=rtol, atol=atol))
        self.assertTrue(Z.requires_grad)
    def testBackwardGrayscaleWithRandomAngles(self,
        nchs, stride, nrows, ncols, datatype):
        rtol,atol=1e-3,1e-6
        omgs = OrthonormalMatrixGenerationSystem(dtype=datatype,partial_difference=False)

        # Parameters
        nSamples = 8
        nDecs = stride[0]*stride[1] # math.prod(stride)
        nChsTotal = sum(nchs)
        nAnglesH = int((nChsTotal-2)*nChsTotal/8)
        anglesW = torch.randn(nAnglesH,dtype=datatype)
        anglesU = torch.randn(nAnglesH,dtype=datatype)
        mus = 1
        # nSamples x nRows x nCols x nDecs
        X = torch.randn(nSamples,nrows,ncols,nDecs,dtype=datatype,requires_grad=True)
        dLdZ = torch.randn(nSamples,nrows,ncols,nChsTotal,dtype=datatype)

        # Expected values
        ps,pa = nchs
        W0T = omgs(anglesW,mus).T
        U0T = omgs(anglesU,mus).T
        # dLdX = dZdX x dLdZ
        ms,ma = int(math.ceil(nDecs/2.)),int(math.floor(nDecs/2.))
        Ys = dLdZ[:,:,:,:ps].view(nSamples*nrows*ncols,ps).T # ps * n
        Ya = dLdZ[:,:,:,ps:].view(nSamples*nrows*ncols,pa).T # pa * n
        Y = torch.cat(
            ( W0T[:ms,:] @ Ys,          # ms x ps @ ps x n
              U0T[:ma,:] @ Ya ), dim=0) # ma x pa @ pa x n
        expctddLdX = Y.T.view(nSamples,nrows,ncols,nDecs) # n x (ms+ma)
        # dLdWi = <dLdZ,(dVdWi)X>
        expctddLdW_W = torch.zeros(nAnglesH,dtype=datatype)
        expctddLdW_U = torch.zeros(nAnglesH,dtype=datatype)
        omgs.partial_difference = True
        for iAngle in range(nAnglesH):
            dW0 = omgs(anglesW,mus,index_pd_angle=iAngle)
            Xs = X[:,:,:,:ms].view(-1,ms).T 
            Zs = dW0[:,:ms] @ Xs # ps x n
            expctddLdW_W[iAngle] = torch.sum(Ys * Zs) # ps x n
            if ma>0:
                dU0 = omgs(anglesU,mus,index_pd_angle=iAngle)
                Xa = X[:,:,:,ms:].view(-1,ma).T
                Za = dU0[:,:ma] @ Xa # pa x n            
                expctddLdW_U[iAngle] = torch.sum(Ya * Za) # pa x n
            
        # Instantiation of target class
        layer = NsoltInitialRotation2dLayer(
            number_of_channels=nchs,
            decimation_factor=stride,
            name='V0')
        layer.orthTransW0.angles.data = anglesW
        layer.orthTransW0.mus = mus
        layer.orthTransU0.angles.data = anglesU
        layer.orthTransU0.mus = mus

        # Actual values
        torch.autograd.set_detect_anomaly(True)
        Z = layer.forward(X)
        layer.zero_grad()
        Z.backward(dLdZ)
        actualdLdX = X.grad
        actualdLdW_W = layer.orthTransW0.angles.grad
        actualdLdW_U = layer.orthTransU0.angles.grad

        # Evaluation
        self.assertEqual(actualdLdX.dtype,datatype)
        self.assertEqual(actualdLdW_W.dtype,datatype)
        self.assertEqual(actualdLdW_U.dtype,datatype)
        self.assertTrue(torch.allclose(actualdLdX,expctddLdX,rtol=rtol,atol=atol))
        self.assertTrue(torch.allclose(actualdLdW_W,expctddLdW_W,rtol=rtol,atol=atol))
        self.assertTrue(torch.allclose(actualdLdW_U,expctddLdW_U,rtol=rtol,atol=atol))
        self.assertTrue(Z.requires_grad)