diff --git a/README.md b/README.md index 83cf1930..76e9517f 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,18 @@ -# Deep playground +# 🌟 Deep Playground ++: a Project of MLS Sup'Com 🚀 -Deep playground is an interactive visualization of neural networks, written in -TypeScript using d3.js. We use GitHub issues for tracking new requests and bugs. -Your feedback is highly appreciated! +Deep Playground Plus is an enhanced version of Deep playground, an interactive visualization of neural networks written in TypeScript using d3.js. We've added a new exciting feature that allows users to change the input of the neural network based on their preferences! 🎨🧠 -**If you'd like to contribute, be sure to review the [contribution guidelines](CONTRIBUTING.md).** +We use GitHub issues to track new requests and bugs. Your feedback is highly appreciated! If you'd like to contribute, be sure to review the contribution guidelines. 📝👀 -## Development +## Development 🛠️ -To run the visualization locally, run: -- `npm i` to install dependencies -- `npm run build` to compile the app and place it in the `dist/` directory -- `npm run serve` to serve from the `dist/` directory and open a page on your browser. +To run the visualization locally, follow these steps: -For a fast edit-refresh cycle when developing run `npm run serve-watch`. -This will start an http server and automatically re-compile the TypeScript, -HTML and CSS files whenever they change. +1. Run `npm i` to install dependencies. +2. Run `npm run build` to compile the app and place it in the `dist/` directory. +3. Run `npm run serve` to serve from the `dist/` directory and open a page on your browser. +4. For a fast edit-refresh cycle when developing, run `npm run serve-watch`. This will start an HTTP server and automatically recompile the TypeScript, HTML, and CSS files whenever they change. 🔄 -## For owners -To push to production: `git subtree push --prefix dist origin gh-pages`. +## For Owners 💼 -This is not an official Google product. +To push to production, use the command: `git subtree push --prefix dist origin gh-pages`. 🚀 diff --git a/index.html b/index.html index 3f6060d6..4b22c54d 100644 --- a/index.html +++ b/index.html @@ -150,6 +150,7 @@

Which dataset do you want to use?

