Git Product home page Git Product logo

libmelee's Introduction

libmelee

Open API written in Python 3 for making your own Smash Bros: Melee AI that works with Slippi Online

Installing Libmelee

Libmelee is on pip, this will be the easiest way to get the library and stay updated.

pip3 install melee

And definitely stay updated, as the library will be actively improved.

pip3 install --upgrade melee

Setup Instructions

Linux / OSX / Windows

  1. Install and configure Slippi, just like you would for rollback netplay. Full instructions here: https://slippi.gg

  2. If you're on Linux using the official appimage, extract it using ./Slippi_Online-x86_64.AppImage --appimage-extract. This will pull apart the app image into a folder in the same directory.

  3. If you want to play interactively with or against your AI, you'll probably want a GameCube Adapter, available on Amazon here: https://www.amazon.com/Super-Smash-GameCube-Adapter-Wii-U/dp/B00L3LQ1FI. Or alternatively the HitBox adapter works well too: https://www.hitboxarcade.com/products/gamecube-controller-adapter

  4. Install some custom Slippi Gecko Codes. You can find them here: https://github.com/altf4/slippi-ssbm-asm/blob/libmelee/Output/Netplay/GALE01r2.ini Simply replace your existing GALE01r2.ini file with this one. On Linux with the appimage, the file is located at squashfs-root/usr/bin/Sys/GameSettings/GALE01r2.ini.

  5. Make sure you have all the Required and Recommended Gecko Codes enabled.

  6. Run ./example.py -e PATH_TO_SLIPPI_FOLDER (Not the exe itself, the folder) If you're using the Linux appimage, set this to squashfs-root/usr/bin/.

Playing Online

Do not play on Unranked There is no libmelee option for it, but don't try. Eventually we'll have a way to register an account as a "bot account" that others will have the ability to opt in or out of playing against. But we don't have it yet. Until then, do not play any bots on Unranked. If you do, we'll know about it, ban your account, overcook all of your food, and seed you against a campy Luigi every tournament. Don't do it.

Quickstart Video

Here's a ~10 minute video that will show you how easy it can be to write a Melee AI from scratch. Libmelee Quickstart Video

Some of the minor aspects of the API have changed since this video was made, but it's still a good resource.

The API

This readme will give you a very high level overview of the API. For a more detailed view into specific functions and their params, check out the ReadTheDocs page here: https://libmelee.readthedocs.io/

GameState

The GameState represents the current state of the game as a snapshot in time. It's your primary way to view what's happening in the game, holding all the information about the game that you probably care about including things like:

  • Current frame count
  • Current stage

Also a list of PlayerState objects that represent the state of the 4 players:

  • Character X,Y coordinates
  • Animation of each character
  • Which frame of the animation the character is in

The GameState object should be treated as immutable. Changing it won't have any effect on the game, and you'll receive a new copy each frame anyway.

Note About Consistency and Binary Compatibility

Libmelee tries to create a sensible and intuitive API for Melee. So it may break with some low-level binary structures that the game creates. Some examples:

  • Melee is wildly inconsistent with whether animations start at 0 or 1. For some animations, the first frame is 0, for others the first frame is 1. This is very annoying when trying to program a bot. So libmelee re-indexes all animations to start at 1. This way the math is always simple and consistent. IE: If grab comes out on "frame 7", you can reliably check character.animation_frame == 7.
  • Libmelee treats Sheik and Zelda as one character that transforms back and forth. This is actually not how the game stores the characters internally, though. Internally to Melee, Sheik and Zelda are the same as Ice Climbers: there's always two of them. One just happens to be invisible and intangible at a time. But dealing with that would be a pain.

Some Values are Unintuitive but Unavoidable

