From 452acbabb3980fa0538f79fa4cd95ea6da36c0fd Mon Sep 17 00:00:00 2001 From: Ayush Date: Mon, 24 Aug 2020 14:26:45 +0530 Subject: [PATCH 1/7] Adding Isolation + Fixing previous import issue --- examples/trees/{ => cart}/cart.go | 5 +- examples/trees/{ => id3}/trees.go | 0 trees/isolation.go | 218 ++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+), 3 deletions(-) rename examples/trees/{ => cart}/cart.go (95%) rename examples/trees/{ => id3}/trees.go (100%) create mode 100644 trees/isolation.go diff --git a/examples/trees/cart.go b/examples/trees/cart/cart.go similarity index 95% rename from examples/trees/cart.go rename to examples/trees/cart/cart.go index 5a19cab..15d5888 100644 --- a/examples/trees/cart.go +++ b/examples/trees/cart/cart.go @@ -7,7 +7,6 @@ import ( "github.com/sjwhitworth/golearn/base" "github.com/sjwhitworth/golearn/trees" - ) func main() { @@ -45,7 +44,7 @@ func main() { // Create New Classification Tree // Hyperparameters - loss function, max Depth (-1 will split until pure), list of unique labels - decTree := NewDecisionTreeClassifier("entropy", -1, []int64{0, 1}) + decTree := trees.NewDecisionTreeClassifier("entropy", -1, []int64{0, 1}) // Train Tree err = decTree.Fit(trainData) @@ -72,7 +71,7 @@ func main() { trainRegData, testRegData := base.InstancesTrainTestSplit(regressionData, 0.5) // Hyperparameters - Loss function, max Depth (-1 will split until pure) - regTree := NewDecisionTreeRegressor("mse", -1) + regTree := trees.NewDecisionTreeRegressor("mse", -1) // Train Tree err = regTree.Fit(trainRegData) diff --git a/examples/trees/trees.go b/examples/trees/id3/trees.go similarity index 100% rename from examples/trees/trees.go rename to examples/trees/id3/trees.go diff --git a/trees/isolation.go b/trees/isolation.go new file mode 100644 index 0000000..bfd9f03 --- /dev/null +++ b/trees/isolation.go @@ -0,0 +1,218 @@ +package trees + +import ( + "math" + "math/rand" + "time" + + "github.com/sjwhitworth/golearn/base" +) + +type IsolationForest struct { + nTrees int + maxDepth int + subSpace int + trees []regressorNode +} + +func selectFeature(data [][]float64) int64 { + rand.Seed(time.Now().UnixNano()) + return int64(rand.Intn(len(data[0]))) +} + +func minMax(feature int64, data [][]float64) (float64, float64) { + + var min, max float64 + + min = math.Inf(1) + max = math.Inf(-1) + for _, instance := range data { + if instance[feature] > max { + max = instance[feature] + } + if instance[feature] < min { + min = instance[feature] + } + } + + return min, max +} + +func selectValue(min, max float64) float64 { + rand.Seed(time.Now().UnixNano()) + val := min + (rand.Float64() * (max - min)) + if val == min { + val += 0.000001 + } else if val == max { + val -= 0.000001 + } + return val +} + +func splitData(val float64, feature int64, data [][]float64) ([][]float64, [][]float64) { + var leftData, rightData [][]float64 + for _, instance := range data { + if instance[feature] <= val { + leftData = append(leftData, instance) + } else { + rightData = append(rightData, instance) + } + } + return leftData, rightData +} + +func checkData(data [][]float64) bool { + for _, instance := range data { + for i, val := range instance { + if val != data[0][i] { + return true + } + } + } + return false +} + +func buildTree(data [][]float64, upperNode regressorNode, depth int, maxDepth int) regressorNode { + depth++ + + upperNode.isNodeNeeded = true + if (depth > maxDepth) || (len(data) <= 1) || !checkData(data) { + upperNode.isNodeNeeded = false + return upperNode + } + + var featureToSplit int64 + var splitVal float64 + var min, max float64 + min, max = 0.0, 0.0 + + for min == max { + featureToSplit = selectFeature(data) + min, max = minMax(featureToSplit, data) + splitVal = selectValue(min, max) + } + + leftData, rightData := splitData(splitVal, featureToSplit, data) + + upperNode.Feature = featureToSplit + upperNode.Threshold = splitVal + upperNode.LeftPred = float64(len(leftData)) + upperNode.RightPred = float64(len(rightData)) + + var leftNode, rightNode regressorNode + leftNode = buildTree(leftData, leftNode, depth, maxDepth) + rightNode = buildTree(rightData, rightNode, depth, maxDepth) + + if leftNode.isNodeNeeded { + upperNode.Left = &leftNode + } + if rightNode.isNodeNeeded { + upperNode.Right = &rightNode + } + + return upperNode +} + +func getRandomData(data [][]float64, subSpace int) [][]float64 { + var randomData [][]float64 + rand.Seed(time.Now().UnixNano()) + for i := 0; i < subSpace; i++ { + randomData = append(randomData, data[rand.Intn(len(data))]) + } + return randomData +} + +func NewIsolationForest(nTrees int, maxDepth int, subSpace int) IsolationForest { + var iForest IsolationForest + iForest.nTrees = nTrees + iForest.maxDepth = maxDepth + iForest.subSpace = subSpace + return iForest +} + +func (iForest *IsolationForest) Fit(X base.FixedDataGrid) { + data := preprocessData(X) + nTrees := iForest.nTrees + subSpace := iForest.subSpace + maxDepth := iForest.maxDepth + + var forest []regressorNode + for i := 0; i < nTrees; i++ { + subData := getRandomData(data, subSpace) + var tree regressorNode + + tree = buildTree(subData, tree, 0, maxDepth) + forest = append(forest, tree) + } + iForest.trees = forest +} + +func pathLength(tree regressorNode, instance []float64, path float64) float64 { + path++ + + if instance[tree.Feature] <= tree.Threshold { + if tree.Left == nil { + if tree.LeftPred <= 1 { + return path + } else { + return path + cFactor(int(tree.LeftPred)) + } + } + path = pathLength(*tree.Left, instance, path) + } else { + if tree.Right == nil { + if tree.RightPred <= 1 { + return path + } else { + return path + cFactor(int(tree.RightPred)) + } + } + path = pathLength(*tree.Right, instance, path) + } + return path +} + +func evaluateInstance(instance []float64, forest []regressorNode) []float64 { + var paths []float64 + for _, tree := range forest { + paths = append(paths, pathLength(tree, instance, 0)) + } + return paths +} + +func cFactor(n int) float64 { + return 2.0*(math.Log(float64(n-1))+0.5772156649) - (float64(2.0*(n-1)) / float64(n)) +} + +func anomalyScore(instance []float64, forest []regressorNode, n int) float64 { + paths := evaluateInstance(instance, forest) + E := 0.0 + for _, path := range paths { + E += path + } + E /= float64(len(paths)) + c := cFactor(n) + return math.Pow(2, (-1 * E / c)) +} +func (iForest *IsolationForest) Predict(X base.FixedDataGrid) []float64 { + data := preprocessData(X) + + var preds []float64 + for _, instance := range data { + score := anomalyScore(instance, iForest.trees, iForest.subSpace) + preds = append(preds, score) + } + return preds +} + +func preprocessData(X base.FixedDataGrid) [][]float64 { + data := convertInstancesToProblemVec(X) + class, err := regressorConvertInstancesToLabelVec(X) + if err != nil { + panic(err) + } + for i, point := range class { + data[i] = append(data[i], point) + } + return data +} From d20c03e2b388fa58e6f7832aa12882680f412b76 Mon Sep 17 00:00:00 2001 From: Ayush Date: Tue, 25 Aug 2020 09:59:19 +0530 Subject: [PATCH 2/7] Adding isolation_test --- trees/isolation_test.go | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 trees/isolation_test.go diff --git a/trees/isolation_test.go b/trees/isolation_test.go new file mode 100644 index 0000000..4219953 --- /dev/null +++ b/trees/isolation_test.go @@ -0,0 +1,42 @@ +package trees + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestIsolation(t *testing.T) { + + Convey("Doing an Isolation Forest Test", t, func() { + + var data [][]float64 + data = append(data, []float64{8, 9, 8, 3}) + data = append(data, []float64{4, 2, 5, 3}) + data = append(data, []float64{3, 2, 5, 9}) + data = append(data, []float64{2, 1, 5, 9}) + + featureChosen := selectFeature(data) + So(featureChosen, ShouldNotBeNil) + + min, max := minMax(0, data) + So(min, ShouldEqual, 2) + So(max, ShouldEqual, 8) + + min, max = minMax(featureChosen, data) + + val := selectValue(min, max) + So(val, ShouldBeBetween, min, max) + + leftData, rightData := splitData(val, featureChosen, data) + So(len(leftData), ShouldBeGreaterThan, 0) + So(len(rightData), ShouldBeGreaterThan, 0) + + checked := checkData(data) + So(checked, ShouldBeTrue) + + randomSubset := getRandomData(data, 2) + So(len(randomSubset), ShouldEqual, 2) + + }) +} From 5a66fb940f8fc22f994efab4ffc6d67407662de5 Mon Sep 17 00:00:00 2001 From: Ayush Date: Thu, 27 Aug 2020 18:00:37 +0530 Subject: [PATCH 3/7] Adding Example Script --- examples/datasets/gaussian_outliers.csv | 1011 +++++++++++++++++ .../trees/isolationForest/isolation_forest.go | 57 + 2 files changed, 1068 insertions(+) create mode 100644 examples/datasets/gaussian_outliers.csv create mode 100644 examples/trees/isolationForest/isolation_forest.go diff --git a/examples/datasets/gaussian_outliers.csv b/examples/datasets/gaussian_outliers.csv new file mode 100644 index 0000000..9e9735b --- /dev/null +++ b/examples/datasets/gaussian_outliers.csv @@ -0,0 +1,1011 @@ +F1,F2 +0.023702107253236473,-0.7203357749463722 +-1.056344272753271,-1.5563880111353698 +1.7366544678265408,-1.0222667594786548 +0.277701375527707,-0.4281074935675912 +1.3779866840331947,-1.0361348964618289 +0.6096579353063047,0.2341907428514227 +1.096855962700895,-0.005811169094786541 +0.37493367010718087,-2.1858055816261923 +-1.0033552959459144,-1.040570292907295 +1.097777087897632,-0.18593316561992165 +-0.13705871873285408,-2.3962446494603182 +-0.4095549959268086,-1.0800450761053546 +-0.2725463734687842,1.0482339715574414 +0.09949243973996885,0.6109555466685334 +-0.21317085931675578,1.029603935823801 +-0.6735941868791542,0.07873683239131536 +-1.2706325132640786,-0.9394750105886207 +0.05608393178920749,0.4270506272130099 +1.0231445739365046,-1.540495218350606 +-0.32021022123348514,0.06684556078411466 +-0.995856936439487,1.0916585724335708 +-0.0662477050361568,0.2870008477940905 +-1.6000716972982665,-0.3936693123573611 +0.9769761054924024,-0.16404316155956736 +1.5332298431016438,-0.23395310290627283 +1.5563056941471904,-0.8486250918456094 +-0.9710817665308864,0.10537803550812928 +-0.5144386385886385,2.1630641727706164 +-1.2063840618169575,-1.388205756495295 +-0.0915644397027798,1.2662662789164152 +-2.032903474809216,1.2821528405423592 +-0.18161591335666089,0.9146103142768536 +-0.5522191459676629,1.0871839023207046 +-0.2675020963561937,1.6490215434131752 +-0.5580044049596554,-0.5759426165365136 +0.5223057709317516,0.12317074146816956 +1.8307573139920394,1.1217941211121838 +-0.8628048844566394,2.4352837872621134 +0.2877279131365035,-0.3433053328795448 +-1.4911987885026587,2.0331472674138285 +0.25283672745609104,-1.2875701798806025 +0.42274340963358675,-0.06605443932259006 +-0.1022261950875974,-0.8686753417804632 +-0.6543552564305656,1.5313804941427513 +-1.7691577542416683,1.4046510052592818 +-1.35966549305657,-0.315705407288172 +0.8298744145739777,1.9190710690173944 +2.1696831285187326,-0.4447312796527254 +-0.5864292099609683,-0.21675456506397847 +-0.3220132887678087,0.6072930216895185 +-0.8863175789321834,-0.37890271744814763 +-1.1102300651960972,-0.21083096758602973 +0.36376231565535544,0.13267262231347837 +-1.0920053096057805,0.5625200978605387 +-0.4359878553546709,0.19546660815621333 +-0.016590085002032462,0.23763010456308223 +-0.9303628770225935,1.178371162639787 +-0.20202119962191176,0.030314084279160446 +-1.3364632503076326,0.1434517163203669 +0.09176700814813755,0.8790299092097098 +-1.0779810950258113,-0.05350123935401387 +-0.5246063069598481,0.4547065456405234 +-0.00996881749263303,-1.125161619470404 +-0.8524607059934628,-1.344625652292588 +-0.05640483181112883,2.028918274363119 +-1.0629274656214744,-0.16240481812976112 +1.297962908910632,1.194062597510596 +-0.9250344619375467,1.0267206768564823 +2.233035610084786,0.49739159264009414 +1.2148481625595098,0.18561635300483725 +-1.8631975886274756,-0.7062069165674798 +0.5374979941178547,1.7382062257123028 +1.3579510592251018,-0.7144554787004237 +-1.9253979395751712,0.6984995686148602 +-0.7260877676847222,1.148578795387194 +-1.6574295112948785,-0.8525689863386012 +0.41633655323421564,1.1313295023238812 +-0.1820679148120617,1.1326221766223714 +-0.43458649462607196,-0.4729713490823393 +2.1841720081435025,0.9284066810379139 +1.1835640452830432,-0.48802299277749805 +-1.286525141555083,1.0477268774849067 +-0.18492041758993605,0.08277740888778054 +1.7089196891809881,0.31694410169962484 +0.36169048433205275,-1.4641537447702482 +-1.588851590089621,-1.2330767725070015 +2.5027343599185286,-0.28197877098840285 +1.1634000558034212,-0.6298197593754739 +0.8663096192491975,0.6299770715475497 +-0.7555662223873691,0.8267394472280858 +-0.49380274658918555,0.11942711771011189 +0.6414913081747836,1.18946700998659 +-1.0501843416315795,-2.320930592965919 +1.6354242334496896,0.46113846094559807 +-1.2962984603225831,1.5328759895623665 +-1.6443093866943777,-0.8706308014676005 +-0.4848278706851593,-1.2100529864292473 +-0.6106155664426884,-0.8112504608279663 +0.9306209322054233,-0.7466037530850619 +-1.421545137511058,-0.12256389790537078 +-1.1786513591519856,1.771417295334806 +0.973920430815049,0.9599846066303299 +-1.2906135428579935,0.2288881139165304 +-1.4074067130480663,0.5944320708372758 +0.832139443615569,1.0662240366446025 +0.6208361264594784,0.04635201386423553 +1.292466431753266,-0.6467894830427992 +1.829307721511366,1.584350804331482 +-1.3081288214536064,0.0022293326696498053 +-0.9189916447713669,1.0883285454001623 +0.18557446673919495,1.9390456936869382 +-0.20213577193553509,1.8170335183992823 +-1.0619599079937792,0.4947294346507529 +-0.37161384879886783,-0.959177884303174 +-0.5443069542970971,-1.8913886595161293 +1.516594267038843,0.43988040278538065 +0.5303982863808446,-0.6859296175827077 +0.41032271097255796,0.05904479280274516 +0.23420607854443173,0.5945089442321493 +1.5622137333347235,-0.7714630597319156 +1.8413929021652147,-1.9613960084377984 +-0.4708494552951487,0.004505770664238547 +1.2760522956138936,-0.9206377931945251 +-1.1048491675941632,-0.6066411335176688 +-1.3176255159459738,-0.3654891379495374 +-0.6804073808145333,-0.18840359595558928 +1.143624795714804,0.11182214049602536 +-1.4850586834222579,1.322859157268923 +0.8514942689994228,-1.1573798579462564 +0.5917499399003432,0.9522031802306231 +-1.3180380234510995,-1.570811893746631 +0.4652701144891279,-1.113275298151253 +0.368533217263627,-0.9469940679957464 +0.14998053087019844,-0.004807926204480771 +0.5758642800159276,-0.8355590807198215 +1.389055312475646,-0.3154178602956908 +0.9095181391438995,1.2146740480242664 +0.46912070342257506,0.9427939036128978 +2.5050191961108386,1.2924009282862086 +0.07834286988801478,-0.4668835400277145 +0.7027866220674708,-0.7298512927647998 +1.0525597286269874,-1.423731178801485 +-1.2298992108920723,-0.747272160373149 +0.43538273969227215,1.791485988299681 +-0.3574990616409847,-0.4352778694575425 +1.067591679121304,0.16384105921795009 +-1.0000152007528242,0.6451948022552951 +0.24678386158065274,1.2178411115256018 +0.9414883909942793,-0.4137301288134352 +-1.1105910347022003,0.3905625492891115 +0.6386768443881544,-1.7428793297265963 +-0.9162339305238586,2.112460072040007 +-0.21594425953774576,0.7351159409140912 +-0.052199670963740716,-0.2204775545845522 +0.6200096621346023,-2.154195892701033 +0.5347723686670403,-0.2535166591425992 +0.033355698431150695,-1.91274725304036 +-0.12731994937362598,-0.18764994714055724 +0.5561096324081014,0.9959569008669875 +0.027955972580902932,0.20473214094823255 +1.1224254510817777,-1.165723549337444 +1.5240505942790123,1.395552401910252 +-0.4413352036601165,-0.052051943224693475 +-0.3997990540632525,-0.6070783533075853 +-0.7781723353512783,-0.1569069680769972 +1.26811848592789,-1.3966228562368053 +-0.8128628770183252,-1.9816329785760831 +0.21540118102955955,0.29364756633756856 +-0.8864151985103478,0.5767373285540405 +-0.11949447545065246,-0.10643869541236714 +0.025186232030254874,-0.26618888084643133 +-0.8059848982350944,-0.1729860874218723 +-1.0073423684251297,0.22152187357383046 +-0.9225216063803009,1.1011432218585036 +0.5119751793902464,-2.1171808888237598 +0.6326859261320135,1.305650946829591 +-1.3347739717985772,0.2967780835780649 +1.8372723977881131,-0.6651591796295121 +-0.0807983097473458,-0.5622123433344024 +-1.7763121386737295,0.26022087469291466 +-0.8709988615202664,-1.0128261811691568 +-0.1646121267081449,-0.7907875325932864 +0.20722434282298421,0.2802966452175681 +-0.3102641145310311,-0.13730762366408955 +-1.938416221059818,1.3219483318581775 +-0.7873979325673119,0.4231935002517445 +0.29880979288213183,-0.8800800182623182 +2.083386504958181,0.526355958857953 +0.07510501261414004,0.03190189689853184 +0.936572024661221,-0.8406555792253776 +-1.3731848507287001,-0.9957776107228095 +-2.6608484800726417,-0.3458278433115705 +-1.069721451679264,1.7085254027812458 +0.35759926274934184,-1.2442402890927216 +-0.03231865243272169,0.26059573837690225 +-0.6608290706634187,1.1320667102165582 +0.6822459175623177,0.7756120916669439 +0.9780011930360364,-0.6120514690430847 +-1.7442520150537977,-0.09856955951652249 +1.6577937184627753,1.142958131079787 +-1.0248570940990123,-0.4049373082618236 +0.5829204992213785,-1.6428410105565427 +-1.473729407427651,0.18066727311759267 +-0.0019008285965632496,0.7209189832097197 +-2.0941204156735473,-0.2630236345161864 +0.20996801365325182,-0.6460536128771883 +0.6053573688497265,-0.672416167452252 +0.29788565068033107,0.9711570866249993 +-0.6050134330237122,-1.1289762502443736 +0.31171906961810103,1.6701049099104106 +-0.5535787122421619,-0.3244922509898557 +1.7436652847574874,0.6146950710623997 +-0.46725408983020855,-0.7161435873073152 +-1.7904781072070926,0.9289234023347819 +-0.6757937968965176,1.063333183809974 +-0.8277647770137543,-1.8327555352119789 +1.34011500444044,-1.1047903527396274 +0.5045759163723991,1.04204466871625 +0.4599583258352168,-1.0859774951528065 +-0.2879775000279167,1.2328381764811722 +-1.9360127380316485,0.007524545004166922 +0.3273160206112702,1.7638073699287293 +0.8136099799270557,-0.12614776687721851 +-0.3491259217383536,0.779809574161266 +0.05224082715409988,0.6074852636875314 +-1.7912833909274004,0.2245575078793787 +0.4065304999998559,0.06886286484742835 +-0.8276290078514376,1.9411131745767662 +-0.21036625131588457,-0.14348606912240552 +-1.1025718593054792,0.9229875944441498 +1.3186015284289783,-1.5187487779566469 +0.3496049738884841,0.9592095816616846 +-1.4335082075108831,0.6025428486289872 +0.1681549561218494,-0.3358530628577222 +-1.8041994158871508,0.1662596749948553 +0.19065647712477757,-1.1989337845173704 +1.1923374898676884,-1.654102686522673 +0.8300086565787742,-1.1965590406956577 +-0.6203109479196915,0.11569374233443033 +-1.799346051410987,-0.14281399396516026 +-0.40617130360695625,-0.9234744444538048 +0.05333655978030418,-1.146150917284589 +0.769573199816417,-1.2196129864473704 +-0.23148455870859808,0.6200723649683523 +0.5586069502070932,-0.23008952439670816 +-1.4530028126141412,1.3044799300391634 +-2.1090984890195315,1.630738640891542 +-0.10219868110588336,-1.5673007886527048 +-0.523801137746503,0.7565236776403399 +-1.1732910419536164,0.2559969493390718 +-0.039292840015711455,-0.4884992535633564 +0.97050570923706,0.5682893291652359 +-1.383046436006387,0.7557280929365326 +-1.4051194871520836,0.7132041826246213 +0.3702727243828308,-0.7064106155999208 +-0.5145604571262603,-0.8405529862541992 +-1.448954774746383,-0.40792721752613353 +-1.1742391151983105,-1.6303655442787426 +-0.9602259470950262,-1.3273413127055382 +-0.04902113986573762,1.484211656393157 +-0.11660281722520208,-0.2706976376352984 +0.5525841580440223,1.095712969694404 +-0.060935064677429186,-0.43088386551134616 +-0.12023678377811386,0.7964895206348713 +0.8559853643590641,2.1433185568946143 +-0.27071899183796605,1.3327591514050907 +0.3249917195239635,1.004750304449324 +-1.7865095521096408,0.3267777587981137 +0.09238570072960772,0.8528244186897354 +-0.3027490060217565,-0.6861960951640277 +-0.9459600096402013,-0.6481193586903927 +2.3473777044931228,-0.9706025499181985 +0.5212452008832439,-0.7813312526793084 +-2.0981318052598765,-1.6479723271408864 +0.6199330113656988,0.4646845489894699 +-0.22766474018501853,-0.4278603564888807 +-1.1192804090391868,-0.475827639486715 +-0.6735198477067946,-0.3352894731768677 +1.1606285019378766,-1.6415470976874897 +-1.4380561733923474,-0.4137977157044547 +-0.6832128109884044,-0.7531472056479721 +-0.3556629323205153,-0.3120833726534724 +0.6202931211739343,1.09077092678973 +1.3054912211963166,-0.4827024717997893 +-0.419330117203681,-2.1146235634432236 +-2.063050104082971,1.8261952057952011 +2.0449745023086328,1.9403906412090433 +-0.2630537566658325,0.020106237668334963 +-0.8598590088166785,-0.3044771115425923 +0.06539137550766004,1.5753568103885005 +-0.8598826174331611,-1.0486162137009192 +-1.5462853255945295,-1.3702542177311423 +-1.483019416751789,1.2044827598268801 +1.377417430665512,-0.42948471574353503 +-0.8779256373956469,-0.016167511358793806 +-0.5263297792926168,1.5691589695458286 +-1.0437550599928855,0.8551654750754034 +-0.4753383891175924,-1.1790049570623227 +0.9704384676425465,0.6727925148362022 +0.27297658705978123,1.3434322702868542 +-0.7874877732530768,0.9079921027121537 +-1.3059600757717016,-0.7006372716040136 +-1.0284201777991828,1.3789614374972725 +-0.3395160902359911,0.19948638399287086 +-2.3285302840285,-0.9658470962342937 +1.7125780145056508,-1.5305469845675073 +-0.49178607907680016,1.4980872359213344 +-0.550014398789203,0.27007996348211244 +-0.10168978844217089,-0.88160898160666 +1.057492422761191,0.4104722069643313 +1.7248106999315742,1.6539994510044236 +0.1298641378939094,-0.016141025108997367 +-0.9610597097374926,0.8150965972739771 +-0.24940947241618486,-0.09459786351222525 +-0.8577539875160382,0.5379403036282076 +-0.1921386668573769,0.9552916724514966 +0.131769407106236,-0.74617808527563 +-0.13558891587629918,-0.7512589709271409 +2.176074884218979,-1.6323501103572677 +-0.014807988844510447,0.7936269153692945 +-1.6872317731899154,0.35950977526280903 +0.52700743424241,0.34268043565450135 +0.09760019079731314,-0.26925707931097714 +0.4080903099631262,0.43251138260178784 +-0.061057520915188374,-0.13302124240358656 +-0.5761909710512474,-0.8311670792030078 +-0.056066697286095125,-0.040277730243038705 +-1.4240611395298193,-0.2297111369625278 +1.9400237289011144,2.055286357471184 +0.5505353568465545,-2.1326397452785852 +-0.1093248385369897,-0.5761897067945304 +-0.07506606466117796,-0.5472530780516811 +0.5039446895487291,0.8600915666034777 +-1.15421040329099,1.0577227445820296 +0.3789585543313736,0.25453593472219654 +-2.4595694284899805,-2.2623795987683026 +2.66855719438216,-0.7593490443888625 +1.36917776850149,1.3103848479419922 +-0.15664552624854947,-0.34886286145288703 +0.3226608366984502,1.2446919403922738 +0.17287556266797194,0.7891457295897959 +1.4552395471431885,0.8187792737224583 +-1.0370152638703871,-0.05951838636778259 +0.0922890430306139,-0.02860181434941633 +0.3592432442976371,-2.535671045192367 +-1.7222414770458083,0.7675784225270199 +-0.5970289129381163,-0.8704101470682923 +0.7689009292690848,-0.08401397051837782 +1.6454556875578414,-0.9818200260352302 +1.1421820619207954,0.377053068556394 +-0.09103229730925734,1.016249920553733 +-1.3348950626618439,-1.2853013180210662 +-1.0891397400580616,0.2618304721688405 +1.6335437051932011,1.4194460708627288 +-0.20409904527295084,0.8389788293842155 +-1.297240072479887,0.13209672642553988 +1.0691829030637885,0.44151267084761076 +1.2264986192874878,0.01000996517643023 +0.36144725936568195,0.41714963132673205 +-0.5730344189022974,0.5099937489483618 +0.49494094570754266,0.5987134892095426 +-0.23899761292398697,1.2983408378067574 +-0.9786377466681058,-0.21770879417781067 +-0.2126374134643521,-1.4649467512408616 +0.30269035159753815,-1.1595088616386033 +-0.7597753413894649,-0.9660841132626715 +-1.385080069357066,-0.43310647760715404 +-0.4111196247421561,0.2490592404218102 +-0.312084625436836,-2.6522586557528496 +0.6941859611630402,0.6781098643324877 +1.5046305024890967,-0.024773240199843612 +0.7864382877194998,1.6633844743465909 +-1.2705060827000043,1.1178516278907573 +1.5542329687145418,-2.2432286174335627 +-1.8553471831691102,-0.6805480148053368 +0.7371749855917664,3.020820218557996 +-0.7660359781694198,0.8180069419937667 +1.4563818694516113,-0.42603817050758236 +0.8287466498611761,0.02529629456748941 +0.30106002991331393,0.7028673791598152 +0.08600988843758572,1.4416799041907322 +0.4006081704982849,0.04493878413217254 +-0.5924012366867185,-0.5600932757444606 +-0.6842880213331598,0.3034650565331134 +0.8825079035330199,-1.3886862859007851 +-0.644952891470043,0.12025230733345336 +-0.622478007075476,-0.6168198582928442 +0.2927993060889714,-1.1979866720786703 +1.8626476878080145,1.1101652257253831 +-2.3732496296698558,0.17319023550829532 +-1.4952431575273402,-0.21373533271295359 +-1.0668582973156844,0.37992199050680453 +1.2741223774272066,-1.6654404801218416 +-0.4712681898931613,-0.9119277054571533 +-0.145258892708905,-1.851407226796467 +-0.25842202021189864,-0.5867148842666475 +-0.8678661626974581,-0.03241249804846455 +-2.406225334470053,0.04588341690634372 +0.5281640246991526,1.364037896142639 +-0.13128379301091214,-0.15078074903195154 +0.2630457770956202,0.5457057515765316 +1.9315357199771312,-1.4203336980989556 +0.42716463275218536,-0.28340510793188006 +-1.7614342781415857,-0.6563387710866977 +-0.6078186597085135,0.38676515104472325 +0.7198254123853532,0.40021773006642264 +1.779627148996426,-0.575354545139461 +1.5828892367158418,-0.1381781181419018 +-1.7425754951610217,-1.9947499536567654 +-0.5221546527108409,0.07401849191239487 +1.518918505017508,0.1444860845528895 +1.17404004313018,0.10741646935690283 +-0.7704894079758763,2.4615684548788708 +0.9912209519166209,0.597821006308153 +1.0476606268102375,0.08504180268004195 +1.339747664578143,1.5514900460105865 +1.0611079623273851,-0.5362734067853924 +2.0577774374976947,-1.745888907344942 +1.7381938129881676,-0.9548055739685403 +1.8095578363473555,-0.4279610707167728 +-0.5276487247722418,-0.19176717718506653 +1.0946067646236444,-1.2862698407265436 +-1.3601999690311903,-0.580949849492026 +-0.4963186102113471,1.3968308724449985 +1.7305062683095758,-2.558610044565538 +-0.35003246907388236,1.9445139578833142 +1.041542469072555,-0.4109823797664307 +-0.7007382708105365,-0.41427025446089216 +0.8457270727094689,1.7905651885624292 +-0.47656900774723976,0.30626114402203425 +-0.40079637454162487,0.1944868242366922 +-1.6704026049048193,0.3108546210707012 +1.9944777579434165,0.3669448269392074 +1.7091902474697076,0.13924535923619372 +-0.08947990745548766,-0.7721920846179523 +-0.10079745210577262,-0.6793638730915109 +0.7001763851688049,-1.4680582659018007 +0.6864869307539224,0.31070656790853357 +0.07775737502413264,-1.808392160965161 +-1.7420157240261736,1.2351939000032464 +-1.9156984802693338,-1.3774802593839306 +0.35413756966321747,-0.8274626941325566 +-1.9287806089428516,-0.37073237206442206 +-1.5494999107088583,-0.3709230803832231 +-0.6380717305586983,-0.8989498199391629 +0.03753433298723059,0.3599383410127182 +-1.3892043553152775,0.5955369892235807 +0.7076074027017282,-1.8294878812359088 +1.4518177147094957,-1.6059906889506066 +-0.8120412641933731,-0.36042648107154757 +-0.5055275643588153,-0.9143559532464457 +2.083369572626048,-0.43689428422467375 +-2.3260243069367035,-1.3619448048023806 +0.5035358630590434,0.4252360733819252 +-0.2742290956586747,-0.06380675932071675 +2.5423667560718153,-0.03636401541777159 +-0.3322357238603317,0.00516535129239385 +1.8290442910804048,-0.11294688800071823 +-0.4115882191069521,-0.015499253963789657 +-1.0783806938230875,0.18542413217288745 +1.052998708449209,-0.3260161332756296 +0.24926447627840762,0.5715951566253024 +-0.004566483958335154,-2.1374132923449967 +-0.862433286422455,1.4681584366366793 +2.405246078877756,0.36195936947871343 +0.15061192643314372,-0.1956843346990425 +0.9129146366647138,-0.7695560068809066 +-0.5929648609093946,-0.7380375234868262 +0.5148603132478344,-0.38289791410529744 +-0.5016269299535256,-0.37125251928179814 +-1.0977075591102137,0.7168257340210474 +-2.419174942812833,-0.5219525054063946 +-2.230602595224531,0.2882216829644826 +0.2572640041254481,1.0527902824457347 +1.252340409380905,-1.3283238895487886 +1.1598389561625821,2.0126937270457113 +0.2858502365838423,0.5056520252303395 +0.29856365974785765,-0.4691353823337425 +0.11435399681177365,0.17497934781648042 +-0.29131428993828096,-0.12912581176693833 +-0.41727594289437964,0.3663688735127867 +-0.3477310079767402,1.659903015309307 +-0.04947963190817374,-0.8441955393259152 +-0.6578735153439139,-1.708135163367313 +2.5625378890816584,0.9370474302335211 +1.5343535732328049,-0.8383201120435512 +0.577697053743504,-0.27344607013418 +-0.1314040913769062,-1.8593679264251406 +-1.9949519903679167,-0.39009908863863857 +0.6006494741039491,-0.5271894170386001 +-0.6630211332201466,0.6347446149843042 +-0.3507817040374523,0.034667209358079536 +-1.994977851230527,0.26864178216849516 +0.8908984062370978,-1.0270751499532478 +-0.01816973350238811,-0.4899033324274766 +-0.7599407446076825,-0.7583851252113272 +-0.7621727133782366,-0.23444352613839659 +-1.269784674016903,-0.19338937313077667 +0.01796452333732768,0.35370741844154413 +-0.05767690657895039,2.0585910495672133 +-0.6055559171437326,1.4603324083927802 +-1.134202945405561,-0.4364087641712683 +-0.5291398159098806,0.2633269890762263 +-1.4230315561377391,0.08087967245641514 +-1.5339787907448599,0.6944358029961797 +-0.20997565254223252,0.7582466923631632 +1.4215390685100264,0.9322637441038881 +1.46716783136547,2.31753784639759 +1.3469449398259146,0.24127043348546603 +1.1612154402267536,-1.3812597371125623 +0.4305688079548257,-0.5923671284413651 +-0.2516019344154094,-0.2330299284598813 +-0.7103606785137611,-0.4034482658220021 +-0.45725503138788703,0.3544793813719241 +0.417960415195679,-0.3183593819757454 +1.165533199586507,0.833747569645234 +-0.3675557339903256,-0.1592177019935122 +-0.768739063652023,0.8730491605353907 +-2.044550102580567,-1.0204471625580092 +0.7797952731675993,-0.09716017191917985 +1.1702203436307077,-0.05898881633682085 +1.234670624391032,0.5649984362698588 +0.8460597085395946,-0.6919816281051501 +2.539817873562509,0.26330612104331536 +0.8785382618054126,-0.5350630034204404 +0.13439934590612093,-1.6063126868496145 +0.016180818194082246,0.8159899976769391 +0.07580199825814399,-1.9213408573100708 +0.03690964740669387,0.89580384967165 +-0.4012041666691836,0.19233762248916322 +0.0018126991202573844,1.3396326471051743 +-0.4629865701705421,-0.33082266098525903 +1.3064981442721513,1.3346330046749766 +1.159808785303986,-1.852847248249151 +1.0897695065540236,0.10677113271933866 +0.1669429464703663,-0.18569268630184954 +-2.056780004465903,-2.0267868807591674 +-0.4281824920753217,-0.008463288964078487 +-1.0057928356738512,-0.6533127156406012 +0.826873232160975,0.9913332300491603 +-0.36910256522955065,1.176514881202171 +0.7205037588178538,0.1677288999529491 +1.2530813677080672,1.5311258376254075 +-2.4763599574221336,2.7153508206628096 +-0.1633351613602232,1.1609845121485398 +-0.6729108956031424,1.141157708037584 +-0.33267322212144373,1.2003361434106394 +0.9640124390520715,-0.08071303311753873 +-0.160022906449728,-1.2078002771109073 +-0.21919794142352594,-1.1354501837507591 +1.3276039544387068,0.06007566035627072 +1.1043804087422535,0.5529493073880267 +-0.1689695680147977,-0.8713514157986483 +0.06963969774476245,0.4981178261686736 +-2.0940751523054533,0.11093765117920758 +1.5234675272106282,0.2586334141217061 +-0.8018873696591525,0.8438308194807764 +0.02534994451995593,0.06574640901738142 +0.5584424735437166,0.7042650136371916 +1.9488349536865883,1.2812054905898234 +-0.20936215478208267,-1.0871496501767326 +0.18681718001595105,0.7157580477973655 +1.324875624600045,0.02581415423186287 +-0.0737923906060551,-1.618861357940584 +-1.8272000165211482,-0.4781014561901414 +-1.5170138155496948,-0.8902834309798292 +1.19027535209217,2.0307777693497906 +1.7020293705333034,0.3347036008791229 +-0.04679847221573574,-2.071217175279739 +-0.9049783857418254,-0.3092916372119417 +0.6109957006286864,-0.20199400754776897 +-0.43515905507223124,0.5857356132577589 +-1.3944050010126416,0.5419306266142767 +0.20437792543638653,1.457717142233078 +-0.5710177979259058,0.3476401682056952 +1.0686075354974025,0.5027894997119915 +-0.5439110662603704,1.2500072647969658 +0.6659521621991159,0.20856300367462774 +2.854969811813834,0.8897690475727763 +1.2311628127476337,0.6680476934510771 +0.7908410738742236,0.3920844685618631 +-0.6262623141053232,0.9628882840251972 +-0.2206047556225137,-0.3000050866722799 +0.13348873919527227,-1.332524219142059 +-2.120523437811264,0.28058537234576536 +0.16000798451570233,2.1741226340855127 +-0.04003878280638275,1.3344271574655509 +1.1443659816111098,-0.1923378260583852 +-0.3592742111948035,1.2773695578900952 +0.32059259184831984,0.01928036675467503 +-0.702402943783952,1.0265750157027265 +-0.7526637618750663,0.24794619585470296 +0.13477067955948988,-2.4435803789876034 +0.5295820976939521,-0.9832948477351265 +0.06183758022587439,-0.7268202924492462 +-0.3720655777521139,0.2175052862463541 +1.01179200955398,0.5305193814844711 +0.9075040815892694,1.2103944323878149 +-0.16986313092107308,0.49411442601064964 +0.5870152065348831,0.6911640289035703 +0.6328878663009319,0.25397814232540644 +1.8685952651622253,1.2094089447334861 +0.38407737925822627,0.4271079888777978 +0.41051711189659024,0.6352956858637692 +-0.11669853170165069,1.6009149525697934 +-0.9431499490582324,0.7154858914907096 +0.35344583292371434,-0.9876177512715136 +0.3622893717568571,0.5937233790599177 +-0.38674138938494845,0.0056826561743382655 +0.05236534093225535,0.1685486478309335 +-0.33641131768830235,0.9681017783291431 +-0.12582286295418657,-1.07738607196283 +1.9701823023881542,-0.5541874310896742 +-1.566208491451826,-3.2191836266086624 +-0.37858494546143745,0.015195499054812753 +0.8279407070301004,-0.2169510474967166 +-0.8577842022121345,0.016239522799306457 +-0.5697863625174944,-0.9637200577076068 +-1.0478576915741504,0.14330944604599713 +-1.4872775681963055,0.23518106532813957 +-1.6445236484927885,-0.25664309112067757 +-0.35537892461263176,1.7573195278674958 +0.3985871625850766,0.7698177409556253 +-0.009791181605383895,0.41431754999378356 +1.6133844183335353,0.7775908022792094 +0.051513808040602994,-0.1309096383934058 +-1.3029070135748382,0.43207396383068025 +-0.24067073410246462,-0.6914156381694165 +0.7135979651071832,-0.14133661230151257 +0.016006954246592986,-1.271025844691946 +-0.04589817865778969,-0.09834336227112257 +-0.1568390897606371,-0.5190690045040719 +0.7151925814590085,-1.7745114794885073 +1.9240087620936097,-0.21224187172187212 +-0.3101773832565824,0.5657586061950555 +0.21526003932287002,1.1736823512019972 +-0.9568996975038669,-0.6320298814968595 +-0.5798160139426114,1.8958974246495381 +-0.2598564609394735,1.4852917795536789 +-0.18269177430705208,1.3314707656616411 +0.5717195982500966,-2.1128778690118972 +-0.5218434744006933,-0.8109365257500175 +1.0478729279213013,-1.1046239691747521 +-1.2451214240384225,0.8102890355935005 +-0.057303809396218444,1.965836604266836 +0.5822404327563676,-0.5476508840585542 +0.43099950825108535,-0.5563044873887872 +0.30148897568731614,3.00441535461268 +0.7564050906879655,0.11440030411106016 +1.0573224528020475,0.04653427236281511 +0.051043577991373316,-1.1826701137612536 +1.3311225201198276,0.990315404711041 +-2.0599969827986713,0.2193172327598031 +2.5449297872015664,1.5566308315844781 +0.5256735041725816,-0.7553493423665972 +0.14084156147400478,-0.352539975811642 +0.7793928495779316,-0.44470721584840117 +-0.4776852947502809,0.3870116320027583 +1.522054091338014,1.0007292075027676 +-0.6125597897913097,1.6466442101360652 +0.39597684200198413,0.7254590562913809 +-0.3574638002063856,1.142026220312406 +1.1669983940514719,0.5491944200795629 +0.9966915377041188,1.6072236641920317 +0.6955934221659864,0.6889225918708245 +2.3997516439458604,-1.7796145831474544 +0.0271555873621357,-0.14475359580969516 +-1.154959565301522,1.440894141682773 +-0.293136305551066,1.7966270888525453 +0.9478556625275818,0.9478965978982947 +1.6640926165638665,0.5067475806614362 +1.0841284296124816,0.43850075450141934 +-2.8269622528576384,-1.6261288138075416 +-1.2807723785741199,-2.84011229736649 +0.36362192071918076,-0.020931779050174137 +-0.30228398204939566,-1.6454421277684679 +0.1208509942459361,1.1203464586589966 +0.7044449191482346,-1.075793859962688 +1.3747605214947278,1.7543716003511356 +-1.4828761923705946,-0.41733507984544593 +0.25674834934292357,2.4222650862410218 +-0.5755853616973006,-0.9837187727917309 +0.6710268255061232,-0.012992130146542501 +1.4421035298835645,1.2100191450661701 +-1.2946056061717663,1.4073133533043702 +0.82115602191245,-0.6576014948640115 +0.5072512799073179,0.692359677029391 +0.32028004499240686,0.3144885101815108 +-1.3295672969634333,1.6488604954211823 +0.25301283387806084,-1.0032596553588315 +-1.069814297515331,-0.1678633613912729 +-1.3263641293674475,0.9672060120221142 +-0.2941351482445798,-0.6405580700124444 +-0.3200819305866568,-0.7223375681050099 +-0.20670360034795496,-0.16058543839905606 +0.19082627336623387,2.2233200207657986 +0.8521620968855117,-0.729353280607938 +0.6010652481753002,-0.8562261817499767 +-1.6499749992491233,-1.8265066178992104 +1.4627877064718267,-2.2438034560327202 +0.04443095141202161,0.5323127850301186 +0.5343469890808349,-0.19646561573090723 +0.4468451746207391,-0.3152571574255589 +0.03010319072426008,-1.2282879010930166 +0.9557460022729088,1.2625799937414748 +0.26829657687493014,0.21417721504005524 +-0.31652339199174667,0.7252572616642802 +-0.7701649911928249,-0.6503135009943551 +0.035773373425008435,0.06135440524012131 +0.2013137727520878,0.3900521361665384 +0.5623234888678121,0.2773163039153634 +-1.5223618823195184,-1.7136241986414593 +0.9818120058783376,0.6611737629083857 +0.11981078019289473,1.1843775025848542 +-1.5547515886183538,-0.4812395607866226 +1.7634320707358577,-0.540697100921184 +-0.8641504767044634,1.5157833140859243 +0.6811522193621178,-1.4297270957186738 +-0.7678882869227172,0.2130572738849842 +0.47633968091139595,-0.06627681082890732 +-1.6230352058372501,-0.32738394549346167 +-0.3737977022821463,-0.797515557183027 +0.4947461224160211,-0.23433250881857626 +-0.2791513321528577,1.103565672803227 +-0.014891436562962612,-2.039430733566662 +1.7668462244255339,-1.2630749782825343 +-1.8337592863575993,-1.0796169864831915 +-0.1416125688326829,-0.8907954727170674 +-0.6833324597997653,0.7364535307633802 +0.27792741399445775,-0.751180081110496 +-0.4321972041319155,-1.0114139794976353 +-0.5595459127153113,-0.33365552971267404 +1.5337192678793878,0.82560720585983 +-0.29643026331656364,1.076877365646284 +-0.84078207730324,-0.5106003059944719 +0.9341906920969881,-1.539921634938871 +-1.3210241587215332,-0.14785990838087903 +-0.6255141918304092,0.9155977765896667 +-0.5308646668858781,0.24819281663275572 +1.5708383990350019,0.4691517952494499 +0.5244298233481924,1.4619619450452865 +-0.5996096830194187,-0.4275403756153512 +0.13416675251258897,0.5535060860818224 +0.8707420355330366,0.4028185746751326 +0.1039026417042417,-0.8723249991787533 +-0.14361267859667132,0.3380006204743978 +-0.6816207798655577,-1.8647655548437212 +-0.43190144903056465,1.354517606072355 +0.8605697259623775,0.45200615131254607 +-0.3644779137105784,-0.6665383272004405 +0.9946628991866352,-1.0475294853820758 +-0.8538589104228881,-0.9376659790985084 +0.4587167278034121,-1.472544838850866 +-0.8368277169282147,-1.7738106215973437 +0.6087250050589348,-0.049570470341786584 +0.6461042826215156,0.139638155166395 +-1.7824211114741568,-0.44834186183104213 +0.4978997920135801,0.542063516240368 +0.7179359520822279,-0.40597836297775025 +-1.4223173727579381,0.5536074128205559 +1.7890066860901859,-0.43158541003170187 +-0.33618025626762493,-0.05365411361367293 +-1.824866228779774,0.598003740181479 +1.5640894965347425,-0.32357329460612233 +0.24798682153063034,0.2521781067212831 +0.36012745539245483,0.24575218475277347 +0.47993391694766213,-0.03203354190442431 +-1.3914735843627979,-0.6113934666367136 +-1.091707466488724,-1.2837390114214249 +0.7876746423683892,0.9695052791939593 +1.0795394193909382,1.571055974506144 +-0.274924620084366,2.3521315697111724 +1.8110380171539031,-1.5397083614857627 +0.8695972487878837,1.2892278370281613 +-0.023846723102954406,0.3711012431165395 +-0.4025963430473009,1.168836345535446 +0.1276701294053584,0.6174138664839265 +0.1829126864497661,0.9144429970950098 +0.35466008410712074,1.7602502302185397 +-1.6080886859886474,-0.016269980951525927 +-0.7128057420036521,-0.12308050502366773 +0.12416162115498522,0.7022912012271296 +-0.18948882385780266,0.6777475574135318 +-0.23679495511085152,-0.1320181245236869 +0.6410825020875474,-0.5407583081876053 +-0.2625118799198323,-1.4778046810687386 +0.44439166629163845,-0.589001818728878 +-0.07198311040043565,0.42630610782374073 +-1.5872238460848203,-1.2779907943185267 +0.49248974215847113,1.26454067804268 +-0.42838720378983064,1.5683779572935246 +0.33429211302697237,-1.1238271472528856 +-0.4450256383846289,0.022859443733425883 +0.7849807033610452,-0.5554910992002215 +0.12452226387792446,0.12101277566622413 +0.7727254671845282,-0.7337645752628994 +1.621523466879364,1.379736880655333 +0.8501903782189948,-0.9905068212659467 +-1.7924423992595702,-0.7249609242257435 +0.08866269395100133,1.344184008711087 +-0.18157728950701896,1.3231996347168629 +0.639952537259716,0.7002024510278043 +0.09540711439948817,0.30668328880608975 +1.6342545558515857,0.527962628623908 +-1.3217381393084562,-2.35824973262349 +1.4024219780557403,-1.583837092368132 +-0.9377055104436774,0.49981822600785863 +-1.1386585002627496,-0.03515225417561202 +-0.3949621406001479,2.0375900351142096 +-0.08673739289103881,-0.41768515871514805 +-0.005385475811097389,-0.2194603590829625 +-0.19437768123966168,0.32924862862595017 +-2.135719671628492,0.0030426355356291557 +-0.2839187724688978,1.0310834062328609 +-0.6791072474834197,0.9740938283521077 +-1.077377936425805,1.0319612260952982 +-2.5843894943677257,-0.9299959579204358 +-2.969614686104965,-0.06263997687825179 +0.5797685914142866,0.9059591978537445 +0.7423613990860409,0.7382685813713677 +-0.04686738628128784,-0.19894944983711568 +-0.11841550400339936,-0.26101087396548667 +-0.6227039414962217,1.3544794209988695 +1.3507579161535233,-1.1102238411452514 +-2.4594837625521357,0.5270775707126745 +-0.8983123082060939,-0.23674489838453674 +1.3367978084285594,1.5531675920897365 +1.2804721838184072,0.0027279327068859267 +0.2176663884822817,-0.27921417943867366 +-0.5241557303537275,0.7638439887062304 +0.24417596007155196,-1.4090833757200052 +-0.3369668572870162,0.023158096948829848 +-0.6841223294287196,0.6513241656565207 +0.6395274607915444,0.7130277160974711 +0.7542380367545368,-1.0042693151059048 +0.9969986295202239,-0.42087360635078436 +-0.14927422770119625,-0.39516738250291644 +0.09449511645975653,0.1668186396835788 +-0.6643546247811563,1.7477948799895906 +-1.0498419189510362,0.11813911579847816 +0.734375856779598,0.1041489175882446 +-0.7765362158504963,0.7698008822605956 +2.132591658364383,-0.10222646863993251 +-0.8626880955669585,-0.13862185495473092 +-1.7850245968906164,0.5073371389565354 +1.953538041015771,-0.2907521547653256 +0.4160328412091432,1.107979466450008 +0.28911541652542205,-0.6145053183170072 +-0.1595944056460957,2.4232845986392286 +-2.2161369446528982,-0.14101722981144943 +1.1308332238594616,0.7143591537047326 +1.1856249382358868,0.004617515026296322 +-0.2899778197097679,0.4818689430103163 +-0.831614895110051,1.1327283262052974 +-0.3056263267030971,-1.553546532247121 +-0.3924885048510687,0.9233682702056497 +-0.32672891873447796,1.6459486526722826 +-0.35201096907592894,-0.7906681839015565 +0.1362653009392645,0.644154991543615 +-0.8697020852183536,-1.0622981200983528 +0.24390434209211465,1.4332089977028009 +-1.2450518139093627,0.6863095431714339 +0.881832374054426,-1.1087953254106455 +0.002118224335542685,0.5093995996527283 +-1.3450672239180474,-0.3786265345360819 +-1.4996935364007502,-1.8057101379321878 +-1.587545231763176,0.44405923405411774 +0.03465641492824878,-0.5396464898931892 +2.1219276506793436,-0.17268738146996132 +0.05524836415944587,-0.6017737572059164 +1.074417550522992,1.2210019730457253 +-0.28908486410234757,-2.000100134270555 +0.8813212649238735,-1.2673811611717796 +-0.5197388742877006,0.1600492529448167 +-0.6923506202737624,-0.4674163918079534 +0.8589014970332836,1.3471458101389298 +-1.8928708840636574,0.5363006891202218 +-1.5961311367599282,-1.718583617873941 +-0.7138461512141447,1.2731348293119495 +0.7509050550480182,-0.057529749800879 +-1.0807574368820585,-0.002086208426701485 +0.7532178510247751,-0.6361637136979034 +-3.1989102302619314,0.6053568756041209 +-2.401894620728357,0.7625338794874651 +-0.7782219491964616,0.3933525830205292 +0.9552609305136742,-0.6322067869324327 +0.618932979802886,-1.1968577819679067 +1.1151884359699082,0.18404328446099888 +-0.07716990406217664,0.3466794563611568 +2.3716308630653806,-1.1333048012923457 +-1.5080433038101009,0.21786718632634375 +1.4797263738103266,0.9928493377521243 +0.746082798670067,0.012740529689588685 +-0.6100262233374371,-0.8514102509981714 +0.28465300713894615,-0.6680810651256736 +-0.016312768301239008,-0.28635636605150316 +0.7865882027219607,2.04760588189903 +0.4112255544938328,-0.02225099053514801 +-0.140796590466804,-0.3759515574375265 +-1.2072974130088114,-0.29787012161396925 +-0.8484246679410756,0.16754130213434174 +1.0055883016573666,-0.5735706351934343 +0.8597701662276618,0.5357539554229128 +-0.010168759704732891,-0.2472367799734683 +2.072871449354906,-0.12104896144554174 +-1.573115436037177,0.9585128103871763 +0.19696937521192734,0.37936751710023575 +-1.9793105835567246,0.24012398237897578 +-1.088836808567075,-1.4491352945621117 +2.298863220140522,-1.2701371250125497 +-0.10086826596699162,0.8910793495656534 +0.6263827851405281,1.7051981628346502 +1.8873830214225034,-0.30358761929896344 +0.41716090336015255,1.1621190622399913 +-0.7654082282378325,0.07030140145205442 +1.0568194081830147,1.8236493463215042 +-1.0173256648566327,1.6930947119233377 +-1.2343226897753665,0.1824480101837163 +0.9238304434027045,0.47180798343833646 +0.7609760811970806,0.05361320247648757 +0.2523543699633308,1.2927592428415278 +0.7682202337901636,-0.1556221619397789 +1.371983498403468,0.3796878017180302 +1.0253930383720011,-1.9528741136126648 +0.7177761070219305,1.9158321574134622 +-1.1649536730809977,1.1004281544334256 +1.1317799075734007,0.4109497212961649 +-0.46755216468604455,-1.865093554453203 +1.0549254352427064,-0.4475098538423933 +0.1155140993156697,-0.9800545413168879 +1.531865079158926,1.9224722740572926 +-1.449162335464353,1.187232922097407 +-0.7052765331644272,-1.3527803643859053 +-0.567326348389912,-1.080194168219511 +0.9216288562920273,0.0691383324043114 +-0.8029592876358124,0.112600541746923 +-1.6468770344303192,-1.9606454620953138 +1.0878526141910552,-0.725494165808055 +-2.3771339458691902,-0.5089143902382938 +1.7750913162008117,0.4036949062867648 +-0.42809143947299017,0.4795046961940112 +0.09129538917522562,-0.2743933559305197 +-0.6944668879301373,0.2757722245355788 +-0.7657403536480937,1.0451264214116909 +-0.11771528670078542,0.9272974987518126 +-0.894845029210062,0.3249958349369981 +1.7861996523371657,0.6921408016664717 +0.09393103072793955,1.4602432608143954 +-2.081785597956125,-0.6250344060292786 +1.3718727642185171,-0.7733719427623793 +0.07753284796499299,-0.3011365670326428 +0.36304509948901204,-1.2550555237969954 +-0.8230351362803415,-0.8099789105970601 +-2.703820417898122,-0.1858601107548008 +0.476641523538688,-0.6416828500582916 +-1.6542138261751462,-0.5886734142002049 +-2.239424511561425,-1.6339997997473594 +-0.4262748747254719,-1.0931388226170469 +1.3462757787098294,-1.551061600019069 +-0.16891380218369617,0.5093672485737274 +-0.1218992186354666,0.9890164991275641 +-1.233137863284262,-0.803900474656606 +1.0668577577683858,-0.09819723513267611 +-0.9047099618336246,-2.0049055334249912 +0.3164764425308395,0.14903879094318 +-0.37322220846744425,0.6181175587081223 +0.5239259320871436,2.0239173313006016 +-1.6304206616914916,-0.36023465809801375 +-0.08989980468065731,-1.0133112142133949 +0.9959126185542378,-0.9318954739550216 +0.4641424684508534,0.5468143895018905 +-0.8751336683757218,1.925389229747027 +0.21896919985970809,0.13583133098146766 +1.6476640408988352,-1.564765365310122 +0.6841725682000278,-0.3284962156426047 +1.04092511931976,-0.1214887407852748 +2.5825027173559505,0.7381162176478759 +-0.16221797597877036,0.7999132368599453 +-1.1055150569905685,0.722663429471247 +1.3544675026113644,-0.026489165583498207 +-0.2086007661804663,-0.33890546898123086 +0.5686941204161726,0.45373711169031794 +-0.28841701394207175,-1.2399713413480025 +0.7354707374881722,-0.8398789527664295 +-0.22236682125420407,0.21906159047038154 +-0.46739414227815496,-0.0550304564247963 +-1.8123401994904689,-1.1047235141212621 +1.8269117135394655,-1.6691407470137236 +-0.7491937888725301,0.4042789979354976 +0.1483143709467585,0.4348892178759407 +1.572117417979168,-0.3883901542309379 +0.15062739129691174,0.007648121566852134 +-0.028101461717115694,1.5247296444595695 +0.17315739586285336,-1.500263879222624 +-1.1460265520671722,1.7010268409386835 +-0.006564252322621968,-0.1321384639583528 +-2.1802003414515703,-0.17627082130626873 +-1.4624746558555621,0.19513471458340062 +2.1118368736188335,-0.6235332963009975 +0.48296686306194453,-1.5961114007504469 +5.0,4.0 +4.0,6.0 +-5.0,7.0 +11.0,1.0 +0.0,-6.0 +-4.0,-4.0 +-3.0,-3.0 +-10.0,-10.0 +6.0,-7.0 +1.0,10.0 diff --git a/examples/trees/isolationForest/isolation_forest.go b/examples/trees/isolationForest/isolation_forest.go new file mode 100644 index 0000000..47c4ebf --- /dev/null +++ b/examples/trees/isolationForest/isolation_forest.go @@ -0,0 +1,57 @@ +// Example of how to use Isolation Forest for outlier detection + +package main + +import ( + "fmt" + + "github.com/sjwhitworth/golearn/base" + "github.com/sjwhitworth/golearn/trees" +) + +func main() { + /* Isolation Forest is used for outlier detection + The algorithm works by randomly splitting the data, so results won't be exactly reproducible + but generally outliers will still be classified as outliers. */ + + // Load data for outlier detection - includes gaussian distribution, and ten outliers at the end + // Dataset has 1000 normal datapoints, and 10 outliers at the ned + csvData, err := base.ParseCSVToInstances("../datasets/gaussian_outliers.csv", true) + if err != nil { + panic(err) + } + + // Create New Isolation Forest with 100 trees, max depth 100, and each tree will use 850 datapoints + forest := trees.NewIsolationForest(100, 100, 850) + + // fit the isolation forest to the data. Note that all class attributes are also used during training. + // Remove all class attributes you don't want to use before calling fit. + forest.Fit(csvData) + + // Make predictions. Generally, IsolationForest is used for Interpolation, not Extrapolation. + // Predictions are returned as Anomaly Scores from 0 to 1. close to 0 - not outlier, close to 1 - outlier + preds := forest.Predict(csvData) + + // Let's find the average and minimum Anomaly Score for normal data + var avgScore float64 + var min float64 + min = 1 + + for i := 0; i < 1000; i++ { + temp := preds[i] + avgScore += temp + if temp < min { + min = temp + } + } + fmt.Println(avgScore / 1000) + fmt.Println(min) + + // Now let's print the anomaly scores for the outliers. + // You should find that these values are much higher (around 0.7) as comapred to the scores for normal data. + fmt.Println("Anomaly Scores for outliers are ") + for i := 1000; i < 1010; i++ { + fmt.Print(" ") + fmt.Println(preds[i]) + } +} From 0270ec857903770d5c31d3bede764d3def3ba584 Mon Sep 17 00:00:00 2001 From: Ayush Date: Thu, 27 Aug 2020 18:04:34 +0530 Subject: [PATCH 4/7] IsolationForest in trees.go Adding info on Isolation Forest in trees.go --- trees/trees.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/trees/trees.go b/trees/trees.go index d968b3e..ccbe813 100644 --- a/trees/trees.go +++ b/trees/trees.go @@ -11,13 +11,13 @@ present, so discretise beforehand (see filters) - CART (Classification and Regression Trees): - Builds a binary decision tree using the CART algorithm - using a greedy approach to find the best split at each node. + CART (Classification and Regression Trees): + Builds a binary decision tree using the CART algorithm + using a greedy approach to find the best split at each node. - Can be used for regression and classficiation. - Attributes have to be FloatAttributes even for classification. - Hence, convert to Integer Labels before hand for Classficiation. + Can be used for regression and classficiation. + Attributes have to be FloatAttributes even for classification. + Hence, convert to Integer Labels before hand for Classficiation. RandomTree: Builds a decision tree using the ID3 algorithm @@ -29,6 +29,14 @@ present, so discretise beforehand (see filters) + IsolationForest: + Unsupervised learning model for outlier detection. + + Builds a tree by randomly picking an attribute and splitting value. + + Attributes must be FloatAttributes. + All Class Attributes will be treated as Normal Feature Attributes, + So remove any Class Attributes you don't want during training beforehand. */ package trees From 333997b0240661be8be219ea6767da8cbe27280d Mon Sep 17 00:00:00 2001 From: Ayush Date: Sun, 30 Aug 2020 18:17:18 +0530 Subject: [PATCH 5/7] Adding Comments --- trees/isolation.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/trees/isolation.go b/trees/isolation.go index bfd9f03..6392a6c 100644 --- a/trees/isolation.go +++ b/trees/isolation.go @@ -15,11 +15,13 @@ type IsolationForest struct { trees []regressorNode } +// Select A random feature for splitting from the data. func selectFeature(data [][]float64) int64 { rand.Seed(time.Now().UnixNano()) return int64(rand.Intn(len(data[0]))) } +// Find the minimum and maximum values of a feature. Used so that we can choose a random threshold. func minMax(feature int64, data [][]float64) (float64, float64) { var min, max float64 @@ -38,6 +40,7 @@ func minMax(feature int64, data [][]float64) (float64, float64) { return min, max } +// Select a random threshold between the minimum and maximum of the feature. func selectValue(min, max float64) float64 { rand.Seed(time.Now().UnixNano()) val := min + (rand.Float64() * (max - min)) @@ -49,6 +52,7 @@ func selectValue(min, max float64) float64 { return val } +// Split the data based on the threshold. func splitData(val float64, feature int64, data [][]float64) ([][]float64, [][]float64) { var leftData, rightData [][]float64 for _, instance := range data { @@ -61,6 +65,7 @@ func splitData(val float64, feature int64, data [][]float64) ([][]float64, [][]f return leftData, rightData } +// Make sure that the data can still be split (all datapoints are not duplicate) func checkData(data [][]float64) bool { for _, instance := range data { for i, val := range instance { @@ -72,6 +77,7 @@ func checkData(data [][]float64) bool { return false } +// Recusrively build a tree by randomly choosing a feature to split until nodes are pure or max depth is reached. func buildTree(data [][]float64, upperNode regressorNode, depth int, maxDepth int) regressorNode { depth++ @@ -113,6 +119,7 @@ func buildTree(data [][]float64, upperNode regressorNode, depth int, maxDepth in return upperNode } +// Get a random subset of the data. Helps making each tree in forest different. func getRandomData(data [][]float64, subSpace int) [][]float64 { var randomData [][]float64 rand.Seed(time.Now().UnixNano()) @@ -122,6 +129,7 @@ func getRandomData(data [][]float64, subSpace int) [][]float64 { return randomData } +// Function to create a new isolation forest. nTrees is number of trees in Forest. Maxdepth is maximum depth of each tree. Subspace is number of data points to use per tree. func NewIsolationForest(nTrees int, maxDepth int, subSpace int) IsolationForest { var iForest IsolationForest iForest.nTrees = nTrees @@ -130,6 +138,7 @@ func NewIsolationForest(nTrees int, maxDepth int, subSpace int) IsolationForest return iForest } +// Fit the data based on hyperparameters and data. func (iForest *IsolationForest) Fit(X base.FixedDataGrid) { data := preprocessData(X) nTrees := iForest.nTrees @@ -147,6 +156,7 @@ func (iForest *IsolationForest) Fit(X base.FixedDataGrid) { iForest.trees = forest } +// Calculate the path length to reach a leaf node for a datapoint. Outliers have smaller path lengths than standard data points. func pathLength(tree regressorNode, instance []float64, path float64) float64 { path++ @@ -172,6 +182,7 @@ func pathLength(tree regressorNode, instance []float64, path float64) float64 { return path } +// Find the path length of a a datapoints from all trees in forest. func evaluateInstance(instance []float64, forest []regressorNode) []float64 { var paths []float64 for _, tree := range forest { @@ -180,10 +191,12 @@ func evaluateInstance(instance []float64, forest []regressorNode) []float64 { return paths } +// Helper function to calculate anomaly score. func cFactor(n int) float64 { return 2.0*(math.Log(float64(n-1))+0.5772156649) - (float64(2.0*(n-1)) / float64(n)) } +// Anamoly Score - How anomalous is a data point. closer to 1 - higher chance of it being outlier. closer to 0 - low chance of it being outlier. func anomalyScore(instance []float64, forest []regressorNode, n int) float64 { paths := evaluateInstance(instance, forest) E := 0.0 @@ -194,6 +207,8 @@ func anomalyScore(instance []float64, forest []regressorNode, n int) float64 { c := cFactor(n) return math.Pow(2, (-1 * E / c)) } + +// Return anamoly score for all datapoints. func (iForest *IsolationForest) Predict(X base.FixedDataGrid) []float64 { data := preprocessData(X) @@ -205,6 +220,7 @@ func (iForest *IsolationForest) Predict(X base.FixedDataGrid) []float64 { return preds } +// Extract data in the form of floats. Used in Fit and predict. Note that class labels are treated as normal data because Isolation Forest is unsupervised. func preprocessData(X base.FixedDataGrid) [][]float64 { data := convertInstancesToProblemVec(X) class, err := regressorConvertInstancesToLabelVec(X) From a380d191f4f0a9043876147310c2363b201877b6 Mon Sep 17 00:00:00 2001 From: Ayush Date: Sun, 6 Sep 2020 09:30:38 +0530 Subject: [PATCH 6/7] Removed Changing Seed --- trees/isolation.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/trees/isolation.go b/trees/isolation.go index 6392a6c..3f83c90 100644 --- a/trees/isolation.go +++ b/trees/isolation.go @@ -3,7 +3,6 @@ package trees import ( "math" "math/rand" - "time" "github.com/sjwhitworth/golearn/base" ) @@ -17,7 +16,6 @@ type IsolationForest struct { // Select A random feature for splitting from the data. func selectFeature(data [][]float64) int64 { - rand.Seed(time.Now().UnixNano()) return int64(rand.Intn(len(data[0]))) } @@ -42,7 +40,6 @@ func minMax(feature int64, data [][]float64) (float64, float64) { // Select a random threshold between the minimum and maximum of the feature. func selectValue(min, max float64) float64 { - rand.Seed(time.Now().UnixNano()) val := min + (rand.Float64() * (max - min)) if val == min { val += 0.000001 @@ -122,7 +119,6 @@ func buildTree(data [][]float64, upperNode regressorNode, depth int, maxDepth in // Get a random subset of the data. Helps making each tree in forest different. func getRandomData(data [][]float64, subSpace int) [][]float64 { var randomData [][]float64 - rand.Seed(time.Now().UnixNano()) for i := 0; i < subSpace; i++ { randomData = append(randomData, data[rand.Intn(len(data))]) } From e3a09cfa34125fc7e6295d1d4c5000c453f9481e Mon Sep 17 00:00:00 2001 From: Ayush Date: Tue, 8 Sep 2020 14:55:47 +0530 Subject: [PATCH 7/7] File paths --- examples/trees/cart/cart.go | 2 +- examples/trees/id3/trees.go | 5 +++-- examples/trees/isolationForest/isolation_forest.go | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/trees/cart/cart.go b/examples/trees/cart/cart.go index 15d5888..628060c 100644 --- a/examples/trees/cart/cart.go +++ b/examples/trees/cart/cart.go @@ -36,7 +36,7 @@ func main() { */ // Load Titanic Data For classification - classificationData, err := base.ParseCSVToInstances("../datasets/titanic.csv", false) + classificationData, err := base.ParseCSVToInstances("../../datasets/titanic.csv", false) if err != nil { panic(err) } diff --git a/examples/trees/id3/trees.go b/examples/trees/id3/trees.go index c73fc4f..9bdd44f 100644 --- a/examples/trees/id3/trees.go +++ b/examples/trees/id3/trees.go @@ -4,12 +4,13 @@ package main import ( "fmt" + "math/rand" + "github.com/sjwhitworth/golearn/base" "github.com/sjwhitworth/golearn/ensemble" "github.com/sjwhitworth/golearn/evaluation" "github.com/sjwhitworth/golearn/filters" "github.com/sjwhitworth/golearn/trees" - "math/rand" ) func main() { @@ -19,7 +20,7 @@ func main() { rand.Seed(44111342) // Load in the iris dataset - iris, err := base.ParseCSVToInstances("../datasets/iris_headers.csv", true) + iris, err := base.ParseCSVToInstances("../../datasets/iris_headers.csv", true) if err != nil { panic(err) } diff --git a/examples/trees/isolationForest/isolation_forest.go b/examples/trees/isolationForest/isolation_forest.go index 47c4ebf..30ddb0a 100644 --- a/examples/trees/isolationForest/isolation_forest.go +++ b/examples/trees/isolationForest/isolation_forest.go @@ -16,7 +16,7 @@ func main() { // Load data for outlier detection - includes gaussian distribution, and ten outliers at the end // Dataset has 1000 normal datapoints, and 10 outliers at the ned - csvData, err := base.ParseCSVToInstances("../datasets/gaussian_outliers.csv", true) + csvData, err := base.ParseCSVToInstances("../../datasets/gaussian_outliers.csv", true) if err != nil { panic(err) }