Skip to content

Commit f07e82e

Browse files
committed
Added Transpose layer support. A Linear layers with bias=False is converting normally for now.
1 parent 48de887 commit f07e82e

File tree

4 files changed

+112
-1
lines changed

4 files changed

+112
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ Layers:
7575
Reshape:
7676

7777
* View (only with 0.2)
78+
* Transpose (only with 0.4)
7879

7980
Activations:
8081

pytorch2keras/layers.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,63 @@ def convert_tanh(params, w_name, scope_name, inputs, layers, weights):
528528
layers[scope_name] = tanh(layers[inputs[0]])
529529

530530

531+
def convert_transpose(params, w_name, scope_name, inputs, layers, weights):
532+
"""
533+
Convert tanh layer.
534+
535+
Args:
536+
params: dictionary with layer parameters
537+
w_name: name prefix in state_dict
538+
scope_name: pytorch scope name
539+
inputs: pytorch node inputs
540+
layers: dictionary with keras tensors
541+
weights: pytorch state_dict
542+
"""
543+
print('Converting transpose ...')
544+
if params['perm'][0] != 0:
545+
# raise AssertionError('Cannot permute batch dimension')
546+
print('!!! Cannot permute batch dimension. Result may be wrong !!!')
547+
layers[scope_name] = layers[inputs[0]]
548+
else:
549+
tf_name = w_name + str(random.random())
550+
permute = keras.layers.Permute(params['perm'][1:], name=tf_name)
551+
layers[scope_name] = permute(layers[inputs[0]])
552+
553+
554+
def convert_matmul(params, w_name, scope_name, inputs, layers, weights):
555+
"""
556+
Convert tanh layer.
557+
558+
Args:
559+
params: dictionary with layer parameters
560+
w_name: name prefix in state_dict
561+
scope_name: pytorch scope name
562+
inputs: pytorch node inputs
563+
layers: dictionary with keras tensors
564+
weights: pytorch state_dict
565+
"""
566+
print('Converting matmul ...')
567+
568+
tf_name = w_name + str(random.random())
569+
570+
if len(inputs) == 1:
571+
weights_name = '{0}.weight'.format(w_name)
572+
573+
W = weights[weights_name].numpy().transpose()
574+
input_channels, output_channels = W.shape
575+
576+
keras_weights = [W]
577+
578+
print(layers[inputs[0]])
579+
dense = keras.layers.Dense(
580+
output_channels,
581+
weights=keras_weights, use_bias=False, name=tf_name
582+
)
583+
layers[scope_name] = dense(layers[inputs[0]])
584+
else:
585+
raise AssertionError('Cannot convert matmul layer')
586+
587+
531588
AVAILABLE_CONVERTERS = {
532589
'Conv': convert_conv,
533590
'ConvTranspose': convert_convtranspose,
@@ -546,4 +603,6 @@ def convert_tanh(params, w_name, scope_name, inputs, layers, weights):
546603
'Sigmoid': convert_sigmoid,
547604
'Softmax': convert_softmax,
548605
'Tanh': convert_tanh,
606+
'Transpose': convert_transpose,
607+
'MatMul': convert_matmul,
549608
}

tests/dense.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class TestDense(nn.Module):
1616

1717
def __init__(self, inp=10, out=16, bias=True):
1818
super(TestDense, self).__init__()
19-
self.linear = nn.Linear(inp, out, bias=True)
19+
self.linear = nn.Linear(inp, out, bias=False)
2020

2121
def forward(self, x):
2222
x = self.linear(x)

tests/transpose.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import keras # work around segfault
2+
import sys
3+
import numpy as np
4+
5+
import torch
6+
import torch.nn as nn
7+
from torch.autograd import Variable
8+
9+
sys.path.append('../pytorch2keras')
10+
from converter import pytorch_to_keras
11+
12+
13+
class TestTranspose(nn.Module):
14+
"""Module for Transpose conversion testing
15+
"""
16+
17+
def __init__(self, inp=10, out=16, kernel_size=3, bias=True):
18+
super(TestTranspose, self).__init__()
19+
self.conv2d = nn.Conv2d(inp, out, kernel_size=kernel_size, bias=bias)
20+
21+
def forward(self, x):
22+
x = self.conv2d(x)
23+
x = torch.transpose(x, 2, 3)
24+
x = torch.nn.Tanh()(x)
25+
return x
26+
27+
28+
if __name__ == '__main__':
29+
max_error = 0
30+
for i in range(100):
31+
kernel_size = np.random.randint(1, 7)
32+
inp = np.random.randint(kernel_size + 1, 100)
33+
out = np.random.randint(1, 100)
34+
35+
model = TestTranspose(inp, out, kernel_size, inp % 2)
36+
37+
input_np = np.random.uniform(0, 1, (1, inp, inp, inp))
38+
input_var = Variable(torch.FloatTensor(input_np))
39+
output = model(input_var)
40+
41+
k_model = pytorch_to_keras(model, input_var, (inp, inp, inp,), verbose=True)
42+
43+
pytorch_output = output.data.numpy()
44+
keras_output = k_model.predict(input_np)
45+
46+
error = np.max(pytorch_output - keras_output)
47+
print(error)
48+
if max_error < error:
49+
max_error = error
50+
51+
print('Max error: {0}'.format(max_error))

0 commit comments

Comments
 (0)