Giter VIP home page Giter VIP logo

gavel's Introduction

Gavel banner

Gavel is a project expo judging system.

Gavel was originally built for HackMIT and first used at HackMIT 2015. It has been used by dozens of other events since then.

If you use Gavel for your event, please add yourself to this list! It only takes a minute, and knowing that Gavel is helping real events helps keep us going <3

Demo

Gavel screenshot

See the demo video here!

Users

See here for a list of events that have used Gavel in the past.

If you use Gavel for your event, please add yourself to the list! It only takes a minute, and knowing that Gavel is helping real events helps keep us going <3

and adding yourself to the list helps keep me motivated to continue working on the software :)

Design

Gavel is based on the method of pairwise comparisons. Before you use Gavel, it's highly recommended that you read about the philosophy behind the implementation as well as hints on how to use it in practice. Read this blog post first, and then read this blog post.

Status

Gavel is stable software. We've used it successfully at HackMIT, and a bunch of other hackathons and events have used it too.

Gavel is a pretty different way of doing judging. If you want to use this for your hackathon or event, we highly recommend that you:

  • Deploy it and play around with it ahead of time to get a feel for how the system works
  • Read the blog posts linked above to get an idea of how to structure the judging process

If you have any questions, feel free to email me.

If you're able to contribute to making Gavel better, that would be awesome! We'd really appreciate any kind of input, especially pull requests.

Deployment

Deploy