+
diff --git a/package-lock.json b/package-lock.json index 80d87e6e..222fb718 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,10 @@ "name": "deep-playground-prototype", "version": "2016.3.10", "dependencies": { + "@types/mathjs": "^0.0.28", "d3": "^3.5.16", "material-design-lite": "^1.3.0", + "mathjs": "^3.4.1", "seedrandom": "^2.4.3" }, "devDependencies": { @@ -26,11 +28,16 @@ } }, "node_modules/@types/d3": { - "version": "3.5.45", - "resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.45.tgz", - "integrity": "sha512-wLICfMtjDEoAJie1MF6OuksAzOapRXgJy+l5HQVpyC1yMAlvHz2QKrrasUHru8xD6cbgQNGeO+CeyjOlKtly2A==", + "version": "3.5.53", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.53.tgz", + "integrity": "sha512-8yKQA9cAS6+wGsJpBysmnhlaaxlN42Qizqkw+h2nILSlS+MAG2z4JdO6p+PJrJ+ACvimkmLJL281h157e52psQ==", "dev": true }, + "node_modules/@types/mathjs": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@types/mathjs/-/mathjs-0.0.28.tgz", + "integrity": "sha512-sp/bMoSHUNTC49ugLSclQXTMQOOSvN23rns/ArGbq/8RHxY3i+qFdidhiTbcyCbCfks3dCBXWMAztyR8ULnKrw==" + }, "node_modules/@zeit/schemas": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", @@ -732,6 +739,14 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/complex.js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.0.4.tgz", + "integrity": "sha512-Syl95HpxUTS0QjwNxencZsKukgh1zdS9uXeXX2Us0pHaqBR6kiZZi0AkZ9VpZFwHJyVIUVzI4EumjWdXP3fy6w==", + "engines": { + "node": "*" + } + }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -962,7 +977,7 @@ "node_modules/d3": { "version": "3.5.17", "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", - "integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g=" + "integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg==" }, "node_modules/dash-ast": { "version": "1.0.0", @@ -988,6 +1003,11 @@ "node": ">=0.10.0" } }, + "node_modules/decimal.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-9.0.1.tgz", + "integrity": "sha512-2h0iKbJwnImBk4TGk7CG1xadoA0g3LDPlQhQzbZ221zvG0p2YVUedbKIPsOZXKZGx6YmZMJKYOalpCMxSdDqTQ==" + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -1171,6 +1191,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/escape-latex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" + }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1262,6 +1287,14 @@ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, + "node_modules/fraction.js": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.0.4.tgz", + "integrity": "sha512-aK/oGatyYLTtXRHjfEsytX5fieeR5H4s8sLorzcT12taFS+dbMZejnvm9gRa8mZAPwci24ucjq9epDyaq5u8Iw==", + "engines": { + "node": "*" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1851,6 +1884,11 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "node_modules/javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1961,6 +1999,27 @@ "node": ">=0.12.0" } }, + "node_modules/mathjs": { + "version": "3.20.2", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-3.20.2.tgz", + "integrity": "sha512-3f6/+uf1cUtIz1rYFz775wekl/UEDSQ3mU6xdxW7qzpvvhc2v28i3UtLsGTRB+u8OqDWoSX6Dz8gehaGFs6tCA==", + "dependencies": { + "complex.js": "2.0.4", + "decimal.js": "9.0.1", + "escape-latex": "^1.0.0", + "fraction.js": "4.0.4", + "javascript-natural-sort": "0.7.1", + "seed-random": "2.2.0", + "tiny-emitter": "2.0.2", + "typed-function": "0.10.7" + }, + "bin": { + "mathjs": "bin/cli.js" + }, + "engines": { + "node": ">= 0.1" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -2644,6 +2703,11 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "node_modules/seed-random": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz", + "integrity": "sha512-34EQV6AAHQGhoc0tn/96a9Fsi6v2xdqe/dMUwljGRaFOzR3EgRmECvD0O8vi8X+/uQ50LGHfkNu/Eue5TPKZkQ==" + }, "node_modules/seedrandom": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.4.tgz", @@ -3129,6 +3193,11 @@ "node": ">=0.6.0" } }, + "node_modules/tiny-emitter": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz", + "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3189,6 +3258,14 @@ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", "dev": true }, + "node_modules/typed-function": { + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-0.10.7.tgz", + "integrity": "sha512-3mlZ5AwRMbLvUKkc8a1TI4RUJUS2H27pmD5q0lHRObgsoWzhDAX01yg82kwSP1FUw922/4Y9ZliIEh0qJZcz+g==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -3520,11 +3597,16 @@ }, "dependencies": { "@types/d3": { - "version": "3.5.45", - "resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.45.tgz", - "integrity": "sha512-wLICfMtjDEoAJie1MF6OuksAzOapRXgJy+l5HQVpyC1yMAlvHz2QKrrasUHru8xD6cbgQNGeO+CeyjOlKtly2A==", + "version": "3.5.53", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.53.tgz", + "integrity": "sha512-8yKQA9cAS6+wGsJpBysmnhlaaxlN42Qizqkw+h2nILSlS+MAG2z4JdO6p+PJrJ+ACvimkmLJL281h157e52psQ==", "dev": true }, + "@types/mathjs": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@types/mathjs/-/mathjs-0.0.28.tgz", + "integrity": "sha512-sp/bMoSHUNTC49ugLSclQXTMQOOSvN23rns/ArGbq/8RHxY3i+qFdidhiTbcyCbCfks3dCBXWMAztyR8ULnKrw==" + }, "@zeit/schemas": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", @@ -4120,6 +4202,11 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "complex.js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.0.4.tgz", + "integrity": "sha512-Syl95HpxUTS0QjwNxencZsKukgh1zdS9uXeXX2Us0pHaqBR6kiZZi0AkZ9VpZFwHJyVIUVzI4EumjWdXP3fy6w==" + }, "compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -4324,7 +4411,7 @@ "d3": { "version": "3.5.17", "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", - "integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g=" + "integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg==" }, "dash-ast": { "version": "1.0.0", @@ -4347,6 +4434,11 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decimal.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-9.0.1.tgz", + "integrity": "sha512-2h0iKbJwnImBk4TGk7CG1xadoA0g3LDPlQhQzbZ221zvG0p2YVUedbKIPsOZXKZGx6YmZMJKYOalpCMxSdDqTQ==" + }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -4503,6 +4595,11 @@ "is-symbol": "^1.0.2" } }, + "escape-latex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -4582,6 +4679,11 @@ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, + "fraction.js": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.0.4.tgz", + "integrity": "sha512-aK/oGatyYLTtXRHjfEsytX5fieeR5H4s8sLorzcT12taFS+dbMZejnvm9gRa8mZAPwci24ucjq9epDyaq5u8Iw==" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5005,6 +5107,11 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -5091,6 +5198,21 @@ "resolved": "https://registry.npmjs.org/material-design-lite/-/material-design-lite-1.3.0.tgz", "integrity": "sha1-0ATOP+6Zoe63Sni4oyUTSl8RcdM=" }, + "mathjs": { + "version": "3.20.2", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-3.20.2.tgz", + "integrity": "sha512-3f6/+uf1cUtIz1rYFz775wekl/UEDSQ3mU6xdxW7qzpvvhc2v28i3UtLsGTRB+u8OqDWoSX6Dz8gehaGFs6tCA==", + "requires": { + "complex.js": "2.0.4", + "decimal.js": "9.0.1", + "escape-latex": "^1.0.0", + "fraction.js": "4.0.4", + "javascript-natural-sort": "0.7.1", + "seed-random": "2.2.0", + "tiny-emitter": "2.0.2", + "typed-function": "0.10.7" + } + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -5659,6 +5781,11 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "seed-random": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz", + "integrity": "sha512-34EQV6AAHQGhoc0tn/96a9Fsi6v2xdqe/dMUwljGRaFOzR3EgRmECvD0O8vi8X+/uQ50LGHfkNu/Eue5TPKZkQ==" + }, "seedrandom": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.4.tgz", @@ -6055,6 +6182,11 @@ "process": "~0.11.0" } }, + "tiny-emitter": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz", + "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==" + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6102,6 +6234,11 @@ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", "dev": true }, + "typed-function": { + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-0.10.7.tgz", + "integrity": "sha512-3mlZ5AwRMbLvUKkc8a1TI4RUJUS2H27pmD5q0lHRObgsoWzhDAX01yg82kwSP1FUw922/4Y9ZliIEh0qJZcz+g==" + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", diff --git a/package.json b/package.json index c127686c..070268d5 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,10 @@ "watchify": "^4.0.0" }, "dependencies": { + "@types/mathjs": "^0.0.28", "d3": "^3.5.16", "material-design-lite": "^1.3.0", + "mathjs": "^3.4.1", "seedrandom": "^2.4.3" } } diff --git a/src/playground.ts b/src/playground.ts index aeac0f9c..9660f1a7 100644 --- a/src/playground.ts +++ b/src/playground.ts @@ -28,8 +28,9 @@ import { import {Example2D, shuffle} from "./dataset"; import {AppendingLineChart} from "./linechart"; import * as d3 from 'd3'; +import {compile} from 'mathjs'; -let mainWidth; +let mainWidth // More scrolling d3.select(".more button").on("click", function() { @@ -57,19 +58,21 @@ enum HoverType { BIAS, WEIGHT } +type FN = ((x: number, y: number) => number) + interface InputFeature { - f: (x: number, y: number) => number; + f: FN | any; label?: string; } let INPUTS: {[name: string]: InputFeature} = { - "x": {f: (x, y) => x, label: "X_1"}, - "y": {f: (x, y) => y, label: "X_2"}, - "xSquared": {f: (x, y) => x * x, label: "X_1^2"}, - "ySquared": {f: (x, y) => y * y, label: "X_2^2"}, - "xTimesY": {f: (x, y) => x * y, label: "X_1X_2"}, - "sinX": {f: (x, y) => Math.sin(x), label: "sin(X_1)"}, - "sinY": {f: (x, y) => Math.sin(y), label: "sin(X_2)"}, + "x": {f: (x, y) => x, label: "X"}, + "y": {f: (x, y) => y, label: "Y"}, + "xSquared": {f: (x, y) => x * x, label: "X^2"}, + "ySquared": {f: (x, y) => y * y, label: "Y^2"}, + "xTimesY": {f: (x, y) => x * y, label: "X.Y"}, + "sinX": {f: (x, y) => Math.sin(x), label: "sin(X)"}, + "sinY": {f: (x, y) => Math.sin(y), label: "sin(Y)"}, }; let HIDABLE_CONTROLS = [ @@ -830,7 +833,11 @@ function updateDecisionBoundary(network: nn.Node[][], firstTime: boolean) { if (firstTime) { // Go through all predefined inputs. for (let nodeId in INPUTS) { - boundary[nodeId][i][j] = INPUTS[nodeId].f(x, y); + if (INPUTS[nodeId].f instanceof Function) { + boundary[nodeId][i][j] = INPUTS[nodeId].f(x, y); + } else { + boundary[nodeId][i][j] = INPUTS[nodeId].f.eval({x:x,y:y}); + } } } } @@ -900,7 +907,11 @@ function constructInput(x: number, y: number): number[] { let input: number[] = []; for (let inputName in INPUTS) { if (state[inputName]) { - input.push(INPUTS[inputName].f(x, y)); + if (INPUTS[inputName].f instanceof Function) { + input.push(INPUTS[inputName].f(x, y)); + } else { + input.push(INPUTS[inputName].f.eval({x:x,y:y})) + } } } return input; @@ -1119,3 +1130,23 @@ makeGUI(); generateData(true); reset(true); hideControls(); + + +function makeid(length) { + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const charactersLength = characters.length; + let counter = 0; + while (counter < length) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + counter += 1; + } + return result; +} + +document.querySelector("#addinput").addEventListener("click", () => { + const form = prompt("enter formula:") + if(!form) return; + INPUTS[makeid(8)] = {f: compile(form), label: form} + reset() +}) diff --git a/tsconfig.json b/tsconfig.json index ae8b1cec..1b386d05 100755 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,9 @@ "compilerOptions": { "module": "commonjs", "removeComments": true, - "preserveConstEnums": true + "preserveConstEnums": true, + "noUnusedLocals": false, + "lib": ["es2015", "dom"] }, "exclude": [ "node_modules"