Giter VIP home page Giter VIP logo

tfdeploy's Introduction

tfdeploy logo

Build Status Documentation Status Package Status

Deploy tensorflow graphs for fast evaluation and export to tensorflow-less environments running NumPy.

Note

This project started as a personal playground to get an in-depth understanding of TensorFlow's operations and kernels. Up to a certain version, the NumPy based operations in tfdeploy provided full feature parity, but it is obvious that such a project cannot keep up with the vast development speed driven by TensorFlow devs and the open-source community.

Therefore, tfdeploy is no longer actively maintained. However, the code base remains active as an easy-to-read reference implementation for most of the kernels that constitute the heart of todays ML landscape.

Evaluation usage
import tfdeploy as td
import numpy as np

model = td.Model("/path/to/model.pkl")
inp, outp = model.get("input", "output")

batch = np.random.rand(10000, 784)
result = outp.eval({inp: batch})
Installation and dependencies

Via pip

pip install tfdeploy

or by simply copying the file into your project.

NumPy โ‰ฅ 1.10 should be installed on your system. SciPy is optional. See optimization for more info on optional packages.

By design, TensorFlow is required when creating a model.

Content

Why?

Working with TensorFlow is awesome. Model definition and training is simple yet powerful, and the range of built-in features is just striking.

Model deployment in environments that are not able to run TensorFlow, however, things can be difficult (note that tfdeploy was developed before TensorFlow Lite was a thing).

To boil it down, tfdeploy

  • is lightweight. A single file with < 150 lines of core code. Just copy it to your project.
  • faster than using TensorFlow's Tensor.eval.
  • does not need TensorFlow during evaluation.
  • only depends on NumPy.
  • can load one or more models from a single file.
  • does not support GPUs (maybe gnumpy is worth a try here).

How?

The central class is tfdeploy.Model. The following two examples demonstrate how a model can be created from a TensorFlow graph, saved to and loaded from disk, and eventually evaluated.

Convert your graph
import tensorflow as tf
import tfdeploy as td

# setup tfdeploy (only when creating models)
td.setup(tf)

# build your graph
sess = tf.Session()

# use names for input and output layers
x = tf.placeholder("float", shape=[None, 784], name="input")
W = tf.Variable(tf.truncated_normal([784, 100], stddev=0.05))
b = tf.Variable(tf.zeros([100]))
y = tf.nn.softmax(tf.matmul(x, W) + b, name="output")

sess.run(tf.global_variables_initializer())

# ... training ...

# create a tfdeploy model and save it to disk
model = td.Model()
model.add(y, sess) # y and all its ops and related tensors are added recursively
model.save("model.pkl")
Load the model and evaluate
import numpy as np
import tfdeploy as td

model = td.Model("model.pkl")

# shorthand to x and y
x, y = model.get("input", "output")

# evaluate
batch = np.random.rand(10000, 784)
result = y.eval({x: batch})
Write your own Operation

tfdeploy supports most of the Operation's implemented in tensorflow. However, if you miss one (in that case, submit a PR or an issue ;) ) or if you're using custom ops, you might want to extend tfdeploy by defining a new class op that inherits from tfdeploy.Operation:

import tensorflow as tf
import tfdeploy as td
import numpy as np

# setup tfdeploy (only when creating models)
td.setup(tf)

# ... write you model here ...

# let's assume your final tensor "y" relies on an op of type "InvertedSoftmax"
# before creating the td.Model, you should add that op to tfdeploy

class InvertedSoftmax(td.Operation):
    @staticmethod
    def func(a):
        e = np.exp(-a)
        # ops should return a tuple
        return np.divide(e, np.sum(e, axis=-1, keepdims=True)),

# this is equivalent to
# @td.Operation.factory
# def InvertedSoftmax(a):
#     e = np.exp(-a)
#     return np.divide(e, np.sum(e, axis=-1, keepdims=True)),

# now we're good to go
model = td.Model()
model.add(y, sess)
model.save("model.pkl")

When writing new ops, three things are important:

  • Try to avoid loops, prefer NumPy vectorization.
  • Return a tuple.
  • Don't change incoming tensors/arrays in-place, always work on and return copies.

Ensembles

tfdeploy provides a helper class to evaluate an ensemble of models: Ensemble. It can load multiple models, evaluate them and combine their output values using different methods.

