Skip to content

Commit

Permalink
Update documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
gmalivenko committed Jan 21, 2019
1 parent 0e74eb5 commit 874e217
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 79 deletions.
15 changes: 8 additions & 7 deletions docs/api.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Here is the only method `pytorch_to_keras` from `pytorch2keras` module.

```
def pytorch_to_keras(
model, args, input_shapes,
Expand All @@ -8,10 +9,10 @@ def pytorch_to_keras(

Options:

* model -- a PyTorch module to convert;
* args -- list of dummy variables with proper shapes;
* input_shapes -- list with shape tuples;
* change_ordering -- boolean, if enabled, the converter will try to change `BCHW` to `BHWC`
* training -- boolean, switch model to training mode (never use it)
* verbose -- boolean, verbose output
* names -- choice from [`keep`, `short`, `random`]. The selector set the target layer naming policy.
* `model` -- a PyTorch module to convert;
* `args` -- list of dummy variables with proper shapes;
* `input_shapes` -- list with shape tuples;
* `change_ordering` -- boolean, if enabled, the converter will try to change `BCHW` to `BHWC`
* `training` -- boolean, switch model to training mode (never use it)
* `verbose` -- boolean, verbose output
* `names` -- choice from [`keep`, `short`, `random`]. The selector set the target layer naming policy.
84 changes: 41 additions & 43 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,48 @@ It's the converter of PyTorch graph to a Keras (Tensorflow backend) model.

Firstly, we need to load (or create) a valid PyTorch model:

```
class TestConv2d(nn.Module):
"""
Module for Conv2d testing
"""
```
class TestConv2d(nn.Module):
"""
Module for Conv2d testing
"""
def __init__(self, inp=10, out=16, kernel_size=3):
super(TestConv2d, self).__init__()
self.conv2d = nn.Conv2d(inp, out, stride=1, kernel_size=kernel_size, bias=True)
def __init__(self, inp=10, out=16, kernel_size=3):
super(TestConv2d, self).__init__()
self.conv2d = nn.Conv2d(inp, out, stride=1, kernel_size=kernel_size, bias=True)
def forward(self, x):
x = self.conv2d(x)
return x
def forward(self, x):
x = self.conv2d(x)
return x
model = TestConv2d()
model = TestConv2d()
# load weights here
# model.load_state_dict(torch.load(path_to_weights.pth))
```
# load weights here
# model.load_state_dict(torch.load(path_to_weights.pth))
```

The next step - create a dummy variable with correct shape:

```
input_np = np.random.uniform(0, 1, (1, 10, 32, 32))
input_var = Variable(torch.FloatTensor(input_np))
```
```
input_np = np.random.uniform(0, 1, (1, 10, 32, 32))
input_var = Variable(torch.FloatTensor(input_np))
```

We use the dummy-variable to trace the model (with jit.trace):

```
from converter import pytorch_to_keras
# we should specify shape of the input tensor
k_model = pytorch_to_keras(model, input_var, [(10, 32, 32,)], verbose=True)
```
```
from converter import pytorch_to_keras
# we should specify shape of the input tensor
k_model = pytorch_to_keras(model, input_var, [(10, 32, 32,)], verbose=True)
```

You can also set H and W dimensions to None to make your model shape-agnostic (e.g. fully convolutional netowrk):

```
from converter import pytorch_to_keras
# we should specify shape of the input tensor
k_model = pytorch_to_keras(model, input_var, [(10, None, None,)], verbose=True)
```
```
from converter import pytorch_to_keras
# we should specify shape of the input tensor
k_model = pytorch_to_keras(model, input_var, [(10, None, None,)], verbose=True)
```

That's all! If all the modules have converted properly, the Keras model will be stored in the `k_model` variable.

Expand All @@ -63,7 +63,6 @@ Here is a short instruction how to get a tensorflow.js model:

2. Now you have Keras model. You can save it as h5 file and then convert it with `tensorflowjs_converter` but it doesn't work sometimes. As alternative, you may get Tensorflow Graph and save it as a frozen model:

```
# Function below copied from here:
# https://stackoverflow.com/questions/45466020/how-to-export-keras-h5-to-tensorflow-pb
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
Expand Down Expand Up @@ -103,22 +102,21 @@ Here is a short instruction how to get a tensorflow.js model:

tf.train.write_graph(frozen_graph, ".", "my_model.pb", as_text=False)
print([i for i in k_model.outputs])
```

3. You will see the output layer name, so, now it's time to convert `my_model.pb` to tfjs model:

```
tensorflowjs_converter \
--input_format=tf_frozen_model \
--output_node_names='TANHTObs/Tanh' \
my_model.pb \
model_tfjs
```
```
tensorflowjs_converter \
--input_format=tf_frozen_model \
--output_node_names='TANHTObs/Tanh' \
my_model.pb \
model_tfjs
```

4. Thats all!

```
const MODEL_URL = `model_tfjs/tensorflowjs_model.pb`;
const WEIGHTS_URL = `model_tfjs/weights_manifest.json`;
cont model = await tf.loadFrozenModel(MODEL_URL, WEIGHTS_URL);
```
```
const MODEL_URL = `model_tfjs/tensorflowjs_model.pb`;
const WEIGHTS_URL = `model_tfjs/weights_manifest.json`;
cont model = await tf.loadFrozenModel(MODEL_URL, WEIGHTS_URL);
```
29 changes: 0 additions & 29 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,3 @@
![PyPI](https://img.shields.io/pypi/v/pytorch2keras.svg)

PyTorch to Keras model converter. This project is created to make a model conversation easier, so, the converter API is developed with maximal simplicity.


## PyTorch 0.4.1 and greater

There is [the problem related to a new version](https://github.com/pytorch/pytorch/issues/13963):

To make it work, please, cast all your `.view()` parameters to `int`. For example:

```
class ResNet(torchvision.models.resnet.ResNet):
def __init__(self, *args, **kwargs):
super(ResNet, self).__init__(*args, **kwargs)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.avgpool(x)
x = x.view(int(x.size(0)), -1) # << Here
x = self.fc(x)
return x
```
31 changes: 31 additions & 0 deletions docs/known_problems.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## Linear layer problem with PyTorch 0.4.1 and greater

There is [the problem related to a new version](https://github.com/pytorch/pytorch/issues/13963):

To make it work, please, cast all your `.view()` parameters to `int`. For example:

```
class ResNet(torchvision.models.resnet.ResNet):
def __init__(self, *args, **kwargs):
super(ResNet, self).__init__(*args, **kwargs)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.avgpool(x)
x = x.view(int(x.size(0)), -1) # << Here
x = self.fc(x)
return x
```

## Recurrent layers

The recurrent layers are not supported due to complicated onnx-translation. The support is planned, but haven't implemented yet.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ pages:
- Getting started: getting_started.md
- Supported layers and models: supported_layers_and_models.md
- API: api.md
- Known problems: known_problems.md
- License: license.md

0 comments on commit 874e217

Please sign in to comment.