Comments (6)
@qiutzh 非常感谢你的工作,代码写的很好,有一处有误。因下载的权重是channels_first的,需要在Conv和MaxPool中填入参数data_format='channels_first'。
附上我修改后的代码和测试结果:
import os
os.environ['TL_BACKEND'] = 'paddle'
# os.environ['TL_BACKEND'] = 'tensorflow'
import tensorlayerx.nn as nn
from tensorlayerx import logging
from tensorlayerx.files import assign_weights
from paddle.utils.download import get_weights_path_from_url
import numpy as np
import paddle
from paddle import to_tensor
from PIL import Image
import copy
import tensorlayerx as tlx
from examples.model_zoo.imagenet_classes import class_names
__all__ = []
model_urls = {
'tlxvgg16': ('https://paddle-hapi.bj.bcebos.com/models/vgg16.pdparams',
'89bbffc0f87d260be9b8cdc169c991c4'),
'tlxvgg19': ('https://paddle-hapi.bj.bcebos.com/models/vgg19.pdparams',
'23b18bb13d8894f60f54e642be79a0dd')
}
class VGG(nn.Module):
"""VGG model from
`"Very Deep Convolutional Networks For Large-Scale Image Recognition" <https://arxiv.org/pdf/1409.1556.pdf>`_
Args:
features (nn.Layer): Vgg features create by function make_layers.
num_classes (int): Output dim of last fc layer. If num_classes <=0, last fc layer
will not be defined. Default: 1000.
with_pool (bool): Use pool before the last three fc layer or not. Default: True.
Examples:
.. code-block:: python
from paddle.vision.models import VGG
from paddle.vision.models.vgg import make_layers
vgg11_cfg = [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M']
features = make_layers(vgg11_cfg)
vgg11 = VGG(features)
"""
def __init__(self, features, num_classes=1000, with_pool=True):
super(VGG, self).__init__()
self.features = features
self.num_classes = num_classes
self.with_pool = with_pool
if self.with_pool:
self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
if num_classes > 0:
self.classifier = nn.Sequential(
nn.Linear(out_features=4096, act=None, in_features=512 * 7 * 7),
nn.ReLU(),
nn.Linear(out_features=4096, act=None, in_features=4096),
nn.ReLU(),
nn.Linear(in_features=4096, out_features=num_classes),
)
def forward(self, x):
print(self.features[0](x).shape)
x = self.features(x)
print("Conv shape", x.shape)
# if self.with_pool:
# x = self.avgpool(x)
if self.num_classes > 0:
x = paddle.flatten(x, 1)
print('x.numpy =', x.shape)
x = self.classifier(x)
return x
def make_layers(cfg, batch_norm=False):
layers = []
in_channels = 3
for v in cfg:
if v == 'M':
layers += [nn.MaxPool2d(kernel_size=2, stride=2, padding=0, data_format='channels_first')] # padding默认为'SAME'
else:
conv2d = nn.Conv2d(out_channels=v, kernel_size=(3, 3), stride=(1, 1), act=None, padding=1,
in_channels=in_channels, data_format='channels_first')
if batch_norm:
layers += [conv2d, nn.BatchNorm2d(num_features=v, data_format='channels_first'), nn.ReLU()]
else:
layers += [conv2d, nn.ReLU()]
in_channels = v
return nn.Sequential(*layers)
cfgs = {
'A': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'B':
[64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'D': [
64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512,
512, 512, 'M'
],
'E': [
64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512,
'M', 512, 512, 512, 512, 'M'
],
}
####################新增pd2tlx#################
pd2tlx = {'features.0.weight': 'features.0.W',
'features.2.weight': 'features.2.W',
'features.5.weight': 'features.5.W',
'features.7.weight': 'features.7.W',
'features.10.weight': 'features.10.W',
'features.12.weight': 'features.12.W',
'features.14.weight': 'features.14.W',
'features.17.weight': 'features.17.W',
'features.19.weight': 'features.19.W',
'features.21.weight': 'features.21.W',
'features.24.weight': 'features.24.W',
'features.26.weight': 'features.26.W',
'features.28.weight': 'features.28.W',
'features.0.bias': 'features.0.b',
'features.2.bias': 'features.2.b',
'features.5.bias': 'features.5.b',
'features.7.bias': 'features.7.b',
'features.10.bias': 'features.10.b',
'features.12.bias': 'features.12.b',
'features.14.bias': 'features.14.b',
'features.17.bias': 'features.17.b',
'features.19.bias': 'features.19.b',
'features.21.bias': 'features.21.b',
'features.24.bias': 'features.24.b',
'features.26.bias': 'features.26.b',
'features.28.bias': 'features.28.b',
'classifier.0.weight': 'classifier.0.W',
'classifier.3.weight': 'classifier.2.W',
'classifier.6.weight': 'classifier.4.W',
'classifier.0.bias': 'classifier.0.b',
'classifier.3.bias': 'classifier.2.b',
'classifier.6.bias': 'classifier.4.b'}
def get_new_weight(param):
'''新增函数,调整参数key'''
new_param = {}
for key in param.keys():
new_param[pd2tlx[key]] = param[key]
print(key, ":", param[key].shape, "vs", pd2tlx[key], ":", new_param[pd2tlx[key]].shape)
return new_param
def restore_model(param, model, model_type='vgg16'):
""" 直接restore """
weights = []
if model_type == 'vgg16':
for val in param.items():
# for val in sorted(param.items()):
weights.append(val[1])
if len(model.all_weights) == len(weights):
break
elif model_type == 'vgg19':
pass
# assign weight values
assign_weights(weights, model)
del weights
def _tlxvgg(arch, cfg, batch_norm, pretrained, **kwargs):
model = VGG(make_layers(cfgs[cfg], batch_norm=batch_norm), **kwargs)
if pretrained:
assert arch in model_urls, "{} model do not have a pretrained model now, you should set pretrained=False".format(
arch)
weight_path = get_weights_path_from_url(model_urls[arch][0],
model_urls[arch][1])
param = paddle.load(weight_path)
# model.load_dict(param)
# new_param = get_new_weight(param)
# model.load_dict(new_param)
restore_model(param, model)
return model
def tlxvgg16(pretrained=False, batch_norm=False, **kwargs):
"""VGG 16-layer model
Args:
pretrained (bool): If True, returns a model pre-trained on ImageNet. Default: False.
batch_norm (bool): If True, returns a model with batch_norm layer. Default: False.
Examples:
.. code-block:: python
from paddle.vision.models import vgg16
# build model
model = vgg16()
# build vgg16 model with batch_norm
model = vgg16(batch_norm=True)
"""
model_name = 'tlxvgg16'
if batch_norm:
model_name += ('_bn')
return _tlxvgg(model_name, 'D', batch_norm, pretrained, **kwargs)
if __name__ == "__main__":
model = tlxvgg16(pretrained=True, batch_norm=False)
model.set_eval()
for w in model.trainable_weights:
print(w.name, w.shape)
# get the whole model
img = tlx.vision.load_image('data/tiger.jpeg')
img = tlx.vision.transforms.Resize((224, 224))(img).astype(np.float32) / 255
img = paddle.unsqueeze(paddle.Tensor(img), 0)
img = tlx.ops.nhwc_to_nchw(img)
output = model(img)
probs = tlx.ops.softmax(output)[0].numpy()
preds = (np.argsort(probs)[::-1])[0:5]
for p in preds:
print(class_names[p], probs[p])
from tensorlayerx.
@qiutzh If you are interested, you can contribute this code to the repository as an example of importing other framework parameters!
from tensorlayerx.
@Laicheng0830 Thank you^_^
from tensorlayerx.
@Laicheng0830 Hi, 大佬,请教您一个有关conv2d算子计算的问题,因为我发现虽然将paddle的vgg模型转成tlx后可以运行且对同一张测试图像的top5预测结果类别一致,但分类器输出的结果并不相同,tlx是概率值,pd是非概率值,这导致在计算diff时存在较大偏差。补充:分类器输出正常,自己没加softmax导致。。。
# paddle predict
Predicted class: kuvasz
kuvasz 74.107735
Great Pyrenees 71.59815
golden retriever 71.3573
Labrador retriever 60.9687
Afghan hound, Afghan 59.363976
# tlx predict
Predicted class: kuvasz
kuvasz 0.8732064
Great Pyrenees 0.07099358
golden retriever 0.055797946
Labrador retriever 1.7175398e-06
Afghan hound, Afghan 3.4513076e-07
然后,我尝试比较各个算子的差异,对比了一下conv2d算子,发现针对同一输入数据,paddle和tlx的conv2d算子输出结果是不同的,参考代码如下:
# coding: utf-8
import unittest
class PaddleTLXOpsCmpTest(unittest.TestCase):
def test_conv2d(self):
import numpy as np
import paddle
import paddle.nn as nn
img = np.random.random(size=(1, 3, 224, 224)).astype('float32')
img = paddle.to_tensor(img)
conv2d = nn.Conv2D(in_channels=3, out_channels=32, kernel_size=(3, 3), stride=2, padding=1)
out_pd = conv2d(img)
print(out_pd.numpy().shape)
print(out_pd.numpy())
import os
os.environ['TL_BACKEND'] = 'paddle'
import tensorlayerx as tlx
img = tlx.convert_to_tensor(img)
# img = tlx.nn.Input([1, 400, 400, 3], name='input')
conv2d = tlx.nn.Conv2d(out_channels=32, kernel_size=(3, 3), stride=(2, 2), padding=1, b_init=None,
in_channels=3, data_format='channels_first')
out_tlx = conv2d(img)
print(out_tlx.numpy().shape)
print(out_tlx.numpy)
if __name__ == '__main__':
unittest.main()
像是一个做了归一化,一个没有做归一化,问下什么原因造成的,如何对齐两个算子的输出?
from tensorlayerx.
@qiutzh ,tlx和paddle卷积的计算结果是一致的。因为卷积是带训练权重,权重初始化方法不一样计算结果自然不一样。对比只需要把paddle的权重赋值给tlx的卷积权重就能计算。附上代码
# coding: utf-8
import unittest
class PaddleTLXOpsCmpTest(unittest.TestCase):
def test_conv2d(self):
import numpy as np
import paddle
import paddle.nn as nn
img = np.random.random(size=(1, 3, 224, 224)).astype('float32')
img = paddle.to_tensor(img)
conv2d = nn.Conv2D(in_channels=3, out_channels=32, kernel_size=(3, 3), stride=2, padding=1)
paddle_weights = conv2d.weight # get paddle weights
out_pd = conv2d(img)
print(out_pd.numpy().shape)
print(out_pd.numpy())
import os
os.environ['TL_BACKEND'] = 'paddle'
import tensorlayerx as tlx
img = tlx.convert_to_tensor(img)
# img = tlx.nn.Input([1, 400, 400, 3], name='input')
conv2d = tlx.nn.Conv2d(out_channels=32, kernel_size=(3, 3), stride=(2, 2), padding=1, b_init=None,
in_channels=3, data_format='channels_first')
conv2d.filters = paddle_weights
out_tlx = conv2d(img)
print(out_tlx.numpy().shape)
print(out_tlx.numpy())
print("comparison", out_pd.numpy() - out_tlx.numpy())
if __name__ == '__main__':
unittest.main()
from tensorlayerx.
@Laicheng0830 好的 明白了谢谢
from tensorlayerx.
Related Issues (20)
- tensorlayerx.nn.PRelu() does not have build in initialisation,self.build() -> inputs_shape no description HOT 1
- tensorlayerx.nn.MaxPool2d()中无参数return_mask,paddle.nn.MaxPool2D有 HOT 1
- tlx.nn.BatchNorm中act参数下没有Swish激活函数
- tlxnn.AvgPool2d() 中没有参数ceil_mode=True HOT 1
- DataLoader()报错,0.5.6可以正常训练,最新版本会报错,报错如下: HOT 1
- tensorlayerx中没找到与paddle.nn.functional.interpolate功能相同的算子,后续是否会添加?
- tensorlayerx.argmax没有参数keepdim,但paddle.argmax有
- F.unfold()在tensorlayerx中没找到对应方法 HOT 2
- paddle.index_select()在tensorlayerx中没找到对应方法 HOT 2
- tensorlayerx.nn以paddle为backend时没有MaxUnPool2D/Pad2d,但paddle.nn有
- tensorlayerx.nn.ConvTranspose2d没有output_padding参数,但paddle.nn.Conv2DTranspose有 HOT 1
- tlx 没有与paddle.nn.functional模块对应的max_pool2d,avg_pool2d,conv2d_transpose,max_unpool2d,normalize算子 HOT 1
- tensorlayerx.nn.UpSampling2d当data_format="channels_first"和paddle.nn.Upsample输出结果维度不一致
- tensorlayerx没有优化函数的基类, 只能使用tlx.optimizers.paddle_optimizers.Optimizer来判断
- tenorlayerx.nn没有paddle.nn.InstanceNorm2D对应的算子
- tensorlayerx 有么有与paddle.expand对应的算子? HOT 1
- tensorlayerx.ops.Pad不支持“channels_first”的data_format,后续会补充“channels_first”的格式吗?
- net.set_eval() seems not work well HOT 1
- Pytorch后端NHWC和NCHW问题
- ImportError: cannot import name 'distributed_init' from 'tensorlayerx.backend.ops.load_backend' HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tensorlayerx.