# create the ensemble
ensemble = td.Ensemble(["model1.pkl", "model2.pkl", ...], method=td.METHOD_MEAN)

# get input and output tensors (which actually are TensorEnsemble instances)
input, output = ensemble.get("input", "output")

# evaluate the ensemble just like a normal model
batch = ...
value = output.eval({input: batch})

The return value of get() is a TensorEnsemble istance. It is basically a wrapper around multiple tensors and should be used as keys in the feed_dict of the eval() call.

You can choose between METHOD_MEAN (the default), METHOD_MAX and METHOD_MIN. If you want to use a custom ensembling method, use METHOD_CUSTOM and overwrite the static func_custom() method of the TensorEnsemble instance.

Optimization

Most ops are written using pure numpy. However, multiple implementations of the same op are allowed that may use additional third-party Python packages providing even faster functionality for some situations.

For example, NumPy does not provide a vectorized lgamma function. Thus, the standard tfdeploy.Lgamma op uses math.lgamma that was previously vectorized using numpy.vectorize. For these situations, additional implementations of the same op are possible (the lgamma example is quite academic, but this definitely makes sense for more sophisticated ops like pooling). We can simply tell the op to use its SciPy implementation instead:

td.Lgamma.use_impl(td.IMPL_SCIPY)

Currently, allowed implementation types are NumPy (IMPL_NUMPY, the default) and SciPy (IMPL_SCIPY).

Adding additional implementations

Additional implementations can be added by setting the impl attribute of the op factory or by using the add_impl decorator of existing operations. The first registered implementation will be the default one.

# create the default lgamma op with numpy implementation
lgamma_vec = np.vectorize(math.lgamma)

@td.Operation.factory
# equivalent to
# @td.Operation.factory(impl=td.IMPL_NUMPY)
def Lgamma(a):
    return lgamma_vec(a),

# add a scipy-based implementation
@Lgamma.add_impl(td.IMPL_SCIPY)
def Lgamma(a):
    return sp.special.gammaln(a),
Auto-optimization

If SciPy is available on your system, it is reasonable to use all ops in their SciPy implementation (if it exists, of course). This should be configured before you create any model from TensorFlow objects using the second argument of the setup function:

td.setup(tf, td.IMPL_SCIPY)

Ops that do not implement IMPL_SCIPY stick with the NumPy version (IMPL_NUMPY).

Performance

tfdeploy is lightweight (1 file, < 150 lines of core code) and fast. Internal evaluation calls have only very few overhead and tensor operations use NumPy vectorization. The actual performance depends on the ops in your graph. While most of the TensorFlow ops have a numpy equivalent or can be constructed from NumPy functions, a few ops require additional Python-based loops (e.g. BatchMatMul). But in many cases (and for small to medium graphs) it's potentially faster than using TensorFlow's Tensor.eval.

This is a comparison for a basic graph where all ops are vectorized (basically Add, MatMul and Softmax):

> ipython -i tests/perf/simple.py

In [1]: %timeit -n 100 test_tf()
100 loops, best of 3: 109 ms per loop

In [2]: %timeit -n 100 test_td()
100 loops, best of 3: 60.5 ms per loop

Contributing

If you want to contribute with new ops and features, I'm happy to receive pull requests. Just make sure to add a new test case to tests/core.py or tests/ops.py and run them via:

> python -m unittest tests
Test grid

In general, tests should be run for different environments:

Variation Values
tensorflow version 1.0.1
python version 2, 3
TD_TEST_SCIPY 0, 1
TD_TEST_GPU 0, 1
Docker

For testing purposes, it is convenient to use docker. Fortunately, the official tensorflow images contain all we need:

git clone https://github.com/riga/tfdeploy.git
cd tfdeploy

docker run --rm -v `pwd`:/root/tfdeploy -w /root/tfdeploy -e "TD_TEST_SCIPY=1" tensorflow/tensorflow:1.0.1 python -m unittest tests

Development

Authors

tfdeploy's People

Contributors

b1t0 avatar riga avatar thran 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  avatar  avatar  avatar  avatar  avatar

tfdeploy's Issues

Error while evaluating saved model

Hi,
I'm trying to restore a model saved with tfdeploy but during evaluation I have the following errors:

