tensorflow / tensorflow

An Open Source Machine Learning Framework for Everyone
https://tensorflow.org
Apache License 2.0
186.24k stars 74.3k forks source link

Go API #10

Closed alonsovidales closed 7 years ago

alonsovidales commented 9 years ago

Hi!, I'm really interested on contribute in my spare time on this project, it would be great for me port the Python libraries to Go, or help with this task, the problem is that after read the "Contributing guidelines" I still don't know how to do it. I tried to sing the Individual CLA, but I get an error that says: "You must be an owner of the contributors group in order to submit this CLA.".

Btw, are you working, or do you plan to implement soon the Go libs?

Some related projects that I implemented in Go: https://github.com/alonsovidales/pit - This is a distributed recommender system based in the "Adaptive Bootstrapping of Recommender Systems Using Decision Trees" paper by Yahoo. The site of the project: http://pitia.info/ And the Go ML: Some machine learning algorithms in Go: https://github.com/alonsovidales/go_ml I also implemented Neural Networks with CUDA: https://github.com/alonsovidales/go_ml/tree/cuda_implementation

Thanks,

jamesliu96 commented 9 years ago

:+1:

pcasaretto commented 9 years ago

I'd be interested in helping @alonsovidales !

jamesliu96 commented 9 years ago

Idk if I'm qualified but I'd like to do whatever to help @alonsovidales !

mrkaspa commented 9 years ago

I can help too because I need this library in Go

chai2010 commented 9 years ago

+1/0

alonsovidales commented 9 years ago

I still have no answer, but we could start working on the libs, and if Google wants, they can use the code, if not we can release the libs as a separate project :) I think that this shouldn't be a problem since the project is licensed using an Apache 2.0 license. My main concern is that we could be doing the same that they are doing the same in parallel, so, by the moment we can keep reading and trying to understand how the currently available libs works, and if this weekend we don't have any news, we can prepare, plan and distribute the different tasks to do the libraries.

What do you think? I'm going to send an e-mail to the golang-nuts mail list.

jamesliu96 commented 9 years ago

agree! wait till weekend then we can decide.

hachi8833 commented 9 years ago

:+1:

1l0 commented 8 years ago

Great move!

vincentvanhoucke commented 8 years ago

The current state of Go is that we have a few people who've expressed interest internally in contributing language bindings, but nothing concrete at the moment. I would suggest that if you got started on this, which would be awesome, you could whip up a proposal (preferably in the form of prototype code) and run the design by the discuss mailing list.

alonsovidales commented 8 years ago

Thanks @vincentvanhoucke , then, let's try to prepare a prototype and let's see how it works :) I had been digging a bit in the Python libs, and it shouldn't be too difficult to prepare the Go libraries.

Btw, which is the discuss mailing list?, I can't find it.

I love the project and it would be awesome for me be able to contribute.

alonsovidales commented 8 years ago

Found the discuss mailing list, sorry :)

davidzchen commented 8 years ago

Should we keep this issue open to track this? I think all the other Go-related issues were de-duped against this one.

alonsovidales commented 8 years ago

Sure, better keep this issue open so other people can find it easily.

I think that it would be better to move the conversation about the prototype, etc to another place, we can:

Regarding to the prototype, my proposal is to use one of the examples: http://tensorflow.org/tutorials/mnist/beginners/index.md And studying how the Python libs works, port just all the involved code to execute the example, since an example like the one for beginners covers most of the functionality, and can give us a great overview of how to port all the libraries. To reproduce the behaviour of the Python libs, the best option would be to use TDD, we can go method by method and based on the input/output of the python code prepare the test on Go.

We can distribute the tasks to prepare the prototype or work in parallel and put all our ideas together at the end. Since for me the goal here is try to get a general idea about how to implement the final version, tasks that we have to do, etc, I think that work in parallel can be a good approach.

What do you think?

babakgh commented 8 years ago

:+1:

alonsovidales commented 8 years ago

Just a little update of what I have been researching this weekend. I couldn't find too much time for this, but I made some small progresses.

