tsne 1.2.0 → 1.3.0
raw patch · 15 files changed
+435/−310 lines, 15 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.Algorithm.TSNE.Internals: Beta :: Double -> Double -> Double -> Beta
- Data.Algorithm.TSNE.Internals: [betaMax] :: Beta -> Double
- Data.Algorithm.TSNE.Internals: [betaMin] :: Beta -> Double
- Data.Algorithm.TSNE.Internals: [betaValue] :: Beta -> Double
- Data.Algorithm.TSNE.Internals: binarySearchBeta :: TSNEOptions -> TSNEInput -> TSNEInputValue -> Beta
- Data.Algorithm.TSNE.Internals: binarySearchBeta' :: TSNEOptions -> TSNEInput -> Double -> Int -> Beta -> TSNEInputValue -> Beta
- Data.Algorithm.TSNE.Internals: cost :: [[Double]] -> TSNEState -> Double
- Data.Algorithm.TSNE.Internals: data Beta
- Data.Algorithm.TSNE.Internals: entropyForInputValue :: Double -> TSNEInput -> TSNEInputValue -> Entropy
- Data.Algorithm.TSNE.Internals: gradients :: [[Probability]] -> TSNEState -> [[Gradient]]
- Data.Algorithm.TSNE.Internals: initSolution2D :: Int -> IO [[Double]]
- Data.Algorithm.TSNE.Internals: initSolution3D :: Int -> IO [[Double]]
- Data.Algorithm.TSNE.Internals: initState2D :: Int -> IO TSNEState
- Data.Algorithm.TSNE.Internals: initState3D :: Int -> IO TSNEState
- Data.Algorithm.TSNE.Internals: inputIsValid :: TSNEInput -> Either String ()
- Data.Algorithm.TSNE.Internals: inputSize :: TSNEInput -> Int
- Data.Algorithm.TSNE.Internals: inputValueSize :: TSNEInput -> Int
- Data.Algorithm.TSNE.Internals: isValidStateForInput :: TSNEInput -> TSNEState -> Either String ()
- Data.Algorithm.TSNE.Internals: neighbourProbabilities :: TSNEOptions -> TSNEInput -> [[Probability]]
- Data.Algorithm.TSNE.Internals: newDelta :: Double -> Int -> Gain -> Delta -> Gradient -> Delta
- Data.Algorithm.TSNE.Internals: newGain :: Gain -> Delta -> Gradient -> Gain
- Data.Algorithm.TSNE.Internals: output2D :: [[Double]] -> TSNEState -> TSNEOutput2D
- Data.Algorithm.TSNE.Internals: output3D :: [[Double]] -> TSNEState -> TSNEOutput3D
- Data.Algorithm.TSNE.Internals: rawNeighbourProbabilities :: TSNEOptions -> TSNEInput -> [[Probability]]
- Data.Algorithm.TSNE.Internals: runTSNE2D :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> Producer TSNEOutput2D IO ()
- Data.Algorithm.TSNE.Internals: runTSNE3D :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> Producer TSNEOutput3D IO ()
- Data.Algorithm.TSNE.Internals: solution2D :: [[Double]] -> [Position2D]
- Data.Algorithm.TSNE.Internals: solution3D :: [[Double]] -> [Position3D]
- Data.Algorithm.TSNE.Internals: stepTSNE :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> TSNEState
- Data.Algorithm.TSNE.Internals: targetEntropy :: TSNEOptions -> Entropy
+ Data.Algorithm.TSNE.Checks: inputIsValid :: TSNEInput -> Either String ()
+ Data.Algorithm.TSNE.Checks: inputSize :: TSNEInput -> Int
+ Data.Algorithm.TSNE.Checks: inputValueSize :: TSNEInput -> Int
+ Data.Algorithm.TSNE.Checks: isValidStateForInput :: Int -> TSNEInput -> TSNEState -> Either String ()
+ Data.Algorithm.TSNE.Preparation: Beta :: Double -> Double -> Double -> Beta
+ Data.Algorithm.TSNE.Preparation: [betaMax] :: Beta -> Double
+ Data.Algorithm.TSNE.Preparation: [betaMin] :: Beta -> Double
+ Data.Algorithm.TSNE.Preparation: [betaValue] :: Beta -> Double
+ Data.Algorithm.TSNE.Preparation: binarySearchBeta :: TSNEOptions -> TSNEInput -> TSNEInputValue -> Beta
+ Data.Algorithm.TSNE.Preparation: binarySearchBeta' :: TSNEOptions -> TSNEInput -> Double -> Int -> Beta -> TSNEInputValue -> Beta
+ Data.Algorithm.TSNE.Preparation: data Beta
+ Data.Algorithm.TSNE.Preparation: entropyForInputValue :: Double -> TSNEInput -> TSNEInputValue -> Entropy
+ Data.Algorithm.TSNE.Preparation: neighbourProbabilities :: TSNEOptions -> TSNEInput -> [[Probability]]
+ Data.Algorithm.TSNE.Preparation: rawNeighbourProbabilities :: TSNEOptions -> TSNEInput -> [[Probability]]
+ Data.Algorithm.TSNE.Preparation: targetEntropy :: TSNEOptions -> Entropy
+ Data.Algorithm.TSNE.Run2D: initSolution2D :: Int -> IO [[Double]]
+ Data.Algorithm.TSNE.Run2D: initState2D :: Int -> IO TSNEState
+ Data.Algorithm.TSNE.Run2D: output2D :: [[Double]] -> TSNEState -> TSNEOutput2D
+ Data.Algorithm.TSNE.Run2D: runTSNE2D :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> Producer TSNEOutput2D IO ()
+ Data.Algorithm.TSNE.Run2D: solution2D :: [[Double]] -> [Position2D]
+ Data.Algorithm.TSNE.Run3D: initSolution3D :: Int -> IO [[Double]]
+ Data.Algorithm.TSNE.Run3D: initState3D :: Int -> IO TSNEState
+ Data.Algorithm.TSNE.Run3D: output3D :: [[Double]] -> TSNEState -> TSNEOutput3D
+ Data.Algorithm.TSNE.Run3D: runTSNE3D :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> Producer TSNEOutput3D IO ()
+ Data.Algorithm.TSNE.Run3D: solution3D :: [[Double]] -> [Position3D]
+ Data.Algorithm.TSNE.Stepping: cost :: [[Double]] -> TSNEState -> Double
+ Data.Algorithm.TSNE.Stepping: gradients :: [[Probability]] -> TSNEState -> [[Gradient]]
+ Data.Algorithm.TSNE.Stepping: newDelta :: Double -> Int -> Gain -> Delta -> Gradient -> Delta
+ Data.Algorithm.TSNE.Stepping: newGain :: Gain -> Delta -> Gradient -> Gain
+ Data.Algorithm.TSNE.Stepping: stepTSNE :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> TSNEState
Files
- src/Data/Algorithm/TSNE.hs +4/−1
- src/Data/Algorithm/TSNE/Checks.hs +21/−0
- src/Data/Algorithm/TSNE/Internals.hs +0/−207
- src/Data/Algorithm/TSNE/Preparation.hs +65/−0
- src/Data/Algorithm/TSNE/Run2D.hs +42/−0
- src/Data/Algorithm/TSNE/Run3D.hs +43/−0
- src/Data/Algorithm/TSNE/Stepping.hs +60/−0
- test/Data/Algorithm/TSNE/InternalsSpec.hs +0/−97
- test/Data/Algorithm/TSNE/PreparationSpec.hs +39/−0
- test/Data/Algorithm/TSNE/Run2DSpec.hs +32/−0
- test/Data/Algorithm/TSNE/Run3DSpec.hs +47/−0
- test/Data/Algorithm/TSNE/SteppingSpec.hs +29/−0
- test/Data/Algorithm/TSNE/TestInput.hs +35/−0
- test/Data/Algorithm/TSNE/TestMisc.hs +5/−0
- tsne.cabal +13/−5
src/Data/Algorithm/TSNE.hs view
@@ -11,8 +11,11 @@ import Pipes import Data.Algorithm.TSNE.Types-import Data.Algorithm.TSNE.Internals import Data.Algorithm.TSNE.Utils+import Data.Algorithm.TSNE.Preparation+import Data.Algorithm.TSNE.Run3D+import Data.Algorithm.TSNE.Run2D+ -- | Generates an infinite stream of 3D tSNE iterations. tsne3D :: TSNEOptions -> TSNEInput -> Producer TSNEOutput3D IO ()
src/Data/Algorithm/TSNE/Checks.hs view
@@ -17,3 +17,24 @@ isRectangular :: [[a]] -> Bool isRectangular xss = has2DShape (shape2D xss) xss +inputSize :: TSNEInput -> Int+inputSize = length++inputValueSize :: TSNEInput -> Int+inputValueSize i = w + where (w,h) = shape2D i ++inputIsValid :: TSNEInput -> Either String ()+inputIsValid [] = Left "empty input data"+inputIsValid xss+ | not (isRectangular xss) = Left "input data values are not all the same length"+ | otherwise = Right () ++isValidStateForInput :: Int -> TSNEInput -> TSNEState -> Either String ()+isValidStateForInput d i st+ | not (has2DShape (n,d) s) = Left $ "solution is wrong shape: " ++ show (shape2D s) + | otherwise = Right ()+ where+ n = inputSize i+ s = stSolution st +
− src/Data/Algorithm/TSNE/Internals.hs
@@ -1,207 +0,0 @@-module Data.Algorithm.TSNE.Internals where--import Control.Applicative-import Control.DeepSeq-import Control.Exception (assert)-import Data.Default (def)-import Data.List(zipWith4)-import Data.Random.Normal (normalsIO')-import Pipes---import Debug.Trace--import Data.Algorithm.TSNE.Types-import Data.Algorithm.TSNE.Utils-import Data.Algorithm.TSNE.Checks---inputSize :: TSNEInput -> Int-inputSize = length--inputValueSize :: TSNEInput -> Int-inputValueSize i = w - where (w,h) = shape2D i --inputIsValid :: TSNEInput -> Either String ()-inputIsValid [] = Left "empty input data"-inputIsValid xss- | not (isRectangular xss) = Left "input data values are not all the same length"- | otherwise = Right () --isValidStateForInput :: TSNEInput -> TSNEState -> Either String ()-isValidStateForInput i st- | not (has2DShape (n,3) s) = Left $ "solution is wrong shape: " ++ show (shape2D s) - | otherwise = Right ()- where- n = inputSize i- s = stSolution st --initState3D :: Int -> IO TSNEState-initState3D n = do- s <- initSolution3D n- return $ TSNEState 0 s (rr 1) (rr 0)- where- rr = repeat.repeat--initState2D :: Int -> IO TSNEState-initState2D n = do- s <- initSolution2D n- return $ TSNEState 0 s (rr 1) (rr 0)- where- rr = repeat.repeat--initSolution3D :: Int -> IO [[Double]]-initSolution3D n = do- let ns = normalsIO' (0, 1e-4)- xs <- ns- ys <- ns- zs <- ns- return $ take n <$> [xs,ys,zs]--initSolution2D :: Int -> IO [[Double]]-initSolution2D n = do- let ns = normalsIO' (0, 1e-4)- xs <- ns- ys <- ns- return $ take n <$> [xs,ys]--runTSNE3D :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> Producer TSNEOutput3D IO ()-runTSNE3D opts vs ps st = do- yield $ output3D ps st- let st' = force $ stepTSNE opts vs ps st- runTSNE3D opts vs ps st'--runTSNE2D :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> Producer TSNEOutput2D IO ()-runTSNE2D opts vs ps st = do- yield $ output2D ps st- let st' = force $ stepTSNE opts vs ps st- runTSNE2D opts vs ps st'--stepTSNE :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> TSNEState-stepTSNE opts vs ps st = TSNEState i' s'' g' d'- where- i = stIteration st- s = stSolution st- g = stGains st- d = stDeltas st- gr = gradients ps st- i' = i + 1- s' = recenter $ z (+) s d'- g' = z3 newGain g d gr- d' = z3 (newDelta (tsneLearningRate opts) i) g' d gr- z = zipWith.zipWith- z3 = zipWith3.zipWith3- s'' = assert (length s' == length vs) s'--newGain :: Gain -> Delta -> Gradient -> Gain-newGain g d gr = max 0.01 g'- where- g' = if signum d == signum gr - then g * 0.8- else g + 0.2 --newDelta :: Double -> Int -> Gain -> Delta -> Gradient -> Delta-newDelta e i g' d gr = (m * d) - (e * g' * gr)- where- m = if i < 250 then 0.5 else 0.8--gradients :: [[Probability]] -> TSNEState -> [[Gradient]]-gradients pss st = gradient <$> ss- where- gradient :: [Double] -> [Gradient]- gradient s = zipWith4 (f s) s pss qss qss'- ss = stSolution st- i = stIteration st- qss = qdist ss- qss' = qdist' ss - f :: [Double] -> Double -> [Double] -> [Double] -> [Double] -> Gradient- f s x ps qs qs' = sum $ zipWith4 g s ps qs qs'- where- g y p q q' = m * (x - y)- where- m = 4 * (k * p - q') * q- k = if i < 100 then 4 else 1--solution3D :: [[Double]] -> [Position3D]-solution3D (xs:ys:zs:_) = zip3 xs ys zs--output3D :: [[Double]] -> TSNEState -> TSNEOutput3D-output3D pss st = TSNEOutput3D i s c- where- i = stIteration st- s = (solution3D . stSolution) st- c = cost pss st--solution2D :: [[Double]] -> [Position2D]-solution2D (xs:ys:_) = zip xs ys--output2D :: [[Double]] -> TSNEState -> TSNEOutput2D-output2D pss st = TSNEOutput2D i s c- where- i = stIteration st- s = (solution2D . stSolution) st- c = cost pss st--cost :: [[Double]] -> TSNEState -> Double-cost pss st = sumsum $ (zipWith.zipWith) c pss (qdist' (stSolution st))- where- c p q = -p * log q --targetEntropy :: TSNEOptions -> Entropy-targetEntropy = log.realToFrac.tsnePerplexity--data Beta = Beta {- betaValue :: Double,- betaMin :: Double,- betaMax :: Double-}--neighbourProbabilities :: TSNEOptions -> TSNEInput -> [[Probability]]-neighbourProbabilities opts vs = symmetrize $ rawNeighbourProbabilities opts vs--rawNeighbourProbabilities :: TSNEOptions -> TSNEInput -> [[Probability]]-rawNeighbourProbabilities opts vs = map np vs- where - np a = aps (beta a) vs a- beta a = betaValue $ binarySearchBeta opts vs a-- aps :: Double -> TSNEInput -> TSNEInputValue -> [Probability]- aps beta bs a = map pj' bs- where- psum = sum $ map pj bs- pj b - | a == b = 0- | otherwise = exp $ -(distanceSquared a b) * beta - pj' b = pj b / psum--binarySearchBeta :: TSNEOptions -> TSNEInput -> TSNEInputValue -> Beta-binarySearchBeta opts vs = binarySearchBeta' opts vs 1e-4 0 (Beta 1 (-infinity) infinity)--binarySearchBeta' :: TSNEOptions -> TSNEInput -> Double -> Int -> Beta -> TSNEInputValue -> Beta-binarySearchBeta' opts bs tol i beta a- | i == 50 = beta- | abs (e - t) < tol = beta- | e > t = r $ incPrecision beta- | otherwise = r $ decPrecision beta - where- t = targetEntropy opts- e = entropyForInputValue (betaValue beta) bs a- incPrecision (Beta b _ bmax) - | bmax == infinity = Beta (b * 2) b bmax- | otherwise = Beta ((b + bmax) / 2) b bmax- decPrecision (Beta b bmin _) - | bmin == -infinity = Beta (b / 2) bmin b- | otherwise = Beta ((b + bmin) / 2) bmin b- r beta' = binarySearchBeta' opts bs tol (i+1) beta' a --entropyForInputValue :: Double -> TSNEInput -> TSNEInputValue -> Entropy-entropyForInputValue beta bs a = sum $ map h bs- where- h b = if x > 1e-7 then -x * log x else 0- where x = pj' b- psum = sum $ map pj bs- pj b - | a == b = 0- | otherwise = exp $ -(distanceSquared a b) * beta - pj' b = pj b / psum--
+ src/Data/Algorithm/TSNE/Preparation.hs view
@@ -0,0 +1,65 @@+module Data.Algorithm.TSNE.Preparation where++import Data.Algorithm.TSNE.Types+import Data.Algorithm.TSNE.Utils+++targetEntropy :: TSNEOptions -> Entropy+targetEntropy = log.realToFrac.tsnePerplexity++data Beta = Beta {+ betaValue :: Double,+ betaMin :: Double,+ betaMax :: Double+}++neighbourProbabilities :: TSNEOptions -> TSNEInput -> [[Probability]]+neighbourProbabilities opts vs = symmetrize $ rawNeighbourProbabilities opts vs++rawNeighbourProbabilities :: TSNEOptions -> TSNEInput -> [[Probability]]+rawNeighbourProbabilities opts vs = map np vs+ where + np a = aps (beta a) vs a+ beta a = betaValue $ binarySearchBeta opts vs a++ aps :: Double -> TSNEInput -> TSNEInputValue -> [Probability]+ aps beta bs a = map pj' bs+ where+ psum = sum $ map pj bs+ pj b + | a == b = 0+ | otherwise = exp $ -(distanceSquared a b) * beta + pj' b = pj b / psum++binarySearchBeta :: TSNEOptions -> TSNEInput -> TSNEInputValue -> Beta+binarySearchBeta opts vs = binarySearchBeta' opts vs 1e-4 0 (Beta 1 (-infinity) infinity)++binarySearchBeta' :: TSNEOptions -> TSNEInput -> Double -> Int -> Beta -> TSNEInputValue -> Beta+binarySearchBeta' opts bs tol i beta a+ | i == 50 = beta+ | abs (e - t) < tol = beta+ | e > t = r $ incPrecision beta+ | otherwise = r $ decPrecision beta + where+ t = targetEntropy opts+ e = entropyForInputValue (betaValue beta) bs a+ incPrecision (Beta b _ bmax) + | bmax == infinity = Beta (b * 2) b bmax+ | otherwise = Beta ((b + bmax) / 2) b bmax+ decPrecision (Beta b bmin _) + | bmin == -infinity = Beta (b / 2) bmin b+ | otherwise = Beta ((b + bmin) / 2) bmin b+ r beta' = binarySearchBeta' opts bs tol (i+1) beta' a ++entropyForInputValue :: Double -> TSNEInput -> TSNEInputValue -> Entropy+entropyForInputValue beta bs a = sum $ map h bs+ where+ h b = if x > 1e-7 then -x * log x else 0+ where x = pj' b+ psum = sum $ map pj bs+ pj b + | a == b = 0+ | otherwise = exp $ -(distanceSquared a b) * beta + pj' b = pj b / psum++
+ src/Data/Algorithm/TSNE/Run2D.hs view
@@ -0,0 +1,42 @@+module Data.Algorithm.TSNE.Run2D where++import Control.Applicative+import Control.DeepSeq+import Data.Random.Normal (normalsIO')+import Pipes++import Data.Algorithm.TSNE.Types+import Data.Algorithm.TSNE.Preparation+import Data.Algorithm.TSNE.Stepping+++initState2D :: Int -> IO TSNEState+initState2D n = do+ s <- initSolution2D n+ return $ TSNEState 0 s (rr 1) (rr 0)+ where+ rr = repeat.repeat++initSolution2D :: Int -> IO [[Double]]+initSolution2D n = do+ let ns = normalsIO' (0, 1e-4)+ xs <- ns+ ys <- ns+ return $ take n <$> [xs,ys]++runTSNE2D :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> Producer TSNEOutput2D IO ()+runTSNE2D opts vs ps st = do+ yield $ output2D ps st+ let st' = force $ stepTSNE opts vs ps st+ runTSNE2D opts vs ps st'++solution2D :: [[Double]] -> [Position2D]+solution2D (xs:ys:_) = zip xs ys++output2D :: [[Double]] -> TSNEState -> TSNEOutput2D+output2D pss st = TSNEOutput2D i s c+ where+ i = stIteration st+ s = (solution2D . stSolution) st+ c = cost pss st+
+ src/Data/Algorithm/TSNE/Run3D.hs view
@@ -0,0 +1,43 @@+module Data.Algorithm.TSNE.Run3D where++import Control.Applicative+import Control.DeepSeq+import Data.Random.Normal (normalsIO')+import Pipes++import Data.Algorithm.TSNE.Types+import Data.Algorithm.TSNE.Preparation+import Data.Algorithm.TSNE.Stepping+++initState3D :: Int -> IO TSNEState+initState3D n = do+ s <- initSolution3D n+ return $ TSNEState 0 s (rr 1) (rr 0)+ where+ rr = repeat.repeat++initSolution3D :: Int -> IO [[Double]]+initSolution3D n = do+ let ns = normalsIO' (0, 1e-4)+ xs <- ns+ ys <- ns+ zs <- ns+ return $ take n <$> [xs,ys,zs]++runTSNE3D :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> Producer TSNEOutput3D IO ()+runTSNE3D opts vs ps st = do+ yield $ output3D ps st+ let st' = force $ stepTSNE opts vs ps st+ runTSNE3D opts vs ps st'++solution3D :: [[Double]] -> [Position3D]+solution3D (xs:ys:zs:_) = zip3 xs ys zs++output3D :: [[Double]] -> TSNEState -> TSNEOutput3D+output3D pss st = TSNEOutput3D i s c+ where+ i = stIteration st+ s = (solution3D . stSolution) st+ c = cost pss st+
+ src/Data/Algorithm/TSNE/Stepping.hs view
@@ -0,0 +1,60 @@+module Data.Algorithm.TSNE.Stepping where++import Control.Applicative+import Control.Exception (assert)+import Data.List(zipWith4)++import Data.Algorithm.TSNE.Types+import Data.Algorithm.TSNE.Utils+++stepTSNE :: TSNEOptions -> TSNEInput -> [[Probability]] -> TSNEState -> TSNEState+stepTSNE opts vs ps st = TSNEState i' s'' g' d'+ where+ i = stIteration st+ s = stSolution st+ g = stGains st+ d = stDeltas st+ gr = gradients ps st+ i' = i + 1+ s' = recenter $ z (+) s d'+ g' = z3 newGain g d gr+ d' = z3 (newDelta (tsneLearningRate opts) i) g' d gr+ z = zipWith.zipWith+ z3 = zipWith3.zipWith3+ s'' = assert (length s' == length vs) s'++newGain :: Gain -> Delta -> Gradient -> Gain+newGain g d gr = max 0.01 g'+ where+ g' = if signum d == signum gr + then g * 0.8+ else g + 0.2 ++newDelta :: Double -> Int -> Gain -> Delta -> Gradient -> Delta+newDelta e i g' d gr = (m * d) - (e * g' * gr)+ where+ m = if i < 250 then 0.5 else 0.8++gradients :: [[Probability]] -> TSNEState -> [[Gradient]]+gradients pss st = gradient <$> ss+ where+ gradient :: [Double] -> [Gradient]+ gradient s = zipWith4 (f s) s pss qss qss'+ ss = stSolution st+ i = stIteration st+ qss = qdist ss+ qss' = qdist' ss + f :: [Double] -> Double -> [Double] -> [Double] -> [Double] -> Gradient+ f s x ps qs qs' = sum $ zipWith4 g s ps qs qs'+ where+ g y p q q' = m * (x - y)+ where+ m = 4 * (k * p - q') * q+ k = if i < 100 then 4 else 1++cost :: [[Double]] -> TSNEState -> Double+cost pss st = sumsum $ (zipWith.zipWith) c pss (qdist' (stSolution st))+ where+ c p q = -p * log q +
− test/Data/Algorithm/TSNE/InternalsSpec.hs
@@ -1,97 +0,0 @@-module Data.Algorithm.TSNE.InternalsSpec (main, spec) where--import Data.Default (def)--import Test.Hspec-import Data.Algorithm.TSNE.Internals-import Data.Algorithm.TSNE.Checks-import Data.Algorithm.TSNE.Types-import Data.Algorithm.TSNE.Utils---- `main` is here so that this module can be run from GHCi on its own. It is--- not needed for automatic spec discovery.-main :: IO ()-main = hspec spec--u = undefined--spec :: Spec-spec = do- let n = inputSize testInput- w = inputValueSize testInput-- describe "testInput" $ do- it "is right shape" $ do- testInput `shouldSatisfy` has2DShape (64, 20)- it "is valid" $ do- inputIsValid testInput `shouldBe` Right ()- it "has right size" $ do- inputSize testInput `shouldBe` 20- it "has right value size" $ do- inputValueSize testInput `shouldBe` 64-- describe "initSolution3D" $ do- it "is right shape" $- --initSolution3D 99 >>= (`shouldSatisfy` (\s -> length s == 3 && all (\xs -> length xs == 99) s))- initSolution3D n >>= (`shouldSatisfy` has2DShape (n,3))-- describe "initState" $ do- it "is valid state" $- initState n >>= (`shouldSatisfy` isRight . (isValidStateForInput testInput))-- describe "neighbourProbabilities" $ do- it "is right shape" $ do- testNeighbourProbs `shouldSatisfy` has2DShape (n,n)-- describe "qdist" $ do- it "is right shape" $ do- s <- initSolution3D n- qdist s `shouldSatisfy` has2DShape (n,n) -- describe "qdist'" $ do- it "is right shape" $ do- s <- initSolution3D n- qdist' s `shouldSatisfy` has2DShape (n,n) -- describe "gradients" $ do- it "is right shape" $ do- s <- initState n- gradients testNeighbourProbs s `shouldSatisfy` has2DShape (n,3)-- describe "stepTSNE" $ do- it "works" $ do - s <- initState n- stepTSNE def testInput testNeighbourProbs s `shouldSatisfy` isRight . (isValidStateForInput testInput)---isRight :: Either a b -> Bool-isRight (Left _) = False-isRight (Right _) = True---- first 20 digits from the Python sklearn digits dataset-testInput :: TSNEInput-testInput = [- [0.0,0.0,5.0,13.0,9.0,1.0,0.0,0.0,0.0,0.0,13.0,15.0,10.0,15.0,5.0,0.0,0.0,3.0,15.0,2.0,0.0,11.0,8.0,0.0,0.0,4.0,12.0,0.0,0.0,8.0,8.0,0.0,0.0,5.0,8.0,0.0,0.0,9.0,8.0,0.0,0.0,4.0,11.0,0.0,1.0,12.0,7.0,0.0,0.0,2.0,14.0,5.0,10.0,12.0,0.0,0.0,0.0,0.0,6.0,13.0,10.0,0.0,0.0,0.0],- [0.0,0.0,0.0,12.0,13.0,5.0,0.0,0.0,0.0,0.0,0.0,11.0,16.0,9.0,0.0,0.0,0.0,0.0,3.0,15.0,16.0,6.0,0.0,0.0,0.0,7.0,15.0,16.0,16.0,2.0,0.0,0.0,0.0,0.0,1.0,16.0,16.0,3.0,0.0,0.0,0.0,0.0,1.0,16.0,16.0,6.0,0.0,0.0,0.0,0.0,1.0,16.0,16.0,6.0,0.0,0.0,0.0,0.0,0.0,11.0,16.0,10.0,0.0,0.0],- [0.0,0.0,0.0,4.0,15.0,12.0,0.0,0.0,0.0,0.0,3.0,16.0,15.0,14.0,0.0,0.0,0.0,0.0,8.0,13.0,8.0,16.0,0.0,0.0,0.0,0.0,1.0,6.0,15.0,11.0,0.0,0.0,0.0,1.0,8.0,13.0,15.0,1.0,0.0,0.0,0.0,9.0,16.0,16.0,5.0,0.0,0.0,0.0,0.0,3.0,13.0,16.0,16.0,11.0,5.0,0.0,0.0,0.0,0.0,3.0,11.0,16.0,9.0,0.0],- [0.0,0.0,7.0,15.0,13.0,1.0,0.0,0.0,0.0,8.0,13.0,6.0,15.0,4.0,0.0,0.0,0.0,2.0,1.0,13.0,13.0,0.0,0.0,0.0,0.0,0.0,2.0,15.0,11.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0,12.0,12.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0,10.0,8.0,0.0,0.0,0.0,8.0,4.0,5.0,14.0,9.0,0.0,0.0,0.0,7.0,13.0,13.0,9.0,0.0,0.0],- [0.0,0.0,0.0,1.0,11.0,0.0,0.0,0.0,0.0,0.0,0.0,7.0,8.0,0.0,0.0,0.0,0.0,0.0,1.0,13.0,6.0,2.0,2.0,0.0,0.0,0.0,7.0,15.0,0.0,9.0,8.0,0.0,0.0,5.0,16.0,10.0,0.0,16.0,6.0,0.0,0.0,4.0,15.0,16.0,13.0,16.0,1.0,0.0,0.0,0.0,0.0,3.0,15.0,10.0,0.0,0.0,0.0,0.0,0.0,2.0,16.0,4.0,0.0,0.0],- [0.0,0.0,12.0,10.0,0.0,0.0,0.0,0.0,0.0,0.0,14.0,16.0,16.0,14.0,0.0,0.0,0.0,0.0,13.0,16.0,15.0,10.0,1.0,0.0,0.0,0.0,11.0,16.0,16.0,7.0,0.0,0.0,0.0,0.0,0.0,4.0,7.0,16.0,7.0,0.0,0.0,0.0,0.0,0.0,4.0,16.0,9.0,0.0,0.0,0.0,5.0,4.0,12.0,16.0,4.0,0.0,0.0,0.0,9.0,16.0,16.0,10.0,0.0,0.0],- [0.0,0.0,0.0,12.0,13.0,0.0,0.0,0.0,0.0,0.0,5.0,16.0,8.0,0.0,0.0,0.0,0.0,0.0,13.0,16.0,3.0,0.0,0.0,0.0,0.0,0.0,14.0,13.0,0.0,0.0,0.0,0.0,0.0,0.0,15.0,12.0,7.0,2.0,0.0,0.0,0.0,0.0,13.0,16.0,13.0,16.0,3.0,0.0,0.0,0.0,7.0,16.0,11.0,15.0,8.0,0.0,0.0,0.0,1.0,9.0,15.0,11.0,3.0,0.0],- [0.0,0.0,7.0,8.0,13.0,16.0,15.0,1.0,0.0,0.0,7.0,7.0,4.0,11.0,12.0,0.0,0.0,0.0,0.0,0.0,8.0,13.0,1.0,0.0,0.0,4.0,8.0,8.0,15.0,15.0,6.0,0.0,0.0,2.0,11.0,15.0,15.0,4.0,0.0,0.0,0.0,0.0,0.0,16.0,5.0,0.0,0.0,0.0,0.0,0.0,9.0,15.0,1.0,0.0,0.0,0.0,0.0,0.0,13.0,5.0,0.0,0.0,0.0,0.0],- [0.0,0.0,9.0,14.0,8.0,1.0,0.0,0.0,0.0,0.0,12.0,14.0,14.0,12.0,0.0,0.0,0.0,0.0,9.0,10.0,0.0,15.0,4.0,0.0,0.0,0.0,3.0,16.0,12.0,14.0,2.0,0.0,0.0,0.0,4.0,16.0,16.0,2.0,0.0,0.0,0.0,3.0,16.0,8.0,10.0,13.0,2.0,0.0,0.0,1.0,15.0,1.0,3.0,16.0,8.0,0.0,0.0,0.0,11.0,16.0,15.0,11.0,1.0,0.0],- [0.0,0.0,11.0,12.0,0.0,0.0,0.0,0.0,0.0,2.0,16.0,16.0,16.0,13.0,0.0,0.0,0.0,3.0,16.0,12.0,10.0,14.0,0.0,0.0,0.0,1.0,16.0,1.0,12.0,15.0,0.0,0.0,0.0,0.0,13.0,16.0,9.0,15.0,2.0,0.0,0.0,0.0,0.0,3.0,0.0,9.0,11.0,0.0,0.0,0.0,0.0,0.0,9.0,15.0,4.0,0.0,0.0,0.0,9.0,12.0,13.0,3.0,0.0,0.0],- [0.0,0.0,1.0,9.0,15.0,11.0,0.0,0.0,0.0,0.0,11.0,16.0,8.0,14.0,6.0,0.0,0.0,2.0,16.0,10.0,0.0,9.0,9.0,0.0,0.0,1.0,16.0,4.0,0.0,8.0,8.0,0.0,0.0,4.0,16.0,4.0,0.0,8.0,8.0,0.0,0.0,1.0,16.0,5.0,1.0,11.0,3.0,0.0,0.0,0.0,12.0,12.0,10.0,10.0,0.0,0.0,0.0,0.0,1.0,10.0,13.0,3.0,0.0,0.0],- [0.0,0.0,0.0,0.0,14.0,13.0,1.0,0.0,0.0,0.0,0.0,5.0,16.0,16.0,2.0,0.0,0.0,0.0,0.0,14.0,16.0,12.0,0.0,0.0,0.0,1.0,10.0,16.0,16.0,12.0,0.0,0.0,0.0,3.0,12.0,14.0,16.0,9.0,0.0,0.0,0.0,0.0,0.0,5.0,16.0,15.0,0.0,0.0,0.0,0.0,0.0,4.0,16.0,14.0,0.0,0.0,0.0,0.0,0.0,1.0,13.0,16.0,1.0,0.0],- [0.0,0.0,5.0,12.0,1.0,0.0,0.0,0.0,0.0,0.0,15.0,14.0,7.0,0.0,0.0,0.0,0.0,0.0,13.0,1.0,12.0,0.0,0.0,0.0,0.0,2.0,10.0,0.0,14.0,0.0,0.0,0.0,0.0,0.0,2.0,0.0,16.0,1.0,0.0,0.0,0.0,0.0,0.0,6.0,15.0,0.0,0.0,0.0,0.0,0.0,9.0,16.0,15.0,9.0,8.0,2.0,0.0,0.0,3.0,11.0,8.0,13.0,12.0,4.0],- [0.0,2.0,9.0,15.0,14.0,9.0,3.0,0.0,0.0,4.0,13.0,8.0,9.0,16.0,8.0,0.0,0.0,0.0,0.0,6.0,14.0,15.0,3.0,0.0,0.0,0.0,0.0,11.0,14.0,2.0,0.0,0.0,0.0,0.0,0.0,2.0,15.0,11.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,15.0,4.0,0.0,0.0,1.0,5.0,6.0,13.0,16.0,6.0,0.0,0.0,2.0,12.0,12.0,13.0,11.0,0.0,0.0],- [0.0,0.0,0.0,8.0,15.0,1.0,0.0,0.0,0.0,0.0,1.0,14.0,13.0,1.0,1.0,0.0,0.0,0.0,10.0,15.0,3.0,15.0,11.0,0.0,0.0,7.0,16.0,7.0,1.0,16.0,8.0,0.0,0.0,9.0,16.0,13.0,14.0,16.0,5.0,0.0,0.0,1.0,10.0,15.0,16.0,14.0,0.0,0.0,0.0,0.0,0.0,1.0,16.0,10.0,0.0,0.0,0.0,0.0,0.0,10.0,15.0,4.0,0.0,0.0],- [0.0,5.0,12.0,13.0,16.0,16.0,2.0,0.0,0.0,11.0,16.0,15.0,8.0,4.0,0.0,0.0,0.0,8.0,14.0,11.0,1.0,0.0,0.0,0.0,0.0,8.0,16.0,16.0,14.0,0.0,0.0,0.0,0.0,1.0,6.0,6.0,16.0,0.0,0.0,0.0,0.0,0.0,0.0,5.0,16.0,3.0,0.0,0.0,0.0,1.0,5.0,15.0,13.0,0.0,0.0,0.0,0.0,4.0,15.0,16.0,2.0,0.0,0.0,0.0],- [0.0,0.0,0.0,8.0,15.0,1.0,0.0,0.0,0.0,0.0,0.0,12.0,14.0,0.0,0.0,0.0,0.0,0.0,3.0,16.0,7.0,0.0,0.0,0.0,0.0,0.0,6.0,16.0,2.0,0.0,0.0,0.0,0.0,0.0,7.0,16.0,16.0,13.0,5.0,0.0,0.0,0.0,15.0,16.0,9.0,9.0,14.0,0.0,0.0,0.0,3.0,14.0,9.0,2.0,16.0,2.0,0.0,0.0,0.0,7.0,15.0,16.0,11.0,0.0],- [0.0,0.0,1.0,8.0,15.0,10.0,0.0,0.0,0.0,3.0,13.0,15.0,14.0,14.0,0.0,0.0,0.0,5.0,10.0,0.0,10.0,12.0,0.0,0.0,0.0,0.0,3.0,5.0,15.0,10.0,2.0,0.0,0.0,0.0,16.0,16.0,16.0,16.0,12.0,0.0,0.0,1.0,8.0,12.0,14.0,8.0,3.0,0.0,0.0,0.0,0.0,10.0,13.0,0.0,0.0,0.0,0.0,0.0,0.0,11.0,9.0,0.0,0.0,0.0],- [0.0,0.0,10.0,7.0,13.0,9.0,0.0,0.0,0.0,0.0,9.0,10.0,12.0,15.0,2.0,0.0,0.0,0.0,4.0,11.0,10.0,11.0,0.0,0.0,0.0,0.0,1.0,16.0,10.0,1.0,0.0,0.0,0.0,0.0,12.0,13.0,4.0,0.0,0.0,0.0,0.0,0.0,12.0,1.0,12.0,0.0,0.0,0.0,0.0,1.0,10.0,2.0,14.0,0.0,0.0,0.0,0.0,0.0,11.0,14.0,5.0,0.0,0.0,0.0],- [0.0,0.0,6.0,14.0,4.0,0.0,0.0,0.0,0.0,0.0,11.0,16.0,10.0,0.0,0.0,0.0,0.0,0.0,8.0,14.0,16.0,2.0,0.0,0.0,0.0,0.0,1.0,12.0,12.0,11.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,11.0,3.0,0.0,0.0,0.0,0.0,0.0,0.0,5.0,11.0,0.0,0.0,0.0,1.0,4.0,4.0,7.0,16.0,2.0,0.0,0.0,7.0,16.0,16.0,13.0,11.0,1.0]- ]--testNeighbourProbs :: [[Probability]]-testNeighbourProbs = neighbourProbabilities def testInput
+ test/Data/Algorithm/TSNE/PreparationSpec.hs view
@@ -0,0 +1,39 @@+module Data.Algorithm.TSNE.PreparationSpec (main, spec) where++import Data.Default (def)++import Test.Hspec+import Data.Algorithm.TSNE.Preparation+import Data.Algorithm.TSNE.Checks+import Data.Algorithm.TSNE.Types+import Data.Algorithm.TSNE.Utils+import Data.Algorithm.TSNE.TestInput+import Data.Algorithm.TSNE.TestMisc++-- `main` is here so that this module can be run from GHCi on its own. It is+-- not needed for automatic spec discovery.+main :: IO ()+main = hspec spec++u = undefined++spec :: Spec+spec = do+ let n = inputSize testInput+ w = inputValueSize testInput++ describe "testInput" $ do+ it "is right shape" $ do+ testInput `shouldSatisfy` has2DShape (64, 20)+ it "is valid" $ do+ inputIsValid testInput `shouldBe` Right ()+ it "has right size" $ do+ inputSize testInput `shouldBe` 20+ it "has right value size" $ do+ inputValueSize testInput `shouldBe` 64++ describe "neighbourProbabilities" $ do+ it "is right shape" $ do+ testNeighbourProbs `shouldSatisfy` has2DShape (n,n)++
+ test/Data/Algorithm/TSNE/Run2DSpec.hs view
@@ -0,0 +1,32 @@+module Data.Algorithm.TSNE.Run2DSpec (main, spec) where++import Data.Default (def)++import Test.Hspec+import Data.Algorithm.TSNE.Run2D+import Data.Algorithm.TSNE.Stepping+import Data.Algorithm.TSNE.Checks+import Data.Algorithm.TSNE.Types+import Data.Algorithm.TSNE.Utils+import Data.Algorithm.TSNE.TestInput+import Data.Algorithm.TSNE.TestMisc++-- `main` is here so that this module can be run from GHCi on its own. It is+-- not needed for automatic spec discovery.+main :: IO ()+main = hspec spec++u = undefined++spec :: Spec+spec = do+ let n = inputSize testInput+ w = inputValueSize testInput++ describe "initSolution2D" $ do+ it "is right shape" $+ initSolution2D n >>= (`shouldSatisfy` has2DShape (n,2))++ describe "initState" $ do+ it "is valid state" $+ initState2D n >>= (`shouldSatisfy` isRight . (isValidStateForInput 2 testInput))
+ test/Data/Algorithm/TSNE/Run3DSpec.hs view
@@ -0,0 +1,47 @@+module Data.Algorithm.TSNE.Run3DSpec (main, spec) where++import Data.Default (def)++import Test.Hspec+import Data.Algorithm.TSNE.Run3D+import Data.Algorithm.TSNE.Stepping+import Data.Algorithm.TSNE.Checks+import Data.Algorithm.TSNE.Types+import Data.Algorithm.TSNE.Utils+import Data.Algorithm.TSNE.TestInput+import Data.Algorithm.TSNE.TestMisc++-- `main` is here so that this module can be run from GHCi on its own. It is+-- not needed for automatic spec discovery.+main :: IO ()+main = hspec spec++u = undefined++spec :: Spec+spec = do+ let n = inputSize testInput+ w = inputValueSize testInput++ describe "initSolution3D" $ do+ it "is right shape" $+ initSolution3D n >>= (`shouldSatisfy` has2DShape (n,3))++ describe "initState" $ do+ it "is valid state" $+ initState3D n >>= (`shouldSatisfy` isRight . (isValidStateForInput 3 testInput))++ describe "qdist" $ do+ it "is right shape" $ do+ s <- initSolution3D n+ qdist s `shouldSatisfy` has2DShape (n,n) ++ describe "qdist'" $ do+ it "is right shape" $ do+ s <- initSolution3D n+ qdist' s `shouldSatisfy` has2DShape (n,n) ++ describe "gradients" $ do+ it "is right shape" $ do+ s <- initState3D n+ gradients testNeighbourProbs s `shouldSatisfy` has2DShape (n,3)
+ test/Data/Algorithm/TSNE/SteppingSpec.hs view
@@ -0,0 +1,29 @@+module Data.Algorithm.TSNE.SteppingSpec (main, spec) where++import Data.Default (def)++import Test.Hspec+import Data.Algorithm.TSNE.Stepping+import Data.Algorithm.TSNE.Run3D+import Data.Algorithm.TSNE.Checks+import Data.Algorithm.TSNE.Types+import Data.Algorithm.TSNE.Utils+import Data.Algorithm.TSNE.TestInput+import Data.Algorithm.TSNE.TestMisc++-- `main` is here so that this module can be run from GHCi on its own. It is+-- not needed for automatic spec discovery.+main :: IO ()+main = hspec spec++u = undefined++spec :: Spec+spec = do+ let n = inputSize testInput+ w = inputValueSize testInput++ describe "stepTSNE" $ do+ it "works" $ do + s <- initState3D n+ stepTSNE def testInput testNeighbourProbs s `shouldSatisfy` isRight . (isValidStateForInput 3 testInput)
+ test/Data/Algorithm/TSNE/TestInput.hs view
@@ -0,0 +1,35 @@+module Data.Algorithm.TSNE.TestInput where++import Data.Default (def)++import Data.Algorithm.TSNE.Types+import Data.Algorithm.TSNE.Preparation++-- first 20 digits from the Python sklearn digits dataset+testInput :: TSNEInput+testInput = [+ [0.0,0.0,5.0,13.0,9.0,1.0,0.0,0.0,0.0,0.0,13.0,15.0,10.0,15.0,5.0,0.0,0.0,3.0,15.0,2.0,0.0,11.0,8.0,0.0,0.0,4.0,12.0,0.0,0.0,8.0,8.0,0.0,0.0,5.0,8.0,0.0,0.0,9.0,8.0,0.0,0.0,4.0,11.0,0.0,1.0,12.0,7.0,0.0,0.0,2.0,14.0,5.0,10.0,12.0,0.0,0.0,0.0,0.0,6.0,13.0,10.0,0.0,0.0,0.0],+ [0.0,0.0,0.0,12.0,13.0,5.0,0.0,0.0,0.0,0.0,0.0,11.0,16.0,9.0,0.0,0.0,0.0,0.0,3.0,15.0,16.0,6.0,0.0,0.0,0.0,7.0,15.0,16.0,16.0,2.0,0.0,0.0,0.0,0.0,1.0,16.0,16.0,3.0,0.0,0.0,0.0,0.0,1.0,16.0,16.0,6.0,0.0,0.0,0.0,0.0,1.0,16.0,16.0,6.0,0.0,0.0,0.0,0.0,0.0,11.0,16.0,10.0,0.0,0.0],+ [0.0,0.0,0.0,4.0,15.0,12.0,0.0,0.0,0.0,0.0,3.0,16.0,15.0,14.0,0.0,0.0,0.0,0.0,8.0,13.0,8.0,16.0,0.0,0.0,0.0,0.0,1.0,6.0,15.0,11.0,0.0,0.0,0.0,1.0,8.0,13.0,15.0,1.0,0.0,0.0,0.0,9.0,16.0,16.0,5.0,0.0,0.0,0.0,0.0,3.0,13.0,16.0,16.0,11.0,5.0,0.0,0.0,0.0,0.0,3.0,11.0,16.0,9.0,0.0],+ [0.0,0.0,7.0,15.0,13.0,1.0,0.0,0.0,0.0,8.0,13.0,6.0,15.0,4.0,0.0,0.0,0.0,2.0,1.0,13.0,13.0,0.0,0.0,0.0,0.0,0.0,2.0,15.0,11.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0,12.0,12.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0,10.0,8.0,0.0,0.0,0.0,8.0,4.0,5.0,14.0,9.0,0.0,0.0,0.0,7.0,13.0,13.0,9.0,0.0,0.0],+ [0.0,0.0,0.0,1.0,11.0,0.0,0.0,0.0,0.0,0.0,0.0,7.0,8.0,0.0,0.0,0.0,0.0,0.0,1.0,13.0,6.0,2.0,2.0,0.0,0.0,0.0,7.0,15.0,0.0,9.0,8.0,0.0,0.0,5.0,16.0,10.0,0.0,16.0,6.0,0.0,0.0,4.0,15.0,16.0,13.0,16.0,1.0,0.0,0.0,0.0,0.0,3.0,15.0,10.0,0.0,0.0,0.0,0.0,0.0,2.0,16.0,4.0,0.0,0.0],+ [0.0,0.0,12.0,10.0,0.0,0.0,0.0,0.0,0.0,0.0,14.0,16.0,16.0,14.0,0.0,0.0,0.0,0.0,13.0,16.0,15.0,10.0,1.0,0.0,0.0,0.0,11.0,16.0,16.0,7.0,0.0,0.0,0.0,0.0,0.0,4.0,7.0,16.0,7.0,0.0,0.0,0.0,0.0,0.0,4.0,16.0,9.0,0.0,0.0,0.0,5.0,4.0,12.0,16.0,4.0,0.0,0.0,0.0,9.0,16.0,16.0,10.0,0.0,0.0],+ [0.0,0.0,0.0,12.0,13.0,0.0,0.0,0.0,0.0,0.0,5.0,16.0,8.0,0.0,0.0,0.0,0.0,0.0,13.0,16.0,3.0,0.0,0.0,0.0,0.0,0.0,14.0,13.0,0.0,0.0,0.0,0.0,0.0,0.0,15.0,12.0,7.0,2.0,0.0,0.0,0.0,0.0,13.0,16.0,13.0,16.0,3.0,0.0,0.0,0.0,7.0,16.0,11.0,15.0,8.0,0.0,0.0,0.0,1.0,9.0,15.0,11.0,3.0,0.0],+ [0.0,0.0,7.0,8.0,13.0,16.0,15.0,1.0,0.0,0.0,7.0,7.0,4.0,11.0,12.0,0.0,0.0,0.0,0.0,0.0,8.0,13.0,1.0,0.0,0.0,4.0,8.0,8.0,15.0,15.0,6.0,0.0,0.0,2.0,11.0,15.0,15.0,4.0,0.0,0.0,0.0,0.0,0.0,16.0,5.0,0.0,0.0,0.0,0.0,0.0,9.0,15.0,1.0,0.0,0.0,0.0,0.0,0.0,13.0,5.0,0.0,0.0,0.0,0.0],+ [0.0,0.0,9.0,14.0,8.0,1.0,0.0,0.0,0.0,0.0,12.0,14.0,14.0,12.0,0.0,0.0,0.0,0.0,9.0,10.0,0.0,15.0,4.0,0.0,0.0,0.0,3.0,16.0,12.0,14.0,2.0,0.0,0.0,0.0,4.0,16.0,16.0,2.0,0.0,0.0,0.0,3.0,16.0,8.0,10.0,13.0,2.0,0.0,0.0,1.0,15.0,1.0,3.0,16.0,8.0,0.0,0.0,0.0,11.0,16.0,15.0,11.0,1.0,0.0],+ [0.0,0.0,11.0,12.0,0.0,0.0,0.0,0.0,0.0,2.0,16.0,16.0,16.0,13.0,0.0,0.0,0.0,3.0,16.0,12.0,10.0,14.0,0.0,0.0,0.0,1.0,16.0,1.0,12.0,15.0,0.0,0.0,0.0,0.0,13.0,16.0,9.0,15.0,2.0,0.0,0.0,0.0,0.0,3.0,0.0,9.0,11.0,0.0,0.0,0.0,0.0,0.0,9.0,15.0,4.0,0.0,0.0,0.0,9.0,12.0,13.0,3.0,0.0,0.0],+ [0.0,0.0,1.0,9.0,15.0,11.0,0.0,0.0,0.0,0.0,11.0,16.0,8.0,14.0,6.0,0.0,0.0,2.0,16.0,10.0,0.0,9.0,9.0,0.0,0.0,1.0,16.0,4.0,0.0,8.0,8.0,0.0,0.0,4.0,16.0,4.0,0.0,8.0,8.0,0.0,0.0,1.0,16.0,5.0,1.0,11.0,3.0,0.0,0.0,0.0,12.0,12.0,10.0,10.0,0.0,0.0,0.0,0.0,1.0,10.0,13.0,3.0,0.0,0.0],+ [0.0,0.0,0.0,0.0,14.0,13.0,1.0,0.0,0.0,0.0,0.0,5.0,16.0,16.0,2.0,0.0,0.0,0.0,0.0,14.0,16.0,12.0,0.0,0.0,0.0,1.0,10.0,16.0,16.0,12.0,0.0,0.0,0.0,3.0,12.0,14.0,16.0,9.0,0.0,0.0,0.0,0.0,0.0,5.0,16.0,15.0,0.0,0.0,0.0,0.0,0.0,4.0,16.0,14.0,0.0,0.0,0.0,0.0,0.0,1.0,13.0,16.0,1.0,0.0],+ [0.0,0.0,5.0,12.0,1.0,0.0,0.0,0.0,0.0,0.0,15.0,14.0,7.0,0.0,0.0,0.0,0.0,0.0,13.0,1.0,12.0,0.0,0.0,0.0,0.0,2.0,10.0,0.0,14.0,0.0,0.0,0.0,0.0,0.0,2.0,0.0,16.0,1.0,0.0,0.0,0.0,0.0,0.0,6.0,15.0,0.0,0.0,0.0,0.0,0.0,9.0,16.0,15.0,9.0,8.0,2.0,0.0,0.0,3.0,11.0,8.0,13.0,12.0,4.0],+ [0.0,2.0,9.0,15.0,14.0,9.0,3.0,0.0,0.0,4.0,13.0,8.0,9.0,16.0,8.0,0.0,0.0,0.0,0.0,6.0,14.0,15.0,3.0,0.0,0.0,0.0,0.0,11.0,14.0,2.0,0.0,0.0,0.0,0.0,0.0,2.0,15.0,11.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,15.0,4.0,0.0,0.0,1.0,5.0,6.0,13.0,16.0,6.0,0.0,0.0,2.0,12.0,12.0,13.0,11.0,0.0,0.0],+ [0.0,0.0,0.0,8.0,15.0,1.0,0.0,0.0,0.0,0.0,1.0,14.0,13.0,1.0,1.0,0.0,0.0,0.0,10.0,15.0,3.0,15.0,11.0,0.0,0.0,7.0,16.0,7.0,1.0,16.0,8.0,0.0,0.0,9.0,16.0,13.0,14.0,16.0,5.0,0.0,0.0,1.0,10.0,15.0,16.0,14.0,0.0,0.0,0.0,0.0,0.0,1.0,16.0,10.0,0.0,0.0,0.0,0.0,0.0,10.0,15.0,4.0,0.0,0.0],+ [0.0,5.0,12.0,13.0,16.0,16.0,2.0,0.0,0.0,11.0,16.0,15.0,8.0,4.0,0.0,0.0,0.0,8.0,14.0,11.0,1.0,0.0,0.0,0.0,0.0,8.0,16.0,16.0,14.0,0.0,0.0,0.0,0.0,1.0,6.0,6.0,16.0,0.0,0.0,0.0,0.0,0.0,0.0,5.0,16.0,3.0,0.0,0.0,0.0,1.0,5.0,15.0,13.0,0.0,0.0,0.0,0.0,4.0,15.0,16.0,2.0,0.0,0.0,0.0],+ [0.0,0.0,0.0,8.0,15.0,1.0,0.0,0.0,0.0,0.0,0.0,12.0,14.0,0.0,0.0,0.0,0.0,0.0,3.0,16.0,7.0,0.0,0.0,0.0,0.0,0.0,6.0,16.0,2.0,0.0,0.0,0.0,0.0,0.0,7.0,16.0,16.0,13.0,5.0,0.0,0.0,0.0,15.0,16.0,9.0,9.0,14.0,0.0,0.0,0.0,3.0,14.0,9.0,2.0,16.0,2.0,0.0,0.0,0.0,7.0,15.0,16.0,11.0,0.0],+ [0.0,0.0,1.0,8.0,15.0,10.0,0.0,0.0,0.0,3.0,13.0,15.0,14.0,14.0,0.0,0.0,0.0,5.0,10.0,0.0,10.0,12.0,0.0,0.0,0.0,0.0,3.0,5.0,15.0,10.0,2.0,0.0,0.0,0.0,16.0,16.0,16.0,16.0,12.0,0.0,0.0,1.0,8.0,12.0,14.0,8.0,3.0,0.0,0.0,0.0,0.0,10.0,13.0,0.0,0.0,0.0,0.0,0.0,0.0,11.0,9.0,0.0,0.0,0.0],+ [0.0,0.0,10.0,7.0,13.0,9.0,0.0,0.0,0.0,0.0,9.0,10.0,12.0,15.0,2.0,0.0,0.0,0.0,4.0,11.0,10.0,11.0,0.0,0.0,0.0,0.0,1.0,16.0,10.0,1.0,0.0,0.0,0.0,0.0,12.0,13.0,4.0,0.0,0.0,0.0,0.0,0.0,12.0,1.0,12.0,0.0,0.0,0.0,0.0,1.0,10.0,2.0,14.0,0.0,0.0,0.0,0.0,0.0,11.0,14.0,5.0,0.0,0.0,0.0],+ [0.0,0.0,6.0,14.0,4.0,0.0,0.0,0.0,0.0,0.0,11.0,16.0,10.0,0.0,0.0,0.0,0.0,0.0,8.0,14.0,16.0,2.0,0.0,0.0,0.0,0.0,1.0,12.0,12.0,11.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,11.0,3.0,0.0,0.0,0.0,0.0,0.0,0.0,5.0,11.0,0.0,0.0,0.0,1.0,4.0,4.0,7.0,16.0,2.0,0.0,0.0,7.0,16.0,16.0,13.0,11.0,1.0]+ ]++testNeighbourProbs :: [[Probability]]+testNeighbourProbs = neighbourProbabilities def testInput+
+ test/Data/Algorithm/TSNE/TestMisc.hs view
@@ -0,0 +1,5 @@+module Data.Algorithm.TSNE.TestMisc where++isRight :: Either a b -> Bool+isRight (Left _) = False+isRight (Right _) = True
tsne.cabal view
@@ -1,5 +1,5 @@ name: tsne-version: 1.2.0+version: 1.3.0 synopsis: t-SNE description: Pure Haskell implementation of the t-SNE dimension reduction algorithm. homepage: https://bitbucket.org/robagar/haskell-tsne@@ -16,9 +16,12 @@ hs-source-dirs: src exposed-modules: Data.Algorithm.TSNE, Data.Algorithm.TSNE.Types, - Data.Algorithm.TSNE.Internals, Data.Algorithm.TSNE.Utils,- Data.Algorithm.TSNE.Checks + Data.Algorithm.TSNE.Checks, + Data.Algorithm.TSNE.Preparation, + Data.Algorithm.TSNE.Stepping, + Data.Algorithm.TSNE.Run2D, + Data.Algorithm.TSNE.Run3D build-depends: base >= 4.7 && < 5, data-default, deepseq,@@ -31,9 +34,14 @@ hs-source-dirs: test main-is: Spec.hs other-modules: Data.Algorithm.TSNESpec,- Data.Algorithm.TSNE.InternalsSpec,+ Data.Algorithm.TSNE.PreparationSpec,+ Data.Algorithm.TSNE.SteppingSpec, Data.Algorithm.TSNE.UtilsSpec,- Data.Algorithm.TSNE.ChecksSpec+ Data.Algorithm.TSNE.ChecksSpec,+ Data.Algorithm.TSNE.Run3DSpec,+ Data.Algorithm.TSNE.Run2DSpec,+ Data.Algorithm.TSNE.TestInput,+ Data.Algorithm.TSNE.TestMisc build-depends: base, hspec, data-default,