<class 'tfdeploy.Tensor'>
<class 'tfdeploy.Tensor'>
Traceback (most recent call last):
  File "ensemble_learning.py", line 71, in <module>
    result = y_test.eval({x_test: test_waves})
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in eval
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 461, in <listcomp>
    args = [t.eval(feed_dict=feed_dict, _uuid=_uuid) for t in self.inputs]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 292, in eval
    self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 469, in eval
    self.value = self.func(*args)
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 481, in func
    return cls.func_numpy(*args)
  File "/home/stefano/Dropbox/DeepWave/tfdeploy.py", line 1296, in Div
    return np.divide(a, b),
TypeError: unsupported operand type(s) for /: 'float' and 'NoneType'

The training code is:

...
deepnn definition, dataset loading....
...

td.setup(tf)
start_time = time.time()
with tf.Session() as sess:
    x = tf.placeholder(tf.float32, [None, 160], name="input")
    y = tf.placeholder(tf.float32, [None, 2], name="y-input")
    keep_prob = tf.placeholder(tf.float32)
    # Build the graph for the deep net
    y_conv = deepnn(x)
    y_soft = tf.nn.softmax(y_conv, name="output")
    prediction_y_conv = tf.argmax(y_conv, 1) # Predicted labels
    prediction_y = tf.argmax(y, 1) # Original labels

    with tf.name_scope('cost'):
        cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=y_conv)) #cost

    with tf.name_scope('train'):
    	train_step = tf.train.AdamOptimizer(LEARNING_RATE).minimize(cross_entropy) #optimizer

    with tf.name_scope('accuracy'):
        with tf.name_scope('correct_prediction'):
    	    correct_prediction = tf.equal(prediction_y_conv, prediction_y)
        with tf.name_scope('accuracy'):
    	    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    # create a summary for our cost and accuracy
    tf.summary.scalar("accuracy", accuracy)
    tf.summary.scalar("cost", cross_entropy)
    merged = tf.summary.merge_all()

    writer = tf.summary.FileWriter(LOG_DIR, sess.graph)

    sess.run(tf.global_variables_initializer())



    best_accuracy = 0
    for e in range(num_epochs):
        print('Epoch num: ', e + 1)
        print('Learning rate: ', LEARNING_RATE)
        for i in range(num_batches):
            if i % 50 == 0:
                train_accuracy = sess.run(accuracy, feed_dict={x: train_waves[i], y: train_labels[i], keep_prob: 1.0})
                print('step %d, %d [s], training accuracy %g' % (i, (time.time() - start_time), train_accuracy))
            summary, _ = sess.run([merged,train_step], feed_dict={x: train_waves[i], y: train_labels[i], keep_prob: 1.0})
            writer.add_summary(summary,i)

        current_accuracy = accuracy.eval(feed_dict={x: test_waves, y: test_labels, keep_prob: 1.0})
        print('test accuracy %g' % current_accuracy)
        if current_accuracy > best_accuracy:
            # create a tfdeploy model and save it to disk
            model = td.Model()
            model.add(y_soft, sess) # y and all its ops and related tensors are added recursively
            model.save(SESS_DIR + '/' + MODEL_NAME)
            best_accuracy = current_accuracy

        # Compute confusion matrix
        cm_labels = prediction_y.eval(feed_dict={y: test_labels})
        cm_predictions = prediction_y_conv.eval(feed_dict={x: test_waves, keep_prob: 1.0})
        print(sess.run(tf.contrib.metrics.confusion_matrix(cm_labels,cm_predictions)))
        # Decrease learning rate with num_epochs
        #LEARNING_RATE = LEARNING_RATE - (LEARNING_RATE/100)*10
        print("Execution time [s]: %d" % (time.time() - start_time))

And the import code is:

....
load dataset
....
model = td.Model(SESS_DIR+"/model1.pkl")
#model = td.Model("model.pkl")

# shorthand to x and y
x_test, y_test = model.get("input", "output")
print(type(x_test))
print(type(y_test))

# evaluate
result = y_test.eval({x_test: test_waves})

Have I done something wrong? :|
Thank you for your work!

EDIT:
I forgot the dropout placeholder! :)
In the training file i modified keep_prob:
keep_prob = tf.placeholder(tf.float32, name="keep_prob")