Other values in Melee are unintuitive, but are a core aspect of how the game works so we can't abstract it away.

  • Melee doesn't have just two velocity values (X, Y) it has five! In particular, the game tracks separately your speed "due to being hit" versus "self-induced" speed. This is why after an Amsah tech, you can still go flying off stage. Because your "attack based speed" was high despite not moving anywhere for a while. Libmelee could produce a single X,Y speed pair but this would not accurately represent the game state. (For example, SmashBot fails at tech chasing without these 5 speed values)
  • Melee tracks whether or not you're "on ground" separately from your character's Y position. It's entirely possible to be "in the air" but be below the stage, and also possible to be "on ground" but have a positive Y value. This is just how the game works and we can't easily abstract this away.
  • Your character model can be in a position very different from the X, Y coordinates. A great example of this is Marth's Forward Smash. Marth leans WAAAAY forward when doing this attack, but his X position never actually changes. This is why Marth can smash off the stage and be "standing" on empty air in the middle of it. (Because the game never actually moves Marth's position forward)

Controller

Libmelee lets you programatically press buttons on a virtual controller via Dolphin's named pipes input mechanism. The interface for this is pretty simple, after setting up a controller and connecting it, you can:

controller.press_button(melee.enums.BUTTON_A)

or

controller.release_button(melee.enums.BUTTON_A)

Or tilt one of the analog sticks by:

controller.tilt_analog(melee.enums.BUTTON_MAIN, X, Y)

(X and Y are numbers between 0->1. Where 0 is left/down and 1 is right/up. 0.5 is neutral)

Note on Controller Input

Dolphin will accept whatever your last button input was each frame. So if you press A, and then release A on the same frame, only the last action will matter and A will never be seen as pressed to the game.

Also, if you don't press a button, Dolphin will just use whatever you pressed last frame. So for example, if on frame 1 you press A, and on frame 2 you press Y, both A and Y will be pressed. The controller does not release buttons for you between frames. Though there is a helper function:

controller.release_all()

which will release all buttons and set all sticks / shoulders to neutral.

API Changes

Each of these old values will be removed in version 1.0.0. So update your programs!

  1. gamestate.player has been changed to gamestate.players (plural) to be more Pythonic.
  2. gamestate.x and gamestate.y have been combined into a named tuple: gamestate.position. So you can now access it via gamestate.position.x.
  3. projectile.x and projectile.y have been combined into a named tuple: projectile.position. So you can now access it via projectile.position.x.
  4. projectile.x_speed and projectile.y_speed have been combined into a named tuple: projectile.speed. So you can now access it via projectile.speed.x
  5. gamestate.stage_select_cursor_x and gamestate.stage_select_cursor_x have both been combined into the PlayerState cursor. It makes the API cleaner to just have cursor be separate for each player, even though it's a shared cursor there.
  6. playerstate.character_selected has been combined into playerstate.charcter. Just use the menu to know the context.
  7. playerstate.ecb_left and the rest have been combined into named tuples like: playerstate.ecb.left.x for each of left, right, top, bottom. And x, y coords.
  8. hitlag boolean has been changed to hitlag_left int
  9. ProjectileSubtype has been renamed to ProjectileType to refer to its primary type enum. There is a new subtype int that refers to a subtype.

OpenAI Gym

libmelee is inspired by, but not exactly conforming to, the OpenAI Gym API.

libmelee's People

Contributors

altf4 avatar atvo912 avatar cabrinegar avatar emersonye avatar kevincranmer avatar pnivlek avatar seanbenner avatar vladfi1 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

libmelee's Issues

Expose button presses in libmelee API

I'm curious about writing a bot to play like a human. I would do this by playing many games and recording my inputs and making the bot "play like me" using supervised learning rather than reinforcement learning.

Is there an easy way to get controller inputs / actions from libmelee?

Thanks in advance,
Jack McKeown

dolphin.run(render=False)

Ran into a problem with libmelee when trying to set dolphin.run(render=False)
It work as intended but setting it back to true did not go back to original settings. It just continued to not render and run in lightning speed.

Tested: restarting my computer but it did not help.
Tested: going back to the original example code, did not work

What I needed to do in the end was going in to dolphin Options>Graphics Settings > General and change the back-end rendered manually

APM count

Keep track of APM. Define what an "action" is in this context, too.