I have been researching how the Python libs works internally, and basically, the logic to generate the graph and plan how to execute it, etc is managed from Python that sends all the graph to be executed to the C++ libraries, this libs take the graph and executes all the nodes of the graph. They are working on a pure C++ version of this logic, but it is still not ready. In order to execute the C++ code from python they use SWIG: www.swig.org and to build the system Bazel: http://bazel.io/ . The good news is that SWIG also supports Go ( http://www.swig.org/Doc2.0/Go.html ) and Bazel introduces support for Go ( http://bazel.io/docs/be/go.html ) after the 0.1.1 version. The bad news are that I couldn't build the system using Bazel 0.1.1 by many different problems with the linker, etc that I'm trying to resolve. And the other problem is that we have to create the .i files for SWIG in order to prepare the build for Go, I almost have this part done, but I'm also having a lot of problems. The main issue is that I have no experience with Bazel and SWIG, so I'm spending most of the time reading documentation and trying to fix stupid problems caused because of I misunderstand something from the docu.

In case of I finally can't prepare a wrapper using SWIG, I think that I'm going to try to prepare the prototype using cgo directly, I already have a small proof of concept that generates the session in Go, but it would be much better if the libs works with SWIG and Bazel as the Python libs does.

I'm not having too much spare time lately, but it is being super interesting for me to research how all this system is done, the code is pretty well documented, and easy to understand.

nathangoulding commented 8 years ago

It seems like Bazel doesn't yet have C/C++ interop for Go so cgo may be the only option unless Bazel adds support for it soon. http://bazel.io/docs/be/go.html

alonsovidales commented 8 years ago

I think that it would be possible to do a small workaround using a sh_binary to compile run swig like they are doing with the Python libs: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/BUILD#L21 But by the moment for the PoC I'm using an ugly MakeFile: https://github.com/alonsovidales/tensorflow/blob/master/tensorflow/go/makefile And setting the flags for the linker here: https://github.com/alonsovidales/tensorflow/blob/master/tensorflow/go/cgoflags.go And also a wrapper to access the C++ libraries from C: https://github.com/alonsovidales/tensorflow/tree/master/tensorflow/go/wrapper But this is just for the prototype, I plan to move all to Bazel + SWIG :)

nathangoulding commented 8 years ago

I'm still not 100% clear on the long-term delineation between the external library's responsibilities and the underlying TF C++ API.

From http://www.tensorflow.org/api_docs/cc/index.html, this sentence implies that maybe at some point in the future the C++ libraries will add the support to build the graphs: "TensorFlow's public C++ API includes only the API for executing graphs, as of version 0.5."

It seems like the supported way outside of python is to still use python to build the graph, then use tf.train.write_graph() to write the graph to a file, and then load it into a session in your language of choice and then run it using the C++ API.

Are you planning to port the graph building mechanism into Go? It seems like it might be a good idea to get the consensus of the TF dev team before embarking on something as ambitious as that if they're planning on supporting this in the public API at some point in the future.

alonsovidales commented 8 years ago

Well, my idea is to build the graph in the Go libs as it is being builded by the Python libs. They are working on the C++ code, but by the moment it is a WIP and it is, by the moment, unstable.

I'm not sure about their future plans, but from my point of view have this process in Python is not a bad approach since the tensors takes a lot of advantage of the dynamic typing and operators overloading that Python offers, this makes the code more simple to write and to understand, this is being one of the biggest problem I'm having porting the code to Go. I also think that keep the graph building process in Python is a good idea since this process requires almost no time compared with the operations that are implemented in C++, so scarify simplicity in favour of performance don't makes too much sense. I think that they make the good choice here.

I'm planning to port the process to Go by two reasons:

And well, port the process is going to be funny for me :)

vladimirvivien commented 8 years ago

@alonsovidales any movement on your PoC ?

alonsovidales commented 8 years ago

No :'( I had a personal problem and I couldn't spend a single min on personal projects during last month, I'll try to resume it on next week.

tmc commented 8 years ago

I have a start of a swig-based binding started here: tmc/tensorflow/go_bindings -- mostly cargo-culted and incomplete.

⚛ ~/go/src/github.com/tensorflow/tensorflow(go_bindings)$ cat tensorflow_test.go
package tensorflow_test

import (
    "fmt"
    "testing"

    "github.com/davecgh/go-spew/spew"
    "github.com/golang/protobuf/proto"
    "github.com/tensorflow/tensorflow"
    tf "github.com/tensorflow/tensorflow/tensorflow/go"
)