Now the import code is:

ciao = td.Model(SESS_DIR+"/model1.pkl")
x, y, keep_prob = ciao.get("input", "output", "keep_prob")

# Get a prediction
pred = y.eval({x: test_waves, keep_prob: 1.0})

But now I have this error:

/home/stefano/Dropbox/DeepWave/tfdeploy.py:2081: RuntimeWarning: overflow encountered in exp
  e = np.exp(a)
/home/stefano/Dropbox/DeepWave/tfdeploy.py:2082: RuntimeWarning: invalid value encountered in true_divide
  return np.divide(e, np.sum(e, axis=-1, keepdims=True)),

EDIT2:
I don't know why.... but now it works!! :D
I had a "normalized" dataset (values between 0 and 1). Removed the normalization the problem is gone. Now i have a dataset with values between 0 and 255.

does tfdeploy support multiple output in a graph?

In the example, tfdeploy get the result of y1=W1x1+b1 by

result1 = y1.eval({x1: batch})

If I have a graph with two output y2=W2(W1x+b1)+b2, and y3=W3(W1x+b1)+b3, in tensorflow I can use

sess.run([y2, y3])

to get y2 and y3 simutaneously while avoiding redundant computation(of y1=W1x1+b1).

is it possible to do the same thing with tfdeploy? or I have to use two commands like below

result2 = y2.eval({x1: batch})
result3 = y3.eval({x1: batch})

Example with Syntaxnet?

Could someone create an example of how you would export the syntaxnet model for use with tfdeploy?

Unknown Operation: Merge

I am trying to deploy a combination of tf.contrib.slim nets including multiple inception_resnet_v1.conv2d and fully_connected that contain an op called Merge. The operation from the model looks like so InceptionResnetV1/Conv2d_1a_3x3/BatchNorm/cond/Merge

This operation is currently unsupported and spews this:
tfdeploy.UnknownOperationException: unknown operation: Merge

After some digging, the tf.Operation Merge is tf.summary.merge. Wanted to get some advice on the viability of adding this operation to tfdeploy? I'd be happy to contribute but wanted to open the issue to begin.

python3 support

This looks like a great project. It would be great to add py3 support! Thanks!

Only save once?

It seems that after saving a model, all subsequent saves are identical.

I made a minimal example that reproduces the problem:

import tensorflow as tf
import tfdeploy.tfdeploy as td

def pickleModel(sess,out,file_name):
    model = td.Model()
    model.add(out,sess)
    model.save(file_name)

def unpickleModel(file_name):
    model = td.Model(file_name)
    out = model.get('output')
    print("td evaluation = ",out.eval())

if __name__ == '__main__':

    counter = tf.Variable(  0.0  , name='counter' )
    out = tf.multiply(counter,1,name ='output')
    increment = tf.assign(counter,counter+1)

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    pickleModel(sess,out,'file1')
    print('tensorflow evaluation = ',sess.run(out))
    unpickleModel('file1')

    sess.run(increment)

    pickleModel(sess,out,'file2')
    print('tensorflow evaluation = ',sess.run(out))
    unpickleModel('file2')

The ouput is :
tensorflow evaluation = 0.0
td evaluation = 0.0
tensorflow evaluation = 1.0
td evaluation = 0.0

But the last td evaluation should be equal to 1.0. What is going on?

unknown operation: ConcatV2

With TensorFlow 1.0 (pip tensorflow-gpu for python 3.6) on linux, when trying tfdeploy in a tf model with tf.concat, tfdeploy raises the following error:

tfdeploy.UnknownOperationException: unknown operation: ConcatV2

reduction functions failed when reduction_indices is numpy.int32

When running the tfdeploy model, I got this error

File "/home/sutony/git/facenet/src/align/tfdeploy.py", line 1838, in Max
axis=tuple(reduction_indices)
TypeError: 'numpy.int32' object is not iterable

It happens when the reduction_indices is an integer

#does not work when reduction_indices is an numpy integer (e.g., np.int32)
tuple(reduction_indices)  

I changed the code in Max() and Sum() to make the program runnable, but the code is not neat and I'm not sure if it works for other cases.

if not isinstance(reduction_indices, np.ndarray):
    return np.amax(a, axis=reduction_indices, keepdims=keep_dims),