The latest stable version is the master branch (and it's signed and tagged). Development happens in the develop branch.

The web application is written in Python 3 using Flask. It also uses NumPy and SciPy for math stuff. Doing a pip --no-cache-dir install -r requirements.txt should install all the dependencies.

The application uses Postgres for the database, so you need to have that on your server. You need to create a database, which you can do with createdb gavel (unless you're using a different database name). Before you use the app, you need to initialize the database by running python initialize.py. Note that Gavel does not preserve database schema compatibility between versions.

In order to send emails, you'll need to install Redis.

When testing, you can run the app with python runserver.py.

In production, you should use something like Gunicorn to serve this. You can run the app with gunicorn -b :<PORT> -w <number of workers> gavel:app. This is sufficient if you want to serve Gavel under its own domain (e.g. judging.example.com). If you are serving Gavel under a subpath, e.g. example.com/judging, you need to set the SCRIPT_NAME environment variable (e.g. by passing -e SCRIPT_NAME=/judging to Gunicorn). If you are running Gavel behind a proxy server, be sure to set PROXY=true in Gavel's settings.

For sending emails, you'll also need to start a celery worker with celery -A gavel:celery worker.

Configuration

Before starting the app, copy config.template.yaml to config.yaml and set all the required settings (the ones that don't have default values).

Most settings can either be set in config.yaml or set as environment variables. There's more detailed documentation in config.template.yaml.

If you don't want to use the config file and use only environment variables, set the environment variable IGNORE_CONFIG_FILE=true.

Troubleshooting

See the troubleshooting guide in the Gavel wiki.

Use

To set up the system, use the admin interface on /admin. Log in with the username admin and the password you set. Once you're logged in, you can input information for all the projects and judges.

As you add judges, they'll automatically get emails with invitation links. After that, the judging and ranking process is fully automated - the judge will be able to read the welcome text, and then they'll be able to start judging.

The admin panel will rank projects in real time, ordered by their inferred quality (Mu).

Admin Panel Features

  • If you want to (temporarily) close the judging system, click the "Close" button under "Global Settings"
  • If you need to force re-send the invite email, use the "Email" button for the judge in the admin panel
  • If you need to manually give a judge a login link, direct them to /login/<secret>
  • If you want to send the next available judge to a certain project, use the "Prioritize" button
  • If you need to deactivate projects or judges at any point, use the "Disable" button
  • If a project hasn't been judged yet, you can delete it using the "Delete" button
  • If a judge hasn't started yet, you can delete them using the "Delete" button
  • If you need to see details for a project or judge, click on the item ID in the admin panel
    • If you need to edit a project (name, location, or description), you can do so on the item detail page
  • If you want to sort the items in the admin panel, click on the table headers

Development

Interested in hacking on Gavel? Awesome. See DEVELOPMENT.md for a dev setup guide.

Notes

If you do end up using this for your competition or hackathon, I would love to hear about how it goes.

If anyone has questions, feel free to email Anish ([email protected]).

Contributing

Do you have a feature request, bug report, or patch? Great! See CONTRIBUTING.md for information on what you can do about that.

Citation

If you use Gavel in any way in academic work, please cite the following:

@misc{athalye2016gavel,
  author = {Anish Athalye},
  title = {Gavel},
  year = {2016},
  howpublished = {\url{https://github.com/anishathalye/gavel}},
}

License

Copyright (c) Anish Athalye. Released under AGPLv3. See LICENSE.txt for details.

gavel's People

Contributors

ajyong avatar anishathalye avatar axnsan12 avatar copperstick6 avatar dalemitchell avatar evantey14 avatar jhollowe avatar joker314 avatar joshuamorton avatar michaelsilver avatar mitchtalmadge avatar ofekby avatar phoenix1796 avatar revalo avatar rjchee avatar

Stargazers

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

Watchers

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

gavel's Issues

Implement CSRF protection

Haven't gotten around to this yet…

In practice, this shouldn't be a problem, but still, it's nice to be thorough.

Implement better (customizable?) selection strategies

Right now, we use an epsilon-greedy method of selecting which project a judge sees next. It could be good to modify it so that each project is judged some minimum number of times before having judges move around to maximize expected information gain.

It would also be good to implement stuff so that there aren't multiple judges overwhelming a project at once.

Making this customizable would be awesome.

This is pretty involved and involves substantial changes, so post here before you start working if you're interested in working on the issue.

Make a link that is sent to judges accessible directly from admin page

As a precaution in case judges aren't getting the email with the voting link, it would be nice to make the link accessible from the admin page so admins can give it to them through other channels like Slack or writing it on a piece of paper (hopefully we never have to do that).

Figure out a way to support category judging

Right now, Gavel doesn't really have a good way of supporting judging for different categories - it just produces an overall ranking.

One way of working around this is to get an overall ranking and then choose category winners based on the highest ranked submission in each category. But maybe there are better ways of doing this.

App crashes every ~10 votes

I deployed Gavel to Heroku on a hobby dyno, and I'm seeing a ton of crashes when voting on items. We had around 170 items and 10 annotators spamming the app simultaneously, and the app would show an Internal Server Error quite regularly after voting.

I checked the Heroku logs and this is the error that keeps repeating:

2016-11-07T17:45:24.292366+00:00 app[web.1]: [2016-11-07 17:45:24,289] ERROR in app: Exception on /vote [POST]
2016-11-07T17:45:24.292378+00:00 app[web.1]: Traceback (most recent call last):
2016-11-07T17:45:24.292380+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
2016-11-07T17:45:24.292382+00:00 app[web.1]: context)
2016-11-07T17:45:24.292383+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/default.py", line 450, in do_execute
2016-11-07T17:45:24.292384+00:00 app[web.1]: cursor.execute(statement, parameters)
2016-11-07T17:45:24.292385+00:00 app[web.1]: psycopg2.extensions.TransactionRollbackError: could not serialize access due to concurrent update
2016-11-07T17:45:24.292386+00:00 app[web.1]:
2016-11-07T17:45:24.292387+00:00 app[web.1]:
2016-11-07T17:45:24.292387+00:00 app[web.1]: The above exception was the direct cause of the following exception:
2016-11-07T17:45:24.292388+00:00 app[web.1]:
2016-11-07T17:45:24.292389+00:00 app[web.1]: Traceback (most recent call last):
2016-11-07T17:45:24.292390+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/app.py", line 1988, in wsgi_app
2016-11-07T17:45:24.292391+00:00 app[web.1]: response = self.full_dispatch_request()
2016-11-07T17:45:24.292392+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/app.py", line 1641, in full_dispatch_request
2016-11-07T17:45:24.292392+00:00 app[web.1]: rv = self.handle_user_exception(e)
2016-11-07T17:45:24.292393+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/app.py", line 1544, in handle_user_exception
2016-11-07T17:45:24.292394+00:00 app[web.1]: reraise(exc_type, exc_value, tb)
2016-11-07T17:45:24.292420+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
2016-11-07T17:45:24.292422+00:00 app[web.1]: raise value
2016-11-07T17:45:24.292422+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/app.py", line 1639, in full_dispatch_request
2016-11-07T17:45:24.292423+00:00 app[web.1]: rv = self.dispatch_request()
2016-11-07T17:45:24.292424+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/flask/app.py", line 1625, in dispatch_request
2016-11-07T17:45:24.292425+00:00 app[web.1]: return self.view_functionsrule.endpoint
2016-11-07T17:45:24.292426+00:00 app[web.1]: File "/app/gavel/controllers/judge.py", line 25, in decorated
2016-11-07T17:45:24.292427+00:00 app[web.1]: return f(*args, **kwargs)
2016-11-07T17:45:24.292428+00:00 app[web.1]: File "/app/gavel/controllers/judge.py", line 33, in decorated
2016-11-07T17:45:24.292429+00:00 app[web.1]: annotator = get_current_annotator()
2016-11-07T17:45:24.292429+00:00 app[web.1]: File "/app/gavel/controllers/judge.py", line 150, in get_current_annotator
2016-11-07T17:45:24.292430+00:00 app[web.1]: return Annotator.by_id(session.get(ANNOTATOR_ID, None))
2016-11-07T17:45:24.292430+00:00 app[web.1]: File "/app/gavel/models/annotator.py", line 59, in by_id
2016-11-07T17:45:24.292431+00:00 app[web.1]: annotator = cls.query.with_for_update().get(uid)
2016-11-07T17:45:24.292432+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 831, in get
2016-11-07T17:45:24.292432+00:00 app[web.1]: return self._get_impl(ident, loading.load_on_ident)
2016-11-07T17:45:24.292433+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 864, in _get_impl
2016-11-07T17:45:24.292433+00:00 app[web.1]: return fallback_fn(self, key)
2016-11-07T17:45:24.292434+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/loading.py", line 219, in load_on_ident
2016-11-07T17:45:24.292434+00:00 app[web.1]: return q.one()
2016-11-07T17:45:24.292435+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2718, in one
2016-11-07T17:45:24.292436+00:00 app[web.1]: ret = list(self)
2016-11-07T17:45:24.292436+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2761, in iter
2016-11-07T17:45:24.292437+00:00 app[web.1]: return self._execute_and_instances(context)
2016-11-07T17:45:24.292438+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2776, in _execute_and_instances
2016-11-07T17:45:24.292439+00:00 app[web.1]: result = conn.execute(querycontext.statement, self._params)
2016-11-07T17:45:24.292439+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 914, in execute
2016-11-07T17:45:24.292440+00:00 app[web.1]: return meth(self, multiparams, params)
2016-11-07T17:45:24.292441+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection
2016-11-07T17:45:24.292441+00:00 app[web.1]: return connection._execute_clauseelement(self, multiparams, params)
2016-11-07T17:45:24.292442+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1010, in _execute_clauseelement
2016-11-07T17:45:24.292443+00:00 app[web.1]: compiled_sql, distilled_params
2016-11-07T17:45:24.292443+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1146, in _execute_context
2016-11-07T17:45:24.292444+00:00 app[web.1]: context)
2016-11-07T17:45:24.292445+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1341, in _handle_dbapi_exception
2016-11-07T17:45:24.292445+00:00 app[web.1]: exc_info
2016-11-07T17:45:24.292446+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/util/compat.py", line 202, in raise_from_cause
2016-11-07T17:45:24.292447+00:00 app[web.1]: reraise(type(exception), exception, tb=exc_tb, cause=cause)
2016-11-07T17:45:24.292448+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/util/compat.py", line 185, in reraise
2016-11-07T17:45:24.292448+00:00 app[web.1]: raise value.with_traceback(tb)
2016-11-07T17:45:24.292449+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
2016-11-07T17:45:24.292450+00:00 app[web.1]: context)
2016-11-07T17:45:24.292450+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/sqlalchemy/engine/default.py", line 450, in do_execute
2016-11-07T17:45:24.292457+00:00 app[web.1]: cursor.execute(statement, parameters)
2016-11-07T17:45:24.292459+00:00 app[web.1]: sqlalchemy.exc.OperationalError: (psycopg2.extensions.TransactionRollbackError) could not serialize access due to concurrent update
2016-11-07T17:45:24.292548+00:00 app[web.1]: [SQL: 'SELECT annotator.id AS annotator_id, annotator.name AS annotator_name, annotator.email AS annotator_email, annotator.active AS annotator_active, annotator.read_welcome AS annotator_read_welcome, annotator.description AS annotator_description, annotator.secret AS annotator_secret, annotator.next_id AS annotator_next_id, annotator.updated AS annotator_updated, annotator.prev_id AS annotator_prev_id, annotator.alpha AS annotator_alpha, annotator.beta AS annotator_beta \nFROM annotator \nWHERE annotator.id = %(param_1)s FOR UPDATE'] [parameters: {'param_1': 6}]

Could this be an issue with limits in the hobby dyno or something else? Would be nice to know that this won't be an issue on game day in three weeks :D

Add guidelines on number of judges needed to readme

Gavel needs a reasonable number of judges - it would be nice to have the readme mention some guidelines on how many judges are needed (or rather, how many votes are needed, and about how much time is required per project, so that organizers can figure out how many judges they need).

Add tests

It would be good to eventually have tests and CI.

Make item editing more discoverable

Feedback from Junction organizers -- the UI for the item name/location/description editing isn't that great / isn't really easily discoverable. We should fix that.

Make a user guide + project splash page

It could be nice to have a splash page (something that's more substantial than the readme). We could also have a detailed user guide there with detailed setup instructions, etc.

Having improved documentation could help with users not knowing how to use software. For example, I've gotten feedback where people have said that they don't know how to deal with projects that have moved locations - we have thought about this, and we support changing locations, but I guess people don't always get around to reading https://github.com/anishathalye/gavel#admin-panel-features

Add better instructions for judging

This is kinda related to #6, in the sense that making the UI easier should make it more intuitive to understand.

But besides that, it would also be nice to have some nice explicit instructions for judges built into the app (instead of having organizers having to explain everything in great detail / having auxiliary instructions).

Thanks to @zacharyliu for reporting this issue!

Better CSV import in admin panel

Feedback from HackBeanpot

For setting up Gavel on the admin panel it went pretty smoothly. It would have been nice to add a note on the admin panel (or on the error page) that you could use quotes to enter descriptions with commas. I completely forgot I could do that with CSVs until after the event. A CSV import feature would be nice. Also an auto reload would also be nice to have.

Auto disable frequently skipped projects?

Maybe this would be a nice feature to add.

Currently, HackMIT has the organizers visit projects that have been skipped lots of times, and if they can't be found, we manually disable them. But maybe making this automatic would be okay, adding some kind of auto_disable_threshold or something.

Add ability to open and close the judging system

At some hackathons, judges didn't know when to stop judging and kept going even after the organizers downloaded the results.

It would be nice to add a feature to explicitly open and close the system for judging.

Thanks to @zacharyliu for reporting this issue!

Add usage reporting

It could be neat to add (opt-out) automatic reporting of certain statistics.

This would probably involve having to maintain a server somewhere, though.

Make troubleshooting guide in Wiki

We need a troubleshooting guide.

One thing that would be nice to include in there is email troubleshooting. Apparently, many people have had trouble with it in the past, and 1a4d362 is going to make troubleshooting email a little more tricky (because errors won't show up in the UI, you'll have to check the celery log output).

Implement better judge assignment to projects

We talked a little bit about this in #10, and some things were fixed. There are still some things that could be explored / improved, though.

For example, we could try to minimize the distance that judges have to walk. At many events, the expo is arranged in a grid, with locations labeled like "B4". I'm sure we could apply some heuristic to try to reduce Euclidean distance that judges walk (while maintaining a good balance with maximizing information gain and all that stuff).

Make all templates fully valid HTML5

The templates need some cleaning up so that they pass all validator checks.

It should be pretty easy making everything HTML5 compliant and cleaning up stuff like <input ... /> by changing it to <input ...>.

Allow pluggable judging schemes / implement some different judging schemes

Gavel has multiple components - the ranking algorithm is just one part of it, but the score collection / admin panel is another important part of the system. It would be neat if these were decoupled enough so that the system could support different judging schemes.

Right now, we only support pairwise comparison as a judging model with Crowd-BT as the algorithm, but maybe it would be cool to support other algorithms (e.g. Elo) and maybe even different judging models (e.g. normalization). It would be nice to write accompanying documentation that describes the tradeoffs of the different models and algorithms (e.g. with very few judges, Crowd-BT might be hard, and absolute scores + normalization may be an okay approach).

This would likely be a very substantial change to Gavel.

Modularize code

Yeah, right now basically everything is in gavel.py. It would be good to make it more modular for the sake of maintainability.

This is pretty involved and involves substantial changes, so post here before you start working if you're interested in working on the issue.

Stats for judges

Feedback from HackBeanpot:

One issue that judges mentioned was that they wanted to know how many projects they had judged and how many more they needed to judge. I do think however if I better explained that they didn't need to judge every project then that probably wouldn't have been an issue.

It might still be nice to show judges some stats about how many projects that they've judged. Or maybe even showing them all the projects they've judged, as well as their votes (and this could double as an interface to edit votes).

Related to #22

Make system more configurable

Right now, some things are hard-coded, but it would be nice to set up some kind of config system thing to make stuff configurable (e.g. parameters in crowd_bt.py).

This is pretty involved and involves substantial changes, so post here before you start working if you're interested in working on the issue.

Allow deletion of projects that have been judged / judges who have judged

Yeah, this is broken right now. It's cause the system keeps track of all decisions (why not store more data), and so if we delete a project, it would be bad, cause the decision would point to a deleted project.

It's possible to delete projects before they're judged, though.

The right way to fix this would be to implement some sort of "deactivated" flag for projects and not have them show up anywhere (but still live in the database).

This is somewhat involved, so post here before you start working if you're interested in working on the issue.

Support a hosted version

Right now, there's no hosted version of Gavel. If someone wants to use the system, they have to run their own server (or use Heroku) - this requires some level of technical sophistication.

It could be neat to modify the system to allow for a hosted version (and then we could have a default hosted version that people could use if they don't want to run their own).

This would involve adding user (organizer) accounts and stuff (and then supporting multiple events running at the same time), setting up a system where people can create events at eventname.<domain> or <domain>/event, and a bunch of other changes like this.

This would probably be a pretty substantial project.

Make the UI better

Yeah, there's a lot of work to be done. Right now, there's basically no styling, so it looks pretty ugly.

Help would be very much appreciated!

This is pretty involved and involves substantial changes, so post here before you start working if you're interested in working on the issue.

Document code better

Yeah… haven't had time to do that yet, but I thought it would be good to open-source this project now. If people want to contribute to this effort, that would be awesome, otherwise I'll probably get to it… eventually…

Node version?

We may be implementing a Node.js version. Subscribe to this issue if you're interested in contributing to that!

Change terminology

As referenced in Gitter, Freetail Hackers (org that runs HackTX) found the terms "annotators" and "items" a bit confusing when we first started looking at Gavel. It would be nice to have the frontend call them "judges" and "projects" instead.

Hacker view

Currently, the app is just designed for judges, and hackers don't interact with it at all.

It could be cool to have some sort of hacker view.

It looks like some other people have thought about this. See hemangandhi@efdec39.

Add explanation for error when removing active judges/projects

Gavel doesn't let you remove judges or projects once they've started (if a project has been judged a nonzero number of times / if a judge has completed a judging). It shows a pretty opaque error message (about a foreign key constraint). It would be nice to show a more understandable error message (or better yet, implement recursive deletion and provide a prompt that asks if people want to do this).

Labeling this as a bug, even though it's not exactly an implementation bug (it's intentional), but it's kinda a UX bug.

Add ability to undo votes and/or clear all votes?

From his experience at HackPrinceton, @zacharyliu said that some issues that they had were:

  • weird issue where one judge had 69 recorded votes within a few minutes, while the others had only ~20 votes by the end
  • some judges started hitting random buttons even when we told them not to
  • unable to delete bad votes from when judges hit random buttons before starting
  • no way to undo accidental votes

Maybe we can improve this by adding:

  • an ability to undo the last vote (to the judge UI)
  • an ability for the organizers to clear votes for a specific judge / clear all votes

We need to have some discussion about exactly how this should be implemented.

Make admin panel live

Factoring out the "auto-reload" from issue #52

Currently, seeing updated data in the admin panel requires a manual reload of the page. It would be nice to make the admin panel live. A lazy way to do that would be to add a meta refresh, but that could be intrusive (it's bad if the page reloads while someone is in the middle of reading something / doing something). A better way to do that would probably be to fetch data using javascript and update the current page without reloading the whole thing.

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.