var exampleGraph = `node {
  name: "output1"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_STRING
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_STRING
        tensor_shape {
        }
        string_val: "Hello, TensorFlow!"
      }
    }
  }
}
node {
  name: "Const_1"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_INT32
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_INT32
        tensor_shape {
        }
        int_val: 10
      }
    }
  }
}
node {
  name: "Const_2"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_INT32
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_INT32
        tensor_shape {
        }
        int_val: 32
      }
    }
  }
}
node {
  name: "output2"
  op: "Add"
  input: "Const_1"
  input: "Const_2"
  attr {
    key: "T"
    value {
      type: DT_INT32
    }
  }
}
version: 5`

func TestNewSession(t *testing.T) {
    graph := &tf.GraphDef{}
    if err := proto.UnmarshalText(exampleGraph, graph); err != nil {
        t.Fatal(err)
    }
    s, err := tensorflow.NewSession()
    if err := s.ExtendGraph(graph); err != nil {
        t.Fatal(err)
    }
    output, err := s.Run(nil, []string{"output1", "output2"}, nil)
    if err != nil {
        t.Fatal(err)
    }
    fmt.Println(output)
    for _, out := range output {
        spew.Dump(out, out.Data())
    }
}
⚛ ~/go/src/github.com/tensorflow/tensorflow(go_bindings)$ go test
[DT_STRING: dims:0 size:27 DT_INT32: dims:0 size:4]
(*tensorflow.Tensor)(0xc820011050)(DT_STRING: dims:0 size:27)
([]uint8) (len=27 cap=27) {
 00000000  00 00 00 00 00 00 00 00  12 48 65 6c 6c 6f 2c 20  |.........Hello, |
 00000010  54 65 6e 73 6f 72 46 6c  6f 77 21                 |TensorFlow!|
}
(*tensorflow.Tensor)(0xc820011080)(DT_INT32: dims:0 size:4)
([]uint8) (len=4 cap=4) {
 00000000  2a 00 00 00                                       |*...|
}
PASS
ok      github.com/tensorflow/tensorflow    0.082s
michilu commented 8 years ago

:+1:

lerenn commented 8 years ago

:+1:

dave-andersen commented 8 years ago

tmc sent a pull request - https://github.com/tensorflow/tensorflow/pull/1237 - which we should be able to get in with a few iterations.

alonsovidales commented 8 years ago

Hi, Based on the @tmc work I'm working on some helpers to create tensors from Go, to access to their data and so on. I'm also trying to cover all the code with tests.

This is the branch where I'm working: https://github.com/alonsovidales/tensorflow/tree/go_bindings_tensors/tensorflow/go

There is a practical example in the README.md that shows how to create and export the Graph from Python, import it on Go, create some tensors from Go in an easy way and read the execution outputs. More or less all the necessary process to run our graphs in Go :) You can also check the *_tests.go to see more practical examples.

This is a work in progress, there are some data types that are still not supported and I'm performing some important changes. I've made a PR to the origin branch, pls check the code and let me know your thoughts, how to improve it, possible bugs, etc: https://github.com/tmc/tensorflow/pull/1/files

I'll try to finish, test and stabilise the code as much as possible and prepare some of the tutos to work with the Go library. I plan to start with this one: https://www.tensorflow.org/versions/r0.7/tutorials/image_recognition/index.html

I also plan to add also methods to save and load tensors and for Graph generation (just for fun and this perhaps could be useful in some situations, but I think that is a better approach to generate and test the Graph on Python), thanks to protobuf this shouldn't be difficult to achieve.

alonsovidales commented 8 years ago

I finally have the C++ example of the Image Recognition tutorial ported to Go. Implement all the Graph construction, constants and other stuff was relatively easy since there is available the list of operations perfectly defined here:

Here you have the Go port of the tuto example:

that corresponds with:

This is how looks like running a picture of Ceres my Labrador:

avidales@bigbrain:~/go-src/src/github.com/tensorflow/tensorflow/tensorflow/examples/label_image_go$ go run main.go data/ceres_paris.jpg
Labrador retriever : 0.9383322
American Staffordshire terrier : 0.009385344
Rhodesian ridgeback : 0.007571198
Chesapeake Bay retriever : 0.0027833031
golden retriever : 0.0026763931

I'm going to clean the code and include a section for Go libs on the tutorial.

girving commented 8 years ago

@dave-andersen What's the status of this?

dave-andersen commented 8 years ago

Closed by #1771.

tmc commented 8 years ago

1771 appears to be in the 'go' branch but not master -- what's the plan to merge that in?