else:
    return np.amax(a, axis=tuple(reduction_indices), keepdims=keep_dims),

The other reduction functions might cause the same error.

Performance issues in tests/perf/measure_runtimes.py(P2)

Hello,I found a performance issue in the definition of create_models ,
tests/perf/measure_runtimes.py,
tf_sess = tf.Session() was repeatedly called and was not closed.
I think it will increase the efficiency and avoid out of memory if you close this session after using it.

Here are two files to support this issue,support1 and support2

Looking forward to your reply. Btw, I am very glad to create a PR to fix it if you are too busy.

max pooling across multiple filters

I defined a CNN in TensorFlow, here's a chunk of it:

import tensorflow as tf

HEIGHT, WIDTH, DEPTH = 144, 192, 3
N_CLASSES = 2

x = tf.placeholder(tf.float32, shape=[None, HEIGHT, WIDTH, DEPTH], name="input")
y_ = tf.placeholder(tf.float32, shape=[None, N_CLASSES], name="y_")

WIN_X, WIN_Y = 5, 5
N_FILTERS = 4

W1 = tf.Variable(tf.truncated_normal([WIN_X, WIN_Y, DEPTH, N_FILTERS],
stddev=1/np.sqrt(WIN_X*WIN_Y)))
b1 = tf.Variable(tf.constant(0.1, shape=[N_FILTERS]))
xw = tf.nn.conv2d(x, W1, strides=[1,1,1,1], padding="SAME", name="xw")
h1 = tf.nn.relu(xw + b1, name="h1")
p1 = tf.nn.max_pool(h1, ksize=[1,2,2,1], strides=[1,2,2,1], padding="VALID", name="p1")
#...

I was able to train and test the model. I then saved the model using tfdeploy. I can then load the model like so:

model = tfdeploy.Model("myModel.pkl")
# THIS CODE WORKS:

x, test_point = model.get("input", "h1")
test_point.eval({x:samps}) # 38 samples
# BUT THIS DOESN'T WORK:

x, test_point = model.get("input", "p1")
test_point.eval({x:samps})

Any idea what is going on? Here's the error message I'm getting:

Traceback (most recent call last):
File "test.py", line 68, in
test_point.eval({x:samps})
File "/home/sbmorphe/Downloads/tfdeploy.py", line 291, in eval
self.value = self.op.eval(feed_dict=feed_dict, _uuid=_uuid)[self.value_index]
File "/home/sbmorphe/Downloads/tfdeploy.py", line 462, in eval
self.value = self.func(*args)
File "/home/sbmorphe/Downloads/tfdeploy.py", line 474, in func
return cls.func_numpy(*args)
File "/home/sbmorphe/Downloads/tfdeploy.py", line 2185, in MaxPool
patches = _conv_patches(a, np.ones(k[1:] + [1]), strides, padding.decode("ascii"), "edge")
File "/home/sbmorphe/Downloads/tfdeploy.py", line 2108, in _conv_patches
src[s + tuple(slice(*tpl) for tpl in zip(pos, pos + f.shape[:-2]))][en] * f
ValueError: could not broadcast input array from shape (38,2,2,4,1) into shape (38,2,2,1,1)

Numpy invalid division issue in restored model

Hi, I'm using a multilayer perceptron with dropout and exponential decay, adapted from the MNIST tutorial in tensorflow. I'm interested in deploying a softmax layer to get class membership probabilities rather than hard predictions. I can train and test the model successfully in tensorflow like this, but when I deploy and restore the model, I run into an "invalid value encountered in true_divide" error from numpy. Here is the (abbreviated) training part:

...
# tf Graph input
x = tf.placeholder("float", shape=[None, n_input],name="input")
y = tf.placeholder("float", [None, n_classes])

# Dropout
keep_prob = tf.placeholder(tf.float32, name="keep_prob")
dropout = 0.75
...

def multilayer_perceptron(x, weights, biases, dropout):
	# Hidden layer with RELU activation
	layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1'])
	layer_1 = tf.nn.relu(layer_1)
	# Apply dropout
	layer_1 = tf.nn.dropout(layer_1, dropout)

	# Hidden layer with RELU activation
	layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2'])
	layer_2 = tf.nn.relu(layer_2)
	# Output layer with linear activation
	out_layer = tf.matmul(layer_2, weights['out']) + biases['out']
	return out_layer
