Giter VIP home page Giter VIP logo

tyra's Introduction

Tyra

Prediction model evaluation dashboard

build status codecov

Screenshot

alt text

Quick Start

  1. Install requirements: pip3 install -r requirements.txt

  2. Copy example_default_profile.yaml to default_profile.yaml and modify to point to your database

  3. Run python3 run_webapp.py

  4. Enter http://localhost:5001/ in your local browser

Database Schema

Tyra is designed to work on different data science projects, but to accomplish this it expects a standard model storage interface; a Postgres database with a results schema containing three tables, models, evaluations, and predictions.

models

  • model_id - integer
  • run_time - timestamp
  • model_type - string
  • model_group_id - integer
  • test - boolean
  • model_comment - string
  • train_end_time - timestamp

model_groups

  • model_group_id - integer

evaluations

  • model_id - integer
  • metric - string (each value should be one of the Available Metrics below)
  • parameter - string
  • value - numeric
  • evaluation_start_time - timestamp

predictions

  • model_id - integer
  • entity_id - bigint
  • unit_score - numeric
  • label_value - int
  • as_of_date - timestamp

feature_importances

  • model_id - integer
  • feature - string
  • feature_importance - numeric

ranked_table (cache_table.sql is an example for creating a ranked table)

  • model_group_id - integer
  • metric_parameter - string
  • avg - numeric
  • run_time - teimstamp
  • model_comment - string

Whether or not the model_id and as_of_date columns in predictions and evaluations are defined as a foreign key, they should act as one as the tables are joined using it.

No assertions are made on other tables in the results schema or other schemas, or on other columns in these tables.

Available Metrics

The list of metrics that will be displayed to the user currently lives in parameters.yaml. The currently shipped list looks like this:

  • precision
  • recall
  • auc
  • true positives
  • true negatives
  • false positives
  • false negatives

Both absolute value and percent thresholding are supported for metric parameters. The format for each one in the results.evaluations.parameter is as follows:

100_abs (top 100 entities) 10.0_pct (top 10%)

Tyra expects these metrics to be computed ahead of time, so if your evaluation code does not compute all of these thresholds for all of the threshold-able metrics ahead of time, we recommend removing entries from parameters.yaml to make the lists match up and avoid confusion in the UI.

Running multiple instances

Since Tyra is built to look at different project databases, being able to run multiple instances side-by-side is helpful. To accomplish this, you can pass environment variables to configure the database credential file path and the port. So these two commands will work:

PROFILE=/path/to/first/profile.yaml PORT=5001 python3 run_webapp.py

PROFILE=/path/to/second/profile.yaml PORT=5002 python3 run_webapp.py

Dev Front-end setup

Tyra uses NodeJS and Webpack to organize and bundle frontend dependencies.

