def cdist2_TTapprox(X, dims_samples, dims_features, rank_tolerance, max_rank, debug=False): """approximate the pair-wise squared distances of all rows using a TT decomposition of the data""" # convert to TT format dims = dims_samples + dims_features n_samples = np.prod(dims_samples) n_features = np.prod(dims_features) Xm = pitts_py.MultiVector_double(n_samples*n_features//dims[-1], dims[-1]) work = pitts_py.MultiVector_double() Xm_view = np.array(Xm, copy=False) # scale by norm -> length 1 Xnorms = np.linalg.norm(X,axis=1) Xm_view[...] = (np.diag(1 / Xnorms) @ X).reshape(Xm_view.shape, order='F') Xtt = pitts_py.fromDense(Xm, work, dims, rankTolerance=0.01, maxRank=200) if debug: X_approx = pitts_py.toDense(Xtt).reshape((n_samples, n_features), order='F') * Xnorms[:, np.newaxis] plt.scatter(X[:,0], X[:,1]) plt.scatter(X_approx[:,0], X_approx[:,1]) plt.savefig('scatter_01_approx.png') plt.close() plt.scatter(X[:,1], X[:,2]) plt.scatter(X_approx[:,1], X_approx[:,2]) plt.savefig('scatter_12_approx.png') plt.close() plt.scatter(X[:,3], X[:,4]) plt.scatter(X_approx[:,3], X_approx[:,4]) plt.savefig('scatter_34_approx.png') plt.close() # setup approximated (US) from SVD (U S V^T) d_samples = len(dims_samples) Xtt_ranks = Xtt.getTTranks() k = Xtt_ranks[d_samples-1] US_tt = pitts_py.TensorTrain_double(dims_samples + [k,]) US_tt.setTTranks(Xtt_ranks[:d_samples-1] + [k,]) for i in range(d_samples): US_tt.setSubTensor(i, Xtt.getSubTensor(i)) # last sub-tensor is just the identity to get an additional direction US_tt.setSubTensor(d_samples, np.eye(k,k).reshape((k,k,1))) US_approx = pitts_py.toDense(US_tt).reshape((n_samples, k), order='F') if debug: plt.matshow(US_approx) plt.savefig('US_approx.png') plt.close() US_approx = np.diag(Xnorms) @ US_approx return cdist2(US_approx)
def test_setOnes(self): tt = pitts_py.TensorTrain_double([2, 3, 4]) tt.setTTranks([2, 4]) tt.setOnes() self.assertEqual([1, 1], tt.getTTranks()) fullTensor = pitts_py.toDense(tt) np.testing.assert_array_almost_equal(np.ones([2, 3, 4]), fullTensor)
def test_from_to_dense_double_random(self): fullTensor_ref = np.random.rand(5, 3, 2, 3).astype(dtype=np.float64) tt = pitts_py.fromDense_classical(fullTensor_ref) self.assertTrue(isinstance(tt, pitts_py.TensorTrain_double)) self.assertEqual(list(fullTensor_ref.shape), tt.dimensions()) fullTensor = pitts_py.toDense(tt) self.assertEqual(fullTensor_ref.dtype, fullTensor.dtype) np.testing.assert_array_almost_equal(fullTensor_ref, fullTensor)
def test_from_to_dense_float_ones(self): fullTensor_ref = np.ones([5, 3, 2, 3], dtype=np.float32) tt = pitts_py.fromDense_classical(fullTensor_ref) self.assertTrue(isinstance(tt, pitts_py.TensorTrain_float)) self.assertEqual(list(fullTensor_ref.shape), tt.dimensions()) self.assertEqual([1, 1, 1], tt.getTTranks()) fullTensor = pitts_py.toDense(tt) self.assertEqual(fullTensor_ref.dtype, fullTensor.dtype) np.testing.assert_array_almost_equal(fullTensor_ref, fullTensor)
def test_setUnit(self): tt = pitts_py.TensorTrain_double([2, 3, 4]) tt.setTTranks([2, 4]) tt.setUnit([1, 0, 3]) self.assertEqual([1, 1], tt.getTTranks()) fullTensor = pitts_py.toDense(tt) fullTensor_ref = np.zeros([2, 3, 4]) fullTensor_ref[1, 0, 3] = 1 np.testing.assert_array_almost_equal(fullTensor_ref, fullTensor)
def test_copy(self): tt = pitts_py.TensorTrain_double([2, 4, 3]) tt2 = pitts_py.TensorTrain_double([2, 4, 3]) tt.setUnit([0, 1, 2]) pitts_py.copy(tt, tt2) tt.setUnit([1, 0, 0]) fullTensor = pitts_py.toDense(tt2) fullTensor_ref = np.zeros([2, 4, 3]) fullTensor_ref[0, 1, 2] = 1 np.testing.assert_array_almost_equal(fullTensor_ref, fullTensor)
def test_axpby(self): fullTensor1 = np.random.rand(2, 4, 3) fullTensor2 = np.random.rand(2, 4, 3) tt1 = pitts_py.fromDense_classical(fullTensor1) tt2 = pitts_py.fromDense_classical(fullTensor2) nrm2 = pitts_py.axpby(1.5, tt1, -0.75, tt2) result = nrm2 * pitts_py.toDense(tt2) np.testing.assert_almost_equal(1.5 * fullTensor1 - 0.75 * fullTensor2, result)
def test_randomize(self): tt = pitts_py.TensorTrain_double([2, 5, 3]) self.assertEqual([1, 1], tt.getTTranks()) fullTensor1 = pitts_py.toDense(tt) pitts_py.randomize(tt) self.assertEqual([1, 1], tt.getTTranks()) fullTensor2 = pitts_py.toDense(tt) pitts_py.randomize(tt) fullTensor3 = pitts_py.toDense(tt) tt.setTTranks([2, 3]) pitts_py.randomize(tt) self.assertEqual([2, 3], tt.getTTranks()) fullTensor4 = pitts_py.toDense(tt) # check for big enough differences... self.assertTrue(np.linalg.norm(fullTensor1 - fullTensor2) > 1.e-4) self.assertTrue(np.linalg.norm(fullTensor2 - fullTensor3) > 1.e-4) self.assertTrue(np.linalg.norm(fullTensor3 - fullTensor4) > 1.e-4)
def test_from_to_dense_tsqr_double_ones(self): fullTensor_ref = np.ones([5, 3, 2, 3], dtype=np.float64) work = pitts_py.MultiVector_double() data = pitts_py.MultiVector_double(5 * 3 * 2, 3) data_view = np.array(data, copy=False) data_view[...] = fullTensor_ref.reshape([5 * 3 * 2, 3]) data_view = None tt = pitts_py.fromDense(data, work, dimensions=[5, 3, 2, 3]) self.assertTrue(isinstance(tt, pitts_py.TensorTrain_double)) self.assertEqual(list(fullTensor_ref.shape), tt.dimensions()) self.assertEqual([1, 1, 1], tt.getTTranks()) fullTensor = pitts_py.toDense(tt) self.assertEqual(fullTensor_ref.dtype, fullTensor.dtype) np.testing.assert_array_almost_equal(fullTensor_ref, fullTensor)