...
pred = multilayer_perceptron(x, weights, biases, keep_prob)
...
# Training cycle
for epoch in range(training_epochs):
	avg_cost = 0.
	total_batch = int(num_examples/batch_size)
	# Loop over all batches
	for i in range(total_batch):
		batch_x, batch_y = next_batch(data,batch_size)
		# Run optimization op (backprop) and cost op (to get loss value)
		_, c = sess.run([optimizer, cost], feed_dict={x: batch_x, y: batch_y, keep_prob: dropout})
		# Compute average loss
		avg_cost += c / total_batch
	# Display logs per epoch step
	if epoch % display_step == 0:
		print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(avg_cost))
print("Optimization Finished!")

y = tf.nn.softmax(pred, name="output")

# Evaluate some row in test data, without dropout, this seems to work
print(y.eval({x: test_x[5, :].reshape(1, 262), keep_prob: 1.}))

# Now save tfdeploy model to disk
model = tfdeploy.Model()
model.add(y, sess) # y and all its ops and related tensors are added recursively
model.save("tdeploy_model.pkl")

This first part works fine. But now the problem comes up:

nn = tfdeploy.Model("tdeploy_model.pkl")
x, y, keep_prob = self.nn.get("input", "output", "keep_prob")
data = np.loadtxt("some_data.tab", delimiter="\t")
# Pick some row
data = data[4:5,0:data.shape[1]-2]
# Get a prediction
y.eval({x: data, keep_prob: 1.})

This last operation throws a warning as below:

tfdeploy.py:2098: RuntimeWarning: invalid value encountered in true_divide
  return np.divide(e, np.sum(e, axis=-1, keepdims=True)),

And the predicted probabilities are [nan], instead of the floats I see when running directly under tensorflow. Any ideas on what is happening here? Thanks for your help!

Add tests

Add test for core code as well as for each Op.

Device setting for test cases

Some ops are only defined for certain devices, e.g. FFT2D works only on GPU.
The test cases should account for that to test ops across devices.

Unknown op RealDiv in tf 1.0.0