Initial setup (If you don't see output.js in /webapp/static/)

  1. Install NodeJS (https://nodejs.org/en/)

  2. cd frontend

  3. npm install to install dependencies (the initial install will take a few minutes, go have a snack!)

  4. npm run build to initially create the bundled javascript file

Troubleshooting

Sometimes node and npm versions from package managers are ancient and need to be upgraded before installation will work.

To upgrade node to the latest stable version:

  1. sudo npm cache clean -f

  2. sudo npm install -g n

  3. sudo n stable

To upgrade npm:

  1. sudo npm install npm@latest -g

During development

npm run start will start a webpack '--watch' command that watches your javascript and compiles it to webapp/static/output.js. The initial startup will probably take 10-15 seconds, but every time you save a javascript file the recompilation will be much quicker.

New components can be added in the frontend/components directory. There is a directory for each component, because soon (not yet) we will start bundling styles in individual component directories. Other components will be able to import your new component right away, but if you would like the component to made available globally (in other words, a Flask template), you will have to add this to frontend/index.js

Installing new modules

In the frontend directory, install the package you want with npm install --save <pkg-name>. The --save option will persist this change to package.json.

tyra's People

Contributors

nanounanue avatar thcrock avatar tweddielin avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

afcarl

tyra's Issues

Order model search results by avg mean squared value of selected metrics

The model search API call should take in a string which refers to a model ranking function. These functions are defined on the backend, and basically take in a metric or list of metrics and rank models based on them.

For now, we will implement only one model ranking function: avg mean squared value of the selected metrics. We will use this by default.

After running cache_table.sql...

Even after running cache_table.sql I got the following errors when try to use tyra

...
food_db         | 2017-08-21T21:20:58.837922331Z ERROR:  syntax error at or near ")" at character 707
food_db         | 2017-08-21T21:20:58.837952550Z STATEMENT:
food_db         | 2017-08-21T21:20:58.837958323Z                SELECT
food_db         | 2017-08-21T21:20:58.837962998Z                model_group_id,
food_db         | 2017-08-21T21:20:58.837967518Z                json_agg((select row_to_json(_)
food_db         | 2017-08-21T21:20:58.837972071Z                        from (select m.model_id,
food_db         | 2017-08-21T21:20:58.837976194Z                                     m.run_time::date,
food_db         | 2017-08-21T21:20:58.837980408Z                                     m.model_comment,
food_db         | 2017-08-21T21:20:58.837984208Z                                     e.value,
food_db         | 2017-08-21T21:20:58.837988093Z                                     e.evaluation_start_time::date)
food_db         | 2017-08-21T21:20:58.837992531Z                                     as _)
food_db         | 2017-08-21T21:20:58.837996499Z                        ORDER BY e.evaluation_start_time
food_db         | 2017-08-21T21:20:58.838000274Z                      ) as series
food_db         | 2017-08-21T21:20:58.838014425Z                FROM results.models as m
food_db         | 2017-08-21T21:20:58.838018568Z                JOIN results.evaluations e using(model_id)
food_db         | 2017-08-21T21:20:58.838022359Z                WHERE evaluation_start_time = train_end_time::timestamp
food_db         | 2017-08-21T21:20:58.838026142Z                AND parameter = '100_abs'
food_db         | 2017-08-21T21:20:58.838029923Z                AND metric = 'precision@'
food_db         | 2017-08-21T21:20:58.838033592Z                AND run_time >= '2017-08-14'
food_db         | 2017-08-21T21:20:58.838042749Z                AND model_group_id in ()
food_db         | 2017-08-21T21:20:58.838045867Z                GROUP BY model_group_id
food_db         | 2017-08-21T21:20:58.838049100Z

Also the stacktrace in python is:

tutorial_tyra   | 2017-08-21T21:28:10.278602622Z Traceback (most recent call last):
tutorial_tyra   | 2017-08-21T21:28:10.278630364Z   File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1836, in __call__
tutorial_tyra   | 2017-08-21T21:28:10.278636885Z     return self.wsgi_app(environ, start_response)
tutorial_tyra   | 2017-08-21T21:28:10.278641641Z   File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1820, in wsgi_app
tutorial_tyra   | 2017-08-21T21:28:10.278646365Z     response = self.make_response(self.handle_exception(e))
tutorial_tyra   | 2017-08-21T21:28:10.278651213Z   File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1403, in handle_exception
tutorial_tyra   | 2017-08-21T21:28:10.278655686Z     reraise(exc_type, exc_value, tb)
tutorial_tyra   | 2017-08-21T21:28:10.278659986Z   File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
tutorial_tyra   | 2017-08-21T21:28:10.278664317Z     raise value
tutorial_tyra   | 2017-08-21T21:28:10.278668560Z   File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1817, in wsgi_app
tutorial_tyra   | 2017-08-21T21:28:10.278675563Z     response = self.full_dispatch_request()
tutorial_tyra   | 2017-08-21T21:28:10.278681861Z   File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1477, in full_dispatch_request
tutorial_tyra   | 2017-08-21T21:28:10.278686428Z     rv = self.handle_user_exception(e)
tutorial_tyra   | 2017-08-21T21:28:10.278690873Z   File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1381, in handle_user_exception
tutorial_tyra   | 2017-08-21T21:28:10.278697360Z     reraise(exc_type, exc_value, tb)
tutorial_tyra   | 2017-08-21T21:28:10.278701467Z   File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
tutorial_tyra   | 2017-08-21T21:28:10.278705802Z     raise value
tutorial_tyra   | 2017-08-21T21:28:10.278709886Z   File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1475, in full_dispatch_request
tutorial_tyra   | 2017-08-21T21:28:10.278714216Z     rv = self.dispatch_request()
tutorial_tyra   | 2017-08-21T21:28:10.278718243Z   File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1461, in dispatch_request
tutorial_tyra   | 2017-08-21T21:28:10.278722570Z     return self.view_functions[rule.endpoint](**req.view_args)
tutorial_tyra   | 2017-08-21T21:28:10.278726693Z   File "/tyra-master/webapp/controller.py", line 107, in get_model_groups
tutorial_tyra   | 2017-08-21T21:28:10.278733135Z     output = query.get_model_groups(query_arg)
tutorial_tyra   | 2017-08-21T21:28:10.278740010Z   File "/tyra-master/webapp/query.py", line 121, in get_model_groups
tutorial_tyra   | 2017-08-21T21:28:10.278746609Z     con=db.engine)
tutorial_tyra   | 2017-08-21T21:28:10.278752193Z   File "/usr/local/lib/python3.6/site-packages/pandas/io/sql.py", line 515, in read_sql
tutorial_tyra   | 2017-08-21T21:28:10.278756657Z     chunksize=chunksize)
tutorial_tyra   | 2017-08-21T21:28:10.278760616Z   File "/usr/local/lib/python3.6/site-packages/pandas/io/sql.py", line 1190, in read_query
tutorial_tyra   | 2017-08-21T21:28:10.278774447Z     result = self.execute(*args)
tutorial_tyra   | 2017-08-21T21:28:10.278778255Z   File "/usr/local/lib/python3.6/site-packages/pandas/io/sql.py", line 1081, in execute
tutorial_tyra   | 2017-08-21T21:28:10.278782004Z     return self.connectable.execute(*args, **kwargs)
tutorial_tyra   | 2017-08-21T21:28:10.278785566Z   File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1991, in execute
tutorial_tyra   | 2017-08-21T21:28:10.278791113Z     return connection.execute(statement, *multiparams, **params)
tutorial_tyra   | 2017-08-21T21:28:10.278794910Z   File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 906, in execute
tutorial_tyra   | 2017-08-21T21:28:10.278799147Z     return self._execute_text(object, multiparams, params)
tutorial_tyra   | 2017-08-21T21:28:10.278805080Z   File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1054, in _execute_text
tutorial_tyra   | 2017-08-21T21:28:10.278811557Z     statement, parameters
tutorial_tyra   | 2017-08-21T21:28:10.278820344Z   File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1146, in _execute_context
tutorial_tyra   | 2017-08-21T21:28:10.278826563Z     context)
tutorial_tyra   | 2017-08-21T21:28:10.278831703Z   File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1341, in _handle_dbapi_exception
tutorial_tyra   | 2017-08-21T21:28:10.278837525Z     exc_info
tutorial_tyra   | 2017-08-21T21:28:10.278843186Z   File "/usr/local/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 202, in raise_from_cause
tutorial_tyra   | 2017-08-21T21:28:10.278849140Z     reraise(type(exception), exception, tb=exc_tb, cause=cause)
tutorial_tyra   | 2017-08-21T21:28:10.278854044Z   File "/usr/local/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 185, in reraise
tutorial_tyra   | 2017-08-21T21:28:10.278859721Z     raise value.with_traceback(tb)
tutorial_tyra   | 2017-08-21T21:28:10.278864433Z   File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
tutorial_tyra   | 2017-08-21T21:28:10.278870158Z     context)
tutorial_tyra   | 2017-08-21T21:28:10.278875656Z   File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 450, in do_execute
tutorial_tyra   | 2017-08-21T21:28:10.278882016Z     cursor.execute(statement, parameters)
tutorial_tyra   | 2017-08-21T21:28:10.278887857Z sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) syntax error at or near ")"
tutorial_tyra   | 2017-08-21T21:28:10.278894390Z LINE 19:         AND model_group_id in ()
tutorial_tyra   | 2017-08-21T21:28:10.278900216Z                                         ^
tutorial_tyra   | 2017-08-21T21:28:10.278907607Z  [SQL: '\n        SELECT\n        model_group_id,\n        json_agg((select row_to_json(_)\n                from (select m.model_id,\n                             m.run_time::date,\n                             m.model_comment,\n                             e.value,\n                             e.evaluation_start_time::date)\n                             as _)\n                ORDER BY e.evaluation_start_time\n              ) as series\n        FROM results.models as m\n        JOIN results.evaluations e using(model_id)\n        WHERE evaluation_start_time = train_end_time::timestamp\n        AND parameter = %(parameter)s\n        AND metric = %(metric)s\n        AND run_time >= %(runtime)s\n        AND model_group_id in ()\n        GROUP BY model_group_id\n        '] [parameters: {'parameter': '100_abs', 'metric': 'precision@', 'runtime': '2017-08-14'}]