Multiple Opponents / Allies

Let's generalize / cleanup the controller choosing code so that we can support multiple opponents and allies. Currently, libmelee assumes that there is exactly one AI player and exactly one opponent.

Helper functions for stage boundaries

It would be really nice to be able to get some values for the stage boundaries. (Blast zones)

IE: Final D: Left: -246.00, Top:188.00, Right: 246.00, Bottom: -140.00

unknown pointer crash

I'm running into a problem with example.py
As far as I can tell, the setup looks good. Everything looks the same as it did when I used smashbot.
I recompiled the linked dolphin, and it loads melee 1.02 fine.

However when running example.py: Dolpgin can't start Melee as it errors out immediately with
Unknown Pointer 0x10000066 PC 0x8000522c LR 0x00000000

I can't find anyone else who has had this specific issue with Melee, only Paper Mario.
Any thoughts?

EDIT more info. This is specifically something that happens to dolphin itself upon running example for the first time that renders it unusable. But I can't find what happens in dolphin.py (I'm guessing) that causes it

TODO: Figure out the best way to add projectiles to the list

I'm not sure if you've been working on this or not but I was looking at the gamestate.py and was thinking why not just append the projectile objects themselves to the list?

Never mind the projectile list is already a list of projectile objects. What's wrong with appending that list to the gamestate list?

Feature Request: Auto select ai character

It would be nice if I could identify what character is selected for the AI (I'm currently selecting it manually with a controller) instead of selecting it when calling the script (like in the example). The idea is that I will be able to change the RL player depending on the selection instead of restarting dolphin, which is kind of annoying. I would like to work on this, but, any ideas of where could I start @altf4?

Breaks Other Versions of Dolphin

After installing the package and running the example script, dolphin emulator keeps crashing with the error: Unknown Pointer 0x10000066 PC 0x8000522c LR 0x00000000 I've tried uninstalling with sudo apt-get purge --auto-remove dolphin but this issue still persists even after reinstalling dolphin. Would appreciate any help so I don't have to reinstall Ubuntu.

Dolphin Build Linked in README.md Fails to Build

When trying to build from https://github.com/altf4/dolphin/tree/memorywatcher, I would get this error message when make starting building the MemoryWatcher.cpp file.

/home/user/Projects/Smash/dolphin/Source/Core/Core/MemoryWatcher.cpp:147:74: error: too many arguments to function ‘void Memory::CopyFromEmu(void*, u32, size_t)’
     if (!Memory::CopyFromEmu(&value, value + offset, sizeof(value), false))
                                                                          ^
In file included from /home/user/Projects/Smash/dolphin/Source/Core/Core/MemoryWatcher.cpp:14:0:
/home/user/Projects/Smash/dolphin/Source/Core/Core/HW/Memmap.h:75:6: note: declared here
 void CopyFromEmu(void* data, u32 address, size_t size);
      ^~~~~~~~~~~
/home/user/Projects/Smash/dolphin/Source/Core/Core/MemoryWatcher.cpp:147:29: error: could not convert ‘Memory::CopyFromEmu(((void*)(& value)), (value + offset), sizeof (value))’ from ‘void’ to ‘bool’
     if (!Memory::CopyFromEmu(&value, value + offset, sizeof(value), false))
          ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/user/Projects/Smash/dolphin/Source/Core/Core/MemoryWatcher.cpp:147:74: error: in argument to unary !
     if (!Memory::CopyFromEmu(&value, value + offset, sizeof(value), false))
                                                                          ^
Source/Core/Core/CMakeFiles/core.dir/build.make:5538: recipe for target 'Source/Core/Core/CMakeFiles/core.dir/MemoryWatcher.cpp.o' failed

I managed to fix this problem by instead using the memorywatcher-rebase branch, and editing the MemoryWatcher.cpp file to match this commit: altf4/dolphin@97abbdd

Now I can run dolphin and use libmelee as intended.

SLP File support?

The console documentation indicates that libmelee has yet to fully-support SLP files.
I was wondering what the current level of support is for SLP files. Can character positions (x/y) be retrieved with the current level of support?

Define and enforce minimim SLP version

We need to figure out what the minimum SLP version that libmelee is going to support, and reject things older than that.

Off the top of my head, 3.0.0 is probably it, since that's when a lot of important game state info got added.

Implement helper attributes

There are some useful bits of derived information that ought to be exposed in an easy way. So that the caller doesn't need to constantly recompute it themselves:

  • Absolute distance to opponent(s)
  • is_off_stage boolean (are we horizontally off the edge of the stage?)
  • etc... (think of more)

Randall location

Libmelee needs a function to get the current location of Randall.

All that we ought to need is the current frame number to calculate the position.

Function should look like:

randall_position(frame)

And it should return a tuple (x, y) where X is the center of Randall and Y is the height of a player standing on Randall. The "center" of randall should be defined as the center point between the X positions of a character teetering on the edges.

Scope of project- modifying memory address values

I am interested in adding the ability to modify game memory state (in order to implement training programs, among other things). Two questions:

  1. Would the project owner (@altf4) be open to expanding the scope of the project to include this, or should I create my own fork?

  2. Does Dolphin provide any mechanism for modifying memory address values?

Building Melee Undelcared identifier error

Hello! I was building your Dolphin project and received the error shown in the attached image. I am running MacOS Sierra V 10.12.6. Any insight into what my problem might be?
screen shot 2018-04-20 at 9 26 53 pm

Support for older slp replays

Hi altf4,
I really appreciate the support of slp files in the console class.

I've noticed that older replay files (I've tested it with a file from Genesis 7) only ever have EventTypes PRE_FRAME and POST_FRAME (and GAME_END once). The process is then stuck in this loop since frame_ended won't turn True.