I'm having some trouble with saving models from Tensorflow 1.0.0. When I save after training I hit an unknown op RealDiv and I get:

    model.add(y, sess) # y and all its ops and related tensors are added recursively
  File "c:\test\tfdeploy.py", line 153, in add
    tensor = Tensor(tensor, tf_sess, **kwargs)
  File "c:\test\tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "c:\test\tfdeploy.py", line 424, in new
    return cls.classes[tf_op.type](tf_op, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 322, in __call__
    inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 396, in __init__
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "c:\test\tfdeploy.py", line 396, in <genexpr>
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "c:\test\tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "c:\test\tfdeploy.py", line 424, in new
    return cls.classes[tf_op.type](tf_op, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 322, in __call__
    inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 396, in __init__
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "c:\test\tfdeploy.py", line 396, in <genexpr>
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "c:\test\tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "c:\test\tfdeploy.py", line 424, in new
    return cls.classes[tf_op.type](tf_op, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 322, in __call__
    inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 396, in __init__
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "c:\test\tfdeploy.py", line 396, in <genexpr>
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "c:\test\tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "c:\test\tfdeploy.py", line 424, in new
    return cls.classes[tf_op.type](tf_op, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 322, in __call__
    inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 396, in __init__
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "c:\test\tfdeploy.py", line 396, in <genexpr>
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "c:\test\tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "c:\test\tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "c:\test\tfdeploy.py", line 422, in new
    raise UnknownOperationException("unknown operation: %s" % tf_op.type)
tfdeploy.UnknownOperationException: unknown operation: RealDiv

This is on Win 10 64 bit, Python 3.5.3 (64 bit) using tensorflow-1.0.0-cp35-cp35m-win_amd64.whl (cpu). If I revert to tf 0.12.0, everything works fine.

Evaluate theano/GPU support

Instead of numpy operations and numpy ndarrays, tfdeploy could also provide theano-backed ops and tensors. This feature is meant to be optional.

Benefits:

  • GPU suport
  • ML specific ops for free

Keras example

An example would be nice that shows how to use tfdeploy with tensorflow-backed keras.

There is no support for tf.strided_slice

Currently, there's no support for tf.strided_slice() so if somewhere in your graph you have x[:,:,:,None] the graph won't execute. It's a complicated function, so it won't be easy to implement.

Comparison to the C++ API

Have you compared how this compares to model evaluation via the c++ API?

I'd think the most common optimization-of-evaluation use case would be generating highly portable C code for production systems where there's no desire to include the 100+ MB of tensorflow libs. (Assuming you could get superior performance with only Eigen maybe)

unknown operation: QueueDequeueManyV2

Hello!

I wonder, how does tfdeploy deal with tf queues? I don't use placeholder in my model but a graph like file_name_queue -> data_reader -> dnn. I get these error messages when saving my model:

...
File "/usr/local/lib/python3.5/dist-packages/tfdeploy.py", line 194, in __call __
inst = super(TensorRegister, cls).call(tf_tensor, *args, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/tfdeploy.py", line 249, in __init __
self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
File "/usr/local/lib/python3.5/dist-packages/tfdeploy.py", line 422, in new
raise UnknownOperationException("unknown operation: %s" % tf_op.type)
tfdeploy.UnknownOperationException: unknown operation: QueueDequeueManyV2

Add subgraphs.

Subgraphs that are entirely encapsulated by internal tensors of a specific framework (theano/tensorflow) potentially speed up evaluation.

Maximum recursion depth exceeded while calling a Python object

When I try to export my model with tf.deploy, I get a RuntimeError because of too many recursions.

Here's part of the stacktrace (rest just keeps on repeating):

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-11-2c22f3704a32> in <module>()
      1 model = td.Model()
      2 
----> 3 model.add(output, sess) # y and all its ops and related tensors are added recursively
      4 model.save("model.pkl")

/usr/local/lib/python2.7/dist-packages/tfdeploy.pyc in add(self, tensor, tf_sess, key, **kwargs)
    151         """
    152         if not isinstance(tensor, Tensor):
--> 153             tensor = Tensor(tensor, tf_sess, **kwargs)
    154 
    155         if key is None:

/usr/local/lib/python2.7/dist-packages/tfdeploy.pyc in __call__(cls, tf_tensor, *args, **kwargs)
    192         # simple caching
    193         if tf_tensor not in cls.instances:
--> 194             inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
    195             cls.instances[tf_tensor] = inst
    196         return cls.instances[tf_tensor]

/usr/local/lib/python2.7/dist-packages/tfdeploy.pyc in __init__(self, tf_tensor, tf_sess, tf_feed_dict)
    247         # no op for variables, placeholders and constants
    248         if tf_tensor.op.type not in ("Variable", "Const", "Placeholder"):
--> 249             self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
    250 
    251     def get(self, *names):

/usr/local/lib/python2.7/dist-packages/tfdeploy.pyc in new(cls, tf_op, *args, **kwargs)
    422             raise UnknownOperationException("unknown operation: %s" % tf_op.type)
    423 
--> 424         return cls.classes[tf_op.type](tf_op, *args, **kwargs)
    425 
    426     def set_attr(self, attr, value):

/usr/local/lib/python2.7/dist-packages/tfdeploy.pyc in __call__(cls, tf_op, *args, **kwargs)
    320         # simple caching
    321         if tf_op not in cls.instances:
--> 322             inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
    323             cls.instances[tf_op] = inst
    324         return cls.instances[tf_op]

/usr/local/lib/python2.7/dist-packages/tfdeploy.pyc in __init__(self, tf_op, *args, **kwargs)
    394 
    395         self.name = tf_op.name
--> 396         self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
    397 
    398         self.value = None

/usr/local/lib/python2.7/dist-packages/tfdeploy.pyc in <genexpr>((tf_tensor,))
    394 
    395         self.name = tf_op.name
--> 396         self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
    397 
    398         self.value = None

/usr/local/lib/python2.7/dist-packages/tfdeploy.pyc in __call__(cls, tf_tensor, *args, **kwargs)
    192         # simple caching
    193         if tf_tensor not in cls.instances:
--> 194             inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
    195             cls.instances[tf_tensor] = inst
    196         return cls.instances[tf_tensor]

Here's the graph that I'm using:
https://1drv.ms/u/s!AjBMlWMdSnfSg7xkXuRAhgMgRNzXRQ
And the code for creating the model looks somewhat like this
https://1drv.ms/u/s!AjBMlWMdSnfSg7xkXuRAhgMgRNzXRQ (small facenet inception model using tf.slim)

Note: I've manually added the new ConcatV2 op using the following code:

@td.Operation.factory
def ConcatV2(inputs, dim):
    """
    Concat op.
    """
    return np.concatenate(inputs, axis=dim),

Haven't really checked if that's correct, but I don't think that's connected to the error as I've encountered it before when I used the old Concat op.

Really like this project and it would be awesome if this error got resolved. Thank you so much for your work!

Ensure that ops return copies

Ops should not change incoming tensors/arrays in-place, this can lead to crucial errors du to non-transparent states.

Allow evaluating models on Quantopian

Hi, I came across this library when searching for ways to run neural networks on Quantopian. This is the closest one I could find that could run on their platform. However, since they only allow certain libraries, some stuff will have to change.

This can hopefully be solved by guarding the imports, or make them conditional, for those modules that aren't allowed. Then it's the big one, encode the model as CSV, because sadly that is the only format they support loading.

Those this sound good/doable?

Error while loading : AttributeError: Can't get attribute 'Mul' on <module 'tfdeploy

so i get : Traceback (most recent call last):
File "game.py", line 7, in
model = td.Model("model.pkl")
File "C:\Users\admin\Miniconda3\lib\site-packages\tfdeploy.py", line 113, in init
self.load(path)
File "C:\Users\admin\Miniconda3\lib\site-packages\tfdeploy.py", line 169, in load
roots = pickle.load(f)

AttributeError: Can't get attribute 'Mul' on <module 'tfdeploy' from 'C:\Users\admin\Miniconda3\lib\site-packages\tfdeploy.py'>.

Looks like it is because of a deprecation of tensorflow. Gotta update this!

Error when creating model `unknown operation: TensorArrayGatherV3`

Hey.

I'm trying to convert a keras model into a tfdeploy model. Below is the code

import tensorflow as tf
import tfdeploy as td
from keras.models import load_model

td.setup(tf)
sess = tf.Session()
K.set_session(sess)

keras_model = load_model('../model.07-0.02.hdf5')

model = td.Model()
model.add(keras_model.output, sess)  #error occurs here
model.save("td-model.pkl")

But I get the error:

tfdeploy.UnknownOperationException: unknown operation: TensorArrayGatherV3

Full stacktrace below. Any ideas?

I'm using keras v. 2.0.2, tensorflow 1.0.1 and tfdeploy 0.4.2

Traceback (most recent call last):
  File "/Users/rbp/dev/normalization/tfdeploy/load.py", line 33, in <module>
    model.add(keras_model.output, sess)  # y and all its ops and related tensors are added recursively
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 153, in add
    tensor = Tensor(tensor, tf_sess, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 424, in new
    return cls.classes[tf_op.type](tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 322, in __call__
    inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in __init__
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in <genexpr>
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 424, in new
    return cls.classes[tf_op.type](tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 322, in __call__
    inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in __init__
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in <genexpr>
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 424, in new
    return cls.classes[tf_op.type](tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 322, in __call__
    inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in __init__
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in <genexpr>
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 424, in new
    return cls.classes[tf_op.type](tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 322, in __call__
    inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in __init__
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in <genexpr>
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 424, in new
    return cls.classes[tf_op.type](tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 322, in __call__
    inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in __init__
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in <genexpr>
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 424, in new
    return cls.classes[tf_op.type](tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 322, in __call__
    inst = super(OperationRegister, cls).__call__(tf_op, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in __init__
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 396, in <genexpr>
    self.inputs = tuple(Tensor(tf_tensor, *args, **kwargs) for tf_tensor in tf_op.inputs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 194, in __call__
    inst = super(TensorRegister, cls).__call__(tf_tensor, *args, **kwargs)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 249, in __init__
    self.op = Operation.new(tf_tensor.op, tf_sess, tf_feed_dict=tf_feed_dict)
  File "/Users/rbp/anaconda/envs/python3/lib/python3.5/site-packages/tfdeploy.py", line 422, in new
    raise UnknownOperationException("unknown operation: %s" % tf_op.type)
tfdeploy.UnknownOperationException: unknown operation: TensorArrayGatherV3

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.