Better handling for the materialized view

By default, Tyra looks for a materialized view called results.ranked_table. Tyra shows many options in the dropdown box (e.g. top 100, top 10%), but it can only display results in that view. For example, if the materialized view only includes results for the top 5%, the top 100 option won't work.

  • Tyra should populate the dropdown box with the options in results.ranked_table. That avoids giving the false impression that Tyra has more results than it does, and it also enables Tyra to handle non-standard results (such as precision on the top 1, which we rarely do)
  • The documentation note that the materialized view needs to be updated if the user wants to see more recent results. In many deployments, we're making predictions and updating the evaluations every night. The documentation could note that a cron job would handle this well.

Missing npm dependency

When running npm run build you got the following error:

root@95a52cdbe85a:/tyra-master/frontend# npm install                                                                                     
npm WARN [email protected] requires a peer of webpack@^2.0.0 || >= 3.0.0-rc.0 || ^3.0.0 but none was installed.
npm WARN [email protected] requires a peer of webpack@^2.2.0 || ^3.0.0 but none was installed.
npm WARN [email protected] license should be a valid SPDX license expression
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

added 114 packages in 7.763s
root@95a52cdbe85a:/tyra-master/frontend# npm run build                                                                                   

> [email protected] build /tyra-master/frontend
> webpack --progress --colors