dave-andersen commented 8 years ago

Realistically, TBD. I've maybe found someone @ google who might be interested in taking ownership of the bigger picture of TF + go. I think we're of a mind that the current state isn't what we need yet -- it's not integrated with the normal tests, nor is it go-buildable in the normal way. Those are the major blockers to getting it into the main branch, but I think there's a further concern that because of the amount of magic that still happens only in Python with shapes & gradients, we're not at a point where we can have the Go bindings we'd like as a first-class supported language. There's some ongoing work looking at improving our ability to support more languages, and I think some of the momentum on Go is stalled waiting on that.

tmc commented 8 years ago

Fair enough. I personally just wanted a way to execute graphs vs have python-level support.

girving commented 8 years ago

Let's leave this bug open then, to go along with the bunch of other open language bugs that are much less far along.

Mistobaan commented 8 years ago

@alonsovidales are you still working on this ? I tried the go branch after a rebase and it works on my mac. Now I would like to propose some changes with a PR (https://github.com/Mistobaan/tensorflow/tree/go). But clearly the current go branch is behind respect to master and the PR is huge. Should we rebase the main go branch or merge it in master and keep continuing the development there? What is the best feasible strategy to keep patches coming into the go interface?

alonsovidales commented 8 years ago

Hi @Mistobaan , I've been a bit out the last months because I'm moving to Dublin. @dave-andersen mentions on a previous comment that someone at Google could be interested on taking ownership of the Go development, the code was lent in the Go branch waiting for the integration with Jenkins and for other people to play with it and provide some feedback, I'm not sure about what is the current status. I've took a look at your commit and it seems really interesting, I think that you could make a PR to the current branch and we can care to rebase it in a future :) I'm using the Go libs on some personal projects and I got feedback from other people that are using them, It would be awesome for us to count with improvements.

Mistobaan commented 8 years ago

@alonsovidales see #3258

damienstanton commented 8 years ago

FYI #3542 resolves a build error I experienced on the Go branch.

jmhodges commented 8 years ago

I've just published a PR to bump the go branch to the latest master and do some minor fixups in #4223

jmhodges commented 8 years ago

I'm not sure what's left to do in the go branch to get it merged to master. I might be able to help!

jmhodges commented 8 years ago

Updated #4223.

I think there was a goal of getting this to build with go get and go install. Currently, the generated protobuf doesn't have the right import paths to build correctly. (It's a version of the problem in https://github.com/golang/protobuf/issues/230)

We're going to have to probably do some sed work to fix it.

jhseu commented 8 years ago

Before you do more work on that branch, keep in mind that we have in-progress Go bindings that the TensorFlow team is making :)

jmhodges commented 8 years ago

That's cool! Didn't know! Maybe missed a comment. Anything I can do to help?

pyanfield commented 8 years ago

@jhseu , do you have any plan about when we can get the official release?

jhseu commented 8 years ago

We've got a handle on them :) For obvious reasons, we're particular about the structure of the Go API and some details (like autosubmitting generated protobuf code).

We need some additions to the C API (work-in-progress) to complete them. Should be in about a week or two.

jhseu commented 8 years ago

Note that it's here: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/go

We're making a more reasonable import path for people to use.

jmhodges commented 8 years ago

Cool! What's the plan for the protobuf generated packages? I'm currently copying the proto files into my own build to pop out the Go code I want and they just barely don't fit there trivially (because protoc-gen-proto has some rules about where its generated code goes and what import paths they refer to each other with)

jmhodges commented 8 years ago

Oh, man, after weeks of hunting, I just found https://github.com/golang/protobuf/issues/139 so now I understand how it'll work

asimshankar commented 8 years ago

@jmhodges : So far whatever functionality the Go API provides doesn't require protobuf. But of course, the functionality is limited at this point.

If y'all have any feedback on the API as it is today and what you'd find most useful in terms of additional functionality or changes, we'd greatly appreciate that.

asimshankar commented 7 years ago

Hello folks, the Go API is in a reasonably usable shape at this point. Graphs can be imported, executed, constructed (using primitives or functions generated from the TensorFlow op definitions). See the example on godoc.org that demonstrates all this.

The API is by no means complete, but at this point I'm tempted to close out this generic "Go API" issue with the expectation that as the Go API sees real usage, new issues will be filed with specific feature requests and bug reports.