Is there hope for these older replay files?

How can I help?

Dude, this is an awesome idea! If you want some help, don't hesitate to share the roadmap 😃

Support for dynamic stage platform locations

FoD and Stadium, specifically.

FoD is easier, there's just two platforms and they change only in height. Finding their locations shouldn't be hard.

Stadium... is harder. There's a tree, and a windmill... I have no clue how it's stored or what the best way to read it would be.

"Double-click to set a games directory..." button is missing

I compiled AltF4's version of Dolphin successfully, and running smashbot.py opens Dolphin, then I can select Melee from there using Open folder. However, I need to open the games directory to edit Gecko codes!! Without it I can't right click the Melee game button to change properties. Here is what my Dolphin looks like:
image

Did I not compile it right? The bot won't take control of Fox or move the cursor. Currently acts as if there isn't a bot, probably bc I don't have FD yet, not sure though. Any suggestions would be great, thanks.

Normalize action frame initializations

An action's "action_counter" is an important number, to know what frame of an animation someone is in. Unfortunately, Melee is inconsistent on whether this counter starts at 0 or at 1. It depends on what animation it is.

Let's normalize this and make it so that every animation starts at frame 1. This is already (mostly) done in the C++ version of SmashBot here, but it needs to be ported in.

https://github.com/altf4/SmashBot/blob/master/Util/GameState.cpp#L1057

I know it's a little heretical to make something index from 1, but it makes our numbers make more intuitive sense. Don't think of this number as an index at all, in fact, but rather a counter. For instance, you may want to know when the hitbox of a particular attack first shows up. Suppose it's Fox's upsmash, which happens on frame 7. You'll do something like:

if opponent_state.action_frame == 7:
    #do something here

port_detector gets it wrong half the time in a ditto

In offline matches, what port your bot is playing on is pretty trivial to find. You have to configure it when you make the console and it doesn't change.

But in online matches, you're assigned a controller port essentially at random (it's not actually random, but it might as well be). So how are we supposed to know what port our bot and our opponent are on?

port_detector() is a little helper function that's pretty stupid. It just looks at the characters in the game and figures that your bot must bot on the port that is the correct character! If your bot plays Falco, then obviously it's the Falco in the Falco vs Marth.

