{"id":314,"date":"2020-08-05T14:50:17","date_gmt":"2020-08-05T22:50:17","guid":{"rendered":"https:\/\/live-cometml.pantheonsite.io\/?p=314"},"modified":"2025-05-09T09:54:12","modified_gmt":"2025-05-09T09:54:12","slug":"introducing-panels-custom-visualizations-for-machine-learning","status":"publish","type":"post","link":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/","title":{"rendered":"Introducing Panels: Custom Visualizations for Machine Learning"},"content":{"rendered":"\n<p>In the last three years since Comet was founded, our users and customers trained millions of models on anything from self-driving cars to speech recognition, and from Covid-19 protein prediction to satellite image object detection. Based on your requests we added more and more visualization capabilities including&nbsp;<a href=\"https:\/\/www.comet.com\/docs\/user-interface\/#project-visualizations\">chart builders<\/a>,&nbsp;<a href=\"https:\/\/www.comet.com\/docs\/python-sdk\/Comet-Confusion-Matrix\/\">confusion matrices<\/a>,&nbsp;<a href=\"https:\/\/www.comet.com\/docs\/user-interface\/#audio-tab\">audio players<\/a>&nbsp;and many more. But as the complexity of the use cases, requirements and customization grew, we realized that we needed a more scalable way to grow Comet\u2019s functionality and provide users the ability to&nbsp;<b>build anything they want!<\/b><\/p>\n\n\n\n<p>Today, we are excited to announce&nbsp;<i>Comet Panels,&nbsp;<\/i>which has been under development and testing for the past year. Starting today, you can tap into the ecosystems of JS\/HTML\/CSS and create new widgets with custom styles and behaviors, or add new visualizations and charting types.&nbsp;<b>Unlimited possibilities!<\/b><\/p>\n\n\n\n<p>The key principles in designing Comet Panels were the following:<br>\n1.&nbsp;<b><strong>Dynamic<\/strong>&nbsp;\u2013&nbsp;<\/b>Panels should be dynamic and update on new experiments and results when they arrive.&nbsp;<i>There\u2019s nothing worse than a stale and misleading visualization.<\/i><br>\n2.&nbsp;<b><strong>Flexible<\/strong>&nbsp; \u2013&nbsp;<\/b>Users should be able to build and customize&nbsp;<i>anything<\/i>&nbsp;they want without the limitations of a GUI or a specific dependency<br>\n3.&nbsp;<b><strong>Reusable<\/strong>&nbsp;<\/b>\u2013 teammates and community members should be able to share and reuse each other\u2019s panels.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><b>The Comet Panel Gallery<\/b><\/h1>\n\n\n\n<p><b><br>\n<\/b>The heart of Panels lies in the&nbsp;<a href=\"https:\/\/www.comet.com\/demo\/gallery\/view\/new#select-panel?gallery-tab=Public\">Comet Panel Gallery<\/a>. Check it out to see what others have built and shared with the community.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"616\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/Screen-Shot-2020-08-03-at-8.01.18-PM-1024x616-1.png\" alt=\"\" class=\"wp-image-316\" srcset=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/Screen-Shot-2020-08-03-at-8.01.18-PM-1024x616-1.png 1024w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/Screen-Shot-2020-08-03-at-8.01.18-PM-1024x616-1-300x180.png 300w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/Screen-Shot-2020-08-03-at-8.01.18-PM-1024x616-1-768x462.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\"><b>Build your own Panel<\/b><\/h1>\n\n\n\n<p>Comet experiments already store your hyper-parameters, metrics, model definition, trained models, dataset samples and much more. Panels build on top of that data to visualize and process anything you\u2019d like.<\/p>\n\n\n\n<p>You can create a new panel by going to the&nbsp;<a href=\"https:\/\/www.comet.com\/demo\/gallery\/view\/new#select-panel?gallery-tab=Public\">Panels Gallery<\/a>&nbsp;and clicking on \u201cCreate New\u201d on the top right corner. You should see a similar code editor:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"470\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panels-full-view-1024x470-1.png\" alt=\"\" class=\"wp-image-321\" srcset=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panels-full-view-1024x470-1.png 1024w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panels-full-view-1024x470-1-300x138.png 300w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panels-full-view-1024x470-1-768x353.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The code editor is divided into three main panes. On the left we have a full code editor with code completion, syntax highlighting etc. On the right we have a live preview of our panel. On the bottom right we see our Console pane which shows errors and exceptions. You\u2019ll also notice the tabs on the top that allow you to switch from code to description, HTML, CSS, resources and query.<\/p>\n\n\n\n<p>To make a snappy user experience in the browser, we will write our Panel in JavaScript.<\/p>\n\n\n\n<p>You can create a new Panel from the Panels Gallery as described in&nbsp;<a href=\"https:\/\/www.comet.com\/docs\/user-interface\/panels\/\">Comet\u2019s User Interface<\/a>. You\u2019ll need to go to the Panels Gallery on the Project View and click on \u201cCreate New.\u201d You should then see a screen similar to the following:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1541\" height=\"708\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panels-full-view.png\" alt=\"\" class=\"wp-image-322\" srcset=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panels-full-view.png 1541w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panels-full-view-300x138.png 300w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panels-full-view-1024x470.png 1024w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panels-full-view-768x353.png 768w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panels-full-view-1536x706.png 1536w\" sizes=\"auto, (max-width: 1541px) 100vw, 1541px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-image\"><\/div>\n\n\n\n<p>Once you are on this screen, you are now ready to write the code (there is some default code provided on the creation of a new Panel, but you can simply select it all with&nbsp;<code>CONTROL+A<\/code>&nbsp;and press&nbsp;<code>Delete<\/code>). Your new Panel code only needs these two things:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>A JavaScript class named&nbsp;<code>MyPanel<\/code><\/li>\n\n\n\n<li>A&nbsp;<code>draw(experimentKeys, projectId){}<\/code>&nbsp;method that takes an array of experiment keys and project ID<\/li>\n<\/ol>\n\n\n\n<p>That\u2019s it! We have also defined a&nbsp;<code>Comet.Panel<\/code>&nbsp;to extend that contains additional functionality. You use it like this:<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>class MyPanel extends Comet.Panel {\n  draw(experimentKeys, projectId) {\n    \/\/ Your code here\n  }\n}<\/code><\/pre>\n\n\n\n<p>In the tradition of introductory programming exercises, let\u2019s explore a \u201cHello world\u201d Panel. We take the basic template from above, and add our instructions to print \u201cHello, world!\u201d in our panel. We will use&nbsp;<code>this.print()<\/code>&nbsp;to display the message.<\/p>\n\n\n\n<p>We\u2019ll also use the HTML&nbsp;<code>&lt;h1&gt;<\/code>&nbsp;tag to make our message large and bold.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>class MyPanel extends Comet.Panel {\n  draw(experimentKeys, projectId) {\n    this.print(\"&lt;h1&gt;Hello, world!&lt;\/h1&gt;\");\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>If you write (or copy and paste) the above code into the Panel Code section, and click on the green arrow button (or press&nbsp;<code>CONTROL+ENTER<\/code>) you should see the following:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1207\" height=\"655\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-world.png\" alt=\"\" class=\"wp-image-329\" srcset=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-world.png 1207w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-world-300x163.png 300w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-world-1024x556.png 1024w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-world-768x417.png 768w\" sizes=\"auto, (max-width: 1207px) 100vw, 1207px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><\/figure>\n\n\n\n<p>Now, you can save your Panel by clicking on the save button (or pressing&nbsp;<code>CONTROL+S<\/code>), which will prompt you for a name:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"228\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/save-prompt-300x228.png\" alt=\"\" class=\"wp-image-328\" srcset=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/save-prompt-300x228.png 300w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/save-prompt.png 377w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><\/figure>\n\n\n\n<p>Name your Panel something like \u201cHello World\u201d, and click \u201cSave\u201d. The first time you save a new Panel, you\u2019ll be asked to capture a thumbnail of your Panel. You can either select a portion of the screen, or upload your own image:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"282\" height=\"300\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/capture-thumbnail-282x300.png\" alt=\"\" class=\"wp-image-327\" srcset=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/capture-thumbnail-282x300.png 282w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/capture-thumbnail.png 417w\" sizes=\"auto, (max-width: 282px) 100vw, 282px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>If you press \u201cDone\u201d then you will go back to the Panels Gallery. Now you can add a \u201cHello World\u201d Panel to your project by clicking the \u201c+ Add\u201d button in the Panels Gallery. A window will appear giving you the chance to set some options (discussed in the next section). For now, just press \u201cDone\u201d.<\/p>\n\n\n\n<p>&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1210\" height=\"733\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/adding-panel-instance.png\" alt=\"\" class=\"wp-image-326\" srcset=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/adding-panel-instance.png 1210w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/adding-panel-instance-300x182.png 300w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/adding-panel-instance-1024x620.png 1024w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/adding-panel-instance-768x465.png 768w\" sizes=\"auto, (max-width: 1210px) 100vw, 1210px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><\/figure>\n\n\n\n<p>Your Project View should now include your \u201cHello World\u201d Panel:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"580\" height=\"467\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-world-panel.png\" alt=\"\" class=\"wp-image-325\" srcset=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-world-panel.png 580w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-world-panel-300x242.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>&nbsp;<\/p>\n\n\n\n<p>In the next section, we\u2019ll explore the idea of an \u201coption.\u201d<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"options\">Options<\/h2>\n\n\n\n<p>It would be very painful if you had to edit code to have slight variations of a Panel. For example, imagine that you wanted to plot the metric \u201cacc\u201d in one chart, but the metric \u201closs\u201d in another. To allow the Panels to be more abstract, we have provided the Panels with the idea of&nbsp;<em>options<\/em>.<\/p>\n\n\n\n<p>To provide these options that can be changed when creating a Panel and without changing code, you only need to define a JavaScript object in the&nbsp;<code>MyPanel<\/code>&nbsp;instance named&nbsp;<code>options<\/code>. Typically, you will define your options in the setup method, as shown below. These are default values that can be overridden by the user when creating a new instance of the Panel.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>class MyPanel extends Comet.Panel {\n  setup() {\n    \/\/ Your setup code here\n    this.options = {\n      \/\/ Your default options here\n    }\n  }\n\n  draw(experimentKeys, projectId) {\n    \/\/ Your code here\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>As a concrete example, let\u2019s change the \u201cHello World\u201d Panel to include a setup() method with the option \u201cmessage\u201d:<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>class MyPanel extends Comet.Panel {\n  setup() {\n    this.options = {\n      message: \"Hello, world!\"\n    }\n  }\n\n  draw(experimentKeys, projectId) {\n    this.print(`&lt;h1&gt;${this.options.message}&lt;\/h1&gt;`);\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>If you try this Panel, you\u2019ll see exactly the same result as before. However, there is a big difference: you can now add two instances of the \u201cHello World\u201d Panel to your Project View, and make each one say something different by merely changing the options when you add the Panel to your Project:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1211\" height=\"732\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-mars.png\" alt=\"\" class=\"wp-image-324\" srcset=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-mars.png 1211w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-mars-300x181.png 300w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-mars-1024x619.png 1024w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/hello-mars-768x464.png 768w\" sizes=\"auto, (max-width: 1211px) 100vw, 1211px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Specifically, the steps are:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create the Hellow World Panel, using the option \u201cmessage\u201d<\/li>\n\n\n\n<li>Add one of these Panels to your Project<\/li>\n\n\n\n<li>Add another of these Panels to your Project, this time changing the message to something else<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-cometpanel-class\">The Comet.Panel Class<\/h2>\n\n\n\n<p>When you extend from&nbsp;<code>Comet.Panel<\/code>&nbsp;you get additional functions, including:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>this.print(object, newLine)<\/code>&nbsp;\u2013 print text in main Panel area; newLine == true means follow with newline<\/li>\n\n\n\n<li><code>this.getOption(\"name\", default)<\/code>&nbsp;\u2013 get a name from the options (return&nbsp;<code>null<\/code>&nbsp;if not defined); return default if not found<\/li>\n\n\n\n<li><code>this.clear(divId)<\/code>&nbsp;\u2013 clear all of the&nbsp;<code>print()<\/code>ed items in the panel area, or give it the ID of a div to clear<\/li>\n\n\n\n<li><code>this.drawOne(experimentKey)<\/code>&nbsp;\u2013 conventional method for single experiment drawing code<\/li>\n\n\n\n<li><code>this.select(label, options, parentId)<\/code>&nbsp;\u2013 create a HTML select widget for selecting widgets; calls&nbsp;<code>this.drawOne(selectedItem)<\/code><\/li>\n\n\n\n<li><code>this.getColor(experimentKey)<\/code>&nbsp;\u2013 get the color associated with this experiment<\/li>\n<\/ul>\n\n\n\n<p>Your class must be named&nbsp;<code>MyPanel<\/code>&nbsp;to use these features. You can, of course, do your own JavaScript processing. In addition, you can also define the following methods to gain additional functionality:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>update(experimentKeys, projectId) {}<\/code>&nbsp;\u2013 method to define code that will not clear the panel, but can be used to update existing UI components (see below)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"the-paneldraw-method\">The Panel.draw() Method<\/h3>\n\n\n\n<p>A Panel\u2019s&nbsp;<code>draw()<\/code>&nbsp;method receives two things:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>an array of experiment keys<\/li>\n\n\n\n<li>a Project ID<\/li>\n<\/ul>\n\n\n\n<p>The array of experiment keys is one of three things, in this order:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>if a Panel filter is set, the experiments keys are all those matching the Panel filter<\/li>\n\n\n\n<li>if a Project View filter is set, the experiment keys are all those matching the Project Filter<\/li>\n\n\n\n<li>if no filter is set, the experiment keys are those&nbsp;<em>visible<\/em>&nbsp;in the Project experiment table<\/li>\n<\/ul>\n\n\n\n<p>Note that there are two ways that an experiment is visible in the experiment table on the Project View:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the experiment must be on the current table page (the table shows a limited number of experiments per page)<\/li>\n\n\n\n<li>the experiment must not be hidden (the \u201ceye\u201d icon must not be grayed out)<\/li>\n<\/ul>\n\n\n\n<p>If you want to always process all experiments (or programmatically select a subset from all of them), you can instead use the Project ID to get all of the experiments in a Project, like this:<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>draw(experimentKeys, projectId) {\n  this.api.experimentsByProjectId(projectId).then(experimentKeys =&gt; {\n    \/\/ process all Project experimentKeys here\n  });\n}\n<\/code><\/pre>\n\n\n\n<p>If you are processing the array of experiment keys (<code>experimentKeys<\/code>) then be aware that these can change and a refresh will occur on any of these events:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>you change the experiment table page limit (number of experiments per page)<\/li>\n\n\n\n<li>you change, add, or remove the experiment filter<\/li>\n\n\n\n<li>you change any experiment\u2019s hide\/show status (either by clicking the \u201ceye\u201d icon in the experiment table, or by selecting experiments to hide via another Panel)<\/li>\n<\/ul>\n\n\n\n<p>If you are instead processing the experiments via the&nbsp;<code>projectId<\/code>&nbsp;key, then you will probably want to flip the toggle on the Panel instance editor to make it \u201cstatic\u201d:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"158\" height=\"110\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/panel-static.png\" alt=\"\" class=\"wp-image-330\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"the-panelupdate-method\">The Panel.update() Method<\/h3>\n\n\n\n<p>Here is a template using the&nbsp;<code>Panel.update()<\/code>&nbsp;method. We restructure the code so that the&nbsp;<code>Panel.draw()<\/code>&nbsp;creates a Plotly plot instance, and a place to cache a set of experiment keys.&nbsp;<code>Panel.update()<\/code>&nbsp;is called whenever new data is received, but we make it so that the update method only processes experiments that it hasn\u2019t seen before.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>class MyPanel extends Comet.Panel {\n  ...\n\n  draw(experimentKeys, projectId) {\n    Plotly.newPlot(this.id, &#91;], this.options.layout);\n    this.cached_experiments = &#91;];\n    this.draw(experimentkeys, projectId);\n  }\n\n  update(experimentKeys, projectId) {\n    experimentKeys = experimentKeys.filter(key =&gt; ! this.cached_experiments.includes(key));\n    this.api\n      .experimentMetricsForChart(\n        experimentKeys,\n        this.options.metrics,\n        this.options.parameters\n      )\n      .then(results =&gt; {\n        Object.keys(results).forEach(experimentKey =&gt; {\n          ...\n          this.cached_experiments.push(experimentKey);\n          Plotly.addTraces(this.id, data);\n        });\n      });\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>Note that if you don\u2019t have a&nbsp;<code>Panel.update()<\/code>&nbsp;method that the entire Panel HTML area will be cleared and&nbsp;<code>Panel.draw()<\/code>&nbsp;will be called each time new data is available. You can use the&nbsp;<code>Panel.update()<\/code>&nbsp;method to do more intelligent processing for a snappier user interface experience.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"javascript-api\">JavaScript API<\/h3>\n\n\n\n<p>The Comet.Panel class also creates an interface to&nbsp;<a href=\"https:\/\/www.comet.com\/docs\/javascript-sdk\/api\/\">Comet\u2019s JavaScript SDK<\/a>&nbsp;through&nbsp;<code>this.api<\/code>. This has all of the methods needed to access your data, plus some that are especially useful in creating a Panel. There are a few methods of special interest here:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>this.api.store(name, data)<\/code>&nbsp;\u2013 save to this Panel instance\u2019s persistent memory<\/li>\n\n\n\n<li><code>this.api.getFromStore(name)<\/code>&nbsp;\u2013 get an item from this Panels\u2019 persistent memory<\/li>\n<\/ul>\n\n\n\n<p>For more details on the complete library, please see&nbsp;<a href=\"https:\/\/www.comet.com\/docs\/javascript-sdk\/api\/\">Comet\u2019s JavaScript SDK<\/a>.<\/p>\n\n\n\n<p>In addition, there are a variety of Comet open source JavaScript libraries that you can use (and build upon) via the&nbsp;<a href=\"https:\/\/www.comet.com\/docs\/user-interface\/panels\/#resources-tab\">Resources Tab<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"single-experiment-workaround\">Single Experiment Workaround<\/h3>\n\n\n\n<p><code>this.select()<\/code>&nbsp;is designed to allow you to select a single experiment from the Project, and works as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>class MyPanel extends Comet.Panel {\n  \/\/ Define your draw method like this\n  draw(experimentKeys, projectId) {\n    if (experimentKeys.length &gt; 0) {\n      this.select(\"Select an experiment: \", experimentKeys);\n      this.drawOne(experimentKeys&#91;0]);\n    }\n  }\n\n  drawOne(experimentKey) {\n    \/\/ Insert code here to do something with one experiment key\n  }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"debugging\">Debugging<\/h3>\n\n\n\n<p>Note that&nbsp;<code>console.log()<\/code>&nbsp;displays the items in the&nbsp;<code>Console<\/code>&nbsp;portion of the user interface.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"full-example\">Full Example<\/h3>\n\n\n\n<p>Here is a basic line chart example using&nbsp;<a href=\"https:\/\/plot.ly\/javascript\/\">Plotly<\/a>:<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>class MyPanel extends Comet.Panel {\n  setup() {\n    \/\/ Your setup code here\n    this.options = {\n      \/\/ Your default options here\n      metrics: &#91;\"loss\", \"acc\"],\n      parameters: &#91;],\n      layout: {\n        showlegend: true,\n        legend: {\n          orientation: 'h',\n        },\n        title: {\n          text: \"My Panel Title\",\n        }\n      },\n    };\n  }\n\n  draw(experimentKeys, projectId) {\n    \/\/ Your code here\n    Plotly.newPlot(this.id, &#91;], this.options.layout);\n    this.api.experimentMetricsForChart(\n      experimentKeys, this.options.metrics, this.options.parameters)\n      .then(results =&gt; {\n        Object.keys(results).forEach(experimentKey =&gt; {\n          const name = this.api.experimentName(experimentKey).then(name =&gt; {\n            results&#91;experimentKey].metrics.forEach(result =&gt; {\n              const data = {\n                y: result.values,\n                x: result.steps,\n                name: `${name} ${result.metricName}`,\n              };\n              Plotly.addTraces(this.id, data);\n            });\n          });\n        });\n      });\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>In this example, we\u2019ve defined&nbsp;<code>this.options<\/code>&nbsp;that defines a list of metrics and parameters to chart, and a layout object. We are using Plotly, so we can put anything there that Plotly can use. See&nbsp;<a href=\"https:\/\/plot.ly\/javascript\/\">Plotly<\/a>&nbsp;for more information.<\/p>\n\n\n\n<p>Any option can be overridden by the user when they instantiate the Panel on their own page. Therefore, you can easily use the same code for plotting multiple items by simply changing the options.<\/p>\n\n\n\n<p>For more details on using Comet Panels, please see&nbsp;<a href=\"https:\/\/www.comet.com\/docs\/user-interface\/panels\/\">Panels<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"javascript-tips\">JavaScript Tips<\/h2>\n\n\n\n<p>JavaScript is designed to give a performant experience on the web. If you adapt your coding style to the way of the JavaScript, you will be rewarded with a fast-loading, snappy experience. But it does take a little bit of extra work.<\/p>\n\n\n\n<p>Comet\u2019s JavaScript SDK is written using&nbsp;<code>Promises<\/code>. These are JavaScript objects that represent a promise to complete some code. The code might be finished already, or you might have to&nbsp;<code>await<\/code>&nbsp;for it to complete. You can do whatever you would like, but JavaScript has some simple syntax for running multiple functions in parallel.<\/p>\n\n\n\n<p>Let\u2019s take a look at some examples. Often, you may want to get some data, and then process it, and finally display it. Ideally, you can do this all in parallel. The example from above does exactly that. Consider that code again:<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>class MyPanel extends Comet.Panel {\n  ...\n  draw(experimentKeys, projectId) {\n    \/\/ Your code here\n    Plotly.newPlot(this.id, &#91;], this.options.layout);\n    this.api.experimentMetricsForChart(\n      experimentKeys, this.options.metrics, this.options.parameters)\n      .then(results => {\n        Object.keys(results).forEach(experimentKey => {\n          const name = this.api.experimentName(experimentKey).then(name => {\n            results&#91;experimentKey].metrics.forEach(result => {\n              const data = {\n                y: result.values,\n                x: result.steps,\n                name: `${name} ${result.metricName}`,\n              };\n              Plotly.addTraces(this.id, data);\n            });\n          });\n        });\n      });\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>Some important things to note:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Line 5 displays an empty Plotly chart, which will get added to in parallel<\/li>\n\n\n\n<li>Lines 6 and 10 represent&nbsp;<code>Promises<\/code>&nbsp;that are followed by a&nbsp;<code>.then()<\/code>&nbsp;method that says what to do after the promise is resolved<\/li>\n\n\n\n<li>Line 17 adds the result of each individual chain of processing to the chart<\/li>\n<\/ul>\n\n\n\n<p>This is the ideal method of JavaScript processing for the web. However, you can\u2019t always work in such a style. For example, if you wanted to find the average of all of a particular metric, then you must collect all of those metrics first. Here is an example of how to do serial processing:<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>class MyPanel extends Comet.Panel {\n  ...\n  async draw(experimentKeys, projectId) {\n    const data = await this.collectData(experimentKeys);\n    this.print(`&lt;p>Average: ${avg(data)}&lt;\/p>`);\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>Things to note:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Line 3 has added the&nbsp;<code>async<\/code>&nbsp;keyword in front of the&nbsp;<code>draw()<\/code>&nbsp;method. This is necessary for any function\/method that needs to&nbsp;<code>await<\/code>&nbsp;on a result<\/li>\n\n\n\n<li>Line 4 has an&nbsp;<code>await<\/code>&nbsp;keyword in front of a method call<\/li>\n<\/ul>\n\n\n\n<p>That\u2019s it, for the structure. Let\u2019s now take a look at how&nbsp;<code>collectData()<\/code>&nbsp;could be written. Consider that you have logged an \u201cother\u201d value (not a metric or parameter) using&nbsp;<code>experiment.log_other(\"x\", value)<\/code>&nbsp;for all of the experiments in this project. Now we want to fetch all of those values, and average them.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>async collectData(experimentKeys) {\n  const values = await Promise.all(\n    experimentKeys.map(experimentKey => {\n      return this.api.experimentOther(experimentKey, \"x\");\n  })\n  return values.filter(v => typeof v == \"string\");\n);<\/code><\/pre>\n\n\n\n<p>Things to note:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Line 1, again we add&nbsp;<code>async<\/code><\/li>\n\n\n\n<li>Line 2, we perform an&nbsp;<code>await<\/code>&nbsp;on a&nbsp;<code>Promise.all(item.map())<\/code>, a very common pattern<\/li>\n\n\n\n<li>Line 6, a bit of technical detail, to filter out&nbsp;<code>NaN<\/code>&nbsp;and other bad values<\/li>\n<\/ul>\n\n\n\n<p>The last example blocks to get all of the values, before proceeding. This is different from the first example. If your code takes a while to process, you can put a&nbsp;<code>this.print(\"&lt;h2&gt;Processing...&lt;\/h2&gt;\")<\/code>&nbsp;before the collection, and&nbsp;<code>this.clear()<\/code>&nbsp;after it.<\/p>\n\n\n\n<p>For more examples, see the shared code examples in the Gallery.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"working-with-plotly\">Working with Plotly<\/h2>\n\n\n\n<p><a href=\"https:\/\/plotly.com\/javascript\/\">Plotly<\/a>&nbsp;is a free and open source JavaScript library built on&nbsp;<a href=\"https:\/\/d3js.org\/\">d3.js<\/a>&nbsp;and&nbsp;<a href=\"https:\/\/github.com\/stackgl\">stack.gl<\/a>.<\/p>\n\n\n\n<p>As shown above, for performance reasons, you typically want to create the Plot and incrementally add traces to it.<\/p>\n\n\n\n<p>Plotly has many options, such as limiting the X and Y axis using the&nbsp;<code>layout.xaxis.range<\/code>&nbsp;and&nbsp;<code>layout.yaxis.range<\/code>&nbsp;values, like this:<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>class MyClass extends Comet.Panel {\n  draw(experimentKeys, projectId) {\n    const data = ... \/\/ get some data here\n    const layout = {\n      xaxis: {range: &#91;1, 10]},\n      yaxis: {range: &#91;5, 7]}\n    };\n    Plotly.newPlot(this.id, data, layout);\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>Here are some of the most useful links for working with Plotly:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/plotly.com\/javascript\/plotly-fundamentals\/\">Chart Fundamentals<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/plotly.com\/javascript\/basic-charts\/\">Basic Charts<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/plotly.com\/javascript\/statistical-charts\/\">Statistical Charts<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/plotly.com\/javascript\/scientific-charts\/\">Scientific Charts<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/plotly.com\/javascript\/3d-charts\/\">3D Charts<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/plotly.com\/javascript\/subplot-charts\/\">Subcharts<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/plotly.com\/javascript\/#chart-events\">Chart Events<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/plotly.com\/javascript\/#animations\">Animations<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"working-with-other-javascript-libraries\">Working with other JavaScript Libraries<\/h2>\n\n\n\n<p>There really is no limit to what you can build with Comet Panels. Here are some additional links to JavaScript libraries that you might find useful:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.chartjs.org\/\">chartjs.org<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/d3js.org\/\">d3.js<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developers.google.com\/chart\/\">Google Charts<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.highcharts.com\/\">highcharts.com<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.zingchart.com\/\">zingchart.com<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In the last three years since Comet was founded, our users and customers trained millions of models on anything from self-driving cars to speech recognition, and from Covid-19 protein prediction to satellite image object detection. Based on your requests we added more and more visualization capabilities including&nbsp;chart builders,&nbsp;confusion matrices,&nbsp;audio players&nbsp;and many more. But as the [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":315,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"customer_name":"","customer_description":"","customer_industry":"","customer_technologies":"","customer_logo":"","footnotes":""},"categories":[8,9],"tags":[],"coauthors":[107],"class_list":["post-314","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-comet-community-hub","category-product"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Introducing Panels Custom Visualizations Machine Learning<\/title>\n<meta name=\"description\" content=\"Comet Panels: custom visualizations for ML are a scalable way to build any visualization you want. Dynamic, flexible, reusable panels offer total freedom.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Introducing Panels: Custom Visualizations for Machine Learning\" \/>\n<meta property=\"og:description\" content=\"Comet Panels: custom visualizations for ML are a scalable way to build any visualization you want. Dynamic, flexible, reusable panels offer total freedom.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/\" \/>\n<meta property=\"og:site_name\" content=\"Comet\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/cometdotml\" \/>\n<meta property=\"article:published_time\" content=\"2020-08-05T22:50:17+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-05-09T09:54:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/launch.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"627\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Gideon Mendels\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@Cometml\" \/>\n<meta name=\"twitter:site\" content=\"@Cometml\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Gideon Mendels\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Introducing Panels Custom Visualizations Machine Learning","description":"Comet Panels: custom visualizations for ML are a scalable way to build any visualization you want. Dynamic, flexible, reusable panels offer total freedom.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/","og_locale":"en_US","og_type":"article","og_title":"Introducing Panels: Custom Visualizations for Machine Learning","og_description":"Comet Panels: custom visualizations for ML are a scalable way to build any visualization you want. Dynamic, flexible, reusable panels offer total freedom.","og_url":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/","og_site_name":"Comet","article_publisher":"https:\/\/www.facebook.com\/cometdotml","article_published_time":"2020-08-05T22:50:17+00:00","article_modified_time":"2025-05-09T09:54:12+00:00","og_image":[{"width":1200,"height":627,"url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/launch.png","type":"image\/png"}],"author":"Gideon Mendels","twitter_card":"summary_large_image","twitter_creator":"@Cometml","twitter_site":"@Cometml","twitter_misc":{"Written by":"Gideon Mendels","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/#article","isPartOf":{"@id":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/"},"author":{"name":"Matt Peternell","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/85aa446f8be987e848ea929ef524b67b"},"headline":"Introducing Panels: Custom Visualizations for Machine Learning","datePublished":"2020-08-05T22:50:17+00:00","dateModified":"2025-05-09T09:54:12+00:00","mainEntityOfPage":{"@id":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/"},"wordCount":2374,"commentCount":0,"publisher":{"@id":"https:\/\/www.comet.com\/site\/#organization"},"image":{"@id":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/#primaryimage"},"thumbnailUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/launch.png","articleSection":["Comet Community Hub","Product"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/","url":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/","name":"Introducing Panels Custom Visualizations Machine Learning","isPartOf":{"@id":"https:\/\/www.comet.com\/site\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/#primaryimage"},"image":{"@id":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/#primaryimage"},"thumbnailUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/launch.png","datePublished":"2020-08-05T22:50:17+00:00","dateModified":"2025-05-09T09:54:12+00:00","description":"Comet Panels: custom visualizations for ML are a scalable way to build any visualization you want. Dynamic, flexible, reusable panels offer total freedom.","breadcrumb":{"@id":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/#primaryimage","url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/launch.png","contentUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/02\/launch.png","width":1200,"height":627,"caption":"Comet Panels | Comet ML"},{"@type":"BreadcrumbList","@id":"https:\/\/www.comet.com\/site\/blog\/introducing-panels-custom-visualizations-for-machine-learning\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.comet.com\/site\/"},{"@type":"ListItem","position":2,"name":"Introducing Panels: Custom Visualizations for Machine Learning"}]},{"@type":"WebSite","@id":"https:\/\/www.comet.com\/site\/#website","url":"https:\/\/www.comet.com\/site\/","name":"Comet","description":"Build Better Models Faster","publisher":{"@id":"https:\/\/www.comet.com\/site\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.comet.com\/site\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.comet.com\/site\/#organization","name":"Comet ML, Inc.","alternateName":"Comet","url":"https:\/\/www.comet.com\/site\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/#\/schema\/logo\/image\/","url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2025\/01\/logo_comet_square.png","contentUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2025\/01\/logo_comet_square.png","width":310,"height":310,"caption":"Comet ML, Inc."},"image":{"@id":"https:\/\/www.comet.com\/site\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/cometdotml","https:\/\/x.com\/Cometml","https:\/\/www.youtube.com\/channel\/UCmN63HKvfXSCS-UwVwmK8Hw"]},{"@type":"Person","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/85aa446f8be987e848ea929ef524b67b","name":"Matt Peternell","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/image\/da003ee51bbeeccfb95147ec69139879","url":"https:\/\/secure.gravatar.com\/avatar\/36058153d701caaf237a96d5d6fb9c2d1678325c3ed0d8e88bf5e487019a2a53?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/36058153d701caaf237a96d5d6fb9c2d1678325c3ed0d8e88bf5e487019a2a53?s=96&d=mm&r=g","caption":"Matt Peternell"},"description":"We re-implemented the architecture of this model to incorporate patient and study information. By comparing our updated model to the original Github repository, we were able to quantify the benefits of classifying by patient as opposed to classifying by individual X-ray. We observed a 0.0254 increase in AUROC when evaluating the DenseNet121 on patients instead of on individual scans.","sameAs":["http:\/\/atre.net"],"url":"https:\/\/www.comet.com\/site\/blog\/author\/mpeternellatre-net\/"}]}},"_links":{"self":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/314","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/comments?post=314"}],"version-history":[{"count":3,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/314\/revisions"}],"predecessor-version":[{"id":15895,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/314\/revisions\/15895"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/media\/315"}],"wp:attachment":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/media?parent=314"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/categories?post=314"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/tags?post=314"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/coauthors?post=314"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}