diff --git a/iris.html b/iris.html index cad0045..d204bee 100644 --- a/iris.html +++ b/iris.html @@ -5,7 +5,11 @@ - + + + + + TF.js Lab @@ -37,6 +41,45 @@

Iris

+
+ +
+ + +
+
+
+
+
+
+
+ + +
+ +
+ @@ -53,6 +96,8 @@

- + + + + \ No newline at end of file diff --git a/irisFed.html b/irisFed.html new file mode 100644 index 0000000..3755294 --- /dev/null +++ b/irisFed.html @@ -0,0 +1,122 @@ + + + + + + + + + + + + + WebFed Lab + + + +
+ + +
+
+

+ Iris Federated +

+
+
+ +
+ +
+ + + + +
+
+
+
+
+
+ +
+
+
+
+ + + + + + \ No newline at end of file diff --git a/irisFed.js b/irisFed.js new file mode 100644 index 0000000..dc19e02 --- /dev/null +++ b/irisFed.js @@ -0,0 +1,957 @@ +// import * as tf from '@tensorflow/tfjs' +import webFed from "./webFed.js" + +const iris = {} +iris.ui = {} +iris.mnistDB = {} +iris.mnist_NUM_CLASSES = 10 +iris.stop = false + +let GUN_SERVER = "http://localhost:8765/gun" + +const indexedDBConfig = { + dbName: "mnistDB", + objectStoreOpts: { + keyPath: "filename", + }, + objectStoreIndex: { + name: "filenameIdx", + keyPath: "filename", + objectParameters: { + unique: true, + }, + }, +} +const filePickerEndpoint = + "https://script.google.com/macros/s/AKfycbyS0oKEIPPN-qcp0RtX9VGFmu0rZ4MI8uMNm_OCPiwllXRBO_F4TTnEfOYavVzYTc3f/exec" +const manifests = { + training: { + filename: "trainingLabels.csv", + count: 60000, + }, + test: { + filename: "testLabels.csv", + count: 10000, + }, +} + +const utils = { + request: (url, opts, returnJson = true) => + fetch(url, opts).then((res) => { + if (res.ok) { + if (returnJson) return res.json() + else return res + } else { + throw Error(res.status) + } + }), +} + +const loadHashParams = () => { + const hashParams = {} + if (window.location.hash.includes("=")) { + window.location.hash.slice(1).split('&').forEach(param => { + let [key, value] = param.split('=') + value = value.replace(/['"]+/g, "") // for when the hash parameter contains quotes. + value = decodeURIComponent(value) + if (key === "extModules") { + try { + hashParams[key] = eval(value) // for when the extModules parameter is an array/object. + } catch (e) { // If eval doesn't work, just add the value as a string. + console.warn("The extModules parameter should be either be a URL without quotes or a proper array containing individual URL(s) inside quotes!", e) + hashParams[key] = value + } + } else { + hashParams[key] = value + } + }) + loadExtModules(hashParams["extModules"]) + } +} + +const loadExtModules = (modules) => { + modules = modules || hashParams["extModules"] + + const loadModule = (modulePath) => { + console.log(`Loading external module at ${modulePath}`) + const scriptElement = document.createElement('script') + scriptElement.src = modulePath + scriptElement.async = "" + scriptElement.type = "text/javascript" + document.head.appendChild(scriptElement) + } + + if (modules) { + if (Array.isArray(modules)) { + modules.forEach(modulePath => loadModule(modulePath)) + } else if (typeof (modules) === "string") { + loadModule(modules) + } + } +} + +iris.ui.writeToConsole = (text, changeLastLine = false, addSeparator) => { + if (changeLastLine) { + document.getElementById("console").lastElementChild.innerText = text + } else { + if (addSeparator === "before") { + document + .getElementById("console") + .insertAdjacentHTML('beforeend', `
`) + } + const textElement = document.createElement("p") + textElement.className = "text-green-500 font-mono" + textElement.innerText = text + document + .getElementById("console") + .insertAdjacentElement('beforeend', textElement) + + if (addSeparator === "after") { + document + .getElementById("console") + .insertAdjacentHTML('beforeend', `
`) + } + } + document.getElementById("consoleParent").scrollTop = !iris.consoleScrolled ? document.getElementById("consoleParent").scrollHeight - document.getElementById("consoleParent").offsetHeight : document.getElementById("consoleParent").scrollTop +} + +iris.ui.recordScrolled = () => { + if (document.getElementById("consoleParent").scrollTop === (document.getElementById("consoleParent").scrollHeight - document.getElementById("consoleParent").offsetHeight)) { + iris.consoleScrolled = false + } else { + iris.consoleScrolled = true + } +} + +iris.setupIndexedDB = ( + dbName, + objectStoreName, + objectStoreOpts = {}, + indexOpts +) => new Promise((resolve) => { + const dbRequest = window.indexedDB.open(dbName) + dbRequest.onupgradeneeded = () => { + const db = dbRequest.result + if (!db.objectStoreNames.contains(objectStoreName)) { + const objectStore = db.createObjectStore( + objectStoreName, + objectStoreOpts + ) + if (indexOpts) { + objectStore.createIndex( + indexOpts.name, + indexOpts.keyPath, + indexOpts.objectParameters + ) + } + } + } + dbRequest.onsuccess = (evt) => { + const db = evt.target.result + resolve(db) + } +}) + +iris.writeToIndexedDB = (objectStoreName, obj) => + new Promise((resolve) => { + const objectStore = iris.mnistDB + .transaction(objectStoreName, "readwrite") + .objectStore(objectStoreName) + objectStore.put(obj).onsuccess = ({ target }) => resolve(target.result) + }) + +iris.getRecordsCount = (objectStoreName) => + new Promise((resolve) => { + const objectStore = iris.mnistDB + .transaction(objectStoreName, "readwrite") + .objectStore(objectStoreName) + objectStore.count().onsuccess = ({ target }) => resolve(target.result) + }) + +iris.getFromIndexedDB = (objectStore, queryOpts = {}) => + new Promise((resolve, reject) => { + const objectStoreTransaction = iris.mnistDB + .transaction(objectStore, "readonly") + .objectStore(objectStore) + + if (queryOpts.query === "all") { + objectStoreTransaction.getAll().onsuccess = (e) => { + resolve({ result: e.target.result }) + } + } else if ( + Array.isArray(queryOpts.query) || + typeof queryOpts.query === "string" || + typeof queryOpts.query === "number" + ) { + // Return a single row. + const attemptGet = objectStoreTransaction.get(queryOpts.query) + attemptGet.onsuccess = (e) => { + resolve({ result: e.target.result }) + } + attemptGet.onerror = (e) => { + reject(e.target.result) + } + } else { + // Return a paginated response. + const queryResult = [] + let offset = + typeof queryOpts.offset === "number" && queryOpts.offset >= 0 + ? queryOpts.offset + : 0 + queryOpts.limit = + typeof queryOpts.limit === "number" && queryOpts.limit > 0 + ? queryOpts.limit + : 25 + // let numRecords = 0 + // numRecords = e.target.result + + let cursorSource = objectStoreTransaction + if (queryOpts.index) { + cursorSource = objectStoreTransaction.index(queryOpts.index) + } + + let pagesSkippedFlag = queryOpts.pageNum && queryOpts.pageNum > 0 + + const cursorRequest = cursorSource.openCursor( + queryOpts.query, + queryOpts.direction + ) + cursorRequest.onsuccess = (e) => { + const cursor = e.target.result + if (!cursor) { + // console.log(`No cursor, found ${queryResult.length} items for query`, queryOpts) + resolve({ result: queryResult, offset }) + return + } + + if (queryOpts.offset > 0 && !pagesSkippedFlag) { + // console.log("Advancing by ", queryOpts.offset, numRecords) + pagesSkippedFlag = true + cursor.advance(queryOpts.offset) + return + } + + if (queryResult.length < queryOpts.limit) { + if ( + queryOpts?.query?.lower && + Array.isArray(queryOpts?.query?.lower) && + queryOpts?.query?.upper && + Array.isArray(queryOpts?.query?.upper) + ) { + for (let i = 1; i < queryOpts.query.lower.length; i++) { + if ( + window.indexedDB.cmp( + cursor.key.slice(i, queryOpts.query.lower.length), + queryOpts.query.lower.slice(i) + ) < 0 + ) { + // console.log("Skipping Because low", cursor.key.slice(0, queryOpts.query.lower.length), queryOpts.query.lower) + cursor.continue([ + ...cursor.key.slice(0, i), + ...queryOpts.query.lower.slice(i), + ...cursor.key.slice(queryOpts.query.lower.length), + ]) + offset++ + return + } + if ( + window.indexedDB.cmp( + cursor.key.slice(i, queryOpts.query.upper.length), + queryOpts.query.upper.slice(i) + ) > 0 + ) { + // console.log("Skipping Because high", cursor.key.slice(0, queryOpts.query.lower.length), queryOpts.query.upper) + cursor.continue([ + ...cursor.key.slice(0, i), + cursor.key[i] + EPSILON, + ...queryOpts.query.upper.slice(i + 1), + ...cursor.key.slice(queryOpts.query.upper.length), + ]) + offset++ + return + } + } + } + // console.log("FOUND!") + queryResult.push(cursor.value) + offset++ + cursor.continue() + } else { + resolve({ result: queryResult, offset }) + } + } + cursorRequest.onerror = (e) => { + console.log(e) + } + } + }) + +iris.setupWorker = () => { + iris.worker = new Worker("./mnistWorker.js") + iris.worker.onmessage = (e) => { + const { op, data } = e.data + switch (op) { + case "loadManifest": + if (data.message === "idxdb_write") { + const consoleMessage = `${data.recordsStored}/${data.totalImages} records written to IndexedDB` + iris.ui.writeToConsole(consoleMessage, true) + } else if (data.message === "idxdb_success") { + const manifestLoadedEvent = new Event("manifestLoaded") + document.dispatchEvent(manifestLoadedEvent) + } + break + } + } +} + +iris.loadManifest = (filename, objectStoreName, subsetSize) => + new Promise(resolve => { + iris.worker.postMessage({ + op: "loadManifest", + data: { + filename, + objectStoreName, + subsetSize + }, + }) + + document.addEventListener("manifestLoaded", resolve) + }) + +const subsetSize = 5000 +iris.startTraining = async () => { + // document.getElementById("console").innerHTML = "" + iris.ui.writeToConsole("Initializing training...") + iris.stop = false + iris.setupWorker() + + document.getElementById("trainCNNBtn").innerText = "Stop training" + document.getElementById("trainCNNBtn").classList.replace("bg-blue-900", "bg-red-900") + document.getElementById("trainCNNBtn").classList.replace("hover:bg-blue-800", "hover:bg-red-800") + document.getElementById("trainCNNBtn").onclick = iris.stopTraining + + iris.ui.writeToConsole("Setting up IndexedDB...") + const trainingObjectStoreName = "trainingData" + iris.mnistDB = await iris.setupIndexedDB( + indexedDBConfig.dbName, + trainingObjectStoreName, + indexedDBConfig.objectStoreOpts, + indexedDBConfig.objectStoreIndex + ) + if ((await iris.getRecordsCount(trainingObjectStoreName)) !== subsetSize) { + iris.ui.writeToConsole("Fetching training manifest...") + // const trainingManifestRequestURL = `${filePickerEndpoint}?filename=${manifests["training"].filename}` + // const trainingCSV = await ( + // await utils.request(trainingManifestRequestURL, {}, false) + // ).text() + + // const csvLines = trainingCSV.split("\n") + + // let idx = 0 + // for (const line of csvLines) { + // if (idx !== 0) { + // const [filename, label] = line.split(",").map((x) => x.trim()) + // await iris.writeToIndexedDB(trainingObjectStoreName, { + // filename, + // label, + // }) + iris.ui.writeToConsole(`0 records written to IndexedDB`) + await iris.loadManifest(manifests["training"].filename, trainingObjectStoreName, subsetSize) + + // } + // idx += 1 + // } + } else { + iris.ui.writeToConsole("Training data already present in IndexedDB") + } + iris.visor = tfvis.visor() + iris.trainModel() +} + +iris.createModel = () => { + const model = tf.sequential() + + // The first layer of the convolutional neural network plays a dual role: + // it is both the input layer of the neural network and a layer that performs + // the first convolution operation on the input. It receives the 28x28 pixels + // black and white images. This input layer uses 16 filters with a kernel size + // of 5 pixels each. It uses a simple RELU activation function which pretty + // much just looks like this: __/ + model.add( + tf.layers.conv2d({ + inputShape: [28, 28, 1], + kernelSize: 5, + filters: 6, + activation: "tanh", + }) + ) + + // Changed to Average Pooling Layer + model.add(tf.layers.avgPool2d({ poolSize: 2, strides: 2 })) + + // Changed to depthwiseConv2d layer + model.add( + tf.layers.conv2d({ kernelSize: 5, filters: 16, activation: "tanh" }) + ) + + // Changed to Average Pooling Layer + model.add(tf.layers.avgPool2d({ poolSize: 2, strides: 2 })) + + model.add(tf.layers.flatten({})) + + // added additional dense layer + model.add(tf.layers.dense({ units: 84, activation: "tanh" })) + model.add(tf.layers.dense({ units: 10, activation: "softmax" })) + + return model +} + +iris.getBatch = async ( + objectStoreName, + offset, + limit, + callback = () => { } +) => { + const xs = [] + const labels = [] + + const { result: files } = await iris.getFromIndexedDB(objectStoreName, { + offset, + limit, + }) + + const getTensorFromImage = async (file) => { + const img = new Image() + img.width = 28 + img.height = 28 + const fileRequestURL = `${filePickerEndpoint}?filename=${file.filename}` + const abortController = new AbortController() + const timeoutRequest = setTimeout(() => abortController.abort(), 10000) + try { + img.src = await (await utils.request(fileRequestURL, { signal: abortController.signal }, false)).text() + } catch (e) { + console.log(e) + clearTimeout(timeoutRequest) + return + } + clearTimeout(timeoutRequest) + img.setAttribute("crossorigin", "Anonymous") + img.onload = () => { + const cv = document.createElement('canvas') + cv.width = img.width + cv.height = img.height + const ctx = cv.getContext('2d') + ctx.drawImage(img, 0, 0, 28, 28) + // document.getElementById("tfjs-visor-container").firstElementChild.firstElementChild.appendChild(cv) + const imageData = ctx.getImageData(0, 0, 28, 28).data + const grayscaledImage = [] + for (let i = 0; i < imageData.length; i += 4) { + if (i % (28 * 4) === 0) { + grayscaledImage.push([]) + } + const maxPixelIntensity = Math.max(imageData[i], imageData[i + 1], imageData[i + 2]) + if (maxPixelIntensity > 0) { + grayscaledImage[grayscaledImage.length - 1].push([1]) + } else { + grayscaledImage[grayscaledImage.length - 1].push([0]) + } + } + + xs.push(grayscaledImage) + labels.push(parseInt(file.label)) + } + } + + const ret = [] + const executing = [] + const poolLimit = 50 + for (const file of files) { + const p = Promise.resolve().then(() => { + if (!iris.stop) { + return getTensorFromImage(file, files) + } else { + return Promise.resolve() + } + }) + ret.push(p) + + if (poolLimit <= files.length && !iris.stop) { + const e = p.then(() => { + executing.splice(executing.indexOf(e), 1) + callback(xs) + }) + executing.push(e) + if (executing.length >= poolLimit) { + await Promise.race(executing) + } + } + } + + await Promise.allSettled(ret) + return tf.tidy(() => { + return { + 'xs': tf.tensor4d(xs, [xs.length, 28, 28, 1]), + 'labels': tf.oneHot(labels, iris.mnist_NUM_CLASSES), + } + }) +} + +iris.trainModel = async () => { + iris.ui.writeToConsole("Creating model architecture:") + iris.mnistModel = iris.createModel() + + const optimizer = "rmsprop" + const loss = "categoricalCrossentropy" + iris.mnistModel.compile({ + optimizer, + loss, + metrics: ["accuracy", "mse"], + }) + + iris.ui.writeToConsole(`Compiled model with ${optimizer} optimizer and ${loss} loss, ready for training`) + const surface = iris.visor.surface({ name: 'Model Summary', tab: 'Model Inspection' }) + tfvis.show.modelSummary(surface, iris.mnistModel) + + const imagesPerGroup = 500 + const validationSplit = 0.15 + const totalNumGroups = subsetSize / imagesPerGroup + const batchSize = 100 + const epochsToTrainFor = 3 + const totalNumEpochs = totalNumGroups * epochsToTrainFor + iris.modelTrainingSurface = { name: "Model Training", tab: "Training" } + const metricsVisualizerCallback = tfvis.show.fitCallbacks(iris.modelTrainingSurface, ['loss', 'acc'], ['onEpochEnd']) + iris.currentEpochNum = 0 + + for (let currentBatchNum = 0; currentBatchNum < totalNumGroups; currentBatchNum++) { + if (!iris.stop) { + iris.ui.writeToConsole(`Starting group ${currentBatchNum + 1}/${totalNumGroups}`, false, "before") + await iris.trainForEpoch(imagesPerGroup, currentBatchNum, batchSize, validationSplit, epochsToTrainFor, metricsVisualizerCallback) + } + } + iris.ui.writeToConsole("Model successfully trained!") +} + +iris.trainForEpoch = async ( + imagesPerGroup, + currentBatchNum, + batchSize, + validationSplit, + epochsToTrainFor, + metricsVisualizerCallback +) => { + iris.ui.writeToConsole( + `0/${imagesPerGroup} images fetched for current group`, + true + ) + const imageFetchCallback = (xs) => { + if (!iris.stop) { + iris.ui.writeToConsole( + `${xs.length}/${imagesPerGroup} images fetched for current group`, + true + ) + } + } + const batchData = await iris.getBatch("trainingData", currentBatchNum * imagesPerGroup, imagesPerGroup, imageFetchCallback) + let trainBatchCount = 0 + console.log(batchData) + await iris.mnistModel.fit(batchData.xs, batchData.labels, { + batchSize, + validationSplit, + epochs: epochsToTrainFor, + shuffle: true, + callbacks: { + onBatchEnd: (batch, logs) => { + trainBatchCount++ + iris.ui.writeToConsole( + `Epoch ${iris.currentEpochNum} ${(trainBatchCount / (imagesPerGroup / batchSize) * 100).toFixed(1)}% complete: Loss = ${logs.loss} ; Accuracy = ${logs.acc}` + ) + }, + onEpochBegin: () => { + iris.currentEpochNum++ + trainBatchCount = 0 + }, + onEpochEnd: (epoch, logs) => { + metricsVisualizerCallback.onEpochEnd(epoch, logs) + const weightsToBeShared = [] + iris.mnistModel.layers.forEach(layer => { + const layerWeights = layer.getWeights().map(weightMat => { + console.log(weightMat) + return weightMat.data() + }).flat() + weightsToBeShared.push(layerWeights) + }) + iris.broadcastToAllPeers(localStorage.currentFederationId, localStorage.clientId, { + epoch, + weights: weightsToBeShared + }) + iris.ui.writeToConsole(`Training Epoch ${iris.currentEpochNum} completed`) + iris.writeToConsole(`Validation Loss = ${logs.val_loss} ; Validation Accuracy = ${logs.val_acc}`) + + } + } + }) +} + +iris.stopTraining = () => { + iris.stop = true + iris.worker.terminate() + document.getElementById("trainCNNBtn").innerText = "Train CNN" + document + .getElementById("trainCNNBtn") + .classList.replace("bg-red-900", "bg-blue-900") + document + .getElementById("trainCNNBtn") + .classList.replace("hover:bg-red-800", "hover:bg-blue-800") + document.getElementById("trainCNNBtn").onclick = iris.startTraining + iris.writeToConsole("Terminated. ") +} + +iris.trainLRSimple = async (datasetIndex=1, iid=true) => { + const prefixFilePathString = iid ? 'iid' : 'noniid' + const irisData = await (await fetch(`https://episphere.github.io/lab/iris_${prefixFilePathString}_${datasetIndex}.json`)).json() + + const trainSplit = 0.8 + const trainSplitIndex = Math.floor(irisData.length) * trainSplit + const irisTrainingData = irisData.sort(() => Math.random() - 0.5).slice(0,trainSplitIndex) + const irisTestData = irisData.slice(trainSplitIndex) + + // const trainingData = irisTrainingData.map(({sepal_length, sepal_width, petal_length, petal_width}) => tf.tensor1d([ + // sepal_length, sepal_width, petal_length, petal_width + // ])) + + // const trainingLabels = irisTrainingData.map(({species}) => tf.tensor1d([ + // species === "setosa" ? 1 : 0, + // species === "virginica" ? 1 : 0, + // species === "versicolor" ? 1 : 0, + // ])) + const trainingData = tf.tensor2d(irisTrainingData.map(({sepal_length, sepal_width, petal_length, petal_width}) => [ + sepal_length, sepal_width, petal_length, petal_width + ])) + + const trainingLabels = tf.tensor2d(irisTrainingData.map(({species}) => [ + species === "setosa" ? 1 : 0, + species === "virginica" ? 1 : 0, + species === "versicolor" ? 1 : 0, + ])) + + const testData = tf.tensor2d(irisTestData.map(({sepal_length, sepal_width, petal_length, petal_width}) => [ + sepal_length, sepal_width, petal_length, petal_width + ])) + + const testLabels = tf.tensor2d(irisTestData.map(({species}) => [ + species === "setosa" ? 1 : 0, + species === "virginica" ? 1 : 0, + species === "versicolor" ? 1 : 0, + ])) + + const model = tf.sequential() + + model.add(tf.layers.dense({ + inputShape: [4], + activation: 'softmax', + units: 3 + })) + // model.add(tf.layers.dense({ + // inputShape: [5], + // activation: "sigmoid", + // units: 3, + // })) + // model.add(tf.layers.dense({ + // activation: "softmax", + // units: 3, + // })) + model.compile({ + loss: "binaryCrossentropy", + optimizer: tf.train.adam(.0008), + metrics: ["accuracy"] + }) + model.summary() + // train/fit our network + iris.ui.writeToConsole("Starting training...") + + tfvis.visor() + tfvis.show.modelSummary({ + 'name': "Model Architecture", + 'tab': "Model" + }, model) + model.layers.forEach(async (layer, index) => { + tfvis.show.layer({ + 'name': `Layer ${index+1}`, + 'tab': "Model" + }, layer) + }) + + // for (let epoch = 0; epoch < 50; epoch++) { + // for (let row in trainingData) { + // const gradientUpdate = await model.trainOnBatch(trainingData[row], trainingLabels[row]) + // } + await model.fit(trainingData, trainingLabels, { + batchSize: irisTrainingData.length, + epochs: 50, + // initialEpoch: epoch, + callbacks: tfvis.show.fitCallbacks({ + 'name': "Training", + 'tab': "Training" + }, ["loss", "acc"], { + 'callbacks': ["onEpochEnd"] + }) + }) + // console.log("Loss:",gradientUpdate.history.loss[0]) + // console.log("Accuracy:",gradientUpdate.history.acc[0]) + iris.ui.writeToConsole(`Training finished.`) + + const predictions = model.predict(testData) + predictions.print() + tf.metrics.categoricalAccuracy(testLabels, predictions).print() +} + +iris.trainLR = async (datasetIndex=1, iid=true) => { + const prefixFilePathString = iid ? 'iid' : 'noniid' + const irisData = await (await fetch(`https://episphere.github.io/lab/iris_${prefixFilePathString}_${datasetIndex}.json`)).json() + + const trainSplit = 0.8 + const trainSplitIndex = Math.floor(irisData.length) * trainSplit + const irisTrainingData = irisData.sort(() => Math.random() - 0.5).slice(0,trainSplitIndex) + const irisTestData = irisData.slice(trainSplitIndex) + + // const trainingData = irisTrainingData.map(({sepal_length, sepal_width, petal_length, petal_width}) => tf.tensor1d([ + // sepal_length, sepal_width, petal_length, petal_width + // ])) + + // const trainingLabels = irisTrainingData.map(({species}) => tf.tensor1d([ + // species === "setosa" ? 1 : 0, + // species === "virginica" ? 1 : 0, + // species === "versicolor" ? 1 : 0, + // ])) + const trainingData = tf.tensor2d(irisTrainingData.map(({sepal_length, sepal_width, petal_length, petal_width}) => [ + sepal_length, sepal_width, petal_length, petal_width + ])) + + const trainingLabels = tf.tensor2d(irisTrainingData.map(({species}) => [ + species === "setosa" ? 1 : 0, + species === "virginica" ? 1 : 0, + species === "versicolor" ? 1 : 0, + ])) + + const testData = tf.tensor2d(irisTestData.map(({sepal_length, sepal_width, petal_length, petal_width}) => [ + sepal_length, sepal_width, petal_length, petal_width + ])) + + const testLabels = tf.tensor2d(irisTestData.map(({species}) => [ + species === "setosa" ? 1 : 0, + species === "virginica" ? 1 : 0, + species === "versicolor" ? 1 : 0, + ])) + + const model = tf.sequential() + + model.add(tf.layers.dense({ + inputShape: [4], + activation: 'softmax', + units: 3 + })) + // model.add(tf.layers.dense({ + // inputShape: [5], + // activation: "sigmoid", + // units: 3, + // })) + // model.add(tf.layers.dense({ + // activation: "softmax", + // units: 3, + // })) + model.compile({ + loss: "binaryCrossentropy", + optimizer: tf.train.adam(.0008), + metrics: ["accuracy"] + }) + model.summary() + // train/fit our network + let responseFromPeers = {} + responseFromPeers['peersReady'] = responseFromPeers['peersReady'] || new Set() + responseFromPeers['weightUpdates'] = responseFromPeers['weightUpdates'] || [] + + document.body.addEventListener("peerMessage", ({detail: e}) => { + if (e.message.op === "startTraining") { + if (e.message.data.ready) { + webFed.sendDataToPeer(e.userID, { + 'op': "startTraining", + 'data': { + 'ack': true + } + }) + } else if (e.message.data.ack) { + // Nothing to be done really + } + responseFromPeers['peersReady'].add(e.userID) + } + else if (e.message.op === "layerWiseWeights") { + let objIndex = responseFromPeers['weightUpdates'].findIndex(o => o.epoch === e.message.data.epoch) + if (objIndex === -1) { + responseFromPeers['weightUpdates'].push({ + 'epoch': e.message.data.epoch, + 'weightUpdates': [] + }) + objIndex = responseFromPeers['weightUpdates'].length - 1 + } + responseFromPeers['weightUpdates'][objIndex].weightUpdates.push({ + 'peerId': e.userID, + 'weights': e.message.data.layerWiseWeights + }) + } + }) + + webFed.broadcastData({ + 'op': "startTraining", + 'data': { + 'ready': true + } + }) + + let allPeersReady = false + iris.ui.writeToConsole("Waiting for all peers to finish setting up...") + + while (!allPeersReady) { + await new Promise(res => setTimeout(res, 500)) + allPeersReady = responseFromPeers['peersReady']?.size === iris.group.userIDs.size - 1 + } + iris.ui.writeToConsole("All peers ready. Starting training...") + + await new Promise(res => setTimeout(res, 1000)) + tfvis.visor() + tfvis.show.modelSummary({ + 'name': "Model Architecture", + 'tab': "Model" + }, model) + model.layers.forEach(async (layer, index) => { + tfvis.show.layer({ + 'name': `Layer ${index+1}`, + 'tab': "Model" + }, layer) + }) + + for (let epoch = 0; epoch < 50; epoch++) { + console.log("Epoch", epoch) + // for (let row in trainingData) { + // const gradientUpdate = await model.trainOnBatch(trainingData[row], trainingLabels[row]) + // } + const gradientUpdate = await model.fit(trainingData, trainingLabels, { + batchSize: irisTrainingData.length, + epochs: epoch+1, + initialEpoch: epoch, + callbacks: tfvis.show.fitCallbacks({ + 'name': "Training", + 'tab': "Training" + }, ["loss", "acc"], { + 'callbacks': ["onEpochEnd"] + }) + }) + // console.log("Loss:",gradientUpdate.history.loss[0]) + // console.log("Accuracy:",gradientUpdate.history.acc[0]) + const layerWiseWeights = model.trainableWeights.map(layer => layer.val.dataSync()) + console.log(layerWiseWeights) + // console.log(layerWiseWeights) + webFed.broadcastData({ + 'op': "layerWiseWeights", + 'data': { + epoch, + layerWiseWeights + } + }) + + let allResponsesReceived = false + while(!allResponsesReceived) { + await new Promise(res => setTimeout(res, 500)) + allResponsesReceived = responseFromPeers['weightUpdates'].find(o => o.epoch === epoch).weightUpdates.length === iris.group.userIDs.size - 1 + } + + const receivedWeights = responseFromPeers['weightUpdates'].find(o => o.epoch === epoch).weightUpdates.map(peerUpdate => { + return peerUpdate.weights.map(arr => new Float32Array(arr)) + }) + receivedWeights.push(layerWiseWeights) + console.log(receivedWeights) + // Aggregate weights and move to the next batch/epoch. + const aggregatedWeights = [] + for (let layer in receivedWeights[0]) { + // const layerWiseAverage = receivedWeights[0][layer].reduce((averagedWeights, curr, ind) => { + const allLayerWiseWeights = receivedWeights.map(peer => peer[layer]) + let averagedLayerWiseWeights = [] + for (let i = 0; i < allLayerWiseWeights[0].length; i++) { + let sumAtNode = 0 + for (let j = 0; j < allLayerWiseWeights.length; j++) { + sumAtNode += allLayerWiseWeights[j][i] + } + averagedLayerWiseWeights.push(sumAtNode/receivedWeights.length) + } + // averagedWeights.push(sumOfWeights.map(sumAtNode => sumAtNode/receivedWeights.length)) + // return averagedWeights + // },[]) + console.log(averagedLayerWiseWeights) + aggregatedWeights.push(tf.tensor(averagedLayerWiseWeights, model.trainableWeights[layer].shape, model.trainableWeights[layer].dtype)) + } + + model.setWeights(aggregatedWeights) + model.getWeights()[0].print() + iris.ui.writeToConsole(`Successfully aggregated weights for epoch ${epoch}.`) + } + + const predictions = model.predict(testData) + predictions.print() + tf.metrics.categoricalAccuracy(testLabels, predictions).print() +} + +iris.ui.joinFederationHandler = async (federationId=localStorage.federationId, clientId=localStorage.clientId) => { + if (!federationId) { + federationId = document.getElementById("federationIdTextInput").value === '' ? undefined : document.getElementById("federationIdTextInput").value + } + if (!clientId) { + clientId = crypto.randomUUID() + } + const newUserCallback = (e) => { + console.log("New User", e.userID) + iris.ui.writeToConsole(`New user ${e.userID} joined!`) + iris.ui.enableTrainLR() + } + const newMessageCallback = (e) => { + console.log(`New message from ${e.userID}:`, e.message) + const peerMessageEvent = new CustomEvent("peerMessage", {detail: e}) + document.body.dispatchEvent(peerMessageEvent) + } + const { connectedClientId, connectedFederationId } = await webFed.initializeFederation({ clientId, federationId, newUserCallback, newMessageCallback }) + iris.group = webFed.group + localStorage.clientId = connectedClientId + localStorage.federationId = connectedFederationId + document.getElementById("federationIdTextInput").value = connectedFederationId + document.getElementById("joinFederationBtn").innerText = "Federation Joined!" + document.getElementById("joinFederationBtn").classList.replace("bg-blue-900", "bg-green-900") + document.getElementById("joinFederationBtn").classList.replace("hover:bg-blue-800", "hover:bg-green-800") + document.getElementById("joinFederationBtn").classList.add("disabled") +} + +iris.ui.enableTrainLR = (e) => { + document.getElementById("trainLROptions").classList.remove("hidden") +} + +iris.ui.trainLRHandler = (e) => { + const datasetSelector = document.getElementById("datasetSelector") + const iidCheckbox = document.getElementById("iidCheckbox") + if (e.target.id === "trainCNNBtn") { + iris.trainLR(datasetSelector.value, iidCheckbox.checked) + } else { + iris.trainLRSimple(datasetSelector.value, iidCheckbox.checked) + } +} + +window.onload = async () => { + localStorage.clear() + loadHashParams() + + document.getElementById("joinFederationBtn")?.addEventListener('click', () => { iris.ui.joinFederationHandler() }) + document.getElementById("trainCNNBtn")?.addEventListener('click', iris.ui.trainLRHandler) + document.getElementById("trainLRBasicBtn")?.addEventListener('click', iris.ui.trainLRHandler) + + // document.addEventListener('federationsChanged', iris.ui.populateFederationsList) + +} +window.onhashchange = loadHashParams; + +export default iris; \ No newline at end of file diff --git a/iris_iid_1.json b/iris_iid_1.json index e3639e4..03ec32b 100644 --- a/iris_iid_1.json +++ b/iris_iid_1.json @@ -1,352 +1,352 @@ [ - { - "sepal_length": 6.9, - "sepal_width": 3.1, - "petal_length": 5.4, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 6.7, - "sepal_width": 3.1, - "petal_length": 4.7, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.3, - "petal_length": 4.4, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 7.6, - "sepal_width": 3, - "petal_length": 6.6, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 4.9, - "sepal_width": 2.5, - "petal_length": 4.5, - "petal_width": 1.7, - "species": "virginica" - }, - { - "sepal_length": 5.1, - "sepal_width": 2.5, - "petal_length": 3, - "petal_width": 1.1, - "species": "versicolor" - }, - { - "sepal_length": 4.3, - "sepal_width": 3, - "petal_length": 1.1, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 5.7, - "sepal_width": 4.4, - "petal_length": 1.5, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 5.5, - "sepal_width": 2.3, - "petal_length": 4, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.6, - "petal_length": 4, - "petal_width": 1.2, - "species": "versicolor" - }, - { - "sepal_length": 5.7, - "sepal_width": 2.8, - "petal_length": 4.1, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 6.8, - "sepal_width": 3, - "petal_length": 5.5, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.7, - "petal_length": 3.9, - "petal_width": 1.2, - "species": "versicolor" - }, - { - "sepal_length": 5.5, - "sepal_width": 2.6, - "petal_length": 4.4, - "petal_width": 1.2, - "species": "versicolor" - }, - { - "sepal_length": 5.2, - "sepal_width": 2.7, - "petal_length": 3.9, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 6.5, - "sepal_width": 2.8, - "petal_length": 4.6, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 5.7, - "sepal_width": 3, - "petal_length": 4.2, - "petal_width": 1.2, - "species": "versicolor" - }, - { - "sepal_length": 4.6, - "sepal_width": 3.1, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.9, - "sepal_width": 2.4, - "petal_length": 3.3, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 6.9, - "sepal_width": 3.1, - "petal_length": 4.9, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 6.2, - "sepal_width": 2.9, - "petal_length": 4.3, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.7, - "sepal_width": 2.8, - "petal_length": 4.5, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.5, - "sepal_width": 2.4, - "petal_length": 3.8, - "petal_width": 1.1, - "species": "versicolor" - }, - { - "sepal_length": 5.4, - "sepal_width": 3, - "petal_length": 4.5, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.8, - "petal_length": 1.9, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 6.1, - "sepal_width": 2.8, - "petal_length": 4.7, - "petal_width": 1.2, - "species": "versicolor" - }, - { - "sepal_length": 5.6, - "sepal_width": 2.7, - "petal_length": 4.2, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.5, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.8, - "sepal_width": 3, - "petal_length": 1.4, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 6.7, - "sepal_width": 3.1, - "petal_length": 4.4, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 5.5, - "sepal_width": 2.4, - "petal_length": 3.7, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 5.5, - "sepal_width": 2.5, - "petal_length": 4, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 4.7, - "sepal_width": 3.2, - "petal_length": 1.6, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.7, - "sepal_width": 2.6, - "petal_length": 3.5, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 5.4, - "sepal_width": 3.9, - "petal_length": 1.3, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 6.4, - "sepal_width": 2.7, - "petal_length": 5.3, - "petal_width": 1.9, - "species": "virginica" - }, - { - "sepal_length": 6.7, - "sepal_width": 3.3, - "petal_length": 5.7, - "petal_width": 2.5, - "species": "virginica" - }, - { - "sepal_length": 4.6, - "sepal_width": 3.4, - "petal_length": 1.4, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 5.2, - "sepal_width": 3.4, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3.2, - "petal_length": 1.2, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.4, - "sepal_width": 3, - "petal_length": 1.3, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 6.3, - "sepal_width": 3.3, - "petal_length": 4.7, - "petal_width": 1.6, - "species": "versicolor" - }, - { - "sepal_length": 7.3, - "sepal_width": 2.9, - "petal_length": 6.3, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.8, - "petal_length": 1.6, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3, - "petal_length": 1.6, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 6.4, - "sepal_width": 3.1, - "petal_length": 5.5, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.1, - "sepal_width": 2.8, - "petal_length": 4, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 4.4, - "sepal_width": 2.9, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.7, - "sepal_width": 3.8, - "petal_length": 1.7, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3.4, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - } + { + "sepal_length": 0.7879, + "sepal_width": 0.381, + "petal_length": 0.7818, + "petal_width": 0.8333, + "species": "virginica" + }, + { + "sepal_length": 0.7273, + "sepal_width": 0.381, + "petal_length": 0.6545, + "petal_width": 0.5833, + "species": "versicolor" + }, + { + "sepal_length": 0.6061, + "sepal_width": 0, + "petal_length": 0.6, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 1, + "sepal_width": 0.3333, + "petal_length": 1, + "petal_width": 0.8333, + "species": "virginica" + }, + { + "sepal_length": 0.1818, + "sepal_width": 0.09524, + "petal_length": 0.6182, + "petal_width": 0.6667, + "species": "virginica" + }, + { + "sepal_length": 0.2424, + "sepal_width": 0.09524, + "petal_length": 0.3455, + "petal_width": 0.4167, + "species": "versicolor" + }, + { + "sepal_length": 0, + "sepal_width": 0.3333, + "petal_length": 0, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 0.4242, + "sepal_width": 1, + "petal_length": 0.07273, + "petal_width": 0.125, + "species": "setosa" + }, + { + "sepal_length": 0.3636, + "sepal_width": 0, + "petal_length": 0.5273, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.4545, + "sepal_width": 0.1429, + "petal_length": 0.5273, + "petal_width": 0.4583, + "species": "versicolor" + }, + { + "sepal_length": 0.4242, + "sepal_width": 0.2381, + "petal_length": 0.5455, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.7576, + "sepal_width": 0.3333, + "petal_length": 0.8, + "petal_width": 0.8333, + "species": "virginica" + }, + { + "sepal_length": 0.4545, + "sepal_width": 0.1905, + "petal_length": 0.5091, + "petal_width": 0.4583, + "species": "versicolor" + }, + { + "sepal_length": 0.3636, + "sepal_width": 0.1429, + "petal_length": 0.6, + "petal_width": 0.4583, + "species": "versicolor" + }, + { + "sepal_length": 0.2727, + "sepal_width": 0.1905, + "petal_length": 0.5091, + "petal_width": 0.5417, + "species": "versicolor" + }, + { + "sepal_length": 0.6667, + "sepal_width": 0.2381, + "petal_length": 0.6364, + "petal_width": 0.5833, + "species": "versicolor" + }, + { + "sepal_length": 0.4242, + "sepal_width": 0.3333, + "petal_length": 0.5636, + "petal_width": 0.4583, + "species": "versicolor" + }, + { + "sepal_length": 0.09091, + "sepal_width": 0.381, + "petal_length": 0.07273, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.1818, + "sepal_width": 0.04762, + "petal_length": 0.4, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.7879, + "sepal_width": 0.381, + "petal_length": 0.6909, + "petal_width": 0.5833, + "species": "versicolor" + }, + { + "sepal_length": 0.5758, + "sepal_width": 0.2857, + "petal_length": 0.5818, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.4242, + "sepal_width": 0.2381, + "petal_length": 0.6182, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.3636, + "sepal_width": 0.04762, + "petal_length": 0.4909, + "petal_width": 0.4167, + "species": "versicolor" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.3333, + "petal_length": 0.6182, + "petal_width": 0.5833, + "species": "versicolor" + }, + { + "sepal_length": 0.2424, + "sepal_width": 0.7143, + "petal_length": 0.1455, + "petal_width": 0.125, + "species": "setosa" + }, + { + "sepal_length": 0.5455, + "sepal_width": 0.2381, + "petal_length": 0.6545, + "petal_width": 0.4583, + "species": "versicolor" + }, + { + "sepal_length": 0.3939, + "sepal_width": 0.1905, + "petal_length": 0.5636, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.2424, + "sepal_width": 0.5714, + "petal_length": 0.05455, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.1515, + "sepal_width": 0.3333, + "petal_length": 0.05455, + "petal_width": 0.08333, + "species": "setosa" + }, + { + "sepal_length": 0.7273, + "sepal_width": 0.381, + "petal_length": 0.6, + "petal_width": 0.5417, + "species": "versicolor" + }, + { + "sepal_length": 0.3636, + "sepal_width": 0.04762, + "petal_length": 0.4727, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.3636, + "sepal_width": 0.09524, + "petal_length": 0.5273, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.1212, + "sepal_width": 0.4286, + "petal_length": 0.09091, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.4242, + "sepal_width": 0.1429, + "petal_length": 0.4364, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.7619, + "petal_length": 0.03636, + "petal_width": 0.125, + "species": "setosa" + }, + { + "sepal_length": 0.6364, + "sepal_width": 0.1905, + "petal_length": 0.7636, + "petal_width": 0.75, + "species": "virginica" + }, + { + "sepal_length": 0.7273, + "sepal_width": 0.4762, + "petal_length": 0.8364, + "petal_width": 1, + "species": "virginica" + }, + { + "sepal_length": 0.09091, + "sepal_width": 0.5238, + "petal_length": 0.05455, + "petal_width": 0.08333, + "species": "setosa" + }, + { + "sepal_length": 0.2727, + "sepal_width": 0.5238, + "petal_length": 0.05455, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.2121, + "sepal_width": 0.4286, + "petal_length": 0.01818, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.0303, + "sepal_width": 0.3333, + "petal_length": 0.03636, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.6061, + "sepal_width": 0.4762, + "petal_length": 0.6545, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.9091, + "sepal_width": 0.2857, + "petal_length": 0.9455, + "petal_width": 0.7083, + "species": "virginica" + }, + { + "sepal_length": 0.2424, + "sepal_width": 0.7143, + "petal_length": 0.09091, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.2121, + "sepal_width": 0.3333, + "petal_length": 0.09091, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.6364, + "sepal_width": 0.381, + "petal_length": 0.8, + "petal_width": 0.7083, + "species": "virginica" + }, + { + "sepal_length": 0.5455, + "sepal_width": 0.2381, + "petal_length": 0.5273, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.0303, + "sepal_width": 0.2857, + "petal_length": 0.05455, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.4242, + "sepal_width": 0.7143, + "petal_length": 0.1091, + "petal_width": 0.08333, + "species": "setosa" + }, + { + "sepal_length": 0.2121, + "sepal_width": 0.5238, + "petal_length": 0.07273, + "petal_width": 0.04167, + "species": "setosa" + } ] \ No newline at end of file diff --git a/iris_iid_2.json b/iris_iid_2.json index 4905999..2e8b929 100644 --- a/iris_iid_2.json +++ b/iris_iid_2.json @@ -1,247 +1,247 @@ [ - { - "sepal_length": 5.1, - "sepal_width": 3.8, - "petal_length": 1.5, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 6.7, - "sepal_width": 3, - "petal_length": 5, - "petal_width": 1.7, - "species": "versicolor" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.5, - "petal_length": 5, - "petal_width": 1.9, - "species": "virginica" - }, - { - "sepal_length": 6, - "sepal_width": 2.2, - "petal_length": 4, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 6.9, - "sepal_width": 3.2, - "petal_length": 5.7, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 5.7, - "sepal_width": 2.5, - "petal_length": 5, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.7, - "petal_length": 5.1, - "petal_width": 1.9, - "species": "virginica" - }, - { - "sepal_length": 5, - "sepal_width": 2.3, - "petal_length": 3.3, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 5.3, - "sepal_width": 3.7, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 6.6, - "sepal_width": 2.9, - "petal_length": 4.6, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.7, - "petal_length": 4.1, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 5.6, - "sepal_width": 2.9, - "petal_length": 3.6, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.8, - "petal_length": 5.1, - "petal_width": 1.5, - "species": "virginica" - }, - { - "sepal_length": 4.8, - "sepal_width": 3.1, - "petal_length": 1.6, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 7.7, - "sepal_width": 2.8, - "petal_length": 6.7, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 6, - "sepal_width": 2.7, - "petal_length": 5.1, - "petal_width": 1.6, - "species": "versicolor" - }, - { - "sepal_length": 4.9, - "sepal_width": 3.1, - "petal_length": 1.5, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.5, - "petal_length": 1.4, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 6.5, - "sepal_width": 3, - "petal_length": 5.5, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.3, - "sepal_width": 3.3, - "petal_length": 6, - "petal_width": 2.5, - "species": "virginica" - }, - { - "sepal_length": 7.7, - "sepal_width": 3, - "petal_length": 6.1, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 6.9, - "sepal_width": 3.1, - "petal_length": 5.1, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.8, - "petal_length": 5.1, - "petal_width": 2.4, - "species": "virginica" - }, - { - "sepal_length": 5, - "sepal_width": 3.6, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.4, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 7.2, - "sepal_width": 3, - "petal_length": 5.8, - "petal_width": 1.6, - "species": "virginica" - }, - { - "sepal_length": 5.9, - "sepal_width": 3, - "petal_length": 4.2, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 6.1, - "sepal_width": 3, - "petal_length": 4.9, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.7, - "sepal_width": 3.3, - "petal_length": 5.7, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 4.6, - "sepal_width": 3.2, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 7.4, - "sepal_width": 2.8, - "petal_length": 6.1, - "petal_width": 1.9, - "species": "virginica" - }, - { - "sepal_length": 7.2, - "sepal_width": 3.2, - "petal_length": 6, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.3, - "sepal_width": 3.4, - "petal_length": 5.6, - "petal_width": 2.4, - "species": "virginica" - }, - { - "sepal_length": 5, - "sepal_width": 3.3, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 6, - "sepal_width": 2.9, - "petal_length": 4.5, - "petal_width": 1.5, - "species": "versicolor" - } + { + "sepal_length": 0.1613, + "sepal_width": 1, + "petal_length": 0.01887, + "petal_width": 0.08333, + "species": "setosa" + }, + { + "sepal_length": 0.6774, + "sepal_width": 0.5, + "petal_length": 0.6792, + "petal_width": 0.6667, + "species": "versicolor" + }, + { + "sepal_length": 0.5484, + "sepal_width": 0.1875, + "petal_length": 0.6792, + "petal_width": 0.75, + "species": "virginica" + }, + { + "sepal_length": 0.4516, + "sepal_width": 0, + "petal_length": 0.4906, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.7419, + "sepal_width": 0.625, + "petal_length": 0.8113, + "petal_width": 0.9167, + "species": "virginica" + }, + { + "sepal_length": 0.3548, + "sepal_width": 0.1875, + "petal_length": 0.6792, + "petal_width": 0.7917, + "species": "virginica" + }, + { + "sepal_length": 0.3871, + "sepal_width": 0.3125, + "petal_length": 0.6981, + "petal_width": 0.75, + "species": "virginica" + }, + { + "sepal_length": 0.129, + "sepal_width": 0.0625, + "petal_length": 0.3585, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.2258, + "sepal_width": 0.9375, + "petal_length": 0.01887, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.6452, + "sepal_width": 0.4375, + "petal_length": 0.6038, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.3871, + "sepal_width": 0.3125, + "petal_length": 0.5094, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.3226, + "sepal_width": 0.4375, + "petal_length": 0.4151, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.5484, + "sepal_width": 0.375, + "petal_length": 0.6981, + "petal_width": 0.5833, + "species": "virginica" + }, + { + "sepal_length": 0.06452, + "sepal_width": 0.5625, + "petal_length": 0.03774, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 1, + "sepal_width": 0.375, + "petal_length": 1, + "petal_width": 0.7917, + "species": "virginica" + }, + { + "sepal_length": 0.4516, + "sepal_width": 0.3125, + "petal_length": 0.6981, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.09677, + "sepal_width": 0.5625, + "petal_length": 0.01887, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 0.1613, + "sepal_width": 0.8125, + "petal_length": 0, + "petal_width": 0.08333, + "species": "setosa" + }, + { + "sepal_length": 0.6129, + "sepal_width": 0.5, + "petal_length": 0.7736, + "petal_width": 0.7083, + "species": "virginica" + }, + { + "sepal_length": 0.5484, + "sepal_width": 0.6875, + "petal_length": 0.8679, + "petal_width": 1, + "species": "virginica" + }, + { + "sepal_length": 1, + "sepal_width": 0.5, + "petal_length": 0.8868, + "petal_width": 0.9167, + "species": "virginica" + }, + { + "sepal_length": 0.7419, + "sepal_width": 0.5625, + "petal_length": 0.6981, + "petal_width": 0.9167, + "species": "virginica" + }, + { + "sepal_length": 0.3871, + "sepal_width": 0.375, + "petal_length": 0.6981, + "petal_width": 0.9583, + "species": "virginica" + }, + { + "sepal_length": 0.129, + "sepal_width": 0.875, + "petal_length": 0, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.1613, + "sepal_width": 0.75, + "petal_length": 0.01887, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.8387, + "sepal_width": 0.5, + "petal_length": 0.8302, + "petal_width": 0.625, + "species": "virginica" + }, + { + "sepal_length": 0.4194, + "sepal_width": 0.5, + "petal_length": 0.5283, + "petal_width": 0.5833, + "species": "versicolor" + }, + { + "sepal_length": 0.4839, + "sepal_width": 0.5, + "petal_length": 0.6604, + "petal_width": 0.7083, + "species": "virginica" + }, + { + "sepal_length": 0.6774, + "sepal_width": 0.6875, + "petal_length": 0.8113, + "petal_width": 0.8333, + "species": "virginica" + }, + { + "sepal_length": 0, + "sepal_width": 0.625, + "petal_length": 0, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.9032, + "sepal_width": 0.375, + "petal_length": 0.8868, + "petal_width": 0.75, + "species": "virginica" + }, + { + "sepal_length": 0.8387, + "sepal_width": 0.625, + "petal_length": 0.8679, + "petal_width": 0.7083, + "species": "virginica" + }, + { + "sepal_length": 0.5484, + "sepal_width": 0.75, + "petal_length": 0.7925, + "petal_width": 0.9583, + "species": "virginica" + }, + { + "sepal_length": 0.129, + "sepal_width": 0.6875, + "petal_length": 0, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.4516, + "sepal_width": 0.4375, + "petal_length": 0.5849, + "petal_width": 0.5833, + "species": "versicolor" + } ] \ No newline at end of file diff --git a/iris_iid_3.json b/iris_iid_3.json index 23ed92c..850a56a 100644 --- a/iris_iid_3.json +++ b/iris_iid_3.json @@ -1,436 +1,436 @@ [ - { - "sepal_length": 6.4, - "sepal_width": 2.8, - "petal_length": 5.6, - "petal_width": 2.2, - "species": "virginica" - }, - { - "sepal_length": 6.4, - "sepal_width": 2.8, - "petal_length": 5.6, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 7, - "sepal_width": 3.2, - "petal_length": 4.7, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 5.9, - "sepal_width": 3.2, - "petal_length": 4.8, - "petal_width": 1.8, - "species": "versicolor" - }, - { - "sepal_length": 6, - "sepal_width": 3.4, - "petal_length": 4.5, - "petal_width": 1.6, - "species": "versicolor" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.3, - "petal_length": 1.7, - "petal_width": 0.5, - "species": "setosa" - }, - { - "sepal_length": 7.9, - "sepal_width": 3.8, - "petal_length": 6.4, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 6.8, - "sepal_width": 3.2, - "petal_length": 5.9, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 4.9, - "sepal_width": 3, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 6.7, - "sepal_width": 3, - "petal_length": 5.2, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 6.5, - "sepal_width": 3, - "petal_length": 5.8, - "petal_width": 2.2, - "species": "virginica" - }, - { - "sepal_length": 5.4, - "sepal_width": 3.4, - "petal_length": 1.7, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.7, - "petal_length": 1.5, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.7, - "petal_length": 4.9, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 5.6, - "sepal_width": 3, - "petal_length": 4.1, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 7.2, - "sepal_width": 3.6, - "petal_length": 6.1, - "petal_width": 2.5, - "species": "virginica" - }, - { - "sepal_length": 5.4, - "sepal_width": 3.7, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.5, - "petal_length": 4.9, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 5.6, - "sepal_width": 3, - "petal_length": 4.5, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 7.7, - "sepal_width": 3.8, - "petal_length": 6.7, - "petal_width": 2.2, - "species": "virginica" - }, - { - "sepal_length": 6.8, - "sepal_width": 2.8, - "petal_length": 4.8, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 6.6, - "sepal_width": 3, - "petal_length": 4.4, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 6.1, - "sepal_width": 3, - "petal_length": 4.6, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 5, - "sepal_width": 3.4, - "petal_length": 1.6, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 6.4, - "sepal_width": 2.9, - "petal_length": 4.3, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 6.1, - "sepal_width": 2.9, - "petal_length": 4.7, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 5.6, - "sepal_width": 2.5, - "petal_length": 3.9, - "petal_width": 1.1, - "species": "versicolor" - }, - { - "sepal_length": 5.8, - "sepal_width": 4, - "petal_length": 1.2, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3.5, - "petal_length": 1.6, - "petal_width": 0.6, - "species": "setosa" - }, - { - "sepal_length": 7.1, - "sepal_width": 3, - "petal_length": 5.9, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 5, - "sepal_width": 3.5, - "petal_length": 1.3, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 2, - "petal_length": 3.5, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 5.2, - "sepal_width": 4.1, - "petal_length": 1.5, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 6.2, - "sepal_width": 2.2, - "petal_length": 4.5, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 4.9, - "sepal_width": 3.1, - "petal_length": 1.5, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 4.8, - "sepal_width": 3.4, - "petal_length": 1.6, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.8, - "sepal_width": 3.4, - "petal_length": 1.9, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 6, - "sepal_width": 3, - "petal_length": 4.8, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.2, - "sepal_width": 2.8, - "petal_length": 4.8, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 4.7, - "sepal_width": 3.2, - "petal_length": 1.3, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.5, - "sepal_width": 3.5, - "petal_length": 1.3, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 6.5, - "sepal_width": 3.2, - "petal_length": 5.1, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 4.6, - "sepal_width": 3.6, - "petal_length": 1, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 6.7, - "sepal_width": 2.5, - "petal_length": 5.8, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.4, - "sepal_width": 3.2, - "petal_length": 5.3, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.7, - "petal_length": 5.1, - "petal_width": 1.9, - "species": "virginica" - }, - { - "sepal_length": 4.8, - "sepal_width": 3, - "petal_length": 1.4, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.9, - "petal_length": 5.6, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.5, - "sepal_width": 3, - "petal_length": 5.2, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 5.6, - "sepal_width": 2.8, - "petal_length": 4.9, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 7.7, - "sepal_width": 2.6, - "petal_length": 6.9, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 6.1, - "sepal_width": 2.6, - "petal_length": 5.6, - "petal_width": 1.4, - "species": "virginica" - }, - { - "sepal_length": 6, - "sepal_width": 2.2, - "petal_length": 5, - "petal_width": 1.5, - "species": "virginica" - }, - { - "sepal_length": 6.7, - "sepal_width": 3.1, - "petal_length": 5.6, - "petal_width": 2.4, - "species": "virginica" - }, - { - "sepal_length": 6.4, - "sepal_width": 3.2, - "petal_length": 4.5, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 5.5, - "sepal_width": 4.2, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.2, - "sepal_width": 3.5, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.5, - "sepal_width": 2.3, - "petal_length": 1.3, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 4.4, - "sepal_width": 3.2, - "petal_length": 1.3, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.4, - "sepal_width": 3.4, - "petal_length": 1.5, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 6.2, - "sepal_width": 3.4, - "petal_length": 5.4, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 4.9, - "sepal_width": 3.1, - "petal_length": 1.5, - "petal_width": 0.1, - "species": "setosa" - } + { + "sepal_length": 0.5714, + "sepal_width": 0.3636, + "petal_length": 0.7797, + "petal_width": 0.875, + "species": "virginica" + }, + { + "sepal_length": 0.5714, + "sepal_width": 0.3636, + "petal_length": 0.7797, + "petal_width": 0.8333, + "species": "virginica" + }, + { + "sepal_length": 0.7429, + "sepal_width": 0.5455, + "petal_length": 0.6271, + "petal_width": 0.5417, + "species": "versicolor" + }, + { + "sepal_length": 0.4286, + "sepal_width": 0.5455, + "petal_length": 0.6441, + "petal_width": 0.7083, + "species": "versicolor" + }, + { + "sepal_length": 0.4571, + "sepal_width": 0.6364, + "petal_length": 0.5932, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.2, + "sepal_width": 0.5909, + "petal_length": 0.1186, + "petal_width": 0.1667, + "species": "setosa" + }, + { + "sepal_length": 1, + "sepal_width": 0.8182, + "petal_length": 0.9153, + "petal_width": 0.7917, + "species": "virginica" + }, + { + "sepal_length": 0.6857, + "sepal_width": 0.5455, + "petal_length": 0.8305, + "petal_width": 0.9167, + "species": "virginica" + }, + { + "sepal_length": 0.1429, + "sepal_width": 0.4545, + "petal_length": 0.0678, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.6571, + "sepal_width": 0.4545, + "petal_length": 0.7119, + "petal_width": 0.9167, + "species": "virginica" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.4545, + "petal_length": 0.8136, + "petal_width": 0.875, + "species": "virginica" + }, + { + "sepal_length": 0.2857, + "sepal_width": 0.6364, + "petal_length": 0.1186, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.2, + "sepal_width": 0.7727, + "petal_length": 0.08475, + "petal_width": 0.125, + "species": "setosa" + }, + { + "sepal_length": 0.5429, + "sepal_width": 0.3182, + "petal_length": 0.661, + "petal_width": 0.7083, + "species": "virginica" + }, + { + "sepal_length": 0.3429, + "sepal_width": 0.4545, + "petal_length": 0.5254, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.8, + "sepal_width": 0.7273, + "petal_length": 0.8644, + "petal_width": 1, + "species": "virginica" + }, + { + "sepal_length": 0.2857, + "sepal_width": 0.7727, + "petal_length": 0.08475, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.5429, + "sepal_width": 0.2273, + "petal_length": 0.661, + "petal_width": 0.5833, + "species": "versicolor" + }, + { + "sepal_length": 0.3429, + "sepal_width": 0.4545, + "petal_length": 0.5932, + "petal_width": 0.5833, + "species": "versicolor" + }, + { + "sepal_length": 0.9429, + "sepal_width": 0.8182, + "petal_length": 0.9661, + "petal_width": 0.875, + "species": "virginica" + }, + { + "sepal_length": 0.6857, + "sepal_width": 0.3636, + "petal_length": 0.6441, + "petal_width": 0.5417, + "species": "versicolor" + }, + { + "sepal_length": 0.6286, + "sepal_width": 0.4545, + "petal_length": 0.5763, + "petal_width": 0.5417, + "species": "versicolor" + }, + { + "sepal_length": 0.4857, + "sepal_width": 0.4545, + "petal_length": 0.6102, + "petal_width": 0.5417, + "species": "versicolor" + }, + { + "sepal_length": 0.1714, + "sepal_width": 0.6364, + "petal_length": 0.1017, + "petal_width": 0.125, + "species": "setosa" + }, + { + "sepal_length": 0.5714, + "sepal_width": 0.4091, + "petal_length": 0.5593, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.4857, + "sepal_width": 0.4091, + "petal_length": 0.6271, + "petal_width": 0.5417, + "species": "versicolor" + }, + { + "sepal_length": 0.3429, + "sepal_width": 0.2273, + "petal_length": 0.4915, + "petal_width": 0.4167, + "species": "versicolor" + }, + { + "sepal_length": 0.4, + "sepal_width": 0.9091, + "petal_length": 0.0339, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.1714, + "sepal_width": 0.6818, + "petal_length": 0.1017, + "petal_width": 0.2083, + "species": "setosa" + }, + { + "sepal_length": 0.7714, + "sepal_width": 0.4545, + "petal_length": 0.8305, + "petal_width": 0.8333, + "species": "virginica" + }, + { + "sepal_length": 0.1714, + "sepal_width": 0.6818, + "petal_length": 0.05085, + "petal_width": 0.08333, + "species": "setosa" + }, + { + "sepal_length": 0.1714, + "sepal_width": 0, + "petal_length": 0.4237, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.2286, + "sepal_width": 0.9545, + "petal_length": 0.08475, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 0.5143, + "sepal_width": 0.09091, + "petal_length": 0.5932, + "petal_width": 0.5833, + "species": "versicolor" + }, + { + "sepal_length": 0.1429, + "sepal_width": 0.5, + "petal_length": 0.08475, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 0.1143, + "sepal_width": 0.6364, + "petal_length": 0.1017, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.1143, + "sepal_width": 0.6364, + "petal_length": 0.1525, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.4571, + "sepal_width": 0.4545, + "petal_length": 0.6441, + "petal_width": 0.7083, + "species": "virginica" + }, + { + "sepal_length": 0.5143, + "sepal_width": 0.3636, + "petal_length": 0.6441, + "petal_width": 0.7083, + "species": "virginica" + }, + { + "sepal_length": 0.08571, + "sepal_width": 0.5455, + "petal_length": 0.05085, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.3143, + "sepal_width": 0.6818, + "petal_length": 0.05085, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.5455, + "petal_length": 0.6949, + "petal_width": 0.7917, + "species": "virginica" + }, + { + "sepal_length": 0.05714, + "sepal_width": 0.7273, + "petal_length": 0, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.6571, + "sepal_width": 0.2273, + "petal_length": 0.8136, + "petal_width": 0.7083, + "species": "virginica" + }, + { + "sepal_length": 0.5714, + "sepal_width": 0.5455, + "petal_length": 0.7288, + "petal_width": 0.9167, + "species": "virginica" + }, + { + "sepal_length": 0.4, + "sepal_width": 0.3182, + "petal_length": 0.6949, + "petal_width": 0.75, + "species": "virginica" + }, + { + "sepal_length": 0.1143, + "sepal_width": 0.4545, + "petal_length": 0.0678, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 0.5429, + "sepal_width": 0.4091, + "petal_length": 0.7797, + "petal_width": 0.7083, + "species": "virginica" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.4545, + "petal_length": 0.7119, + "petal_width": 0.7917, + "species": "virginica" + }, + { + "sepal_length": 0.3429, + "sepal_width": 0.3636, + "petal_length": 0.661, + "petal_width": 0.7917, + "species": "virginica" + }, + { + "sepal_length": 0.9429, + "sepal_width": 0.2727, + "petal_length": 1, + "petal_width": 0.9167, + "species": "virginica" + }, + { + "sepal_length": 0.4857, + "sepal_width": 0.2727, + "petal_length": 0.7797, + "petal_width": 0.5417, + "species": "virginica" + }, + { + "sepal_length": 0.4571, + "sepal_width": 0.09091, + "petal_length": 0.678, + "petal_width": 0.5833, + "species": "virginica" + }, + { + "sepal_length": 0.6571, + "sepal_width": 0.5, + "petal_length": 0.7797, + "petal_width": 0.9583, + "species": "virginica" + }, + { + "sepal_length": 0.5714, + "sepal_width": 0.5455, + "petal_length": 0.5932, + "petal_width": 0.5833, + "species": "versicolor" + }, + { + "sepal_length": 0.3143, + "sepal_width": 1, + "petal_length": 0.0678, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.2286, + "sepal_width": 0.6818, + "petal_length": 0.08475, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.02857, + "sepal_width": 0.1364, + "petal_length": 0.05085, + "petal_width": 0.08333, + "species": "setosa" + }, + { + "sepal_length": 0, + "sepal_width": 0.5455, + "petal_length": 0.05085, + "petal_width": 0.04167, + "species": "setosa" + }, + { + "sepal_length": 0.2857, + "sepal_width": 0.6364, + "petal_length": 0.08475, + "petal_width": 0.125, + "species": "setosa" + }, + { + "sepal_length": 0.5143, + "sepal_width": 0.6364, + "petal_length": 0.7458, + "petal_width": 0.9167, + "species": "virginica" + }, + { + "sepal_length": 0.1429, + "sepal_width": 0.5, + "petal_length": 0.08475, + "petal_width": 0, + "species": "setosa" + } ] \ No newline at end of file diff --git a/iris_noniid_1.json b/iris_noniid_1.json index 8174670..46a029a 100644 --- a/iris_noniid_1.json +++ b/iris_noniid_1.json @@ -1,345 +1,345 @@ [ - { - "sepal_length": 5.1, - "sepal_width": 3.5, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.9, - "sepal_width": 3, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.7, - "sepal_width": 3.2, - "petal_length": 1.3, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.6, - "sepal_width": 3.1, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3.6, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.6, - "sepal_width": 3.4, - "petal_length": 1.4, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3.4, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.4, - "sepal_width": 2.9, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.9, - "sepal_width": 3.1, - "petal_length": 1.5, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 5.4, - "sepal_width": 3.7, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.8, - "sepal_width": 3.4, - "petal_length": 1.6, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.8, - "sepal_width": 3, - "petal_length": 1.4, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 4.3, - "sepal_width": 3, - "petal_length": 1.1, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 5.8, - "sepal_width": 4, - "petal_length": 1.2, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.7, - "sepal_width": 4.4, - "petal_length": 1.5, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 5.4, - "sepal_width": 3.9, - "petal_length": 1.3, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.5, - "petal_length": 1.4, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 5.7, - "sepal_width": 3.8, - "petal_length": 1.7, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.8, - "petal_length": 1.5, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 5.4, - "sepal_width": 3.4, - "petal_length": 1.7, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.7, - "petal_length": 1.5, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 4.6, - "sepal_width": 3.6, - "petal_length": 1, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.3, - "petal_length": 1.7, - "petal_width": 0.5, - "species": "setosa" - }, - { - "sepal_length": 4.8, - "sepal_width": 3.4, - "petal_length": 1.9, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3, - "petal_length": 1.6, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3.4, - "petal_length": 1.6, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 5.2, - "sepal_width": 3.5, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.2, - "sepal_width": 3.4, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.7, - "sepal_width": 3.2, - "petal_length": 1.6, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.8, - "sepal_width": 3.1, - "petal_length": 1.6, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.4, - "sepal_width": 3.4, - "petal_length": 1.5, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 5.2, - "sepal_width": 4.1, - "petal_length": 1.5, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 5.5, - "sepal_width": 4.2, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.9, - "sepal_width": 3.1, - "petal_length": 1.5, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3.2, - "petal_length": 1.2, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.5, - "sepal_width": 3.5, - "petal_length": 1.3, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.9, - "sepal_width": 3.1, - "petal_length": 1.5, - "petal_width": 0.1, - "species": "setosa" - }, - { - "sepal_length": 4.4, - "sepal_width": 3, - "petal_length": 1.3, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.4, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3.5, - "petal_length": 1.3, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 4.5, - "sepal_width": 2.3, - "petal_length": 1.3, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 4.4, - "sepal_width": 3.2, - "petal_length": 1.3, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3.5, - "petal_length": 1.6, - "petal_width": 0.6, - "species": "setosa" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.8, - "petal_length": 1.9, - "petal_width": 0.4, - "species": "setosa" - }, - { - "sepal_length": 4.8, - "sepal_width": 3, - "petal_length": 1.4, - "petal_width": 0.3, - "species": "setosa" - }, - { - "sepal_length": 5.1, - "sepal_width": 3.8, - "petal_length": 1.6, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 4.6, - "sepal_width": 3.2, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5.3, - "sepal_width": 3.7, - "petal_length": 1.5, - "petal_width": 0.2, - "species": "setosa" - }, - { - "sepal_length": 5, - "sepal_width": 3.3, - "petal_length": 1.4, - "petal_width": 0.2, - "species": "setosa" - } + { + "sepal_length": 0.5333, + "sepal_width": 0.5714, + "petal_length": 0.4444, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.4, + "sepal_width": 0.3333, + "petal_length": 0.4444, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.2667, + "sepal_width": 0.4286, + "petal_length": 0.3333, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.2, + "sepal_width": 0.381, + "petal_length": 0.5556, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.619, + "petal_length": 0.4444, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.2, + "sepal_width": 0.5238, + "petal_length": 0.4444, + "petal_width": 0.4, + "species": "setosa" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.5238, + "petal_length": 0.5556, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.06667, + "sepal_width": 0.2857, + "petal_length": 0.4444, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.4, + "sepal_width": 0.381, + "petal_length": 0.5556, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 0.7333, + "sepal_width": 0.6667, + "petal_length": 0.5556, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.5238, + "petal_length": 0.6667, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.3333, + "petal_length": 0.4444, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 0, + "sepal_width": 0.3333, + "petal_length": 0.1111, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 1, + "sepal_width": 0.8095, + "petal_length": 0.2222, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.9333, + "sepal_width": 1, + "petal_length": 0.5556, + "petal_width": 0.6, + "species": "setosa" + }, + { + "sepal_length": 0.7333, + "sepal_width": 0.7619, + "petal_length": 0.3333, + "petal_width": 0.6, + "species": "setosa" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.5714, + "petal_length": 0.4444, + "petal_width": 0.4, + "species": "setosa" + }, + { + "sepal_length": 0.9333, + "sepal_width": 0.7143, + "petal_length": 0.7778, + "petal_width": 0.4, + "species": "setosa" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.7143, + "petal_length": 0.5556, + "petal_width": 0.4, + "species": "setosa" + }, + { + "sepal_length": 0.7333, + "sepal_width": 0.5238, + "petal_length": 0.7778, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.6667, + "petal_length": 0.5556, + "petal_width": 0.6, + "species": "setosa" + }, + { + "sepal_length": 0.2, + "sepal_width": 0.619, + "petal_length": 0, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.4762, + "petal_length": 0.7778, + "petal_width": 0.8, + "species": "setosa" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.5238, + "petal_length": 1, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.3333, + "petal_length": 0.6667, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.5238, + "petal_length": 0.6667, + "petal_width": 0.6, + "species": "setosa" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.5714, + "petal_length": 0.5556, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.5238, + "petal_length": 0.4444, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.2667, + "sepal_width": 0.4286, + "petal_length": 0.6667, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.381, + "petal_length": 0.6667, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.7333, + "sepal_width": 0.5238, + "petal_length": 0.5556, + "petal_width": 0.6, + "species": "setosa" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.8571, + "petal_length": 0.5556, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 0.8, + "sepal_width": 0.9048, + "petal_length": 0.4444, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.4, + "sepal_width": 0.381, + "petal_length": 0.5556, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.4286, + "petal_length": 0.2222, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.8, + "sepal_width": 0.5714, + "petal_length": 0.3333, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.4, + "sepal_width": 0.381, + "petal_length": 0.5556, + "petal_width": 0, + "species": "setosa" + }, + { + "sepal_length": 0.06667, + "sepal_width": 0.3333, + "petal_length": 0.3333, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.5238, + "petal_length": 0.5556, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.5714, + "petal_length": 0.3333, + "petal_width": 0.4, + "species": "setosa" + }, + { + "sepal_length": 0.1333, + "sepal_width": 0, + "petal_length": 0.3333, + "petal_width": 0.4, + "species": "setosa" + }, + { + "sepal_length": 0.06667, + "sepal_width": 0.4286, + "petal_length": 0.3333, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.5714, + "petal_length": 0.6667, + "petal_width": 1, + "species": "setosa" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.7143, + "petal_length": 1, + "petal_width": 0.6, + "species": "setosa" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.3333, + "petal_length": 0.4444, + "petal_width": 0.4, + "species": "setosa" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.7143, + "petal_length": 0.6667, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.2, + "sepal_width": 0.4286, + "petal_length": 0.4444, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.6667, + "sepal_width": 0.6667, + "petal_length": 0.5556, + "petal_width": 0.2, + "species": "setosa" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.4762, + "petal_length": 0.4444, + "petal_width": 0.2, + "species": "setosa" + } ] \ No newline at end of file diff --git a/iris_noniid_2.json b/iris_noniid_2.json index 477f582..c90336c 100644 --- a/iris_noniid_2.json +++ b/iris_noniid_2.json @@ -1,345 +1,345 @@ [ - { - "sepal_length": 7, - "sepal_width": 3.2, - "petal_length": 4.7, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 6.4, - "sepal_width": 3.2, - "petal_length": 4.5, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 6.9, - "sepal_width": 3.1, - "petal_length": 4.9, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 5.5, - "sepal_width": 2.3, - "petal_length": 4, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 6.5, - "sepal_width": 2.8, - "petal_length": 4.6, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 5.7, - "sepal_width": 2.8, - "petal_length": 4.5, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 6.3, - "sepal_width": 3.3, - "petal_length": 4.7, - "petal_width": 1.6, - "species": "versicolor" - }, - { - "sepal_length": 4.9, - "sepal_width": 2.4, - "petal_length": 3.3, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 6.6, - "sepal_width": 2.9, - "petal_length": 4.6, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.2, - "sepal_width": 2.7, - "petal_length": 3.9, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 5, - "sepal_width": 2, - "petal_length": 3.5, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 5.9, - "sepal_width": 3, - "petal_length": 4.2, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 6, - "sepal_width": 2.2, - "petal_length": 4, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 6.1, - "sepal_width": 2.9, - "petal_length": 4.7, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 5.6, - "sepal_width": 2.9, - "petal_length": 3.6, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 6.7, - "sepal_width": 3.1, - "petal_length": 4.4, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 5.6, - "sepal_width": 3, - "petal_length": 4.5, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.7, - "petal_length": 4.1, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 6.2, - "sepal_width": 2.2, - "petal_length": 4.5, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 5.6, - "sepal_width": 2.5, - "petal_length": 3.9, - "petal_width": 1.1, - "species": "versicolor" - }, - { - "sepal_length": 5.9, - "sepal_width": 3.2, - "petal_length": 4.8, - "petal_width": 1.8, - "species": "versicolor" - }, - { - "sepal_length": 6.1, - "sepal_width": 2.8, - "petal_length": 4, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.5, - "petal_length": 4.9, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 6.1, - "sepal_width": 2.8, - "petal_length": 4.7, - "petal_width": 1.2, - "species": "versicolor" - }, - { - "sepal_length": 6.4, - "sepal_width": 2.9, - "petal_length": 4.3, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 6.6, - "sepal_width": 3, - "petal_length": 4.4, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 6.8, - "sepal_width": 2.8, - "petal_length": 4.8, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 6.7, - "sepal_width": 3, - "petal_length": 5, - "petal_width": 1.7, - "species": "versicolor" - }, - { - "sepal_length": 6, - "sepal_width": 2.9, - "petal_length": 4.5, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 5.7, - "sepal_width": 2.6, - "petal_length": 3.5, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 5.5, - "sepal_width": 2.4, - "petal_length": 3.8, - "petal_width": 1.1, - "species": "versicolor" - }, - { - "sepal_length": 5.5, - "sepal_width": 2.4, - "petal_length": 3.7, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.7, - "petal_length": 3.9, - "petal_width": 1.2, - "species": "versicolor" - }, - { - "sepal_length": 6, - "sepal_width": 2.7, - "petal_length": 5.1, - "petal_width": 1.6, - "species": "versicolor" - }, - { - "sepal_length": 5.4, - "sepal_width": 3, - "petal_length": 4.5, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 6, - "sepal_width": 3.4, - "petal_length": 4.5, - "petal_width": 1.6, - "species": "versicolor" - }, - { - "sepal_length": 6.7, - "sepal_width": 3.1, - "petal_length": 4.7, - "petal_width": 1.5, - "species": "versicolor" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.3, - "petal_length": 4.4, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.6, - "sepal_width": 3, - "petal_length": 4.1, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.5, - "sepal_width": 2.5, - "petal_length": 4, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.5, - "sepal_width": 2.6, - "petal_length": 4.4, - "petal_width": 1.2, - "species": "versicolor" - }, - { - "sepal_length": 6.1, - "sepal_width": 3, - "petal_length": 4.6, - "petal_width": 1.4, - "species": "versicolor" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.6, - "petal_length": 4, - "petal_width": 1.2, - "species": "versicolor" - }, - { - "sepal_length": 5, - "sepal_width": 2.3, - "petal_length": 3.3, - "petal_width": 1, - "species": "versicolor" - }, - { - "sepal_length": 5.6, - "sepal_width": 2.7, - "petal_length": 4.2, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.7, - "sepal_width": 3, - "petal_length": 4.2, - "petal_width": 1.2, - "species": "versicolor" - }, - { - "sepal_length": 6.2, - "sepal_width": 2.9, - "petal_length": 4.3, - "petal_width": 1.3, - "species": "versicolor" - }, - { - "sepal_length": 5.1, - "sepal_width": 2.5, - "petal_length": 3, - "petal_width": 1.1, - "species": "versicolor" - }, - { - "sepal_length": 5.7, - "sepal_width": 2.8, - "petal_length": 4.1, - "petal_width": 1.3, - "species": "versicolor" - } + { + "sepal_length": 1, + "sepal_width": 0.8571, + "petal_length": 0.8095, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.7143, + "sepal_width": 0.8571, + "petal_length": 0.7143, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.9524, + "sepal_width": 0.7857, + "petal_length": 0.9048, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.2857, + "sepal_width": 0.2143, + "petal_length": 0.4762, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.7619, + "sepal_width": 0.5714, + "petal_length": 0.7619, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.381, + "sepal_width": 0.5714, + "petal_length": 0.7143, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.6667, + "sepal_width": 0.9286, + "petal_length": 0.8095, + "petal_width": 0.75, + "species": "versicolor" + }, + { + "sepal_length": 0, + "sepal_width": 0.2857, + "petal_length": 0.1429, + "petal_width": 0, + "species": "versicolor" + }, + { + "sepal_length": 0.8095, + "sepal_width": 0.6429, + "petal_length": 0.7619, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.1429, + "sepal_width": 0.5, + "petal_length": 0.4286, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.04762, + "sepal_width": 0, + "petal_length": 0.2381, + "petal_width": 0, + "species": "versicolor" + }, + { + "sepal_length": 0.4762, + "sepal_width": 0.7143, + "petal_length": 0.5714, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.5238, + "sepal_width": 0.1429, + "petal_length": 0.4762, + "petal_width": 0, + "species": "versicolor" + }, + { + "sepal_length": 0.5714, + "sepal_width": 0.6429, + "petal_length": 0.8095, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.6429, + "petal_length": 0.2857, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.8571, + "sepal_width": 0.7857, + "petal_length": 0.6667, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.7143, + "petal_length": 0.7143, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.4286, + "sepal_width": 0.5, + "petal_length": 0.5238, + "petal_width": 0, + "species": "versicolor" + }, + { + "sepal_length": 0.619, + "sepal_width": 0.1429, + "petal_length": 0.7143, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.3571, + "petal_length": 0.4286, + "petal_width": 0.125, + "species": "versicolor" + }, + { + "sepal_length": 0.4762, + "sepal_width": 0.8571, + "petal_length": 0.8571, + "petal_width": 1, + "species": "versicolor" + }, + { + "sepal_length": 0.5714, + "sepal_width": 0.5714, + "petal_length": 0.4762, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.6667, + "sepal_width": 0.3571, + "petal_length": 0.9048, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.5714, + "sepal_width": 0.5714, + "petal_length": 0.8095, + "petal_width": 0.25, + "species": "versicolor" + }, + { + "sepal_length": 0.7143, + "sepal_width": 0.6429, + "petal_length": 0.619, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.8095, + "sepal_width": 0.7143, + "petal_length": 0.6667, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.9048, + "sepal_width": 0.5714, + "petal_length": 0.8571, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.8571, + "sepal_width": 0.7143, + "petal_length": 0.9524, + "petal_width": 0.875, + "species": "versicolor" + }, + { + "sepal_length": 0.5238, + "sepal_width": 0.6429, + "petal_length": 0.7143, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.381, + "sepal_width": 0.4286, + "petal_length": 0.2381, + "petal_width": 0, + "species": "versicolor" + }, + { + "sepal_length": 0.2857, + "sepal_width": 0.2857, + "petal_length": 0.381, + "petal_width": 0.125, + "species": "versicolor" + }, + { + "sepal_length": 0.2857, + "sepal_width": 0.2857, + "petal_length": 0.3333, + "petal_width": 0, + "species": "versicolor" + }, + { + "sepal_length": 0.4286, + "sepal_width": 0.5, + "petal_length": 0.4286, + "petal_width": 0.25, + "species": "versicolor" + }, + { + "sepal_length": 0.5238, + "sepal_width": 0.5, + "petal_length": 1, + "petal_width": 0.75, + "species": "versicolor" + }, + { + "sepal_length": 0.2381, + "sepal_width": 0.7143, + "petal_length": 0.7143, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.5238, + "sepal_width": 1, + "petal_length": 0.7143, + "petal_width": 0.75, + "species": "versicolor" + }, + { + "sepal_length": 0.8571, + "sepal_width": 0.7857, + "petal_length": 0.8095, + "petal_width": 0.625, + "species": "versicolor" + }, + { + "sepal_length": 0.6667, + "sepal_width": 0.2143, + "petal_length": 0.6667, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.7143, + "petal_length": 0.5238, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.2857, + "sepal_width": 0.3571, + "petal_length": 0.4762, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.2857, + "sepal_width": 0.4286, + "petal_length": 0.6667, + "petal_width": 0.25, + "species": "versicolor" + }, + { + "sepal_length": 0.5714, + "sepal_width": 0.7143, + "petal_length": 0.7619, + "petal_width": 0.5, + "species": "versicolor" + }, + { + "sepal_length": 0.4286, + "sepal_width": 0.4286, + "petal_length": 0.4762, + "petal_width": 0.25, + "species": "versicolor" + }, + { + "sepal_length": 0.04762, + "sepal_width": 0.2143, + "petal_length": 0.1429, + "petal_width": 0, + "species": "versicolor" + }, + { + "sepal_length": 0.3333, + "sepal_width": 0.5, + "petal_length": 0.5714, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.381, + "sepal_width": 0.7143, + "petal_length": 0.5714, + "petal_width": 0.25, + "species": "versicolor" + }, + { + "sepal_length": 0.619, + "sepal_width": 0.6429, + "petal_length": 0.619, + "petal_width": 0.375, + "species": "versicolor" + }, + { + "sepal_length": 0.09524, + "sepal_width": 0.3571, + "petal_length": 0, + "petal_width": 0.125, + "species": "versicolor" + }, + { + "sepal_length": 0.381, + "sepal_width": 0.5714, + "petal_length": 0.5238, + "petal_width": 0.375, + "species": "versicolor" + } ] \ No newline at end of file diff --git a/iris_noniid_3.json b/iris_noniid_3.json index 1287533..b8f8f36 100644 --- a/iris_noniid_3.json +++ b/iris_noniid_3.json @@ -1,345 +1,345 @@ [ - { - "sepal_length": 6.3, - "sepal_width": 3.3, - "petal_length": 6, - "petal_width": 2.5, - "species": "virginica" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.7, - "petal_length": 5.1, - "petal_width": 1.9, - "species": "virginica" - }, - { - "sepal_length": 7.1, - "sepal_width": 3, - "petal_length": 5.9, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.9, - "petal_length": 5.6, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.5, - "sepal_width": 3, - "petal_length": 5.8, - "petal_width": 2.2, - "species": "virginica" - }, - { - "sepal_length": 7.6, - "sepal_width": 3, - "petal_length": 6.6, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 4.9, - "sepal_width": 2.5, - "petal_length": 4.5, - "petal_width": 1.7, - "species": "virginica" - }, - { - "sepal_length": 7.3, - "sepal_width": 2.9, - "petal_length": 6.3, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.7, - "sepal_width": 2.5, - "petal_length": 5.8, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 7.2, - "sepal_width": 3.6, - "petal_length": 6.1, - "petal_width": 2.5, - "species": "virginica" - }, - { - "sepal_length": 6.5, - "sepal_width": 3.2, - "petal_length": 5.1, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 6.4, - "sepal_width": 2.7, - "petal_length": 5.3, - "petal_width": 1.9, - "species": "virginica" - }, - { - "sepal_length": 6.8, - "sepal_width": 3, - "petal_length": 5.5, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 5.7, - "sepal_width": 2.5, - "petal_length": 5, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.8, - "petal_length": 5.1, - "petal_width": 2.4, - "species": "virginica" - }, - { - "sepal_length": 6.4, - "sepal_width": 3.2, - "petal_length": 5.3, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 6.5, - "sepal_width": 3, - "petal_length": 5.5, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 7.7, - "sepal_width": 3.8, - "petal_length": 6.7, - "petal_width": 2.2, - "species": "virginica" - }, - { - "sepal_length": 7.7, - "sepal_width": 2.6, - "petal_length": 6.9, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 6, - "sepal_width": 2.2, - "petal_length": 5, - "petal_width": 1.5, - "species": "virginica" - }, - { - "sepal_length": 6.9, - "sepal_width": 3.2, - "petal_length": 5.7, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 5.6, - "sepal_width": 2.8, - "petal_length": 4.9, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 7.7, - "sepal_width": 2.8, - "petal_length": 6.7, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.7, - "petal_length": 4.9, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.7, - "sepal_width": 3.3, - "petal_length": 5.7, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 7.2, - "sepal_width": 3.2, - "petal_length": 6, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.2, - "sepal_width": 2.8, - "petal_length": 4.8, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.1, - "sepal_width": 3, - "petal_length": 4.9, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.4, - "sepal_width": 2.8, - "petal_length": 5.6, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 7.2, - "sepal_width": 3, - "petal_length": 5.8, - "petal_width": 1.6, - "species": "virginica" - }, - { - "sepal_length": 7.4, - "sepal_width": 2.8, - "petal_length": 6.1, - "petal_width": 1.9, - "species": "virginica" - }, - { - "sepal_length": 7.9, - "sepal_width": 3.8, - "petal_length": 6.4, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 6.4, - "sepal_width": 2.8, - "petal_length": 5.6, - "petal_width": 2.2, - "species": "virginica" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.8, - "petal_length": 5.1, - "petal_width": 1.5, - "species": "virginica" - }, - { - "sepal_length": 6.1, - "sepal_width": 2.6, - "petal_length": 5.6, - "petal_width": 1.4, - "species": "virginica" - }, - { - "sepal_length": 7.7, - "sepal_width": 3, - "petal_length": 6.1, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 6.3, - "sepal_width": 3.4, - "petal_length": 5.6, - "petal_width": 2.4, - "species": "virginica" - }, - { - "sepal_length": 6.4, - "sepal_width": 3.1, - "petal_length": 5.5, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6, - "sepal_width": 3, - "petal_length": 4.8, - "petal_width": 1.8, - "species": "virginica" - }, - { - "sepal_length": 6.9, - "sepal_width": 3.1, - "petal_length": 5.4, - "petal_width": 2.1, - "species": "virginica" - }, - { - "sepal_length": 6.7, - "sepal_width": 3.1, - "petal_length": 5.6, - "petal_width": 2.4, - "species": "virginica" - }, - { - "sepal_length": 6.9, - "sepal_width": 3.1, - "petal_length": 5.1, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 5.8, - "sepal_width": 2.7, - "petal_length": 5.1, - "petal_width": 1.9, - "species": "virginica" - }, - { - "sepal_length": 6.8, - "sepal_width": 3.2, - "petal_length": 5.9, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 6.7, - "sepal_width": 3.3, - "petal_length": 5.7, - "petal_width": 2.5, - "species": "virginica" - }, - { - "sepal_length": 6.7, - "sepal_width": 3, - "petal_length": 5.2, - "petal_width": 2.3, - "species": "virginica" - }, - { - "sepal_length": 6.3, - "sepal_width": 2.5, - "petal_length": 5, - "petal_width": 1.9, - "species": "virginica" - }, - { - "sepal_length": 6.5, - "sepal_width": 3, - "petal_length": 5.2, - "petal_width": 2, - "species": "virginica" - }, - { - "sepal_length": 6.2, - "sepal_width": 3.4, - "petal_length": 5.4, - "petal_width": 2.3, - "species": "virginica" - } + { + "sepal_length": 0.4667, + "sepal_width": 0.6875, + "petal_length": 0.625, + "petal_width": 1, + "species": "virginica" + }, + { + "sepal_length": 0.3, + "sepal_width": 0.3125, + "petal_length": 0.25, + "petal_width": 0.4545, + "species": "virginica" + }, + { + "sepal_length": 0.7333, + "sepal_width": 0.5, + "petal_length": 0.5833, + "petal_width": 0.6364, + "species": "virginica" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.4375, + "petal_length": 0.4583, + "petal_width": 0.3636, + "species": "virginica" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.5, + "petal_length": 0.5417, + "petal_width": 0.7273, + "species": "virginica" + }, + { + "sepal_length": 0.9, + "sepal_width": 0.5, + "petal_length": 0.875, + "petal_width": 0.6364, + "species": "virginica" + }, + { + "sepal_length": 0, + "sepal_width": 0.1875, + "petal_length": 0, + "petal_width": 0.2727, + "species": "virginica" + }, + { + "sepal_length": 0.8, + "sepal_width": 0.4375, + "petal_length": 0.75, + "petal_width": 0.3636, + "species": "virginica" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.1875, + "petal_length": 0.5417, + "petal_width": 0.3636, + "species": "virginica" + }, + { + "sepal_length": 0.7667, + "sepal_width": 0.875, + "petal_length": 0.6667, + "petal_width": 1, + "species": "virginica" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.625, + "petal_length": 0.25, + "petal_width": 0.5455, + "species": "virginica" + }, + { + "sepal_length": 0.5, + "sepal_width": 0.3125, + "petal_length": 0.3333, + "petal_width": 0.4545, + "species": "virginica" + }, + { + "sepal_length": 0.6333, + "sepal_width": 0.5, + "petal_length": 0.4167, + "petal_width": 0.6364, + "species": "virginica" + }, + { + "sepal_length": 0.2667, + "sepal_width": 0.1875, + "petal_length": 0.2083, + "petal_width": 0.5455, + "species": "virginica" + }, + { + "sepal_length": 0.3, + "sepal_width": 0.375, + "petal_length": 0.25, + "petal_width": 0.9091, + "species": "virginica" + }, + { + "sepal_length": 0.5, + "sepal_width": 0.625, + "petal_length": 0.3333, + "petal_width": 0.8182, + "species": "virginica" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.5, + "petal_length": 0.4167, + "petal_width": 0.3636, + "species": "virginica" + }, + { + "sepal_length": 0.9333, + "sepal_width": 1, + "petal_length": 0.9167, + "petal_width": 0.7273, + "species": "virginica" + }, + { + "sepal_length": 0.9333, + "sepal_width": 0.25, + "petal_length": 1, + "petal_width": 0.8182, + "species": "virginica" + }, + { + "sepal_length": 0.3667, + "sepal_width": 0, + "petal_length": 0.2083, + "petal_width": 0.09091, + "species": "virginica" + }, + { + "sepal_length": 0.6667, + "sepal_width": 0.625, + "petal_length": 0.5, + "petal_width": 0.8182, + "species": "virginica" + }, + { + "sepal_length": 0.2333, + "sepal_width": 0.375, + "petal_length": 0.1667, + "petal_width": 0.5455, + "species": "virginica" + }, + { + "sepal_length": 0.9333, + "sepal_width": 0.375, + "petal_length": 0.9167, + "petal_width": 0.5455, + "species": "virginica" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.3125, + "petal_length": 0.1667, + "petal_width": 0.3636, + "species": "virginica" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.6875, + "petal_length": 0.5, + "petal_width": 0.6364, + "species": "virginica" + }, + { + "sepal_length": 0.7667, + "sepal_width": 0.625, + "petal_length": 0.625, + "petal_width": 0.3636, + "species": "virginica" + }, + { + "sepal_length": 0.4333, + "sepal_width": 0.375, + "petal_length": 0.125, + "petal_width": 0.3636, + "species": "virginica" + }, + { + "sepal_length": 0.4, + "sepal_width": 0.5, + "petal_length": 0.1667, + "petal_width": 0.3636, + "species": "virginica" + }, + { + "sepal_length": 0.5, + "sepal_width": 0.375, + "petal_length": 0.4583, + "petal_width": 0.6364, + "species": "virginica" + }, + { + "sepal_length": 0.7667, + "sepal_width": 0.5, + "petal_length": 0.5417, + "petal_width": 0.1818, + "species": "virginica" + }, + { + "sepal_length": 0.8333, + "sepal_width": 0.375, + "petal_length": 0.6667, + "petal_width": 0.4545, + "species": "virginica" + }, + { + "sepal_length": 1, + "sepal_width": 1, + "petal_length": 0.7917, + "petal_width": 0.5455, + "species": "virginica" + }, + { + "sepal_length": 0.5, + "sepal_width": 0.375, + "petal_length": 0.4583, + "petal_width": 0.7273, + "species": "virginica" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.375, + "petal_length": 0.25, + "petal_width": 0.09091, + "species": "virginica" + }, + { + "sepal_length": 0.4, + "sepal_width": 0.25, + "petal_length": 0.4583, + "petal_width": 0, + "species": "virginica" + }, + { + "sepal_length": 0.9333, + "sepal_width": 0.5, + "petal_length": 0.6667, + "petal_width": 0.8182, + "species": "virginica" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.75, + "petal_length": 0.4583, + "petal_width": 0.9091, + "species": "virginica" + }, + { + "sepal_length": 0.5, + "sepal_width": 0.5625, + "petal_length": 0.4167, + "petal_width": 0.3636, + "species": "virginica" + }, + { + "sepal_length": 0.3667, + "sepal_width": 0.5, + "petal_length": 0.125, + "petal_width": 0.3636, + "species": "virginica" + }, + { + "sepal_length": 0.6667, + "sepal_width": 0.5625, + "petal_length": 0.375, + "petal_width": 0.6364, + "species": "virginica" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.5625, + "petal_length": 0.4583, + "petal_width": 0.9091, + "species": "virginica" + }, + { + "sepal_length": 0.6667, + "sepal_width": 0.5625, + "petal_length": 0.25, + "petal_width": 0.8182, + "species": "virginica" + }, + { + "sepal_length": 0.3, + "sepal_width": 0.3125, + "petal_length": 0.25, + "petal_width": 0.4545, + "species": "virginica" + }, + { + "sepal_length": 0.6333, + "sepal_width": 0.625, + "petal_length": 0.5833, + "petal_width": 0.8182, + "species": "virginica" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.6875, + "petal_length": 0.5, + "petal_width": 1, + "species": "virginica" + }, + { + "sepal_length": 0.6, + "sepal_width": 0.5, + "petal_length": 0.2917, + "petal_width": 0.8182, + "species": "virginica" + }, + { + "sepal_length": 0.4667, + "sepal_width": 0.1875, + "petal_length": 0.2083, + "petal_width": 0.4545, + "species": "virginica" + }, + { + "sepal_length": 0.5333, + "sepal_width": 0.5, + "petal_length": 0.2917, + "petal_width": 0.5455, + "species": "virginica" + }, + { + "sepal_length": 0.4333, + "sepal_width": 0.75, + "petal_length": 0.375, + "petal_width": 0.8182, + "species": "virginica" + } ] \ No newline at end of file diff --git a/peerJsWrapper.js b/peerJsWrapper.js new file mode 100644 index 0000000..da8e7ef --- /dev/null +++ b/peerJsWrapper.js @@ -0,0 +1,71 @@ +// import peerjs from "https://cdn.skypack.dev/peerjs" + +const p2p = (() => { + const setupDeps = () => { + const peerJSScript = document.createElement("script") + peerJSScript.src = "https://unpkg.com/peerjs@1.5.1/dist/peerjs.min.js" + const peerJSGroupsScript = document.createElement("script") + peerJSGroupsScript.src = "https://cdn.jsdelivr.net/gh/ElizabethHudnott/peerjs-groups@master/dist/peerjs-groups.js" + + document.body.appendChild(peerJSScript) + document.body.appendChild(peerJSGroupsScript) + } + setupDeps() + return {} +})() + +p2p.initializeFederation = (initOptions) => new Promise(resolve => { + const { + clientId=crypto.randomUUID(), + federationId, + signalingServerHost="0.peerjs.com", + signalingServerPort=443, + newUserCallback, + newMessageCallback + } = initOptions + p2p.group = new PeerGroup((err)=> { + console.error("Error initializing federation:", err) + }, { + host: signalingServerHost, + port: signalingServerPort, + debug: 2 + }) + + p2p.group.addEventListener('connected', (e) => { + console.log(`Connected to session ${e.sessionID}`); + p2p.clientId = clientId + p2p.federationId = e.sessionID + }) + + p2p.group.addEventListener('joined', (e) => { + console.log(`Joined session ${e.sessionID}`); + p2p.clientId = clientId + p2p.federationId = e.sessionID + resolve({ clientId: p2p.clientId, federationId: p2p.federationId }) + }) + + p2p.group.addEventListener('userpresent', (e) => { + console.log(`New User`, e.userID) + newUserCallback(e) + }) + + p2p.group.addEventListener('message', (e) => { + // console.log(`Message received:`, e.message) + newMessageCallback(e) + }) + + // p2p.group.addEventListener('joined', (e) => console.log(`Joined session ${e.sessionId}`)) + console.log(`Attempting connection to federation ${federationId} from ${clientId}`) + p2p.group.connect(federationId, clientId) + +}) + +p2p.sendDataToPeer = (peerId, data) => { + p2p.group.sendPrivate(peerId, data) +} + +p2p.broadcastData = (data) => { + p2p.group.send(data) +} + +export default p2p \ No newline at end of file diff --git a/webFed.js b/webFed.js index 5545d6a..e286603 100644 --- a/webFed.js +++ b/webFed.js @@ -1,5 +1,5 @@ -import gunDB from './gunWrapper.js' - +// import gunDB from './gunWrapper.js' +import p2p from './peerJsWrapper.js' const configuration = { 'iceServers': [{ 'urls': 'stun:stun.l.google.com:19302' }] } const GUN_TLN_KEY = "federatedTest" @@ -78,11 +78,6 @@ webFed.getAllFederationIds = () => { return webFed.allFederationIds } -// webFed.getAllFederationIds = async () => { -// console.warn("Multiple federations not yet supported") -// return await gunDB.getObject([GUN_TLN_KEY, GUN_KEYS_SPEC.fedDetails]) -// } - webFed.getFederation = async (federationId) => { console.warn("Multiple federations not yet supported") return await gunDB.getObject([GUN_TLN_KEY, GUN_KEYS_SPEC.fedDetails, federationId]) @@ -242,7 +237,7 @@ webFed.connectToPeer = async (federationId=webFed.currentFederation.id, selfClie gunDB.trackObject([GUN_TLN_KEY, federationId, peerId, "answers", selfClientId], (answer) => { // const answer = await mnist.getFromObjectProps(peerId, `answer/${localStorage.clientId}`) - if (answer && !webFed.currentFederation.clients[peerId].connectionState !== "receiving_answer") { + if (answer && webFed.currentFederation.clients[peerId].connectionState !== "receiving_answer") { webFed.currentFederation.clients[peerId].connectionState = "receiving_answer" webFed.currentFederation.clients[peerId].dataChannel.onopen = (e) => { webFed.currentFederation.clients[peerId].connectionState = "connected" @@ -327,48 +322,58 @@ webFed.broadcastToAllPeers = async (federationId, clientId, data) => { return peersCommunicated } +webFed.sendDataToPeer = (peerId, data) => { + p2p.sendDataToPeer(peerId, data) +} + +webFed.broadcastData = (data) => { + p2p.broadcastData(data) +} + webFed.listenForMessageFromPeer = (peerId, cb, once=true) => webFed.currentFederation.clients[peerId].dataChannel.addEventListener("message", cb, { once }) -webFed.initialize = async (gunServerPath, clientId, currentFederationId) => { - if (!gunServerPath) { - console.error("Path to Gun server required") - } - if (!clientId) { - clientId = crypto.randomUUID() - } - gunDB.initialize(gunServerPath) +webFed.initializeFederation = async (initOptions) => { + const { clientId: connectedClientId, federationId: connectedFederationId } = await p2p.initializeFederation(initOptions) + webFed.group = p2p.group + // if (!gunServerPath) { + // console.error("Path to Gun server required") + // } + // if (!clientId) { + // clientId = crypto.randomUUID() + // } + // gunDB.initialize(gunServerPath) - const refreshFederationsFromDB = async () => { - const allFederations = await gunDB.getObject([GUN_TLN_KEY, GUN_KEYS_SPEC['fedDetails']]) + // const refreshFederationsFromDB = async () => { + // const allFederations = await gunDB.getObject([GUN_TLN_KEY, GUN_KEYS_SPEC['fedDetails']]) - if (allFederations && !Object.keys(allFederations).every((fed, ind) => fed === webFed.allFederationIds[ind])) { - webFed.allFederationIds = Object.keys(allFederations) + // if (allFederations && !Object.keys(allFederations).every((fed, ind) => fed === webFed.allFederationIds[ind])) { + // webFed.allFederationIds = Object.keys(allFederations) - if (currentFederationId) { - await webFed.updateAllClientsList(currentFederationId, clientId) - if (webFed.currentFederation.clients?.[clientId] && webFed.currentFederation.id !== currentFederationId) { + // if (currentFederationId) { + // await webFed.updateAllClientsList(currentFederationId, clientId) + // if (webFed.currentFederation.clients?.[clientId] && webFed.currentFederation.id !== currentFederationId) { - if (webFed.currentFederation.id) { - gunDB.untrackObject([GUN_TLN_KEY, webFed.currentFederation.id, GUN_KEYS_SPEC['users']]) - } + // if (webFed.currentFederation.id) { + // gunDB.untrackObject([GUN_TLN_KEY, webFed.currentFederation.id, GUN_KEYS_SPEC['users']]) + // } - webFed.currentFederation.id = currentFederationId + // webFed.currentFederation.id = currentFederationId - } else { - currentFederationId = undefined - } - } - document.dispatchEvent(new CustomEvent('federationsChanged')) - } - } + // } else { + // currentFederationId = undefined + // } + // } + // document.dispatchEvent(new CustomEvent('federationsChanged')) + // } + // } - await refreshFederationsFromDB() - gunDB.trackObject([GUN_TLN_KEY, GUN_KEYS_SPEC['fedDetails']], refreshFederationsFromDB) + // await refreshFederationsFromDB() + // gunDB.trackObject([GUN_TLN_KEY, GUN_KEYS_SPEC['fedDetails']], refreshFederationsFromDB) - return { clientId, currentFederationId } + return { connectedClientId, connectedFederationId } } export default webFed \ No newline at end of file