But what happens when the match is a ditto? Well... we just sort of assume that the bot is on port one.

This is hard to fix, because the SLP spec only has player tags in the metadata field, which is computed after the game is over. We need to add it to the game start event, which is... tricky.

Support Sheik and IC's

Melee stores Sheik and Zelda as separate characters, both of which exist at all times. When you "transform", you're actually not changing into Sheik (in terms of the game's data structures) but rather Zelda goes into an invisible and inactive state. It's just like Nana/Popo.

libmelee currently doesn't even see Sheik / Nana, since we're only looking at one character. Look into what it would take to see Sheik / Nana. (It might be something as simple as an addition to Locations.txt, or it might be complicated and require a Dolphin patch)

MacOS Support

As mentioned, the MacOS support is supposed to work, but it's not really the case.

When the folders MemoryWatch is in my Application\ Support/Dolphin, I keep getting a pointer error when launching any game.
capture d ecran 2017-09-15 a 16 31 05
capture d ecran 2017-09-15 a 16 31 33

Having full mac support would be a blast, thanks

Initial dash forward

If you dash forward while not already in dashdance, you must dash forward initially for at least 3 frames before you can input a dash back. For any dashes which take place after a smash turn (i.e. an initial backdash, or any subsequent dashes), you can turnaround/dashback any time as soon as DASHING frame 1.

Right now, libmelee does not keep track of whether or not you're in this "initial dash" state

Notes on current proposed changes

Optional unit-circle based stick tilt, e.g. tilt_analog_unit(x, y) where x and y are unit vectors, or tilt_unit_degrees(float). tilt_unit_degrees could be useful for any change in degrees over time.

Character detection on Slippi occasionally faults if both players select the same character. (Or maybe the other player is also a bot who is performing the same character check...?)

controller.empty_input() renamed to controller.release_all()

Character Support in framedata

We don't yet fully have support for all characters in the framedata. Currently missing:

Doc
Mario
Luigi
Bowser
Yoshi
DK
Ganondorf
Ness
Ice Climbers
Kirby
Link
Y Link
Pichu
Mewtwo
G&W
Roy

Of these, Ice Climbers is going to be the most challenging. Since there's two of them.... Making it so that it doesn't bork the whole API is going to be difficult. Much of the API and logic assumes that you only have one character at a time. I'll have to think about it.

Controller won't connect on latest dolphin rebased, memorywatcher-rebased version doesn't work

Hi,

I tried to install the version of memorywatcher-rebased dolphin you linked, but it won't run properly on linux (ubuntu 18.04).

I then downloaded latest dolphin off github and rebased your changes on to it, however, the controller won't run. The code in example.py makes it all the way to the controller connection line but does not progress past that.

Do you have any fix for making the controller work? Any help would be amazing, as we are on a deadline for a project.

Thanks

Ignore projectiles without hit/hurtboxes.

Some projectiles have neither hit nor hurboxes. Falco's Gun, for example, is its own "projectile". There's no reason to expose these over the libmelee API. Let's ignore all projectiles that have neither a hit nor hurtbox. They have no impact on the game and just mess up logic.

Compile frame data helper functions

We need helper functions to be able to pull up information about every action in the game for every character. I'm imagining this would come in the form of a CSV file as the backend data, with helper functions to expose information including:

  • Is this animation a roll? (For a liberal definition of "roll", including spot dodges, techs and such)
  • Is the animation a grab?
  • Is the animation an attack?
  • What is the first frame a hit/grab box happens?
  • When does the last hitbox frame go away? (the last frame that has a hitbox)
  • How long is the animation?
  • What is the first frame the animation is interruptible?
  • Can the animation be L-canceled?
  • What is the first frame of invincibility?
  • What is the last frame of invincibility?

Hit/grab box sizes:

  • Hitbox offset (from character center)
  • Hitbox radius

Occasional skipping of postgame