Hash: 7844a6039f9ad1830e9b
Version: webpack 1.15.0
Time: 5260ms
    Asset     Size  Chunks             Chunk Names
output.js  4.34 MB       0  [emitted]  main
    + 788 hidden modules

ERROR in ./components/rankcorr-chart/component.js
Module not found: Error: Cannot resolve module 'react-faux-dom' in /tyra-master/frontend/components/rankcorr-chart
 @ ./components/rankcorr-chart/component.js 15:20-45

You can fix that installing that package:

root@95a52cdbe85a:/tyra-master/frontend# npm install react-faux-dom

But it should be added to the proper place in code

Fix install steps

Put Initial setup in list of initial install steps. First time I tried to use tyra was unsuccessful because I hadn't installed the requirements and didn't realize they were there

Implement more model ranking functions and make them customizable

Once there is a basic model ranking system in place ( #37 ) we would like to implement some more rankings based on the selected metrics and allow them to be switched between. Examples:

  • a slope close to 0
  • variance closest to 0
  • the highest minimum value
  • the highest maximum value

We will likely want to include some kind of training explanations for what these mean, once we are referencing them in the UI. This may even be encoded in the name; for instance, 'slope closest to 0' could mean 'most stable over time', with a more detailed explanation available as an info box.

Tyra crashed suddenly and a restart causes this error

python3 run_webapp.py
Failed to import the site module
Traceback (most recent call last):
  File "/mnt/data/public_safety/charlotte_eis/tyra_cmpd_dump/tyra_venv/lib/python3.5/site.py", line 703, in <module>
    main()
  File "/mnt/data/public_safety/charlotte_eis/tyra_cmpd_dump/tyra_venv/lib/python3.5/site.py", line 683, in main
    paths_in_sys = addsitepackages(paths_in_sys)
  File "/mnt/data/public_safety/charlotte_eis/tyra_cmpd_dump/tyra_venv/lib/python3.5/site.py", line 282, in addsitepackages
    addsitedir(sitedir, known_paths)
  File "/mnt/data/public_safety/charlotte_eis/tyra_cmpd_dump/tyra_venv/lib/python3.5/site.py", line 204, in addsitedir
    addpackage(sitedir, name, known_paths)
  File "/mnt/data/public_safety/charlotte_eis/tyra_cmpd_dump/tyra_venv/lib/python3.5/site.py", line 173, in addpackage
    exec(line)
  File "<string>", line 1, in <module>
  File "/mnt/data/public_safety/charlotte_eis/tyra_cmpd_dump/tyra_venv/lib/python3.5/types.py", line 166, in <module>
    import functools as _functools
  File "/mnt/data/public_safety/charlotte_eis/tyra_cmpd_dump/tyra_venv/lib/python3.5/functools.py", line 23, in <module>
    from weakref import WeakKeyDictionary
  File "/mnt/data/public_safety/charlotte_eis/tyra_cmpd_dump/tyra_venv/lib/python3.5/weakref.py", line 12, in <module>
    from _weakref import (
ImportError: cannot import name '_remove_dead_weakref'

Fix first graph to show accuracy at time x rather than average accuracy over time x+t

Need to fix: The first plot the user sees in Tyra displays the average metric over test sets, rather than the metric for the test set at that given time.

For example, if you train a model through December 31, 2012, and then test that model on 2012, then 2013, then 2014, and finally 2015, the current implementation plots a point at January 1, 2015 (the start of the final test set) using the average value across those test sets.

The current implementation hides that nuance and reduces variance in performance.

Allow installations of Tyra to configure the graphs shown

We have reached a point where different users can have different needs. We want to be able to implement something that allows them to have a bit of customization, so for instance each project can have a different graph or set of graphs on the model selection page.

There are many ways to do this. For example:

  1. Show all suitable graphs by default, but allow users to click a button on graphs to hide them; so in the model selection graphs use case, we would show both model selection graphs, but a user who only wants the grid would click a button to hide it. This choice is serialized, maybe to a YAML file, and that component would just be hidden by default.

  2. Instead of involving user input in the UI, a YAML file with boolean flags for each component is provided.

  3. We build out different pages/endpoints for different projects, and the YAML configuration decides which endpoint is mounted to the root '/'

I'm leaning towards #2 right now. #1 is more complicated to add UI elements for doing this, and #3 probably lets too many project-specific details bleed into a generic repo.

Create separate testing and main URLs

We aren't hooking all of our graphs up to real data just yet, so arrange them on a testing page instead of removing them from master entirely. Mount the full list of graphs at another endpoint.

The main endpoint will only have the Model Summary and Within-Model tabs (for now)

Remaining test graphs need to link to real data

The following charts are linked to test data and should be linked to real data:

ScatterChart
FeatureDistChart (FeatureDistribution)
ScoreTimeModelChart (Risk Score Across Time and Models)
MetricTimeChart (Metrics Over Time)
BarChart (Feature Importance)

Model selection: grid of small per-model graphs

Display metrics over time as small multiples for a subset of "top" models. Should be able to display a few metrics on a single graph per model. Top models may be models where the key selection metric has:

a slope close to 0
variance closest to 0
the highest minimum value
the highest maximum value

May also be useful to know which models appear on each of these lists, or, for a given model, which of the lists it appears on.

Instructions in README are misleading

If you follow the section Quick Start, you will get an empty screen after login,
you must run all in the section Dev Front-end setup (and solve the issue #79 by yourself)

But even after that you need to run the script cache_table.sql

Also, it is important that the user knows about the configuration files (see #77 and #78 )

The installation instructions need to be stated better.

Add documentation on expected database schema

It's not currently in scope for this project to create or maintain a database; a variety of ML projects are expected to output data into a certain schema, and credentials are supplied to this app to simply view the data. But we should document what the expected schema is. Likely, we should put it in the README.

Problem with capital feature names in the feature distribution graph

Eg the query should be:

SELECT
  "ir_id_P1Y_IncidentsOfType_complaint_sum",
  "officer_id",
  label_value
FROM "historical_features_daily"."ir_aggregation" f
  JOIN results.predictions p ON f.officer_id=p.entity_id
WHERE model_id=493
      AND p.as_of_date = '2015-08-01 00:00:00'

buth the query run is:

SELECT
  "ir_id_p1y_incidentsoftype_complaint_sum",
  "officer_id",
  label_value
FROM "historical_features_daily"."ir_aggregation" f
  JOIN results.predictions p ON f.officer_id=p.entity_id
WHERE model_id=493
      AND p.as_of_date = '2015-08-01 00:00:00'

it is correct for the test set but not for the training

Score distribution seems weird

The score distribution plot seems to be plotted using the model_group_id, to be useful it should show the scores of each of the model_id that belong to the model_group_id.

(We should discuss how to plot this @jtwalsh0 any ideas?)

Increase granularity of "precision and recall by threshold" plot

This plot's smoothness hides interesting and useful performance issues, e.g. a flat part of the recall curve helps identify cases that have similar scores and are all wrong, and we might find ways to improve model performance by taking a closer look at them. The current plot skips from 1% to 5% to 10% to.... If there were a flat part of the recall curve, it would be hard to tell.

Given that we're already pulling the data and making the sklearn calls, this plot should show more granularity (in most applied cases, the curve will be jagged)

Add model group

Model groups! We have a schema:

The models table has a model_group_id. Each model_id within a given model_group_id has all of the same attributes except for the test_end_date. Each model_group_id in the database at one time is understood to have the same set of test_end_dates, though this is not enforced in the schema (procedure outlined below to work around this).

Model search table should:

  1. Work with model groups (display model_group_id instead of model_id), and
  2. Only show the results for the second to most recent test_end_date from each group, as this is the most relevant at a glance. (Later we may add this as a search option).

To compute the list of available model dates, select the most recent model_id (by runtime) and take all of the test_end_dates in the model's model_group. Then take the second-most-recent date, and only show the metrics for the models of that test_end_date.

Add nginx support

Use nginx to redirect requests from the web browser to the tyra dockerfile so partners don't need to set up ssh tunnels

Model search tweaks

  • Change copy from 'predicting' to 'testing'
  • Make default run date search a month ago, instead of hardcoded to 2016-08-03

Add linting npm script

To make it easier to use eslint, wrap it in an npm script.

Command to lint all files: node_modules/eslint/bin/eslint.js -c ../.eslintrc.json ./

We can add this to the scripts in package.json. Extra points if we can figure out how to pass arguments through npm scripts to enable a file-specific interface instead of just the entire directory:

npm run lint components/newcomponent/component.js

Create model comparison graph

We want to show a graph with one metric over time for many models, on the model selection front page. This only makes sense for one metric, so only one metric should be selectable at a time.

It should graph the top n models at a time, and n should be selectable.

This should just be on the testing page for now.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.