{"id":13736230,"url":"https://github.com/mariusbrataas/flowpoints_ml","last_synced_at":"2025-05-08T12:32:25.997Z","repository":{"id":34080547,"uuid":"165913527","full_name":"mariusbrataas/flowpoints_ml","owner":"mariusbrataas","description":"An intuitive approach to creating deep learning models","archived":false,"fork":false,"pushed_at":"2023-01-04T09:41:26.000Z","size":11083,"stargazers_count":370,"open_issues_count":20,"forks_count":61,"subscribers_count":24,"default_branch":"master","last_synced_at":"2024-11-15T04:32:01.491Z","etag":null,"topics":["deep-learning","flowchart","js","machine-learning","python","pytorch","react","tensorflow"],"latest_commit_sha":null,"homepage":"https://mariusbrataas.github.io/flowpoints_ml","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mariusbrataas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-15T19:49:35.000Z","updated_at":"2024-06-30T14:58:09.000Z","dependencies_parsed_at":"2023-01-15T04:30:41.003Z","dependency_job_id":null,"html_url":"https://github.com/mariusbrataas/flowpoints_ml","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariusbrataas%2Fflowpoints_ml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariusbrataas%2Fflowpoints_ml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariusbrataas%2Fflowpoints_ml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariusbrataas%2Fflowpoints_ml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mariusbrataas","download_url":"https://codeload.github.com/mariusbrataas/flowpoints_ml/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253068892,"owners_count":21848884,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deep-learning","flowchart","js","machine-learning","python","pytorch","react","tensorflow"],"created_at":"2024-08-03T03:01:17.866Z","updated_at":"2025-05-08T12:32:25.249Z","avatar_url":"https://github.com/mariusbrataas.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"![](public/imagine_deep_learning.png)\n\n\n# Flowpoints\n\nCreate deep learning models without all the typing and dimension mismatches! Follow [this link](https://mariusbrataas.github.io/flowpoints_ml) to play around with this on your own :)\n\n[This npm package](https://www.npmjs.com/package/flowpoints) is a spin-off of this project, which this project is now utilizing.\n\nHere's a [colab](https://colab.research.google.com/drive/15zC7TMheMzwllEShgN45Y7JLXtS-syMn) using this PyTorch [model.](https://mariusbrataas.github.io/flowpoints_ml/?p=9fehu18ra4ty)\n\n![](public/cifar10net.png)\n\nAnd here's similar [colab](https://colab.research.google.com/drive/1rkJItfTb8fB0mWQRmL-shsiReFLJ57vR) using this TensorFlow [model](https://mariusbrataas.github.io/flowpoints_ml/?p=KlHpdLzP3SDx)\n\n![](public/tf_cifar10.png)\n\n## Overview\nThis project is used to host a website in which users can quickly create drafts for deep learning models and have the equivalent plug-and-play code output immediately.\n\nThe code output to the user is written in python and utilizes [PyTorch](https://pytorch.org/) and [TensorFlow](https://www.tensorflow.org/alpha).\n\n- [Overview](#overview)\n- [User guide](#user-guide)\n\t- [How I use these diagrams](#how-i-use-these-diagrams)\n\t- [Building new models](#building-new-models)\n\t\t- [Adding flowpoints](#adding-flowpoints)\n\t\t- [Adding and removing connections](#adding-and-removing-connections)\n\t\t- [Changing the parameters of your model](#changing-the-parameters-of-your-model)\n\t- [Changing appearance](#changing-appearance)\n\t- [Extracting the model code](#extracting-the-model-code)\n\t- [Sharing your model](#sharing-your-model)\n- [Example output](#example-output)\n- [Contributing to this project](#contributing-to-this-project)\n- [Dependencies](#dependencies)\n- [License](#license)\n\n## User guide\n\nOr maybe just play around with it yourself?\n\n### How I use these diagrams\n1. Start by adding an input block and edit it's parameters to get the correct number of dimensions and features.\n2. Add a bunch of blocks, organize them a little bit and add all connections.\n3. Start from the top and move downstream, editing block parameters to ensure their outputs match the desired dimensions.\n4. Add names to all blocks (if needed).\n5. Quickly review code.\n6. Copy code, plug it into existing pipeline, lean back, and watch the magic.\n\n\n### Building new models\n\n#### Adding flowpoints\nIn the lower left corner of the [website](https://mariusbrataas.github.io/flowpoints_ml/) there are five buttons. These can be used to add new flowpoints (blocks) to the model, copy code to clipboard, generate a link to the current model, hide/show sidebar, and display a dialog to help users get started.\n\nTo build a new model start by clicking the blue + button. This will add a Flowpoint.\n\nClick the + button a few more times to add more points. These will automatically connect if you don't click anywhere else on the screen.\n\n\n#### Adding and removing connections\nTo connect one Flowpoint to another, start by clicking on the first point. Then hold shift while clicking the second point. The points should now be connected. To disconnect the two simply repeat this process.\n\n#### Changing the parameters of your model\nEach flowpoint represents one operation in your model. To edit a Flowpoint's function and parameters, click the \"Flowpoint\"-tab in the sidebar (if the sidebar is not showing click the menu-button in the bottom left of your screen).\n\nThe top field in the sidebar allow you to change the operation of the selected flowpoint. Simply click it to display a list of all available operations.\n\nIn the second field you can enter a name for your flowpoint. If you don't type a name your flowpoint will be named p_1, p_2, p_3, etc.. in the output python code.\n\nIn the parameters area all the available parameters of the flowpoint can be viewed, and most of them can be changed. The \"in_features\" field will automatically be set to a valid size.\n\n\n### Changing appearance\nIn the \"Settings\"-tab you can change the appearance of your diagrams. Theme and variant changes the look of your flowpoints, while the switches change the background and what information your flowpoints should display.\n\n\n### Extracting the model code\nIf you click the \"Code\"-tab you'll see all the code for your model. The easiest way to copy this code to your clipboard is by clicking the \"copy\"-button, just beneath the + button.\n\n\n### Sharing your model\nTo share your model, simply click the \"link\"-button. This will generate a link which will get copied to your clipboard.\n\n## Example output\nThe following code was generated for [this model.](https://mariusbrataas.github.io/flowpoints_ml?p=A4xw9sjChG9B)\n\n![](public/sample_output_pic.png)\n\n\nIn TensorFlow:\n\n```python\n'''\nCreated using flowpoints.io\n\nLink to model:\nhttps://mariusbrataas.github.io/flowpoints_ml/?p=A4xw9sjChG9B\n\nLICENSE:\nhttps://github.com/mariusbrataas/flowpoints_ml/blob/master/LICENSE\n'''\n\n\n# Importing TensorFlow tools\nimport tensorflow as tf\n\n\n# Model\ndef NeuralNet(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']):\n\n    # Initializing inputs\n    in_data = tf.keras.layers.Input((1,10,), name='in_data')\n\n    # Initializing layers\n    fc1 = tf.keras.layers.Dense(\n        name               = \"fc1\",\n        units              = 96,\n        use_bias           = True,\n        kernel_initializer = \"glorot_uniform\",\n        bias_initializer   = \"zeros\",\n    )(in_data)\n    do1 = tf.keras.layers.Dropout(\n        name = \"do1\",\n        rate = 1,\n    )(fc1)\n    act1 = tf.keras.layers.ReLU(\n        name           = \"act1\",\n        negative_slope = 0,\n        threshold      = 0,\n    )(do1)\n    fc2 = tf.keras.layers.Dense(\n        name               = \"fc2\",\n        units              = 96,\n        use_bias           = True,\n        kernel_initializer = \"glorot_uniform\",\n        bias_initializer   = \"zeros\",\n    )(act1)\n    do2 = tf.keras.layers.Dropout(\n        name = \"do2\",\n        rate = 1,\n    )(fc2)\n    act2 = tf.keras.layers.ReLU(\n        name           = \"act2\",\n        negative_slope = 0,\n        threshold      = 0,\n    )(do2)\n    fc3 = tf.keras.layers.Dense(\n        name               = \"fc3\",\n        units              = 5,\n        use_bias           = True,\n        kernel_initializer = \"glorot_uniform\",\n        bias_initializer   = \"zeros\",\n    )(act2)\n    do3 = tf.keras.layers.Dropout(\n        name = \"do3\",\n        rate = 1,\n    )(fc3)\n    act3 = tf.keras.layers.Softmax(\n        name = \"act3\",\n        axis = -1,\n    )(do3)\n\n    # Creating model\n    _model = tf.keras.models.Model(\n        inputs  = [in_data],\n        outputs = [act3],\n        name    = 'flowpoints.io/?p=A4xw9sjChG9B'\n    )\n\n    # Compiling model\n    _model.compile(\n        optimizer = optimizer,\n        loss      = loss,\n        metrics   = metrics\n    )\n\n    # Returning model\n    return _model\n```\n\n\nOr similarly, in PyTorch:\n\n```python\n'''\nCreated using flowpoints.io\n\nLink to model:\nhttps://mariusbrataas.github.io/flowpoints_ml/?p=A4xw9sjChG9B\n\nLICENSE:\nhttps://github.com/mariusbrataas/flowpoints_ml/blob/master/LICENSE\n'''\n\n\n# Importing PyTorch tools\nimport torch\nfrom torch import nn, optim, cuda\n\n\n# Importing other libraries\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport time\n\n\n# Model\nclass NeuralNet(nn.Module):\n\n\n    def __init__(self, optimizer=optim.SGD, alpha=0.01, criterion=nn.CrossEntropyLoss(), use_cuda=None):\n\n        # Basics\n        super(NeuralNet, self).__init__()\n\n        # Settings\n        self.optim_type = optimizer\n        self.optimizer  = None\n        self.alpha      = alpha\n        self.criterion  = criterion\n\n        # Use CUDA?\n        self.use_cuda = use_cuda if (use_cuda != None and cuda.is_available()) else cuda.is_available()\n\n        # Current loss and loss history\n        self.train_loss      = 0\n        self.valid_loss      = 0\n        self.train_loss_hist = []\n        self.valid_loss_hist = []\n\n        # Initializing all layers\n        self.fc1 = nn.Linear(\n            in_features  = 10,\n            out_features = 96,\n            bias         = False,\n        )\n        self.do1 = nn.Dropout(\n            p       = 0.25,\n            inplace = False,\n        )\n        self.act1 = nn.ReLU(\n            inplace = False,\n        )\n        self.fc2 = nn.Linear(\n            in_features  = 96,\n            out_features = 96,\n            bias         = False,\n        )\n        self.do2 = nn.Dropout(\n            p       = 0.25,\n            inplace = False,\n        )\n        self.act2 = nn.ReLU(\n            inplace = False,\n        )\n        self.fc3 = nn.Linear(\n            in_features  = 96,\n            out_features = 5,\n            bias         = False,\n        )\n        self.do3 = nn.Dropout(\n            p       = 0.25,\n            inplace = False,\n        )\n        self.act3 = nn.Softmax()\n\n        # Running startup routines\n        self.startup_routines()\n\n\n    def startup_routines(self):\n        self.optimizer = self.optim_type(self.parameters(), lr=self.alpha)\n        if self.use_cuda:\n            self.cuda()\n\n\n    def predict(self, in_data):\n\n        # Switching off autograd\n        with torch.no_grad():\n\n            # Use CUDA?\n            if self.use_cuda:\n                in_data = in_data.cuda()\n\n            # Running inference\n            return self.forward(in_data)\n\n\n    def forward(self, in_data):\n        in_data = self.fc1(in_data)     # Linear\n        in_data = self.do1(in_data)     # Dropout\n        in_data = self.act1(in_data)    # ReLU\n        in_data = self.fc2(in_data)     # Linear\n        in_data = self.do2(in_data)     # Dropout\n        in_data = self.act2(in_data)    # ReLU\n        in_data = self.fc3(in_data)     # Linear\n        in_data = self.do3(in_data)     # Dropout\n        self.state = self.act3(in_data) # Softmax\n        return self.state\n\n\n    def fit_step(self, training_loader):\n\n        # Preparations for fit step\n        self.train_loss = 0 # Resetting training loss\n        self.train()        # Switching to autograd\n\n        # Looping through data\n        for in_data, act3_target in training_loader:\n\n            # Use CUDA?\n            if self.use_cuda:\n                in_data = in_data.cuda()\n                act3_target = act3_target.cuda()\n\n            # Forward pass\n            self.forward(in_data)\n\n            # Calculating loss\n            loss = self.criterion(self.state, act3_target)\n            self.train_loss += loss.item() # Adding to epoch loss\n\n            # Backward pass and optimization\n            loss.backward()                      # Backward pass\n            self.optimizer.step()                # Optimizing weights\n            self.optimizer.zero_grad()           # Clearing gradients\n\n        # Adding loss to history\n        self.train_loss_hist.append(self.train_loss / len(training_loader))\n\n\n    def validation_step(self, validation_loader):\n\n        # Preparations for validation step\n        self.valid_loss = 0 # Resetting validation loss\n\n        # Switching off autograd\n        with torch.no_grad():\n\n            # Looping through data\n            for in_data, act3_target in validation_loader:\n\n                # Use CUDA?\n                if self.use_cuda:\n                    in_data = in_data.cuda()\n                    act3_target = act3_target.cuda()\n\n                # Forward pass\n                self.forward(in_data)\n\n                # Calculating loss\n                loss = self.criterion(self.state, act3_target)\n                self.valid_loss += loss.item() # Adding to epoch loss\n\n            # Adding loss to history\n            self.valid_loss_hist.append(self.valid_loss / len(validation_loader))\n\n\n    def fit(self, training_loader, validation_loader=None, epochs=10, show_progress=True, save_best=False):\n\n        # Helpers\n        best_validation = 1e5\n\n        # Possibly prepping progress message\n        if show_progress:\n            epoch_l = max(len(str(epochs)), 2)\n            print('Training model...')\n            print('%sEpoch   Training loss   Validation loss   Duration   Time remaining' % ''.rjust(2 * epoch_l - 4, ' '))\n            t = time.time()\n\n        # Looping through epochs\n        for epoch in range(epochs):\n            self.fit_step(training_loader) # Optimizing\n            if validation_loader != None:  # Perform validation?\n                self.validation_step(validation_loader) # Calculating validation loss\n\n            # Possibly printing progress\n            if show_progress:\n                eta_s = (time.time() - t) * (epochs - epoch)\n                eta = '%sm %ss' % (round(eta_s / 60), 60 - round(eta_s % 60))\n                print('%s/%s' % (str(epoch + 1).rjust(epoch_l, ' '), str(epochs).ljust(epoch_l, ' ')),\n                    '| %s' % str(round(self.train_loss_hist[-1], 8)).ljust(13, ' '),\n                    '| %s' % str(round(self.valid_loss_hist[-1], 8)).ljust(15, ' '),\n                    '| %ss' % str(round(time.time() - t, 3)).rjust(7, ' '),\n                    '| %s' % eta.ljust(14, ' '))\n                t = time.time()\n\n            # Possibly saving model\n            if save_best:\n                if self.valid_loss_hist[-1] \u003c best_validation:\n                    self.save('best_validation')\n                    best_validation = self.valid_loss_hist[-1]\n\n        # Switching to eval\n        self.eval()\n\n\n    def plot_hist(self):\n\n        # Adding plots\n        plt.plot(self.train_loss_hist, color='blue', label='Training loss')\n        plt.plot(self.valid_loss_hist, color='springgreen', label='Validation loss')\n\n        # Axis labels\n        plt.xlabel('Epoch')\n        plt.ylabel('Loss')\n        plt.legend(loc='upper right')\n\n        # Displaying plot\n        plt.show()\n\n\n    def save(self, name='model.pth'):\n        if not '.pth' in name: name += '.pth'\n        torch.save({\n            'fc1': self.fc1,\n            'do1': self.do1,\n            'act1': self.act1,\n            'fc2': self.fc2,\n            'do2': self.do2,\n            'act2': self.act2,\n            'fc3': self.fc3,\n            'do3': self.do3,\n            'act3': self.act3,\n            'train_loss':      self.train_loss,\n            'valid_loss':      self.valid_loss,\n            'train_loss_hist': self.train_loss_hist,\n            'valid_loss_hist': self.valid_loss_hist,\n            'optim_type':      self.optim_type,\n            'alpha':           self.alpha,\n            'criterion':       self.criterion,\n            'use_cuda':        self.use_cuda\n        }, name)\n\n\n    @staticmethod\n    def load(name='model.pth'):\n        if not '.pth' in name: name += '.pth'\n        checkpoint = torch.load(name)\n        model = NeuralNet(\n            optimizer = checkpoint['optim_type'],\n            alpha     = checkpoint['alpha'],\n            criterion = checkpoint['criterion'],\n            use_cuda  = checkpoint['use_cuda']\n        )\n        model.fc1 = checkpoint['fc1']\n        model.do1 = checkpoint['do1']\n        model.act1 = checkpoint['act1']\n        model.fc2 = checkpoint['fc2']\n        model.do2 = checkpoint['do2']\n        model.act2 = checkpoint['act2']\n        model.fc3 = checkpoint['fc3']\n        model.do3 = checkpoint['do3']\n        model.act3 = checkpoint['act3']\n        model.train_loss      = checkpoint['train_loss']\n        model.valid_loss      = checkpoint['valid_loss']\n        model.train_loss_hist = checkpoint['train_loss_hist']\n        model.valid_loss_hist = checkpoint['valid_loss_hist']\n        model.startup_routines()\n        return model\n```\n\n## Contributing to this project\nI'd love some help maintaining this project or adding more and better functionality!\n\nThe code is maintained in the master branch, while the website is hosted from the gh-pages branch.\n\nAs of right now the code is not properly commented, but I'll do that pretty soon.\n\nSome ideas I'd like to implement:\n\n- __Pre-processing.__ Maybe something utilizing the [torch data loader](https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader), with support for multiple workers and use of [transforms](https://pytorch.org/docs/stable/torchvision/transforms.html).\n- __Better support for mobile.__ Not so great on my phone, kinda ok on my iPad.\n- __Python load model by link??__ Maybe not possible, but would be awesome!\n\nAlso, this project is structured in a somewhat okay manner, but I'm not entirely happy with it, and might change it soon.\n\n```\nflowpoints_ml\n├── .gitattributes\n├── .gitignore\n├── LICENSE\n├── package-lock.json\n├── package.json\n├── README.md\n│\n├── public\n│   ├── favicon.ico\n│   ├── index.html\n│   └── manifest.json\n│\n└── src\n    ├── App.css\n    ├── App.js\n    ├── Cryptographer.js\n    ├── DataBaseHandler.js\n    ├── HelpDialog.js\n    ├── Helpers.js\n    ├── index.css\n    ├── index.js\n    ├── LibraryParser.js\n    ├── MainButtons.js\n    ├── MainLibrary.js\n    ├── NotificationContainer.js\n    ├── PasswordDialog.js\n    ├── serviceWorker.js\n    │\n    ├── libraries\n    │   ├── base_library.js\n    │   ├── pytorch_autoparams.js\n    │   ├── pytorch_library.js\n    │   └── tensorflow_library.js\n    │\n    ├── parser\n    │   ├── FlowOrder.js\n    │   ├── Parser.js\n    │   ├── PyTorchParser.js\n    │   └── TensorflowParser.js\n    │\n    └── sidebar\n        ├── CodeTab.js\n        ├── FlowpointTab.js\n        ├── FrontHelpers.css\n        ├── FrontHelpers.js\n        ├── MiscTab.js\n        ├── Sidebar.css\n        ├── Sidebar.js\n        ├── SidebarContents.css\n        ├── SidebarContents.js\n        └── SidebarHead.js\n```\n\n\n## Dependencies\nCurrent dependencies in this project are:\n\n- [Flowpoints](https://github.com/mariusbrataas/flowpoints)\n- [Material UI](https://material-ui.com/)\n- [React JS](https://reactjs.org/)\n- [react-copy-to-clipboard](https://github.com/nkbt/react-copy-to-clipboard)\n- [Axios](https://github.com/axios/axios)\n- [react-icons](https://github.com/react-icons/react-icons)\n- [react-syntax-highlighter](https://github.com/conorhastings/react-syntax-highlighter)\n\n\n\n## License\n[MIT](https://github.com/mariusbrataas/flowpoints_ml/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmariusbrataas%2Fflowpoints_ml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmariusbrataas%2Fflowpoints_ml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmariusbrataas%2Fflowpoints_ml/lists"}