I think I did this to myself, pretty positive actually.
But melee will pretty often skip the post-game altogether.
When a match is finished, the next frame is just the next match, skipping post-game, character select, and stage select.
The given example works fine, so its not my dolphin installation.
Nevertheless I can't find where I would have even enabled some sort of persistent game option.

menuhelper.choosecharacter should work for any controller

Right now it uses gamestate.ai_state, but there are cases where you want several bots on several controllers.

Probably the best fix is for the Controller class to record the port and control using gamestate.player[controller.port].

Error running dolphin

I followed your setup instructions by building dolphin from the commit here and installing your PyPI package. I run run ./dolphin-emu and interact with the GUI just fine. However, when I try to start the game, I get the error

This does not seem to be a copy of Super Smash Bros. Melee. Please use regular Dolphin (https://dolphin-emu.org/) for running games other than Super Smash Bros. Melee.

I am confident it is not an issue with my ISO. I verified the checksum, and it works with both the official version of dolphin, as well as the slippi r18 build. My question is, should I be building dolphin from the exact commit I linked or is there a different version used to reproduce your results?

Command

Run ./dolphin-emu and manually select the ISO from the GUI. Running ./example.py -e PATH/TO/DOLPHIN breaks with the same error

Expected Behavior

I should be able to launch the SSBM game either from inside dolphin or from the example.py script

System info

OS: Ubuntu 18.04
Python 3.6

Aerial landing lag values

Melee does not store landing lag as simply as non lcanceled landing lag vs l canceled landing lag. For whatever reason, the stored landing lag animations are like, twice the duration of even a non l-canceled aerial, and it just skips frames for some reason. whenever you l-cancel, it just skips more frames at a time, and it's different for every aerial
For example

L canceled nair: (1, 5, 9, 13, 18, 22, 26) - 7 frames total, goes up by 4 each time
Non L canceled nair: (1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29) - 15 frames total, going up by 2 each time

L canceled dair: (1, 4, 7, 11, 14, 17, 21, 24, 27) - 9 frames total, going up by 3
Non L-canceled dair: (1, 2, 4, 6, 7, 9, 11, 12, 14, 16, 17, 19, 21, 22, 24, 26, 27, 29) - 18 frames total, going up by 1 OR 2

Windows Support

I'd like to have Windows support in libmelee, but there's some roadblocks:

  1. Dolphin talks to libmelee via its MemoryWatcher feature, using a Unix Domain Socket as the transport. As the name suggests, this doesn't exist on Windows. Some other roughly equivalent transport will have to be made there, and integrated into Dolphin's code.

  2. Paths in libmelee will have to be updated to read Dolphin's config files on a Windows filesystem.

AI state cursor not updating

In the character selection screen, it loops in the following block:

#Move up if we're too low
if ai_state.cursor_y < target_y - wiggleroom:
    controller.tilt_analog(enums.Button.BUTTON_MAIN, .5, 1)
     return

being, and not updating:

cursor_y: 1.9197228441864264e-40
cursor_x: 1.9196667922478534e-40

My version is:

─── dolphin-emu-nogui -version
Dolphin [memorywatcher] 5.0-523

cannot import filterfalse

Any familiarity with this issue?

libmelee git:(master) python example.py
Traceback (most recent call last):
  File "example.py", line 2, in <module>
    import melee
  File "/Users/joeyleung/workspace/melee/libmelee/melee/__init__.py", line 10, in <module>
    from melee import menuhelper, techskill, framedata, stages, dtmreader
  File "/Users/joeyleung/workspace/melee/libmelee/melee/framedata.py", line 6, in <module>
    from itertools import filterfalse
ImportError: cannot import name filterfalse```

SLP file console backend

Let's support reading from SLP files as a "console" backend. We can't meaningfully press buttons in this scenario, but it's useful for ML. Or any other applications that just want to read an SLP file from python

Support bot vs bot :enhancement

Haven't tried since 0.52 but I would really enjoy being able to test bots against each other.
Do you plan on supporting a bot vs bot ecosystem?
(am attempting to adapt smashbot to play falco, have a friend who is thinking about a rest bot)

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.