diff --git a/README.md b/README.md index 95fb31f1..ba8ce50a 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,13 @@ global_step = global_step_t.eval() ### Running Tests -Use `tox` to run the test suite on all supported environments. +Use `tox` to run the test suite in both Python 2 and Python 3 environments. + +To also run slower integration tests (marked with `pytest.mark.slow`), specify the `--run-slow` option for pytest, which can be passed through `tox` like so: + +``` +tox -- --run-slow +``` To run tests only for a specific module, pass a folder to `tox`: `tox tests/misc/io` diff --git a/lucid/modelzoo/caffe_models/AlexNet.py b/lucid/modelzoo/caffe_models/AlexNet.py new file mode 100644 index 00000000..72d2d42a --- /dev/null +++ b/lucid/modelzoo/caffe_models/AlexNet.py @@ -0,0 +1,76 @@ +# Copyright 2018 The Lucid Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import, division, print_function +from lucid.modelzoo.vision_base import Model, IMAGENET_MEAN_BGR + + +class AlexNet_caffe(Model): + """Original AlexNet weights ported to TF. + + AlexNet is the breakthrough vision model from Krizhevsky, et al (2012): + https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf + This implementation is a caffe re-implementation: + http://www.cs.toronto.edu/~guerzhoy/tf_alexnet/ + It was converted to TensorFlow by this GitHub project: + https://github.com/huanzhang12/tensorflow-alexnet-model + It appears the parameters are the actual original parameters. + """ + + # The authors of code to convert AlexNet to TF host weights at + # http://jaina.cs.ucdavis.edu/datasets/adv/imagenet/alexnet_frozen.pb + # but it seems more polite and reliable to host our own. + model_path = 'gs://modelzoo/AlexNet.pb' + labels_path = 'gs://modelzoo/ImageNet_labels_caffe.txt' + image_shape = [227, 227, 3] + is_BGR = True + image_value_range = (-IMAGENET_MEAN_BGR, 255-IMAGENET_MEAN_BGR) + input_name = 'Placeholder' + + # TODO - Sanity check this graph and layers + layers = [ + {'type': 'conv', 'name': 'concat_2', 'size': 256}, + {'type': 'conv', 'name': 'conv5_1', 'size': 256}, + {'type': 'dense', 'name': 'Relu', 'size': 4096}, + {'type': 'dense', 'name': 'Relu_1', 'size': 4096}, + {'type': 'dense', 'name': 'Softmax', 'size': 1000}, + ] + + +class AlexNet_caffe_Places365(Model): + """AlexNet re-implementation trained on Places365. + + This model is a reimplementation of AlexNet + https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf + trained on the MIT Places365 dataset, retrieved here: + https://github.com/CSAILVision/places365 + and then ported to TensorFlow using caffe-tensorflow. + """ + + model_path = 'gs://modelzoo/AlexNet_caffe_places365.pb' + labels_path = 'gs://modelzoo/InceptionV1_caffe_places365-labels.txt' + image_shape = [227, 227, 3] + is_BGR = True + image_value_range = (-IMAGENET_MEAN_BGR, 255-IMAGENET_MEAN_BGR) + input_name = 'input' + + # TODO - Sanity check this graph and layers + layers = [ + {'type': 'conv', 'name': 'conv5/concat', 'size': 256} , + {'type': 'conv', 'name': 'conv5/conv5', 'size': 256} , + {'type': 'dense', 'name': 'fc6/fc6', 'size': 4096} , + {'type': 'dense', 'name': 'fc7/fc7', 'size': 4096} , + {'type': 'dense', 'name': 'prob', 'size': 365} , + ] diff --git a/lucid/modelzoo/caffe_models/InceptionV1.py b/lucid/modelzoo/caffe_models/InceptionV1.py new file mode 100644 index 00000000..3d0b3715 --- /dev/null +++ b/lucid/modelzoo/caffe_models/InceptionV1.py @@ -0,0 +1,118 @@ +# Copyright 2018 The Lucid Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import, division, print_function +from lucid.modelzoo.vision_base import Model, IMAGENET_MEAN_BGR + + +class InceptionV1_caffe(Model): + """InceptionV1 (or 'GoogLeNet') as reimplemented in caffe. + + This model is a reimplementation of GoogLeNet: + https://www.cs.unc.edu/~wliu/papers/GoogLeNet.pdf + reimplemented in caffe by BVLC / Sergio Guadarrama: + https://github.com/BVLC/caffe/tree/master/models/bvlc_googlenet + and then ported to TensorFlow using caffe-tensorflow. + """ + model_path = 'gs://modelzoo/InceptionV1_caffe.pb' + labels_path = 'gs://modelzoo/InceptionV1_caffe-labels.txt' + image_shape = [224, 224, 3] + is_BGR = True + image_value_range = (-IMAGENET_MEAN_BGR, 255-IMAGENET_MEAN_BGR) + input_name = 'data' + + layers = [ + {'type': 'conv', 'name': 'conv1_7x7_s2/conv1_7x7_s2', 'size': 64}, + {'type': 'conv', 'name': 'conv2_3x3_reduce/conv2_3x3_reduce', 'size': 64}, + {'type': 'conv', 'name': 'conv2_3x3/conv2_3x3', 'size': 192}, + {'type': 'conv', 'name': 'inception_3a_output', 'size': 256}, + {'type': 'conv', 'name': 'inception_3b_output', 'size': 480}, + {'type': 'conv', 'name': 'inception_4a_output', 'size': 512}, + {'type': 'conv', 'name': 'inception_4b_output', 'size': 512}, + {'type': 'conv', 'name': 'inception_4c_output', 'size': 512}, + {'type': 'conv', 'name': 'inception_4d_output', 'size': 528}, + {'type': 'conv', 'name': 'inception_4e_output', 'size': 832}, + {'type': 'conv', 'name': 'inception_5a_output', 'size': 832}, + {'type': 'conv', 'name': 'inception_5b_output', 'size': 1024}, + {'type': 'dense', 'name': 'prob', 'size': 1000}, + ] + + +class InceptionV1_caffe_Places205(Model): + """InceptionV1 (or 'GoogLeNet') trained on Places205. + + This model is a caffe reimplementation of GoogLeNet: + https://www.cs.unc.edu/~wliu/papers/GoogLeNet.pdf + trained on the MIT Places205 dataset, retrieved here: + http://places.csail.mit.edu/downloadCNN.html + and then ported to TensorFlow using caffe-tensorflow. + """ + model_path = 'gs://modelzoo/InceptionV1_caffe_places205.pb' + labels_path = 'gs://modelzoo/InceptionV1_caffe_places205-labels.txt' + image_shape = [224, 224, 3] + # range based on emperical testing + image_value_range = (-1,1) + input_name = 'data' + + layers = [ + {'type': 'conv', 'name': 'conv1_7x7_s2/conv1_7x7_s2', 'size': 64}, + {'type': 'conv', 'name': 'conv2_3x3_reduce/conv2_3x3_reduce', 'size': 64}, + {'type': 'conv', 'name': 'conv2_3x3/conv2_3x3', 'size': 192}, + {'type': 'conv', 'name': 'inception_3a_output', 'size': 256}, + {'type': 'conv', 'name': 'inception_3b_output', 'size': 480}, + {'type': 'conv', 'name': 'inception_4a_output', 'size': 512}, + {'type': 'conv', 'name': 'inception_4b_output', 'size': 512}, + {'type': 'conv', 'name': 'inception_4c_output', 'size': 512}, + {'type': 'conv', 'name': 'inception_4d_output', 'size': 528}, + {'type': 'conv', 'name': 'inception_4e_output', 'size': 832}, + {'type': 'conv', 'name': 'inception_5a_output', 'size': 832}, + {'type': 'conv', 'name': 'inception_5b_output', 'size': 1024}, + {'type': 'dense', 'name': 'prob', 'size': 205}, + ] + + +class InceptionV1_caffe_Places365(Model): + """InceptionV1 (or 'GoogLeNet') trained on Places365. + + This model is a caffe reimplementation of GoogLeNet: + https://www.cs.unc.edu/~wliu/papers/GoogLeNet.pdf + trained on the MIT Places365 dataset, retrieved here: + https://github.com/CSAILVision/places365 + and then ported to TensorFlow using caffe-tensorflow. + """ + model_path = 'gs://modelzoo/InceptionV1_caffe_places365.pb' + # TODO - check labels match predictions + labels_path = 'gs://modelzoo/InceptionV1_caffe_places365-labels.txt' + image_shape = [224, 224, 3] + # What is the correct input range??? + is_BGR = True + image_value_range = (-IMAGENET_MEAN_BGR, 255-IMAGENET_MEAN_BGR) + input_name = 'data' + + layers = [ + {'type': 'conv', 'name': 'conv1_7x7_s2/conv1_7x7_s2', 'size': 64}, + {'type': 'conv', 'name': 'conv2_3x3_reduce/conv2_3x3_reduce', 'size': 64}, + {'type': 'conv', 'name': 'conv2_3x3/conv2_3x3', 'size': 192}, + {'type': 'conv', 'name': 'inception_3a_output', 'size': 256}, + {'type': 'conv', 'name': 'inception_3b_output', 'size': 480}, + {'type': 'conv', 'name': 'inception_4a_output', 'size': 512}, + {'type': 'conv', 'name': 'inception_4b_output', 'size': 512}, + {'type': 'conv', 'name': 'inception_4c_output', 'size': 512}, + {'type': 'conv', 'name': 'inception_4d_output', 'size': 528}, + {'type': 'conv', 'name': 'inception_4e_output', 'size': 832}, + {'type': 'conv', 'name': 'inception_5a_output', 'size': 832}, + {'type': 'conv', 'name': 'inception_5b_output', 'size': 1024}, + {'type': 'dense', 'name': 'prob', 'size': 365}, + ] diff --git a/lucid/modelzoo/caffe_models/README.md b/lucid/modelzoo/caffe_models/README.md new file mode 100644 index 00000000..4deb83f1 --- /dev/null +++ b/lucid/modelzoo/caffe_models/README.md @@ -0,0 +1,3 @@ +Models imported from caffe. + +See `lucid/scripts/import_caffe/` for details on how to import more. diff --git a/lucid/modelzoo/caffe_models/__init__.py b/lucid/modelzoo/caffe_models/__init__.py new file mode 100644 index 00000000..a6934359 --- /dev/null +++ b/lucid/modelzoo/caffe_models/__init__.py @@ -0,0 +1,2 @@ +from lucid.modelzoo.caffe_models.InceptionV1 import * +from lucid.modelzoo.caffe_models.others import * diff --git a/lucid/modelzoo/caffe_models/others.py b/lucid/modelzoo/caffe_models/others.py new file mode 100644 index 00000000..b043a30b --- /dev/null +++ b/lucid/modelzoo/caffe_models/others.py @@ -0,0 +1,118 @@ +# Copyright 2018 The Lucid Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import, division, print_function +from lucid.modelzoo.vision_base import Model, IMAGENET_MEAN_BGR + +class CaffeNet_caffe(Model): + """CaffeNet (AlexNet variant included in Caffe) + + CaffeNet is a slight variant on AlexNet, described here: + https://github.com/BVLC/caffe/tree/master/models/bvlc_reference_caffenet + """ + + model_path = 'gs://modelzoo/CaffeNet_caffe.pb' + labels_path = 'gs://modelzoo/ImageNet_labels_caffe.txt' + image_shape = [227, 227, 3] + is_BGR = True + image_value_range = (-IMAGENET_MEAN_BGR, 255-IMAGENET_MEAN_BGR) + input_name = 'data' + + layers = [ + {'type': 'conv', 'name': 'conv5/concat', 'size': 256} , + {'type': 'conv', 'name': 'conv5/conv5', 'size': 256} , + {'type': 'dense', 'name': 'fc6/fc6', 'size': 4096} , + {'type': 'dense', 'name': 'fc7/fc7', 'size': 4096} , + {'type': 'dense', 'name': 'prob', 'size': 1000} , + ] + + +class VGG16_caffe(Model): + """VGG16 model used in ImageNet ILSVRC-2014, ported from caffe. + + VGG16 was introduced by Simonyan & Zisserman (2014): + https://arxiv.org/pdf/1409.1556.pdf + http://www.robots.ox.ac.uk/~vgg/research/very_deep/ + as the Oxford Visual Geometry Group's submission for the ImageNet ILSVRC-2014 + contest. We download their caffe trained model from + https://gist.github.com/ksimonyan/211839e770f7b538e2d8#file-readme-md + and convert it with caffe-tensorflow. + """ + model_path = 'gs://modelzoo/VGG16_caffe.pb' + labels_path = 'gs://modelzoo/InceptionV1_caffe-labels.txt' + image_shape = [224, 224, 3] + is_BGR = True + image_value_range = (-IMAGENET_MEAN_BGR, 255-IMAGENET_MEAN_BGR) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'conv1_1/conv1_1', 'size': 64}, + {'type': 'conv', 'name': 'conv1_2/conv1_2', 'size': 64}, + {'type': 'conv', 'name': 'conv2_1/conv2_1', 'size': 128}, + {'type': 'conv', 'name': 'conv2_2/conv2_2', 'size': 128}, + {'type': 'conv', 'name': 'conv3_1/conv3_1', 'size': 256}, + {'type': 'conv', 'name': 'conv3_2/conv3_2', 'size': 256}, + {'type': 'conv', 'name': 'conv3_3/conv3_3', 'size': 256}, + {'type': 'conv', 'name': 'conv4_1/conv4_1', 'size': 512}, + {'type': 'conv', 'name': 'conv4_2/conv4_2', 'size': 512}, + {'type': 'conv', 'name': 'conv4_3/conv4_3', 'size': 512}, + {'type': 'conv', 'name': 'conv5_1/conv5_1', 'size': 512}, + {'type': 'conv', 'name': 'conv5_2/conv5_2', 'size': 512}, + {'type': 'conv', 'name': 'conv5_3/conv5_3', 'size': 512}, + {'type': 'dense', 'name': 'fc6/fc6', 'size': 4096}, + {'type': 'dense', 'name': 'fc7/fc7', 'size': 4096}, + {'type': 'dense', 'name': 'prob', 'size': 1000}, + ] + + +class VGG19_caffe(Model): + """VGG16 model used in ImageNet ILSVRC-2014, ported from caffe. + + VGG19 was introduced by Simonyan & Zisserman (2014): + https://arxiv.org/pdf/1409.1556.pdf + http://www.robots.ox.ac.uk/~vgg/research/very_deep/ + as the Oxford Visual Geometry Group's submission for the ImageNet ILSVRC-2014 + contest. We download their caffe trained model from + https://gist.github.com/ksimonyan/3785162f95cd2d5fee77#file-readme-md + and convert it with caffe-tensorflow. + """ + model_path = 'gs://modelzoo/VGG19_caffe.pb' + labels_path = 'gs://modelzoo/InceptionV1_caffe-labels.txt' + image_shape = [224, 224, 3] + is_BGR = True + image_value_range = (-IMAGENET_MEAN_BGR, 255-IMAGENET_MEAN_BGR) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'conv1_1/conv1_1', 'size': 64}, + {'type': 'conv', 'name': 'conv1_2/conv1_2', 'size': 64}, + {'type': 'conv', 'name': 'conv2_1/conv2_1', 'size': 128}, + {'type': 'conv', 'name': 'conv2_2/conv2_2', 'size': 128}, + {'type': 'conv', 'name': 'conv3_1/conv3_1', 'size': 256}, + {'type': 'conv', 'name': 'conv3_2/conv3_2', 'size': 256}, + {'type': 'conv', 'name': 'conv3_3/conv3_3', 'size': 256}, + {'type': 'conv', 'name': 'conv3_4/conv3_4', 'size': 256}, + {'type': 'conv', 'name': 'conv4_1/conv4_1', 'size': 512}, + {'type': 'conv', 'name': 'conv4_2/conv4_2', 'size': 512}, + {'type': 'conv', 'name': 'conv4_3/conv4_3', 'size': 512}, + {'type': 'conv', 'name': 'conv4_4/conv4_4', 'size': 512}, + {'type': 'conv', 'name': 'conv5_1/conv5_1', 'size': 512}, + {'type': 'conv', 'name': 'conv5_2/conv5_2', 'size': 512}, + {'type': 'conv', 'name': 'conv5_3/conv5_3', 'size': 512}, + {'type': 'conv', 'name': 'conv5_4/conv5_4', 'size': 512}, + {'type': 'dense', 'name': 'fc6/fc6', 'size': 4096}, + {'type': 'dense', 'name': 'fc7/fc7', 'size': 4096}, + {'type': 'dense', 'name': 'prob', 'size': 1000}, + ] diff --git a/lucid/modelzoo/nets_factory.py b/lucid/modelzoo/nets_factory.py new file mode 100644 index 00000000..a47b7c91 --- /dev/null +++ b/lucid/modelzoo/nets_factory.py @@ -0,0 +1,68 @@ +# Copyright 2018 The Lucid Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Contains a factory function for accessing models. + +You can either use the provided `get_model` function, or directly access the +`models_map` variable containing a dictionary from a model name to its class. +""" + +from __future__ import absolute_import, division, print_function + +import inspect +import tensorflow as tf + +from lucid.modelzoo import vision_models +from lucid.modelzoo import vision_base + + +def _generate_models_map(): + base_classes = inspect.getmembers(vision_base, inspect.isclass) + + list_all_models = [] + list_all_models += inspect.getmembers(vision_models, inspect.isclass) + + list_filtered = filter(lambda c: c not in base_classes, list_all_models) + return dict(list_filtered) + + +models_map = _generate_models_map() + + +def get_model(name): + """Returns a model instance such as `model = vision_models.InceptionV1()`. + In the future may be expanded to filter by additional criteria, such as + architecture, dataset, and task the model was trained on. + Args: + name: The name of the model, as given by the class name in vision_models. + Returns: + An instantiated Model class with the requested model. Users still need to + manually `load_graphdef` on the return value, and manually import this + model's graph into their current graph. + Raises: + ValueError: If network `name` is not recognized. + """ + if name not in models_map: + candidates = filter(lambda key: name in key, models_map.keys()) + candidates_string = ", ".join(candidates) + raise ValueError( + "No network named {}. Did you mean one of {}?".format( + name, candidates_string + ) + ) + + model_class = models_map[name] + model = model_class() + return model diff --git a/lucid/modelzoo/other_models/InceptionV1.py b/lucid/modelzoo/other_models/InceptionV1.py new file mode 100644 index 00000000..01b3e672 --- /dev/null +++ b/lucid/modelzoo/other_models/InceptionV1.py @@ -0,0 +1,79 @@ +# Copyright 2018 The Lucid Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import, division, print_function +import tensorflow as tf +from lucid.modelzoo.vision_base import Model + + +def _populate_inception_bottlenecks(scope): + """Add Inception bottlenecks and their pre-Relu versions to the graph.""" + graph = tf.get_default_graph() + for op in graph.get_operations(): + if op.name.startswith(scope+'/') and 'Concat' in op.type: + name = op.name.split('/')[1] + pre_relus = [] + for tower in op.inputs[1:]: + if tower.op.type == 'Relu': + tower = tower.op.inputs[0] + pre_relus.append(tower) + concat_name = scope + '/' + name + '_pre_relu' + _ = tf.concat(pre_relus, -1, name=concat_name) + + +class InceptionV1(Model): + """InceptionV1 (or 'GoogLeNet') + + This is a (re?)implementation of InceptionV1 + https://www.cs.unc.edu/~wliu/papers/GoogLeNet.pdf + The weights were trained at Google and released in an early TensorFlow + tutorial. It is possible the parameters are the original weights + (trained in TensorFlow's predecessor), but we haven't been able to + confirm this. + + As far as we can tell, it is exactly the same as the model described in + the original paper, where as the slim and caffe implementations have + minor implementation differences (such as eliding the heads). + """ + model_path = 'gs://modelzoo/InceptionV1.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' + image_shape = [224, 224, 3] + image_value_range = (-117, 255-117) + input_name = 'input:0' + + def post_import(self, scope): + _populate_inception_bottlenecks(scope) + + layers = [ + {'type': 'conv', 'name': 'conv2d0', 'size': 64}, + {'type': 'conv', 'name': 'conv2d1', 'size': 64}, + {'type': 'conv', 'name': 'conv2d2', 'size': 192}, + {'type': 'conv', 'name': 'mixed3a', 'size': 256}, + {'type': 'conv', 'name': 'mixed3b', 'size': 480}, + {'type': 'conv', 'name': 'mixed4a', 'size': 508}, + {'type': 'conv', 'name': 'mixed4b', 'size': 512}, + {'type': 'conv', 'name': 'mixed4c', 'size': 512}, + {'type': 'conv', 'name': 'mixed4d', 'size': 528}, + {'type': 'conv', 'name': 'mixed4e', 'size': 832}, + {'type': 'conv', 'name': 'mixed5a', 'size': 832}, + {'type': 'conv', 'name': 'mixed5b', 'size': 1024}, + {'type': 'conv', 'name': 'head0_bottleneck', 'size': 128}, + {'type': 'dense', 'name': 'nn0', 'size': 1024}, + {'type': 'dense', 'name': 'softmax0', 'size': 1008}, + {'type': 'conv', 'name': 'head1_bottleneck', 'size': 128}, + {'type': 'dense', 'name': 'nn1', 'size': 1024}, + {'type': 'dense', 'name': 'softmax1', 'size': 1008}, + {'type': 'dense', 'name': 'softmax2', 'size': 1008}, + ] diff --git a/lucid/modelzoo/other_models/__init__.py b/lucid/modelzoo/other_models/__init__.py new file mode 100644 index 00000000..4c95045d --- /dev/null +++ b/lucid/modelzoo/other_models/__init__.py @@ -0,0 +1 @@ +from lucid.modelzoo.other_models.InceptionV1 import InceptionV1 diff --git a/lucid/modelzoo/slim_models/Inception.py b/lucid/modelzoo/slim_models/Inception.py new file mode 100644 index 00000000..25cd7029 --- /dev/null +++ b/lucid/modelzoo/slim_models/Inception.py @@ -0,0 +1,284 @@ +# Copyright 2018 The Lucid Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import, division, print_function +from lucid.modelzoo.vision_base import Model, IMAGENET_MEAN + + +class InceptionV1_slim(Model): + """InceptionV1 as implemented by the TensorFlow slim framework. + + InceptionV1 was introduced by Szegedy, et al (2014): + https://arxiv.org/pdf/1409.4842v1.pdf + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + corresponding to the name "inception_v1". + """ + + model_path = 'gs://modelzoo/InceptionV1_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Conv2d_1a_7x7/Relu', 'size': 64}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Conv2d_2b_1x1/Relu', 'size': 64}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Conv2d_2c_3x3/Relu', 'size': 192}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Mixed_3b/concat', 'size': 256}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Mixed_3c/concat', 'size': 480}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Mixed_4b/concat', 'size': 512}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Mixed_4c/concat', 'size': 512}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Mixed_4d/concat', 'size': 512}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Mixed_4e/concat', 'size': 528}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Mixed_4f/concat', 'size': 832}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Mixed_5b/concat', 'size': 832}, + {'type': 'conv', 'name': 'InceptionV1/InceptionV1/Mixed_5c/concat', 'size': 1024}, + {'type': 'dense', 'name': 'InceptionV1/Logits/Predictions/Softmax', 'size': 1001}, + ] + + +class InceptionV2_slim(Model): + """InceptionV2 as implemented by the TensorFlow slim framework. + + InceptionV2 was introduced by Ioffe & Szegedy (2015): + https://arxiv.org/pdf/1502.03167.pdf + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + corresponding to the name "inception_v2". + """ + + model_path = 'gs://modelzoo/InceptionV2_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Conv2d_1a_7x7/Relu', 'size': 64}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Conv2d_2b_1x1/Relu', 'size': 64}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Conv2d_2c_3x3/Relu', 'size': 192}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Mixed_3b/concat', 'size': 256}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Mixed_3c/concat', 'size': 320}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Mixed_4a/concat', 'size': 576}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Mixed_4b/concat', 'size': 576}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Mixed_4c/concat', 'size': 576}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Mixed_4d/concat', 'size': 576}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Mixed_4e/concat', 'size': 576}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Mixed_5a/concat', 'size': 1024}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Mixed_5b/concat', 'size': 1024}, + {'type': 'conv', 'name': 'InceptionV2/InceptionV2/Mixed_5c/concat', 'size': 1024}, + {'type': 'dense', 'name': 'InceptionV2/Predictions/Softmax', 'size': 1001}, + ] + + +class InceptionV3_slim(Model): + """InceptionV3 as implemented by the TensorFlow slim framework. + + InceptionV3 was introduced by Szegedy, et al (2015) + https://arxiv.org/pdf/1512.00567.pdf + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + corresponding to the name "inception_v3". + """ + + model_path = 'gs://modelzoo/InceptionV3_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' + image_shape = [299, 299, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Conv2d_1a_3x3/Relu', 'size': 32}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Conv2d_2a_3x3/Relu', 'size': 32}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Conv2d_2b_3x3/Relu', 'size': 64}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Conv2d_3b_1x1/Relu', 'size': 80}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Conv2d_4a_3x3/Relu', 'size': 192}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_5b/concat', 'size': 256}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_5c/concat', 'size': 288}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_5d/concat', 'size': 288}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_6a/concat', 'size': 768}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_6b/concat', 'size': 768}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_6c/concat', 'size': 768}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_6d/concat', 'size': 768}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_6e/concat', 'size': 768}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_7a/concat', 'size': 1280}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_7b/concat', 'size': 2048}, + {'type': 'conv', 'name': 'InceptionV3/InceptionV3/Mixed_7c/concat', 'size': 2048}, + {'type': 'dense', 'name': 'InceptionV3/Predictions/Softmax', 'size': 1001}, + ] + + +class InceptionV4_slim(Model): + """InceptionV4 as implemented by the TensorFlow slim framework. + + InceptionV4 was introduced by Szegedy, et al (2016): + https://arxiv.org/pdf/1602.07261.pdf + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + corresponding to the name "inception_v4". + """ + + model_path = 'gs://modelzoo/InceptionV4_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [299, 299, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Conv2d_1a_3x3/Relu', 'size': 32}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Conv2d_2a_3x3/Relu', 'size': 32}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Conv2d_2b_3x3/Relu', 'size': 64}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_3a/concat', 'size': 160}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_4a/concat', 'size': 192}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_5a/concat', 'size': 384}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_5b/concat', 'size': 384}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_5c/concat', 'size': 384}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_5d/concat', 'size': 384}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_5e/concat', 'size': 384}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_6a/concat', 'size': 1024}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_6b/concat', 'size': 1024}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_6c/concat', 'size': 1024}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_6d/concat', 'size': 1024}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_6e/concat', 'size': 1024}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_6f/concat', 'size': 1024}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_6g/concat', 'size': 1024}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_6h/concat', 'size': 1024}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_7a/concat', 'size': 1536}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_7b/concat', 'size': 1536}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_7c/concat', 'size': 1536}, + {'type': 'conv', 'name': 'InceptionV4/InceptionV4/Mixed_7d/concat', 'size': 1536}, + {'type': 'dense', 'name': 'InceptionV4/Logits/Predictions', 'size': 1001}, + ] + + +class InceptionResnetV2_slim(Model): + """InceptionResnetV2 as implemented by the TensorFlow slim framework. + + InceptionResnetV2 was introduced in this paper by Szegedy, et al (2016): + https://arxiv.org/pdf/1602.07261.pdf + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + corresponding to the name "inception_resnet_v2". + """ + + model_path = 'gs://modelzoo/InceptionResnetV2_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [299, 299, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + # TODO: understand this graph, see if we can delete some add or relu nodes from layers + layers = [ + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Conv2d_1a_3x3/Relu', 'size': 32}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Conv2d_2a_3x3/Relu', 'size': 32}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Conv2d_2b_3x3/Relu', 'size': 64}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Conv2d_3b_1x1/Relu', 'size': 80}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Conv2d_4a_3x3/Relu', 'size': 192}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Mixed_5b/concat', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_1/add', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_1/Relu', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_2/add', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_2/Relu', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_3/add', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_3/Relu', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_4/add', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_4/Relu', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_5/add', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_5/Relu', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_6/add', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_6/Relu', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_7/add', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_7/Relu', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_8/add', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_8/Relu', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_9/add', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_9/Relu', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_10/add', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat/block35_10/Relu', 'size': 320}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Mixed_6a/concat', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_1/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_1/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_2/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_2/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_3/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_3/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_4/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_4/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_5/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_5/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_6/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_6/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_7/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_7/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_8/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_8/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_9/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_9/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_10/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_10/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_11/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_11/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_12/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_12/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_13/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_13/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_14/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_14/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_15/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_15/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_16/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_16/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_17/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_17/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_18/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_18/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_19/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_19/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_20/add', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_1/block17_20/Relu', 'size': 1088}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Mixed_7a/concat', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_1/add', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_1/Relu', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_2/add', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_2/Relu', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_3/add', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_3/Relu', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_4/add', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_4/Relu', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_5/add', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_5/Relu', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_6/add', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_6/Relu', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_7/add', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_7/Relu', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_8/add', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_8/Relu', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_9/add', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Repeat_2/block8_9/Relu', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Block8/add', 'size': 2080}, + {'type': 'conv', 'name': 'InceptionResnetV2/InceptionResnetV2/Conv2d_7b_1x1/Relu', 'size': 1536}, + {'type': 'dense', 'name': 'InceptionResnetV2/Logits/Predictions', 'size': 1001}, + ] diff --git a/lucid/modelzoo/slim_models/README.md b/lucid/modelzoo/slim_models/README.md new file mode 100644 index 00000000..258cf90f --- /dev/null +++ b/lucid/modelzoo/slim_models/README.md @@ -0,0 +1,3 @@ +Models imported from tf-slim's [pre-trained models](https://github.com/tensorflow/models/tree/master/research/slim#pre-trained-models). + +See `lucid/scripts/import_slim/` for details on how to import more. diff --git a/lucid/modelzoo/slim_models/ResNetV1.py b/lucid/modelzoo/slim_models/ResNetV1.py new file mode 100644 index 00000000..8d659048 --- /dev/null +++ b/lucid/modelzoo/slim_models/ResNetV1.py @@ -0,0 +1,280 @@ +# Copyright 2018 The Lucid Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import, division, print_function +from lucid.modelzoo.vision_base import Model, IMAGENET_MEAN + + +class ResnetV1_50_slim(Model): + """ResnetV150 as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + """ + + model_path = 'gs://modelzoo/ResnetV1_50_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'resnet_v1_50/conv1/Relu', 'size': 64} , + {'type': 'conv', 'name': 'resnet_v1_50/block1/unit_1/bottleneck_v1/add', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_50/block1/unit_1/bottleneck_v1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_50/block1/unit_2/bottleneck_v1/add', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_50/block1/unit_2/bottleneck_v1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_50/block1/unit_3/bottleneck_v1/add', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_50/block1/unit_3/bottleneck_v1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_50/block2/unit_1/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_50/block2/unit_1/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_50/block2/unit_2/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_50/block2/unit_2/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_50/block2/unit_3/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_50/block2/unit_3/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_50/block2/unit_4/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_50/block2/unit_4/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_1/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_1/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_2/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_2/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_3/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_3/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_4/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_4/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_5/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_5/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_6/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block3/unit_6/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_50/block4/unit_1/bottleneck_v1/add', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_50/block4/unit_1/bottleneck_v1/Relu', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_50/block4/unit_2/bottleneck_v1/add', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_50/block4/unit_2/bottleneck_v1/Relu', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_50/block4/unit_3/bottleneck_v1/add', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_50/block4/unit_3/bottleneck_v1/Relu', 'size': 2048} , + {'type': 'dense', 'name': 'resnet_v1_50/predictions/Softmax', 'size': 1000} , + ] + + +class ResnetV1_101_slim(Model): + """ResnetV1101 as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + """ + + model_path = 'gs://modelzoo/ResnetV1_101_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'resnet_v1_101/conv1/Relu', 'size': 64} , + {'type': 'conv', 'name': 'resnet_v1_101/block1/unit_1/bottleneck_v1/add', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_101/block1/unit_1/bottleneck_v1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_101/block1/unit_2/bottleneck_v1/add', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_101/block1/unit_2/bottleneck_v1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_101/block1/unit_3/bottleneck_v1/add', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_101/block1/unit_3/bottleneck_v1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_101/block2/unit_1/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_101/block2/unit_1/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_101/block2/unit_2/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_101/block2/unit_2/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_101/block2/unit_3/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_101/block2/unit_3/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_101/block2/unit_4/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_101/block2/unit_4/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_1/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_1/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_2/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_2/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_3/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_3/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_4/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_4/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_5/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_5/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_6/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_6/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_7/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_7/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_8/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_8/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_9/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_9/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_10/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_10/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_11/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_11/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_12/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_12/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_13/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_13/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_14/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_14/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_15/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_15/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_16/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_16/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_17/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_17/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_18/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_18/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_19/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_19/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_20/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_20/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_21/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_21/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_22/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_22/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_23/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block3/unit_23/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_101/block4/unit_1/bottleneck_v1/add', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_101/block4/unit_1/bottleneck_v1/Relu', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_101/block4/unit_2/bottleneck_v1/add', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_101/block4/unit_2/bottleneck_v1/Relu', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_101/block4/unit_3/bottleneck_v1/add', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_101/block4/unit_3/bottleneck_v1/Relu', 'size': 2048} , + {'type': 'dense', 'name': 'resnet_v1_101/predictions/Softmax', 'size': 1000} , + ] + + + +class ResnetV1_152_slim(Model): + """ResnetV1152 as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + """ + + model_path = 'gs://modelzoo/ResnetV1_152_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'resnet_v1_152/conv1/Relu', 'size': 64} , + {'type': 'conv', 'name': 'resnet_v1_152/block1/unit_1/bottleneck_v1/add', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_152/block1/unit_1/bottleneck_v1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_152/block1/unit_2/bottleneck_v1/add', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_152/block1/unit_2/bottleneck_v1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_152/block1/unit_3/bottleneck_v1/add', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_152/block1/unit_3/bottleneck_v1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_1/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_1/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_2/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_2/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_3/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_3/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_4/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_4/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_5/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_5/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_6/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_6/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_7/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_7/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_8/bottleneck_v1/add', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block2/unit_8/bottleneck_v1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_1/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_1/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_2/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_2/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_3/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_3/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_4/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_4/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_5/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_5/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_6/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_6/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_7/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_7/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_8/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_8/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_9/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_9/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_10/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_10/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_11/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_11/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_12/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_12/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_13/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_13/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_14/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_14/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_15/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_15/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_16/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_16/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_17/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_17/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_18/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_18/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_19/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_19/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_20/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_20/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_21/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_21/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_22/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_22/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_23/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_23/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_24/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_24/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_25/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_25/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_26/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_26/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_27/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_27/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_28/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_28/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_29/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_29/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_30/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_30/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_31/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_31/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_32/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_32/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_33/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_33/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_34/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_34/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_35/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_35/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_36/bottleneck_v1/add', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block3/unit_36/bottleneck_v1/Relu', 'size': 1024} , + {'type': 'conv', 'name': 'resnet_v1_152/block4/unit_1/bottleneck_v1/add', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_152/block4/unit_1/bottleneck_v1/Relu', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_152/block4/unit_2/bottleneck_v1/add', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_152/block4/unit_2/bottleneck_v1/Relu', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_152/block4/unit_3/bottleneck_v1/add', 'size': 2048} , + {'type': 'conv', 'name': 'resnet_v1_152/block4/unit_3/bottleneck_v1/Relu', 'size': 2048} , + {'type': 'dense', 'name': 'resnet_v1_152/predictions/Softmax', 'size': 1000} , + ] + diff --git a/lucid/modelzoo/slim_models/ResNetV2.py b/lucid/modelzoo/slim_models/ResNetV2.py new file mode 100644 index 00000000..661706ba --- /dev/null +++ b/lucid/modelzoo/slim_models/ResNetV2.py @@ -0,0 +1,200 @@ +# Copyright 2018 The Lucid Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import, division, print_function +from lucid.modelzoo.vision_base import Model, IMAGENET_MEAN + + +class ResnetV2_50_slim(Model): + """ResnetV2_50 as implemented by the TensorFlow slim framework. + + ResnetV2_50 was introduced by He, et al (2016): + https://arxiv.org/pdf/1603.05027.pdf + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + corresponding to the name "resnet_v2_50". + """ + + model_path = 'gs://modelzoo/ResnetV2_50_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'resnet_v2_50/block1/unit_1/bottleneck_v2/preact/Relu', 'size': 64}, + {'type': 'conv', 'name': 'resnet_v2_50/block1/unit_1/bottleneck_v2/add', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_50/block1/unit_2/bottleneck_v2/add', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_50/block1/unit_3/bottleneck_v2/add', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_50/block2/unit_1/bottleneck_v2/preact/Relu', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_50/block2/unit_1/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_50/block2/unit_2/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_50/block2/unit_3/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_50/block2/unit_4/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_50/block3/unit_1/bottleneck_v2/preact/Relu', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_50/block3/unit_1/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_50/block3/unit_2/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_50/block3/unit_3/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_50/block3/unit_4/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_50/block3/unit_5/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_50/block3/unit_6/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_50/block4/unit_1/bottleneck_v2/preact/Relu', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_50/block4/unit_1/bottleneck_v2/add', 'size': 2048}, + {'type': 'conv', 'name': 'resnet_v2_50/block4/unit_2/bottleneck_v2/add', 'size': 2048}, + {'type': 'conv', 'name': 'resnet_v2_50/block4/unit_3/bottleneck_v2/add', 'size': 2048}, + {'type': 'conv', 'name': 'resnet_v2_50/postnorm/Relu', 'size': 2048}, + {'type': 'dense', 'name': 'resnet_v2_50/predictions/Softmax', 'size': 1001}, + ] + + +class ResnetV2_101_slim(Model): + """ResnetV2_101 as implemented by the TensorFlow slim framework. + + ResnetV2_101 was introduced by He, et al (2016): + https://arxiv.org/pdf/1603.05027.pdf + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + corresponding to the name "resnet_v2_101". + """ + + model_path = 'gs://modelzoo/ResnetV2_101_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'resnet_v2_101/block1/unit_1/bottleneck_v2/preact/Relu', 'size': 64}, + {'type': 'conv', 'name': 'resnet_v2_101/block1/unit_1/bottleneck_v2/add', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_101/block1/unit_2/bottleneck_v2/add', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_101/block1/unit_3/bottleneck_v2/add', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_101/block2/unit_1/bottleneck_v2/preact/Relu', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_101/block2/unit_1/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_101/block2/unit_2/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_101/block2/unit_3/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_101/block2/unit_4/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_1/bottleneck_v2/preact/Relu', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_1/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_2/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_3/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_4/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_5/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_6/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_7/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_8/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_9/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_10/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_11/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_12/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_13/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_14/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_15/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_16/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_17/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_18/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_19/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_20/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_21/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_22/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block3/unit_23/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block4/unit_1/bottleneck_v2/preact/Relu', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_101/block4/unit_1/bottleneck_v2/add', 'size': 2048}, + {'type': 'conv', 'name': 'resnet_v2_101/block4/unit_2/bottleneck_v2/add', 'size': 2048}, + {'type': 'conv', 'name': 'resnet_v2_101/block4/unit_3/bottleneck_v2/add', 'size': 2048}, + {'type': 'conv', 'name': 'resnet_v2_101/postnorm/Relu', 'size': 2048}, + {'type': 'dense', 'name': 'resnet_v2_101/predictions/Softmax', 'size': 1001}, + ] + + +class ResnetV2_152_slim(Model): + """ResnetV2_152 as implemented by the TensorFlow slim framework. + + ResnetV2_152 was introduced by He, et al (2016): + https://arxiv.org/pdf/1603.05027.pdf + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + corresponding to the name "resnet_v2_152". + """ + + model_path = 'gs://modelzoo/ResnetV2_152_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'resnet_v2_152/block1/unit_1/bottleneck_v2/preact/Relu', 'size': 64}, + {'type': 'conv', 'name': 'resnet_v2_152/block1/unit_1/bottleneck_v2/add', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_152/block1/unit_2/bottleneck_v2/add', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_152/block1/unit_3/bottleneck_v2/add', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_152/block2/unit_1/bottleneck_v2/preact/Relu', 'size': 256}, + {'type': 'conv', 'name': 'resnet_v2_152/block2/unit_1/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_152/block2/unit_2/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_152/block2/unit_3/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_152/block2/unit_4/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_152/block2/unit_5/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_152/block2/unit_6/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_152/block2/unit_7/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_152/block2/unit_8/bottleneck_v2/add', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_1/bottleneck_v2/preact/Relu', 'size': 512}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_1/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_2/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_3/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_4/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_5/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_6/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_7/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_8/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_9/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_10/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_11/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_12/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_13/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_14/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_15/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_16/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_17/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_18/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_19/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_20/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_21/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_22/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_23/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_24/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_25/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_26/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_27/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_28/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_29/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_30/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_31/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_32/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_33/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_34/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_35/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block3/unit_36/bottleneck_v2/add', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block4/unit_1/bottleneck_v2/preact/Relu', 'size': 1024}, + {'type': 'conv', 'name': 'resnet_v2_152/block4/unit_1/bottleneck_v2/add', 'size': 2048}, + {'type': 'conv', 'name': 'resnet_v2_152/block4/unit_2/bottleneck_v2/add', 'size': 2048}, + {'type': 'conv', 'name': 'resnet_v2_152/block4/unit_3/bottleneck_v2/add', 'size': 2048}, + {'type': 'conv', 'name': 'resnet_v2_152/postnorm/Relu', 'size': 2048}, + {'type': 'dense', 'name': 'resnet_v2_152/predictions/Softmax', 'size': 1001}, + ] diff --git a/lucid/modelzoo/slim_models/__init__.py b/lucid/modelzoo/slim_models/__init__.py new file mode 100644 index 00000000..c6f5ac7b --- /dev/null +++ b/lucid/modelzoo/slim_models/__init__.py @@ -0,0 +1,4 @@ +from lucid.modelzoo.slim_models.Inception import * +from lucid.modelzoo.slim_models.ResNetV1 import * +from lucid.modelzoo.slim_models.ResNetV2 import * +from lucid.modelzoo.slim_models.others import * diff --git a/lucid/modelzoo/slim_models/others.py b/lucid/modelzoo/slim_models/others.py new file mode 100644 index 00000000..6738c5c4 --- /dev/null +++ b/lucid/modelzoo/slim_models/others.py @@ -0,0 +1,213 @@ +# Copyright 2018 The Lucid Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import, division, print_function +from lucid.modelzoo.vision_base import Model, IMAGENET_MEAN + + +class VGG16_slim(Model): + """VGG16 as implemented by the TensorFlow slim framework. + + VGG16 was introduced by Simonyan & Zisserman (2014): + https://arxiv.org/pdf/1409.1556.pdf + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + We believe the weights were actually trained in caffe and ported. + """ + + model_path = 'gs://modelzoo/VGG16_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'vgg_16/conv1/conv1_1/Relu', 'size': 64} , + {'type': 'conv', 'name': 'vgg_16/conv1/conv1_2/Relu', 'size': 64} , + {'type': 'conv', 'name': 'vgg_16/conv2/conv2_1/Relu', 'size': 128} , + {'type': 'conv', 'name': 'vgg_16/conv2/conv2_2/Relu', 'size': 128} , + {'type': 'conv', 'name': 'vgg_16/conv3/conv3_1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'vgg_16/conv3/conv3_2/Relu', 'size': 256} , + {'type': 'conv', 'name': 'vgg_16/conv3/conv3_3/Relu', 'size': 256} , + {'type': 'conv', 'name': 'vgg_16/conv4/conv4_1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_16/conv4/conv4_2/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_16/conv4/conv4_3/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_16/conv5/conv5_1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_16/conv5/conv5_2/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_16/conv5/conv5_3/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_16/fc6/Relu', 'size': 4096} , + {'type': 'conv', 'name': 'vgg_16/fc7/Relu', 'size': 4096} , + ] + + +class VGG19_slim(Model): + """VGG19 as implemented by the TensorFlow slim framework. + + VGG19 was introduced by Simonyan & Zisserman (2014): + https://arxiv.org/pdf/1409.1556.pdf + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + We believe the weights were actually trained in caffe and ported. + """ + + model_path = 'gs://modelzoo/VGG19_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + + layers = [ + {'type': 'conv', 'name': 'vgg_19/conv1/conv1_1/Relu', 'size': 64} , + {'type': 'conv', 'name': 'vgg_19/conv1/conv1_2/Relu', 'size': 64} , + {'type': 'conv', 'name': 'vgg_19/conv2/conv2_1/Relu', 'size': 128} , + {'type': 'conv', 'name': 'vgg_19/conv2/conv2_2/Relu', 'size': 128} , + {'type': 'conv', 'name': 'vgg_19/conv3/conv3_1/Relu', 'size': 256} , + {'type': 'conv', 'name': 'vgg_19/conv3/conv3_2/Relu', 'size': 256} , + {'type': 'conv', 'name': 'vgg_19/conv3/conv3_3/Relu', 'size': 256} , + {'type': 'conv', 'name': 'vgg_19/conv3/conv3_4/Relu', 'size': 256} , + {'type': 'conv', 'name': 'vgg_19/conv4/conv4_1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_19/conv4/conv4_2/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_19/conv4/conv4_3/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_19/conv4/conv4_4/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_19/conv5/conv5_1/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_19/conv5/conv5_2/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_19/conv5/conv5_3/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_19/conv5/conv5_4/Relu', 'size': 512} , + {'type': 'conv', 'name': 'vgg_19/fc6/Relu', 'size': 4096} , + {'type': 'conv', 'name': 'vgg_19/fc7/Relu', 'size': 4096} , + ] + + +class MobilenetV1_slim(Model): + """MobilenetV1 as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + """ + + model_path = 'gs://modelzoo/MobilenetV1_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + layers = [] + + +class MobilenetV1_050_slim(Model): + """MobilenetV1050 as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + """ + + model_path = 'gs://modelzoo/MobilenetV1050_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + layers = [] + + +class MobilenetV1_025_slim(Model): + """MobilenetV1025 as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + """ + + model_path = 'gs://modelzoo/MobilenetV1025_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + layers = [] + + +class NasnetMobile_slim(Model): + """NasnetMobile as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + """ + + model_path = 'gs://modelzoo/NasnetMobile_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + layers = [] + + +class NasnetLarge_slim(Model): + """NasnetLarge as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + """ + + model_path = 'gs://modelzoo/NasnetLarge_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [331, 331, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + layers = [] + + +class PnasnetLarge_slim(Model): + """PnasnetLarge as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + """ + + model_path = 'gs://modelzoo/PnasnetLarge_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [331, 331, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + layers = [] + + +class PnasnetMobile_slim(Model): + """PnasnetMobile as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + """ + + model_path = 'gs://modelzoo/PnasnetMobile_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = [224, 224, 3] + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = 'input' + layers = [] diff --git a/lucid/modelzoo/vision_base.py b/lucid/modelzoo/vision_base.py index 0c2667d9..070e9e87 100644 --- a/lucid/modelzoo/vision_base.py +++ b/lucid/modelzoo/vision_base.py @@ -17,9 +17,14 @@ from os import path import tensorflow as tf +import numpy as np + from lucid.modelzoo.util import load_text_labels, load_graphdef, forget_xy from lucid.misc.io import load +IMAGENET_MEAN = np.array([123.68, 116.779, 103.939]) +IMAGENET_MEAN_BGR = np.flip(IMAGENET_MEAN, 0) + class Model(object): """Base pretrained model importer.""" @@ -49,6 +54,8 @@ def create_input(self, t_input=None, forget_xy_shape=True): t_prep_input = tf.expand_dims(t_prep_input, 0) if forget_xy_shape: t_prep_input = forget_xy(t_prep_input) + if hasattr(self, "is_BGR") and self.is_BGR == True: + t_prep_input = tf.reverse(t_prep_input, [-1]) lo, hi = self.image_value_range t_prep_input = lo + t_prep_input * (hi-lo) return t_input, t_prep_input diff --git a/lucid/modelzoo/vision_models.py b/lucid/modelzoo/vision_models.py index 1b439a64..ca496956 100644 --- a/lucid/modelzoo/vision_models.py +++ b/lucid/modelzoo/vision_models.py @@ -15,31 +15,6 @@ from __future__ import absolute_import, division, print_function -import tensorflow as tf -from lucid.modelzoo.vision_base import Model - - -def populate_inception_bottlenecks(scope): - """Add Inception bottlenecks and their pre-Relu versions to the graph.""" - graph = tf.get_default_graph() - for op in graph.get_operations(): - if op.name.startswith(scope+'/') and 'Concat' in op.type: - name = op.name.split('/')[1] - pre_relus = [] - for tower in op.inputs[1:]: - if tower.op.type == 'Relu': - tower = tower.op.inputs[0] - pre_relus.append(tower) - concat_name = scope + '/' + name + '_pre_relu' - _ = tf.concat(pre_relus, -1, name=concat_name) - - -class InceptionV1(Model): - model_path = 'gs://modelzoo/InceptionV1.pb' - labels_path = 'gs://modelzoo/InceptionV1-labels.txt' - image_shape = [224, 224, 3] - image_value_range = (-117, 255-117) - input_name = 'input:0' - - def post_import(self, scope): - populate_inception_bottlenecks(scope) +from lucid.modelzoo.caffe_models import * +from lucid.modelzoo.slim_models import * +from lucid.modelzoo.other_models import * diff --git a/lucid/scratch/scripts/get_model_layers.py b/lucid/scratch/scripts/get_model_layers.py new file mode 100644 index 00000000..052739db --- /dev/null +++ b/lucid/scratch/scripts/get_model_layers.py @@ -0,0 +1,67 @@ +import lucid.optvis.render as render + + +def predecessors(graphdef, name): + node_map = {} + for n in graphdef.node: + node_map[n.name] = n + + seen = [] + def get_predecessors(node_name): + if node_name not in node_map: return [] + node = node_map[node_name] + preds = [] + for inp in node.input: + if inp in seen: continue + seen.append(inp) + preds.append(inp) + inp_preds = get_predecessors(inp) + preds += inp_preds + return list(set(preds)) + + return get_predecessors(name) + + +def get_branch_nodes(graphdef, concat_node): + branch_head_names = concat_node.input[:] + branch_head_preds = [predecessors(graphdef, name) + [name] for name in branch_head_names] + uniqs = [] + for n in range(len(branch_head_preds)): + pres_preds = branch_head_preds[n] + other_preds = branch_head_preds[:n] + branch_head_preds[n+1:] + uniqs += [name for name in pres_preds + if not any(name in others for others in other_preds)] + return uniqs + + +def propose_layers(graphdef): + concats = [node for node in graphdef.node + if node.op in ["Concat", "ConcatV2", "Add"]] + branch_nodes = [] + for node in concats: + branch_nodes += get_branch_nodes(graphdef, node) + + layer_proposals = [node for node in graphdef.node + if node.op in ["Relu", "Concat", "ConcatV2", "Softmax", "Add"] and node.name not in branch_nodes] + + return layer_proposals + + +def propose_layers_with_shapes(model): + proposed_layers = propose_layers(model.graph_def) + with tf.Graph().as_default(), tf.Session() as sess: + t_input = tf.placeholder(tf.float32, [1] + model.image_shape) + T = render.import_model(model, t_input, t_input) + t_shapes = [tf.shape(T(node.name))[1:] for node in proposed_layers] + shapes = sess.run(t_shapes, {t_input: np.zeros([1] + model.image_shape)}) + return zip(proposed_layers, shapes) + + +def print_model_layer_code(model): + print("layers = [") + for node, shape in propose_layers_with_shapes(model): + layer_type = "conv" if len(shape) == 3 else "dense" + name = node.name.encode("ascii", "replace") + layer = {"name": name, "type": layer_type, "size": shape[-1]} + print(" ", layer, ",") + print(" ]") diff --git a/lucid/scratch/scripts/import_caffe/import_model.sh b/lucid/scratch/scripts/import_caffe/import_model.sh new file mode 100644 index 00000000..914bf4f3 --- /dev/null +++ b/lucid/scratch/scripts/import_caffe/import_model.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# Config +MODEL_NAME="VGG_ILSVRC_16_layers" +PROTO_URL="https://gist.githubusercontent.com/ksimonyan/211839e770f7b538e2d8/raw/ded9363bd93ec0c770134f4e387d8aaaaa2407ce/VGG_ILSVRC_16_layers_deploy.prototxt" +CAFFE_URL="http://www.robots.ox.ac.uk/~vgg/software/very_deep/caffe/VGG_ILSVRC_16_layers.caffemodel" + +# Enter virtualenv (for old TF version, etc) +cd workspace/ +. bin/activate + +# Fetch caffe model files +echo "" +echo "----------------------------------------" +echo "Fetching models" +echo "----------------------------------------" +curl -sS ${PROTO_URL} --output ${MODEL_NAME}.prototxt +curl -sS ${CAFFE_URL} --output ${MODEL_NAME}.caffemodel + +# Upgrade prototxt, in case it's for an old unsupported version of caffe. +echo "" +echo "----------------------------------------" +echo "Attempting to upgrade proto file format" +echo "----------------------------------------" +upgrade_net_proto_text ${MODEL_NAME}.prototxt ${MODEL_NAME}_upgraded.prototxt + +# caffe-tensorflow will fail if .tmp/ already exists +rm -rf .tmp/ + +# Run caffe-tensorflow conversion script +echo "" +echo "----------------------------------------" +echo "Attempting to convert to tensorflow" +echo "----------------------------------------" +python caffe-tensorflow/convert.py \ + --caffemodel ${MODEL_NAME}.caffemodel \ + --standalone-output-path ${MODEL_NAME}.pb \ + ${MODEL_NAME}_upgraded.prototxt + +echo "Frozen tensflow graph:" +echo " workspace/${MODEL_NAME}.pb" diff --git a/lucid/scratch/scripts/import_caffe/make_workspace.sh b/lucid/scratch/scripts/import_caffe/make_workspace.sh new file mode 100644 index 00000000..720d2d18 --- /dev/null +++ b/lucid/scratch/scripts/import_caffe/make_workspace.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# Run this script once to create the workspace for us to export models +# from caffe. This is necessary because caffe-tensorflow needs old tf versions. + +# Create and enter virtualenv +virtualenv workspace +cd workspace +. bin/activate + +# Install virtualenv dependencies +pip install tensorflow==1.2 +git clone https://github.com/linkfluence/caffe-tensorflow diff --git a/lucid/scratch/scripts/import_caffe/readme.md b/lucid/scratch/scripts/import_caffe/readme.md new file mode 100644 index 00000000..bf634ff0 --- /dev/null +++ b/lucid/scratch/scripts/import_caffe/readme.md @@ -0,0 +1,14 @@ + + +One way to import caffe models is [caffe-tensorflow](https://github.com/ethereon/caffe-tensorflow) which now has a `--standalone-output-path` for directly crating frozen models (see ethereon/caffe-tensorflow#76). + +Getting this to work reliably takes a number of tricks, including using an old tensorflow version, running a caffe model update script, and manually cleaning up temp files. The included scripts should handle all of this for you. + +(1) Install global dependencies: + ```sh + apt install -y caffe-cpu + pip install virtualenv + ``` +(2) Run `make_workspace.sh` (in this directory) to create isolated workspace +(3) Edit the "Config" section in `import_model.sh` +(4) Run `import_model.sh` (in this directory) to import specified model diff --git a/lucid/scratch/scripts/import_slim/import_models.ipy b/lucid/scratch/scripts/import_slim/import_models.ipy new file mode 100644 index 00000000..9e8d9589 --- /dev/null +++ b/lucid/scratch/scripts/import_slim/import_models.ipy @@ -0,0 +1,101 @@ +from lucid.modelzoo.vision_base import load_graphdef + + +path=!pwd +path=path[0] +!rm -rf exports/ +!mkdir exports +!mkdir frozen + +model_defs = open("model_defs.py", "w") + +def get_model_info(graphdef_path): + graphdef = load_graphdef(graphdef_path) + info = {} + + inp_node = graphdef.node[0] + info['input_name' ] = inp_node.name + info['input_shape'] = [int(dim.size) for dim in inp_node.attr['shape'].shape.dim] + + info['out_name' ] = graphdef.node[-1].name + return info + + +with open("weight_urls.txt") as wf, open("names.txt") as nf: + for weight_url, name, in zip(wf, nf)[::1]: + weight_url, name = weight_url[:-1], name[:-1] + + print "" + print "" + print "" + print "" + print "## ", name + + export_path = path + "/exports/" + name + !mkdir {export_path} + %cd {export_path} + + # Deal with checkpoints + print "" + print "Fetching checkpoint (weights)..." + !curl -sS {weight_url} --output {name}.tgz + !tar xf {name}.tgz + ckpt = !find . | grep "ckpt$" + ckpt2 = !find . | grep ".ckpt.index" + ckpt = (ckpt+ckpt2)[0] + if ".index" in ckpt: ckpt = ckpt.replace(".index", "") + !find . + print ">", ckpt + + print "" + print "Exporting inference graph...." + if "vgg" not in name and "resnet_v1" not in name: + !echo "{path}/models/research/slim/export_inference_graph.py --alsologtostderr --model_name={name} --output_file=model.pb" + !{path}/tf.sh {path}/models/research/slim/export_inference_graph.py --alsologtostderr --model_name={name} --output_file=model.pb + else: + !echo "{path}/models/research/slim/export_inference_graph.py --alsologtostderr --model_name={name} --output_file=model.pb --labels_offset=1" + !{path}/tf.sh {path}/models/research/slim/export_inference_graph.py --alsologtostderr --model_name={name} --output_file=model.pb --labels_offset=1 + + + info = get_model_info("model.pb") + out_name = info["out_name"] + input_name = info["input_name"] + input_shape = info["input_shape"] + + pretty_name = name + pretty_name = pretty_name.replace("vgg", "VGG") + pretty_name = pretty_name.replace("-", "_") + pieces = pretty_name.split("_") + for i in range(len(pieces)): + pieces[i] = pieces[i][0:1].upper() + pieces[i][1:] + pretty_name = "".join(pieces) + + print "" + print "Freezing variables into graph...." + !echo "{path}/freeze_graph.py --input_graph=model.pb --input_checkpoint={ckpt} --input_binary=true --output_graph=frozen.pb --output_node_names={out_name}" + !{path}/tf.sh {path}/freeze_graph.py --input_graph=model.pb --input_checkpoint={ckpt} --input_binary=true --output_graph=frozen.pb --output_node_names={out_name} + !cp frozen.pb {path}/frozen/{pretty_name}_slim.pb + + print "" + + + + model_defs.write("""\n\n +class {pretty_name}_slim(Model): + \"\"\"{pretty_name} as implemented by the TensorFlow slim framework. + + This function provides the pre-trained reimplementation from TF slim: + https://github.com/tensorflow/models/tree/master/research/slim + \"\"\" + + model_path = 'gs://modelzoo/{pretty_name}_slim.pb' + labels_path = 'gs://modelzoo/InceptionV1-labels.txt' #TODO + image_shape = {input_shape} + # inpute range taken from: + # https://github.com/tensorflow/models/blob/master/research/slim/preprocessing/inception_preprocessing.py#L280 + image_value_range = (-1, 1) + input_name = '{input_name}' + """.format(**locals()) + ) + +model_defs.close() diff --git a/lucid/scratch/scripts/import_slim/parse_readme_table.sh b/lucid/scratch/scripts/import_slim/parse_readme_table.sh new file mode 100644 index 00000000..2700289e --- /dev/null +++ b/lucid/scratch/scripts/import_slim/parse_readme_table.sh @@ -0,0 +1,17 @@ + +# Extract list of urls for checkpoints +cat slim_readme_table.md \ + | sed "s/[|\\(\\)]/\n/g" \ + | grep download.tensorflow.org \ + > url_list.txt + +# Create proposed list of model names (will need to be modified) +cat url_list.txt \ + | sed "s/\\//\n/g" \ + | grep "gz$" \ + | sed "s/_201[0-9]_[0-9][0-9]_[0-9][0-9].tar.gz//g" \ + | sed "s/_[0-9][0-9]_[0-9][0-9]_201[0-9].tar.gz//g" \ + > names.txt + +# TODO - make sure to sanity check the output of this script before +# running the next one. diff --git a/lucid/scratch/scripts/import_slim/readme.md b/lucid/scratch/scripts/import_slim/readme.md new file mode 100644 index 00000000..71cdaa9e --- /dev/null +++ b/lucid/scratch/scripts/import_slim/readme.md @@ -0,0 +1,12 @@ +# Importing models from tf-slim + +(1) Install dependencies *into this directory*: + ```sh + git clone https://github.com/tensorflow/models.git + wget https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/python/tools/freeze_graph.py + ``` +(2) Save latest table of slim models and checkpoints as `slim_readme_table.md` +(3) Run `parse_readme_table.sh` (from within this directory) +(4) Sanity check the output (`url_list.txt` and `names.txt`) +(5) Run `import_models.ipy` (from within this directory) +(6) See `frozen/*.pb` and `model_defs.py` diff --git a/lucid/scratch/scripts/import_slim/slim_readme_table.md b/lucid/scratch/scripts/import_slim/slim_readme_table.md new file mode 100644 index 00000000..fb466eb8 --- /dev/null +++ b/lucid/scratch/scripts/import_slim/slim_readme_table.md @@ -0,0 +1,23 @@ +[Inception V1](http://arxiv.org/abs/1409.4842v1)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_v1.py)|[inception_v1_2016_08_28.tar.gz](http://download.tensorflow.org/models/inception_v1_2016_08_28.tar.gz)|69.8|89.6| +[Inception V2](http://arxiv.org/abs/1502.03167)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_v2.py)|[inception_v2_2016_08_28.tar.gz](http://download.tensorflow.org/models/inception_v2_2016_08_28.tar.gz)|73.9|91.8| +[Inception V3](http://arxiv.org/abs/1512.00567)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_v3.py)|[inception_v3_2016_08_28.tar.gz](http://download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz)|78.0|93.9| +[Inception V4](http://arxiv.org/abs/1602.07261)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_v4.py)|[inception_v4_2016_09_09.tar.gz](http://download.tensorflow.org/models/inception_v4_2016_09_09.tar.gz)|80.2|95.2| +[Inception-ResNet-v2](http://arxiv.org/abs/1602.07261)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/inception_resnet_v2.py)|[inception_resnet_v2_2016_08_30.tar.gz](http://download.tensorflow.org/models/inception_resnet_v2_2016_08_30.tar.gz)|80.4|95.3| +[ResNet V1 50](https://arxiv.org/abs/1512.03385)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/resnet_v1.py)|[resnet_v1_50_2016_08_28.tar.gz](http://download.tensorflow.org/models/resnet_v1_50_2016_08_28.tar.gz)|75.2|92.2| +[ResNet V1 101](https://arxiv.org/abs/1512.03385)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/resnet_v1.py)|[resnet_v1_101_2016_08_28.tar.gz](http://download.tensorflow.org/models/resnet_v1_101_2016_08_28.tar.gz)|76.4|92.9| +[ResNet V1 152](https://arxiv.org/abs/1512.03385)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/resnet_v1.py)|[resnet_v1_152_2016_08_28.tar.gz](http://download.tensorflow.org/models/resnet_v1_152_2016_08_28.tar.gz)|76.8|93.2| +[ResNet V2 50](https://arxiv.org/abs/1603.05027)^|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/resnet_v2.py)|[resnet_v2_50_2017_04_14.tar.gz](http://download.tensorflow.org/models/resnet_v2_50_2017_04_14.tar.gz)|75.6|92.8| +[ResNet V2 101](https://arxiv.org/abs/1603.05027)^|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/resnet_v2.py)|[resnet_v2_101_2017_04_14.tar.gz](http://download.tensorflow.org/models/resnet_v2_101_2017_04_14.tar.gz)|77.0|93.7| +[ResNet V2 152](https://arxiv.org/abs/1603.05027)^|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/resnet_v2.py)|[resnet_v2_152_2017_04_14.tar.gz](http://download.tensorflow.org/models/resnet_v2_152_2017_04_14.tar.gz)|77.8|94.1| +[ResNet V2 200](https://arxiv.org/abs/1603.05027)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/resnet_v2.py)|[TBA]()|79.9\*|95.2\*| +[VGG 16](http://arxiv.org/abs/1409.1556.pdf)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/vgg.py)|[vgg_16_2016_08_28.tar.gz](http://download.tensorflow.org/models/vgg_16_2016_08_28.tar.gz)|71.5|89.8| +[VGG 19](http://arxiv.org/abs/1409.1556.pdf)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/vgg.py)|[vgg_19_2016_08_28.tar.gz](http://download.tensorflow.org/models/vgg_19_2016_08_28.tar.gz)|71.1|89.8| +[MobileNet_v1_1.0_224](https://arxiv.org/pdf/1704.04861.pdf)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet_v1.py)|[mobilenet_v1_1.0_224.tgz](http://download.tensorflow.org/models/mobilenet_v1_2018_02_22/mobilenet_v1_1.0_224.tgz)|70.9|89.9| +[MobileNet_v1_0.50_160](https://arxiv.org/pdf/1704.04861.pdf)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet_v1.py)|[mobilenet_v1_0.50_160.tgz](http://download.tensorflow.org/models/mobilenet_v1_2018_02_22/mobilenet_v1_0.5_160.tgz)|59.1|81.9| +[MobileNet_v1_0.25_128](https://arxiv.org/pdf/1704.04861.pdf)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet_v1.py)|[mobilenet_v1_0.25_128.tgz](http://download.tensorflow.org/models/mobilenet_v1_2018_02_22/mobilenet_v1_0.25_128.tgz)|41.5|66.3| +[MobileNet_v2_1.4_224^*](https://arxiv.org/abs/1801.04381)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet_v2.py)| [mobilenet_v2_1.4_224.tgz](https://storage.googleapis.com/mobilenet_v2/checkpoints/mobilenet_v2_1.4_224.tgz) | 74.9 | 92.5| +[MobileNet_v2_1.0_224^*](https://arxiv.org/abs/1801.04381)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet_v2.py)| [mobilenet_v2_1.0_224.tgz](https://storage.googleapis.com/mobilenet_v2/checkpoints/mobilenet_v2_1.0_224.tgz) | 71.9 | 91.0 +[NASNet-A_Mobile_224](https://arxiv.org/abs/1707.07012)#|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/nasnet/nasnet.py)|[nasnet-a_mobile_04_10_2017.tar.gz](https://storage.googleapis.com/download.tensorflow.org/models/nasnet-a_mobile_04_10_2017.tar.gz)|74.0|91.6| +[NASNet-A_Large_331](https://arxiv.org/abs/1707.07012)#|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/nasnet/nasnet.py)|[nasnet-a_large_04_10_2017.tar.gz](https://storage.googleapis.com/download.tensorflow.org/models/nasnet-a_large_04_10_2017.tar.gz)|82.7|96.2| +[PNASNet-5_Large_331](https://arxiv.org/abs/1712.00559)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/nasnet/pnasnet.py)|[pnasnet-5_large_2017_12_13.tar.gz](https://storage.googleapis.com/download.tensorflow.org/models/pnasnet-5_large_2017_12_13.tar.gz)|82.9|96.2| +[PNASNet-5_Mobile_224](https://arxiv.org/abs/1712.00559)|[Code](https://github.com/tensorflow/models/blob/master/research/slim/nets/nasnet/pnasnet.py)|[pnasnet-5_mobile_2017_12_13.tar.gz](https://storage.googleapis.com/download.tensorflow.org/models/pnasnet-5_mobile_2017_12_13.tar.gz)|74.2|91.9| diff --git a/tests/conftest.py b/tests/conftest.py index 8591d03b..7abb38be 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,3 +8,19 @@ def inceptionv1(): model = InceptionV1() model.load_graphdef() return model + + +def pytest_addoption(parser): + parser.addoption( + "--run-slow", action="store_true", default=False, help="run slow tests" + ) + + +def pytest_collection_modifyitems(config, items): + if config.getoption("--run-slow"): + return + else: + skip_slow = pytest.mark.skip(reason="need --runslow option to run") + for item in items: + if "slow" in item.keywords: + item.add_marker(skip_slow) diff --git a/tests/misc/test_channel_reducer.py b/tests/misc/test_channel_reducer.py index bb8031b3..8e6f06ab 100644 --- a/tests/misc/test_channel_reducer.py +++ b/tests/misc/test_channel_reducer.py @@ -7,14 +7,14 @@ def test_channel_reducer_trivial(): - array = np.zeros((10,10,10), dtype=np.float32) - for d in range(array.shape[-1]): - array[:,:,d] = np.eye(10,10) + array = np.zeros((10, 10, 10)) + for d in range(array.shape[-1]): + array[:, :, d] = np.eye(10, 10) - channel_reducer = ChannelReducer(n_features=2) - channel_reducer.fit(array) - reduced = channel_reducer.transform(array) + channel_reducer = ChannelReducer(n_features=2) + channel_reducer.fit(array) + reduced = channel_reducer.transform(array) - assert reduced.shape == (10,10,2) - assert (reduced[:,:,0] == array[:,:,0]).all() - assert (reduced[:,:,1] == 0).all() + assert reduced.shape == (10, 10, 2) + # the hope here is that this was reduced to use only the first channel + assert np.sum(reduced[:, :, 1]) == 0 diff --git a/tests/modelzoo/test_InceptionV1.py b/tests/modelzoo/test_InceptionV1.py new file mode 100644 index 00000000..ccac0ab8 --- /dev/null +++ b/tests/modelzoo/test_InceptionV1.py @@ -0,0 +1,42 @@ +from __future__ import absolute_import, division, print_function + +import pytest + +import tensorflow as tf +from lucid.modelzoo.vision_models import InceptionV1 + +important_layer_names = [ + "mixed3a", + "mixed3b", + "mixed4a", + "mixed4b", + "mixed4c", + "mixed4d", + "mixed4e", + "mixed5a", + "mixed5b", +] + + +@pytest.mark.slow +def test_InceptionV1_model_download(): + model = InceptionV1() + model.load_graphdef() + assert model.graph_def is not None + + +@pytest.mark.slow +def test_InceptionV1_graph_import(): + model = InceptionV1() + model.load_graphdef() + model.import_graph() + nodes = tf.get_default_graph().as_graph_def().node + node_names = set(node.name for node in nodes) + for layer_name in important_layer_names: + assert "import/" + layer_name + "_pre_relu" in node_names + + +def test_InceptionV1_labels(): + model = InceptionV1() + assert model.labels is not None + assert model.labels[0] == "dummy" diff --git a/tests/modelzoo/test_nets_factory.py b/tests/modelzoo/test_nets_factory.py new file mode 100644 index 00000000..44a15136 --- /dev/null +++ b/tests/modelzoo/test_nets_factory.py @@ -0,0 +1,42 @@ +# Copyright 2018 The Lucid Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import pytest +import tensorflow as tf + +from lucid.modelzoo.nets_factory import get_model, models_map +from lucid.modelzoo.vision_models import InceptionV1 +from lucid.modelzoo.vision_base import Model, SerializedModel, FrozenGraphModel + +def test_models_map(): + assert len(models_map) > 1 + assert Model.__name__ not in models_map + assert SerializedModel.__name__ not in models_map + assert FrozenGraphModel.__name__ not in models_map + assert InceptionV1.__name__ in models_map + +def test_get_model(): + model = get_model("InceptionV1") + assert model is not None + assert type(model) == InceptionV1 + +def test_get_model_fuzzy_feedback(): + with pytest.raises(ValueError) as excinfo: + _ = get_model("InceptionV2") + assert "InceptionV2_slim" in str(excinfo.value) diff --git a/tests/modelzoo/test_vision_models.py b/tests/modelzoo/test_vision_models.py index a972b4d7..42df8933 100644 --- a/tests/modelzoo/test_vision_models.py +++ b/tests/modelzoo/test_vision_models.py @@ -1,30 +1,22 @@ from __future__ import absolute_import, division, print_function import pytest - import tensorflow as tf -from lucid.modelzoo.vision_models import InceptionV1 - -important_layer_names = [ - "mixed3a", "mixed3b", "mixed4a", "mixed4b", "mixed4c", "mixed4d", "mixed4e", - "mixed5a", "mixed5b" -] -def test_InceptionV1_model_download(): - model = InceptionV1() - model.load_graphdef() - assert model.graph_def is not None +from lucid.modelzoo.nets_factory import models_map, get_model -def test_InceptionV1_graph_import(): - model = InceptionV1() - model.load_graphdef() - model.import_graph() - nodes = tf.get_default_graph().as_graph_def().node - node_names = set(node.name for node in nodes) - for layer_name in important_layer_names: - assert "import/"+layer_name+"_pre_relu" in node_names -def test_InceptionV1_labels(): - model = InceptionV1() - assert model.labels is not None - assert model.labels[0] == "dummy" +@pytest.mark.slow +@pytest.mark.parametrize("name,model_class", models_map.items()) +def test_model_layers_shapes(name, model_class): + scope = "TestLucidModelzoo" + model = model_class() + model.load_graphdef() + with tf.Graph().as_default() as graph: + model.import_graph(scope=scope) + for layer in model.layers: + name, declared_size = (layer[key] for key in ("name", "size")) + imported_name = "{}/{}:0".format(scope, name) + tensor = graph.get_tensor_by_name(imported_name) + actual_size = tensor.shape[-1] + assert int(actual_size) == int(declared_size) diff --git a/tests/optvis/param/test_cppn.py b/tests/optvis/param/test_cppn.py index 7502e6ea..497034fa 100644 --- a/tests/optvis/param/test_cppn.py +++ b/tests/optvis/param/test_cppn.py @@ -12,23 +12,34 @@ log = logging.getLogger(__name__) + +@pytest.mark.slow def test_cppn_fits_xor(): - with tf.Graph().as_default(), tf.Session() as sess: - cppn_param = cppn(16, num_output_channels=1)[0] - - def xor_objective(a): - return -(tf.square(a[0, 0]) + tf.square(a[-1, -1]) + - tf.square(1.0-a[-1, 0]) + tf.square(1.0-a[0, -1])) - - loss_t = xor_objective(cppn_param) - optimizer = tf.train.AdamOptimizer(0.01) - objective = optimizer.minimize(loss_t) - tf.global_variables_initializer().run() - loss = loss_t.eval() - for i in range(100): - _, vis = sess.run([objective, cppn_param]) - close_enough = vis[ 0, 0] > .99 and vis[-1, -1] > .99 and \ - vis[-1, 0] < .01 and vis[ 0, -1] < .01 - if close_enough: return - assert False, "fitting XOR took more than 100 steps, failing test" + with tf.Graph().as_default(), tf.Session() as sess: + cppn_param = cppn(16, num_output_channels=1)[0] + + def xor_objective(a): + return -( + tf.square(a[0, 0]) + + tf.square(a[-1, -1]) + + tf.square(1.0 - a[-1, 0]) + + tf.square(1.0 - a[0, -1]) + ) + + loss_t = xor_objective(cppn_param) + optimizer = tf.train.AdamOptimizer(0.01) + objective = optimizer.minimize(loss_t) + tf.global_variables_initializer().run() + loss = loss_t.eval() + for i in range(100): + _, vis = sess.run([objective, cppn_param]) + close_enough = ( + vis[0, 0] > .99 + and vis[-1, -1] > .99 + and vis[-1, 0] < .01 + and vis[0, -1] < .01 + ) + if close_enough: + return + assert False, "fitting XOR took more than 100 steps, failing test" diff --git a/tests/optvis/test_integration.py b/tests/optvis/test_integration.py index e49efaca..8a5b6154 100644 --- a/tests/optvis/test_integration.py +++ b/tests/optvis/test_integration.py @@ -6,6 +6,7 @@ from lucid.optvis import objectives, param, render, transform +@pytest.mark.slow @pytest.mark.parametrize("decorrelate", [True, False]) @pytest.mark.parametrize("fft", [True, False]) def test_integration(decorrelate, fft, inceptionv1): diff --git a/tox.ini b/tox.ini index ae112e63..0faac0d7 100644 --- a/tox.ini +++ b/tox.ini @@ -5,8 +5,8 @@ envlist = py{27,36} deps = tensorflow .[test] -commands = coverage run --source lucid -m py.test +commands = coverage run --source lucid -m py.test {posargs} [pytest] -addopts = --verbose +addopts = --verbose --run-slow testpaths = ./tests/