diff --git a/how-to-use-azureml/deployment/accelerated-models/NOTICE.txt b/how-to-use-azureml/deployment/accelerated-models/NOTICE.txt deleted file mode 100644 index 96973939..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/NOTICE.txt +++ /dev/null @@ -1,219 +0,0 @@ - -NOTICES AND INFORMATION -Do Not Translate or Localize - -This Azure Machine Learning service example notebooks repository includes material from the projects listed below. - - -1. SSD-Tensorflow (https://github.com/balancap/ssd-tensorflow) - - -%% SSD-Tensorflow NOTICES AND INFORMATION BEGIN HERE -========================================= - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - -========================================= -END OF SSD-Tensorflow NOTICES AND INFORMATION - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331885.7651057.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331885.7651057.jpg deleted file mode 100644 index db68228a..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331885.7651057.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331885.7651057.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331885.7651057.xml deleted file mode 100644 index f9042633..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331885.7651057.xml +++ /dev/null @@ -1,26 +0,0 @@ - - runfourftbackdropvalidation - 1556331885.7651057.jpg - F:\runfourftbackdropvalidation\1556331885.7651057.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 19 - 108 - 62 - 177 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331892.593489.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331892.593489.jpg deleted file mode 100644 index f9648fa2..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331892.593489.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331892.593489.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331892.593489.xml deleted file mode 100644 index 3355d325..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331892.593489.xml +++ /dev/null @@ -1,38 +0,0 @@ - - runfourftbackdropvalidation - 1556331892.593489.jpg - F:\runfourftbackdropvalidation\1556331892.593489.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 155 - 85 - 204 - 165 - - - - stockout - Unspecified - 0 - 0 - - 24 - 101 - 59 - 175 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331893.711867.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331893.711867.jpg deleted file mode 100644 index 46a1ac00..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331893.711867.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331893.711867.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331893.711867.xml deleted file mode 100644 index ac9cfdb3..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331893.711867.xml +++ /dev/null @@ -1,38 +0,0 @@ - - runfourftbackdropvalidation - 1556331893.711867.jpg - F:\runfourftbackdropvalidation\1556331893.711867.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 156 - 87 - 205 - 166 - - - - stockout - Unspecified - 0 - 0 - - 25 - 107 - 62 - 175 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331899.4232247.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331899.4232247.jpg deleted file mode 100644 index 950ad85a..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331899.4232247.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331899.4232247.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331899.4232247.xml deleted file mode 100644 index 835cdf12..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331899.4232247.xml +++ /dev/null @@ -1,50 +0,0 @@ - - runfourftbackdropvalidation - 1556331899.4232247.jpg - F:\runfourftbackdropvalidation\1556331899.4232247.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 248 - 79 - 299 - 160 - - - - stockout - Unspecified - 0 - 0 - - 158 - 84 - 201 - 163 - - - - stockout - Unspecified - 0 - 0 - - 25 - 98 - 67 - 175 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331908.5590174.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331908.5590174.jpg deleted file mode 100644 index d94691ec..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331908.5590174.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331908.5590174.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331908.5590174.xml deleted file mode 100644 index 240d4a3b..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331908.5590174.xml +++ /dev/null @@ -1,62 +0,0 @@ - - runfourftbackdropvalidation - 1556331908.5590174.jpg - F:\runfourftbackdropvalidation\1556331908.5590174.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 363 - 78 - 433 - 165 - - - - stockout - Unspecified - 0 - 0 - - 249 - 79 - 306 - 163 - - - - stockout - Unspecified - 0 - 0 - - 156 - 81 - 204 - 164 - - - - stockout - Unspecified - 0 - 0 - - 24 - 102 - 66 - 177 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331915.4019358.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331915.4019358.jpg deleted file mode 100644 index 7f250a14..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331915.4019358.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331915.4019358.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331915.4019358.xml deleted file mode 100644 index 667542e7..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331915.4019358.xml +++ /dev/null @@ -1,74 +0,0 @@ - - runfourftbackdropvalidation - 1556331915.4019358.jpg - F:\runfourftbackdropvalidation\1556331915.4019358.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 363 - 70 - 432 - 163 - - - - stockout - Unspecified - 0 - 0 - - 248 - 78 - 307 - 162 - - - - stockout - Unspecified - 0 - 0 - - 157 - 87 - 201 - 162 - - - - stockout - Unspecified - 0 - 0 - - 22 - 105 - 62 - 175 - - - - stockout - Unspecified - 0 - 0 - - 309 - 177 - 374 - 246 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331924.4523242.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331924.4523242.jpg deleted file mode 100644 index ce7dab24..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331924.4523242.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331924.4523242.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331924.4523242.xml deleted file mode 100644 index be938849..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331924.4523242.xml +++ /dev/null @@ -1,86 +0,0 @@ - - runfourftbackdropvalidation - 1556331924.4523242.jpg - F:\runfourftbackdropvalidation\1556331924.4523242.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 362 - 70 - 435 - 162 - - - - stockout - Unspecified - 0 - 0 - - 252 - 80 - 304 - 160 - - - - stockout - Unspecified - 0 - 0 - - 152 - 81 - 205 - 162 - - - - stockout - Unspecified - 0 - 0 - - 23 - 99 - 67 - 175 - - - - stockout - Unspecified - 0 - 0 - - 180 - 179 - 248 - 249 - - - - stockout - Unspecified - 0 - 0 - - 309 - 177 - 373 - 245 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331925.6244981.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331925.6244981.jpg deleted file mode 100644 index c0240b27..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331925.6244981.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331925.6244981.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331925.6244981.xml deleted file mode 100644 index 891d5e95..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331925.6244981.xml +++ /dev/null @@ -1,62 +0,0 @@ - - runfourftbackdropvalidation - 1556331925.6244981.jpg - F:/runfourftbackdropvalidation/1556331925.6244981.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 365 - 67 - 432 - 163 - - - - stockout - Unspecified - 0 - 0 - - 252 - 72 - 300 - 160 - - - - stockout - Unspecified - 0 - 0 - - 31 - 94 - 70 - 172 - - - - stockout - Unspecified - 0 - 0 - - 310 - 175 - 379 - 246 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331930.159372.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331930.159372.jpg deleted file mode 100644 index 7bba24af..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331930.159372.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331930.159372.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331930.159372.xml deleted file mode 100644 index 8e6fcb6a..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331930.159372.xml +++ /dev/null @@ -1,98 +0,0 @@ - - runfourftbackdropvalidation - 1556331930.159372.jpg - F:\runfourftbackdropvalidation\1556331930.159372.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 359 - 70 - 430 - 160 - - - - stockout - Unspecified - 0 - 0 - - 246 - 77 - 308 - 161 - - - - stockout - Unspecified - 0 - 0 - - 154 - 84 - 205 - 163 - - - - stockout - Unspecified - 0 - 0 - - 24 - 101 - 65 - 179 - - - - stockout - Unspecified - 0 - 0 - - 58 - 188 - 116 - 254 - - - - stockout - Unspecified - 0 - 0 - - 179 - 177 - 247 - 247 - - - - stockout - Unspecified - 0 - 0 - - 308 - 178 - 375 - 247 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331932.4657435.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331932.4657435.jpg deleted file mode 100644 index 15be4311..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331932.4657435.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331932.4657435.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331932.4657435.xml deleted file mode 100644 index 72db507e..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331932.4657435.xml +++ /dev/null @@ -1,98 +0,0 @@ - - runfourftbackdropvalidation - 1556331932.4657435.jpg - F:\runfourftbackdropvalidation\1556331932.4657435.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 358 - 70 - 436 - 168 - - - - stockout - Unspecified - 0 - 0 - - 248 - 76 - 307 - 161 - - - - stockout - Unspecified - 0 - 0 - - 156 - 77 - 206 - 163 - - - - stockout - Unspecified - 0 - 0 - - 22 - 97 - 64 - 175 - - - - stockout - Unspecified - 0 - 0 - - 309 - 178 - 374 - 244 - - - - stockout - Unspecified - 0 - 0 - - 176 - 178 - 247 - 238 - - - - stockout - Unspecified - 0 - 0 - - 58 - 187 - 107 - 250 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331939.207552.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331939.207552.jpg deleted file mode 100644 index ca996e26..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331939.207552.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331939.207552.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331939.207552.xml deleted file mode 100644 index 89da46e5..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331939.207552.xml +++ /dev/null @@ -1,110 +0,0 @@ - - runfourftbackdropvalidation - 1556331939.207552.jpg - F:\runfourftbackdropvalidation\1556331939.207552.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 362 - 66 - 432 - 164 - - - - stockout - Unspecified - 0 - 0 - - 250 - 77 - 304 - 160 - - - - stockout - Unspecified - 0 - 0 - - 156 - 81 - 203 - 162 - - - - stockout - Unspecified - 0 - 0 - - 23 - 99 - 65 - 177 - - - - stockout - Unspecified - 0 - 0 - - 60 - 188 - 115 - 255 - - - - stockout - Unspecified - 0 - 0 - - 182 - 178 - 244 - 245 - - - - stockout - Unspecified - 0 - 0 - - 309 - 177 - 373 - 245 - - - - stockout - Unspecified - 0 - 0 - - 136 - 264 - 195 - 312 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331946.024382.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331946.024382.jpg deleted file mode 100644 index c70acb0e..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331946.024382.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331946.024382.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331946.024382.xml deleted file mode 100644 index 45614e2e..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331946.024382.xml +++ /dev/null @@ -1,122 +0,0 @@ - - runfourftbackdropvalidation - 1556331946.024382.jpg - F:\runfourftbackdropvalidation\1556331946.024382.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 362 - 68 - 433 - 166 - - - - stockout - Unspecified - 0 - 0 - - 248 - 79 - 303 - 160 - - - - stockout - Unspecified - 0 - 0 - - 158 - 82 - 204 - 163 - - - - stockout - Unspecified - 0 - 0 - - 27 - 102 - 63 - 175 - - - - stockout - Unspecified - 0 - 0 - - 185 - 176 - 244 - 246 - - - - stockout - Unspecified - 0 - 0 - - 309 - 176 - 373 - 244 - - - - stockout - Unspecified - 0 - 0 - - 58 - 189 - 113 - 257 - - - - stockout - Unspecified - 0 - 0 - - 129 - 265 - 196 - 311 - - - - stockout - Unspecified - 0 - 0 - - 227 - 260 - 287 - 309 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331947.1424165.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331947.1424165.jpg deleted file mode 100644 index 4a972690..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331947.1424165.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331947.1424165.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331947.1424165.xml deleted file mode 100644 index 302ee5fe..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331947.1424165.xml +++ /dev/null @@ -1,98 +0,0 @@ - - runfourftbackdropvalidation - 1556331947.1424165.jpg - F:\runfourftbackdropvalidation\1556331947.1424165.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 362 - 77 - 439 - 166 - - - - stockout - Unspecified - 0 - 0 - - 157 - 81 - 204 - 165 - - - - stockout - Unspecified - 0 - 0 - - 250 - 78 - 284 - 138 - - - - stockout - Unspecified - 0 - 0 - - 25 - 101 - 62 - 177 - - - - stockout - Unspecified - 0 - 0 - - 60 - 188 - 114 - 253 - - - - stockout - Unspecified - 0 - 0 - - 132 - 262 - 195 - 311 - - - - stockout - Unspecified - 0 - 0 - - 305 - 175 - 378 - 247 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331958.545843.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331958.545843.jpg deleted file mode 100644 index e594946a..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331958.545843.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331958.545843.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331958.545843.xml deleted file mode 100644 index e2c25c5c..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331958.545843.xml +++ /dev/null @@ -1,134 +0,0 @@ - - runfourftbackdropvalidation - 1556331958.545843.jpg - F:\runfourftbackdropvalidation\1556331958.545843.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 366 - 68 - 433 - 165 - - - - stockout - Unspecified - 0 - 0 - - 250 - 79 - 305 - 161 - - - - stockout - Unspecified - 0 - 0 - - 159 - 85 - 204 - 164 - - - - stockout - Unspecified - 0 - 0 - - 21 - 99 - 60 - 172 - - - - stockout - Unspecified - 0 - 0 - - 62 - 187 - 114 - 254 - - - - stockout - Unspecified - 0 - 0 - - 177 - 178 - 245 - 248 - - - - stockout - Unspecified - 0 - 0 - - 308 - 177 - 374 - 246 - - - - stockout - Unspecified - 0 - 0 - - 127 - 263 - 197 - 311 - - - - stockout - Unspecified - 0 - 0 - - 229 - 259 - 281 - 307 - - - - stockout - Unspecified - 0 - 0 - - 338 - 260 - 390 - 310 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331964.128358.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331964.128358.jpg deleted file mode 100644 index 3e665bdb..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331964.128358.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331964.128358.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331964.128358.xml deleted file mode 100644 index 33b820cc..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331964.128358.xml +++ /dev/null @@ -1,134 +0,0 @@ - - runfourftbackdropvalidation - 1556331964.128358.jpg - F:\runfourftbackdropvalidation\1556331964.128358.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 365 - 70 - 428 - 162 - - - - stockout - Unspecified - 0 - 0 - - 247 - 75 - 305 - 160 - - - - stockout - Unspecified - 0 - 0 - - 154 - 79 - 203 - 163 - - - - stockout - Unspecified - 0 - 0 - - 23 - 101 - 62 - 174 - - - - stockout - Unspecified - 0 - 0 - - 173 - 178 - 246 - 248 - - - - stockout - Unspecified - 0 - 0 - - 303 - 178 - 378 - 246 - - - - stockout - Unspecified - 0 - 0 - - 335 - 257 - 389 - 309 - - - - stockout - Unspecified - 0 - 0 - - 227 - 262 - 289 - 311 - - - - stockout - Unspecified - 0 - 0 - - 155 - 262 - 198 - 311 - - - - stockout - Unspecified - 0 - 0 - - 327 - 317 - 368 - 352 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331967.5599852.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331967.5599852.jpg deleted file mode 100644 index bbef6d25..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331967.5599852.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331967.5599852.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331967.5599852.xml deleted file mode 100644 index bef6629f..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331967.5599852.xml +++ /dev/null @@ -1,146 +0,0 @@ - - runfourftbackdropvalidation - 1556331967.5599852.jpg - F:\runfourftbackdropvalidation\1556331967.5599852.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 368 - 71 - 432 - 164 - - - - stockout - Unspecified - 0 - 0 - - 253 - 76 - 301 - 160 - - - - stockout - Unspecified - 0 - 0 - - 157 - 81 - 203 - 162 - - - - stockout - Unspecified - 0 - 0 - - 309 - 177 - 373 - 247 - - - - stockout - Unspecified - 0 - 0 - - 180 - 180 - 246 - 246 - - - - stockout - Unspecified - 0 - 0 - - 59 - 185 - 115 - 254 - - - - stockout - Unspecified - 0 - 0 - - 127 - 262 - 194 - 311 - - - - stockout - Unspecified - 0 - 0 - - 228 - 262 - 285 - 306 - - - - stockout - Unspecified - 0 - 0 - - 336 - 260 - 386 - 306 - - - - stockout - Unspecified - 0 - 0 - - 324 - 319 - 368 - 354 - - - - stockout - Unspecified - 0 - 0 - - 25 - 103 - 64 - 176 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331976.6628668.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331976.6628668.jpg deleted file mode 100644 index 25023982..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331976.6628668.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331976.6628668.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331976.6628668.xml deleted file mode 100644 index 570ced67..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331976.6628668.xml +++ /dev/null @@ -1,158 +0,0 @@ - - runfourftbackdropvalidation - 1556331976.6628668.jpg - F:\runfourftbackdropvalidation\1556331976.6628668.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 368 - 66 - 427 - 163 - - - - stockout - Unspecified - 0 - 0 - - 250 - 81 - 307 - 161 - - - - stockout - Unspecified - 0 - 0 - - 159 - 83 - 205 - 164 - - - - stockout - Unspecified - 0 - 0 - - 24 - 103 - 64 - 173 - - - - stockout - Unspecified - 0 - 0 - - 56 - 188 - 122 - 254 - - - - stockout - Unspecified - 0 - 0 - - 172 - 180 - 249 - 247 - - - - stockout - Unspecified - 0 - 0 - - 309 - 177 - 375 - 246 - - - - stockout - Unspecified - 0 - 0 - - 336 - 258 - 389 - 306 - - - - stockout - Unspecified - 0 - 0 - - 330 - 318 - 368 - 354 - - - - stockout - Unspecified - 0 - 0 - - 132 - 264 - 197 - 310 - - - - stockout - Unspecified - 0 - 0 - - 229 - 258 - 285 - 307 - - - - stockout - Unspecified - 0 - 0 - - 227 - 321 - 284 - 356 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331980.031822.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331980.031822.jpg deleted file mode 100644 index 866cfda4..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331980.031822.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331980.031822.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331980.031822.xml deleted file mode 100644 index 1d047093..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331980.031822.xml +++ /dev/null @@ -1,146 +0,0 @@ - - Converted JPG with xml runfourftbackdropvalidation - 1556331980.031822.jpg - C:\Users\ZachPerkel\Desktop\Kroger_Olympus\Converted JPG with xml runfourftbackdropvalidation\1556331980.031822.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 367 - 70 - 429 - 164 - - - - stockout - Unspecified - 0 - 0 - - 252 - 81 - 307 - 160 - - - - stockout - Unspecified - 0 - 0 - - 153 - 84 - 206 - 163 - - - - stockout - Unspecified - 0 - 0 - - 23 - 94 - 64 - 176 - - - - stockout - Unspecified - 0 - 0 - - 180 - 181 - 246 - 246 - - - - stockout - Unspecified - 0 - 0 - - 309 - 178 - 375 - 246 - - - - stockout - Unspecified - 0 - 0 - - 337 - 259 - 388 - 306 - - - - stockout - Unspecified - 0 - 0 - - 231 - 260 - 284 - 310 - - - - stockout - Unspecified - 0 - 0 - - 228 - 320 - 284 - 357 - - - - stockout - Unspecified - 0 - 0 - - 330 - 319 - 368 - 354 - - - - stockout - Unspecified - 0 - 0 - - 67 - 187 - 114 - 250 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331991.2960002.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331991.2960002.jpg deleted file mode 100644 index c7ab3302..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331991.2960002.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331991.2960002.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331991.2960002.xml deleted file mode 100644 index 02a2952c..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556331991.2960002.xml +++ /dev/null @@ -1,170 +0,0 @@ - - runfourftbackdropvalidation - 1556331991.2960002.jpg - F:\runfourftbackdropvalidation\1556331991.2960002.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 251 - 77 - 303 - 163 - - - - stockout - Unspecified - 0 - 0 - - 367 - 68 - 425 - 164 - - - - stockout - Unspecified - 0 - 0 - - 152 - 83 - 203 - 164 - - - - stockout - Unspecified - 0 - 0 - - 24 - 98 - 62 - 175 - - - - stockout - Unspecified - 0 - 0 - - 182 - 179 - 245 - 245 - - - - stockout - Unspecified - 0 - 0 - - 307 - 175 - 376 - 247 - - - - stockout - Unspecified - 0 - 0 - - 58 - 184 - 119 - 255 - - - - stockout - Unspecified - 0 - 0 - - 132 - 265 - 197 - 311 - - - - stockout - Unspecified - 0 - 0 - - 227 - 262 - 281 - 309 - - - - stockout - Unspecified - 0 - 0 - - 336 - 258 - 389 - 309 - - - - stockout - Unspecified - 0 - 0 - - 322 - 318 - 372 - 354 - - - - stockout - Unspecified - 0 - 0 - - 226 - 320 - 290 - 360 - - - - stockout - Unspecified - 0 - 0 - - 111 - 326 - 187 - 364 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332002.5715525.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332002.5715525.jpg deleted file mode 100644 index b9fec1b6..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332002.5715525.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332002.5715525.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332002.5715525.xml deleted file mode 100644 index 61ba9454..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332002.5715525.xml +++ /dev/null @@ -1,158 +0,0 @@ - - runfourftbackdropvalidation - 1556332002.5715525.jpg - F:\runfourftbackdropvalidation\1556332002.5715525.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 153 - 81 - 202 - 165 - - - - stockout - Unspecified - 0 - 0 - - 252 - 73 - 305 - 161 - - - - stockout - Unspecified - 0 - 0 - - 368 - 69 - 434 - 165 - - - - stockout - Unspecified - 0 - 0 - - 308 - 177 - 372 - 246 - - - - stockout - Unspecified - 0 - 0 - - 178 - 179 - 245 - 247 - - - - stockout - Unspecified - 0 - 0 - - 60 - 182 - 115 - 256 - - - - stockout - Unspecified - 0 - 0 - - 133 - 264 - 194 - 308 - - - - stockout - Unspecified - 0 - 0 - - 228 - 261 - 282 - 309 - - - - stockout - Unspecified - 0 - 0 - - 338 - 258 - 389 - 307 - - - - stockout - Unspecified - 0 - 0 - - 326 - 318 - 372 - 354 - - - - stockout - Unspecified - 0 - 0 - - 226 - 321 - 286 - 358 - - - - stockout - Unspecified - 0 - 0 - - 115 - 325 - 181 - 364 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332004.8638506.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332004.8638506.jpg deleted file mode 100644 index 0bf52db4..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332004.8638506.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332004.8638506.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332004.8638506.xml deleted file mode 100644 index e469403b..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332004.8638506.xml +++ /dev/null @@ -1,146 +0,0 @@ - - runfourftbackdropvalidation - 1556332004.8638506.jpg - F:\runfourftbackdropvalidation\1556332004.8638506.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 157 - 85 - 203 - 162 - - - - stockout - Unspecified - 0 - 0 - - 252 - 71 - 305 - 160 - - - - stockout - Unspecified - 0 - 0 - - 363 - 66 - 434 - 166 - - - - stockout - Unspecified - 0 - 0 - - 310 - 175 - 373 - 245 - - - - stockout - Unspecified - 0 - 0 - - 183 - 177 - 247 - 246 - - - - stockout - Unspecified - 0 - 0 - - 62 - 188 - 113 - 240 - - - - stockout - Unspecified - 0 - 0 - - 230 - 259 - 281 - 308 - - - - stockout - Unspecified - 0 - 0 - - 337 - 258 - 386 - 305 - - - - stockout - Unspecified - 0 - 0 - - 323 - 316 - 373 - 353 - - - - stockout - Unspecified - 0 - 0 - - 227 - 318 - 289 - 357 - - - - stockout - Unspecified - 0 - 0 - - 150 - 262 - 197 - 311 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332011.6702049.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332011.6702049.jpg deleted file mode 100644 index 56c61bb9..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332011.6702049.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332011.6702049.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332011.6702049.xml deleted file mode 100644 index 99ce5415..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332011.6702049.xml +++ /dev/null @@ -1,146 +0,0 @@ - - runfourftbackdropvalidation - 1556332011.6702049.jpg - F:\runfourftbackdropvalidation\1556332011.6702049.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 157 - 83 - 202 - 162 - - - - stockout - Unspecified - 0 - 0 - - 253 - 79 - 302 - 160 - - - - stockout - Unspecified - 0 - 0 - - 361 - 66 - 430 - 162 - - - - stockout - Unspecified - 0 - 0 - - 310 - 175 - 374 - 246 - - - - stockout - Unspecified - 0 - 0 - - 176 - 178 - 246 - 247 - - - - stockout - Unspecified - 0 - 0 - - 59 - 187 - 116 - 256 - - - - stockout - Unspecified - 0 - 0 - - 127 - 262 - 197 - 311 - - - - stockout - Unspecified - 0 - 0 - - 227 - 260 - 281 - 308 - - - - stockout - Unspecified - 0 - 0 - - 332 - 256 - 384 - 307 - - - - stockout - Unspecified - 0 - 0 - - 317 - 317 - 374 - 353 - - - - stockout - Unspecified - 0 - 0 - - 229 - 314 - 289 - 356 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332026.4848802.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332026.4848802.jpg deleted file mode 100644 index f061a283..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332026.4848802.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332026.4848802.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332026.4848802.xml deleted file mode 100644 index ca4710dd..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332026.4848802.xml +++ /dev/null @@ -1,134 +0,0 @@ - - runfourftbackdropvalidation - 1556332026.4848802.jpg - F:\runfourftbackdropvalidation\1556332026.4848802.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 153 - 83 - 205 - 165 - - - - stockout - Unspecified - 0 - 0 - - 250 - 78 - 305 - 160 - - - - stockout - Unspecified - 0 - 0 - - 360 - 68 - 436 - 166 - - - - stockout - Unspecified - 0 - 0 - - 307 - 177 - 375 - 246 - - - - stockout - Unspecified - 0 - 0 - - 178 - 178 - 246 - 250 - - - - stockout - Unspecified - 0 - 0 - - 50 - 185 - 114 - 255 - - - - stockout - Unspecified - 0 - 0 - - 133 - 263 - 197 - 313 - - - - stockout - Unspecified - 0 - 0 - - 229 - 260 - 281 - 307 - - - - stockout - Unspecified - 0 - 0 - - 337 - 259 - 390 - 306 - - - - stockout - Unspecified - 0 - 0 - - 228 - 321 - 285 - 358 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332027.6408842.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332027.6408842.jpg deleted file mode 100644 index e04fd48d..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332027.6408842.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332027.6408842.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332027.6408842.xml deleted file mode 100644 index 72384da1..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332027.6408842.xml +++ /dev/null @@ -1,98 +0,0 @@ - - runfourftbackdropvalidation - 1556332027.6408842.jpg - F:\runfourftbackdropvalidation\1556332027.6408842.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 155 - 84 - 203 - 164 - - - - stockout - Unspecified - 0 - 0 - - 251 - 72 - 303 - 163 - - - - stockout - Unspecified - 0 - 0 - - 361 - 66 - 435 - 165 - - - - stockout - Unspecified - 0 - 0 - - 308 - 179 - 375 - 242 - - - - stockout - Unspecified - 0 - 0 - - 178 - 175 - 246 - 243 - - - - stockout - Unspecified - 0 - 0 - - 59 - 187 - 115 - 255 - - - - stockout - Unspecified - 0 - 0 - - 133 - 264 - 197 - 311 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332033.268194.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332033.268194.jpg deleted file mode 100644 index 7455cf53..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332033.268194.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332033.268194.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332033.268194.xml deleted file mode 100644 index df588de5..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332033.268194.xml +++ /dev/null @@ -1,122 +0,0 @@ - - runfourftbackdropvalidation - 1556332033.268194.jpg - F:\runfourftbackdropvalidation\1556332033.268194.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 360 - 68 - 436 - 166 - - - - stockout - Unspecified - 0 - 0 - - 250 - 71 - 307 - 164 - - - - stockout - Unspecified - 0 - 0 - - 154 - 83 - 204 - 162 - - - - stockout - Unspecified - 0 - 0 - - 56 - 187 - 115 - 256 - - - - stockout - Unspecified - 0 - 0 - - 178 - 180 - 247 - 248 - - - - stockout - Unspecified - 0 - 0 - - 308 - 177 - 372 - 245 - - - - stockout - Unspecified - 0 - 0 - - 336 - 259 - 388 - 308 - - - - stockout - Unspecified - 0 - 0 - - 227 - 258 - 282 - 309 - - - - stockout - Unspecified - 0 - 0 - - 130 - 263 - 195 - 310 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332040.04427.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332040.04427.jpg deleted file mode 100644 index 102df833..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332040.04427.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332040.04427.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332040.04427.xml deleted file mode 100644 index 655a33df..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332040.04427.xml +++ /dev/null @@ -1,110 +0,0 @@ - - runfourftbackdropvalidation - 1556332040.04427.jpg - F:\runfourftbackdropvalidation\1556332040.04427.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 155 - 83 - 203 - 165 - - - - stockout - Unspecified - 0 - 0 - - 252 - 71 - 301 - 160 - - - - stockout - Unspecified - 0 - 0 - - 361 - 66 - 436 - 164 - - - - stockout - Unspecified - 0 - 0 - - 308 - 177 - 375 - 246 - - - - stockout - Unspecified - 0 - 0 - - 337 - 256 - 391 - 307 - - - - stockout - Unspecified - 0 - 0 - - 175 - 179 - 246 - 246 - - - - stockout - Unspecified - 0 - 0 - - 229 - 261 - 285 - 307 - - - - stockout - Unspecified - 0 - 0 - - 131 - 265 - 199 - 311 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332044.550062.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332044.550062.jpg deleted file mode 100644 index 9f340035..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332044.550062.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332044.550062.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332044.550062.xml deleted file mode 100644 index c7ad36bf..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332044.550062.xml +++ /dev/null @@ -1,86 +0,0 @@ - - Converted JPG with xml runfourftbackdropvalidation - 1556332044.550062.jpg - C:\Users\ZachPerkel\Desktop\Kroger_Olympus\Converted JPG with xml runfourftbackdropvalidation\1556332044.550062.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 250 - 72 - 305 - 160 - - - - stockout - Unspecified - 0 - 0 - - 357 - 68 - 435 - 164 - - - - stockout - Unspecified - 0 - 0 - - 308 - 177 - 376 - 244 - - - - stockout - Unspecified - 0 - 0 - - 174 - 179 - 246 - 245 - - - - stockout - Unspecified - 0 - 0 - - 228 - 260 - 283 - 310 - - - - stockout - Unspecified - 0 - 0 - - 337 - 258 - 388 - 309 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332045.6620882.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332045.6620882.jpg deleted file mode 100644 index 58e4ab74..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332045.6620882.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332045.6620882.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332045.6620882.xml deleted file mode 100644 index f20381e8..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332045.6620882.xml +++ /dev/null @@ -1,86 +0,0 @@ - - runfourftbackdropvalidation - 1556332045.6620882.jpg - F:\runfourftbackdropvalidation\1556332045.6620882.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 252 - 71 - 303 - 160 - - - - stockout - Unspecified - 0 - 0 - - 363 - 65 - 429 - 160 - - - - stockout - Unspecified - 0 - 0 - - 310 - 175 - 378 - 248 - - - - stockout - Unspecified - 0 - 0 - - 174 - 174 - 246 - 248 - - - - stockout - Unspecified - 0 - 0 - - 132 - 264 - 196 - 312 - - - - stockout - Unspecified - 0 - 0 - - 228 - 260 - 283 - 310 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332051.3751378.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332051.3751378.jpg deleted file mode 100644 index 88009346..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332051.3751378.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332051.3751378.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332051.3751378.xml deleted file mode 100644 index 14310494..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/examples/1556332051.3751378.xml +++ /dev/null @@ -1,98 +0,0 @@ - - runfourftbackdropvalidation - 1556332051.3751378.jpg - F:\runfourftbackdropvalidation\1556332051.3751378.jpg - - Unknown - - - 452 - 376 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 251 - 78 - 304 - 160 - - - - stockout - Unspecified - 0 - 0 - - 361 - 70 - 435 - 168 - - - - stockout - Unspecified - 0 - 0 - - 309 - 177 - 375 - 246 - - - - stockout - Unspecified - 0 - 0 - - 179 - 177 - 246 - 248 - - - - stockout - Unspecified - 0 - 0 - - 134 - 262 - 195 - 311 - - - - stockout - Unspecified - 0 - 0 - - 232 - 260 - 285 - 309 - - - - stockout - Unspecified - 0 - 0 - - 337 - 260 - 388 - 308 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/Deploy Accelerated.ipynb b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/Deploy Accelerated.ipynb deleted file mode 100644 index 1c2eaf5f..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/Deploy Accelerated.ipynb +++ /dev/null @@ -1,369 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Deploy SSD-VGG Model as Web Service on FPGA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext autoreload\n", - "%autoreload 2\n", - "\n", - "import os, sys\n", - "import tensorflow as tf\n", - "import azureml\n", - "\n", - "import warnings\n", - "warnings.filterwarnings('ignore')\n", - "\n", - "sys.path.insert(0, os.path.abspath(\"../tfssd\"))\n", - "from tfutil import endpoints\n", - "from finetune.model_saver import SaverVggSsd" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Restore AzureML workspace & register Model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from azureml.core import Workspace\n", - "\n", - "ws = Workspace.from_config()\n", - "print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\\n')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from azureml.core.model import Model\n", - "from azureml.core.image import Image\n", - "from azureml.accel import AccelOnnxConverter\n", - "from azureml.accel import AccelContainerImage\n", - "from os.path import expanduser\n", - "\n", - "\n", - "model_ckpt_dir = expanduser(\"~/azml_ssd_vgg\")\n", - "model_name = r'ssdvgg-fpga'\n", - "model_save_path = os.path.join(model_ckpt_dir, model_name)\n", - "\n", - "# model_save_path should NOT exist prior to saving the model\n", - "not os.path.exists(model_save_path)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "with SaverVggSsd(model_ckpt_dir) as saver:\n", - " saver.save_for_deployment(model_save_path)\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Register model\n", - "registered_model = Model.register(workspace = ws,\n", - " model_path = model_save_path,\n", - " model_name = model_name)\n", - "\n", - "print(\"Successfully registered: \", registered_model.name, registered_model.description, registered_model.version, '\\n', sep = '\\t')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Convert inference model to ONNX format" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "#Convert the TensorFlow graph to the Open Neural Network Exchange format (ONNX). \n", - "\n", - "input_tensor = saver.input_name_str\n", - "output_tensors_str = \",\".join(saver.output_names)\n", - "\n", - "# Convert model\n", - "convert_request = AccelOnnxConverter.convert_tf_model(ws, registered_model, input_tensor, output_tensors_str)\n", - "\n", - "# If it fails, you can run wait_for_completion again with show_output=True.\n", - "convert_request.wait_for_completion(show_output=True)\n", - "converted_model = convert_request.result\n", - "\n", - "print(\"\\nSuccessfully converted: \", converted_model.name, converted_model.url, converted_model.version, \n", - " converted_model.id, converted_model.created_time, '\\n')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Create Docker Image" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "image_config = AccelContainerImage.image_configuration()\n", - "\n", - "# Image name must be lowercase\n", - "image_name = \"{}-image\".format(model_name)\n", - "\n", - "image = Image.create(name = image_name,\n", - " models = [converted_model],\n", - " image_config = image_config, \n", - " workspace = ws)\n", - "image.wait_for_creation(show_output=True)\n", - "\n", - "# List the images by tag and get the detailed logs for any debugging.\n", - "print(\"Created AccelContainerImage: {} {} {}\\n\".format(image.name, image.creation_state, image.image_location))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Deploy to the cloud" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Create a new Azure Kubernetes Service\n", - "\n", - "from azureml.core.compute import AksCompute, ComputeTarget\n", - "\n", - "# Uses the specific FPGA enabled VM (sku: Standard_PB6s)\n", - "# Standard_PB6s are available in: eastus, westus2, westeurope, southeastasia\n", - "prov_config = AksCompute.provisioning_configuration(vm_size = \"Standard_PB6s\",\n", - " agent_count = 1, \n", - " location = \"westus2\")\n", - "\n", - "aks_name = 'aks-pb6-obj'\n", - "\n", - "# Create the cluster\n", - "aks_target = ComputeTarget.create(workspace = ws, \n", - " name = aks_name, \n", - " provisioning_configuration = prov_config)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Monitor deployment\n", - "aks_target.wait_for_completion(show_output=True)\n", - "print(aks_target.provisioning_state)\n", - "print(aks_target.provisioning_errors)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from azureml.core.webservice import Webservice, AksWebservice\n", - "\n", - "# Set the web service configuration (for creating a test service, we don't want autoscale enabled)\n", - "# Authentication is enabled by default, but for testing we specify False\n", - "aks_config = AksWebservice.deploy_configuration(autoscale_enabled=False,\n", - " num_replicas=1,\n", - " auth_enabled = False)\n", - "\n", - "aks_service_name ='fpga-aks-service'\n", - "\n", - "aks_service = Webservice.deploy_from_image(workspace = ws,\n", - " name = aks_service_name,\n", - " image = image,\n", - " deployment_config = aks_config,\n", - " deployment_target = aks_target)\n", - "aks_service.wait_for_deployment(show_output = True)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Test the cloud service " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Using the grpc client in AzureML Accelerated Models SDK\n", - "from azureml.accel import PredictionClient\n", - "\n", - "address = aks_service.scoring_uri\n", - "ssl_enabled = address.startswith(\"https\")\n", - "address = address[address.find('/')+2:].strip('/')\n", - "port = 443 if ssl_enabled else 80\n", - "print(f\"address={address}, port={port}, ssl={ssl_enabled}, name={aks_service.name}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Initialize AzureML Accelerated Models client\n", - "client = PredictionClient(address=address,\n", - " port=port,\n", - " use_ssl=ssl_enabled,\n", - " service_name=aks_service.name)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from tfutil import visualization\n", - "output_tensors = saver.output_names" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Visualize prediction using the deployed model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import glob\n", - "import matplotlib as plt\n", - "import cv2\n", - "\n", - "# Select an example image to test. \n", - "# Default directory is the image_dir created in the Finetune VGG SSD notebook.\n", - "\n", - "image_dir = expanduser(\"~/azml_ssd_vgg/JPEGImages\")\n", - "\n", - "im_files = glob.glob(os.path.join(image_dir, '*.jpg'))\n", - "\n", - "im_file = im_files[0]\n", - "\n", - "\n", - "import azureml.accel._external.ssdvgg_utils as ssdvgg_utils\n", - "\n", - "result = client.score_file(path=im_file, \n", - " input_name=saver.input_name_str, \n", - " outputs=output_tensors)\n", - "\n", - "classes, scores, bboxes = ssdvgg_utils.postprocess(result, select_threshold=0.5)\n", - "\n", - "plt.rcParams['figure.figsize'] = 15, 15\n", - "img = cv2.imread(im_file)\n", - "img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n", - "visualization.plt_bboxes(img, classes, scores, bboxes)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Clean up image (optional)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Delete your web service, image, and model (must be done in this order since there are dependencies).\n", - "\n", - "#aks_service.delete()\n", - "#aks_target.delete()\n", - "#image.delete()\n", - "#registered_model.delete()\n", - "#converted_model.delete()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "authors": [ - { - "name": "v-borisk" - }, - { - "name": "v-zaper" - } - ], - "kernelspec": { - "display_name": "python 3.6 brain", - "language": "python", - "name": "brain" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.8" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/Finetune VGG SSD.ipynb b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/Finetune VGG SSD.ipynb deleted file mode 100644 index 6b4baeff..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/Finetune VGG SSD.ipynb +++ /dev/null @@ -1,331 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Finetuning VGG-SSD Object Detection Model" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Prerequisites for Local Training\n", - "\n", - "* CUDA 10.0, cuDNN 7.4\n", - "* Recent Anaconda environment\n", - "* Matplotlib\n", - "* OpenCV-Python cv2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": false - }, - "outputs": [], - "source": [ - "# install supported FPGA ML models, including VGG SSD\n", - "# skip if already installed\n", - "!pip install azureml-accel-models\n", - "\n", - "# Install Tensorflow. You may select to install Tensorflow for CPU or GPU. \n", - "# Instructions are here: https://pypi.org/project/azureml-accel-models/\n", - "\n", - "!pip install azureml-accel-models[gpu]\n", - "#!pip install azureml-accel-models[cpu]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext autoreload\n", - "%autoreload 2\n", - "import os, sys, glob\n", - "import tensorflow as tf\n", - "import warnings\n", - "warnings.filterwarnings('ignore')\n", - "\n", - "# Tensorflow Finetuning Package\n", - "sys.path.insert(0, os.path.abspath('../tfssd/'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import Training / Validation Data\n", - "\n", - "Images are .jpg files and annotations - .xml files in PASCAL VOC format.\n", - "Each image file has a matching annotations file\n", - "\n", - "In this notebook we are looking for gaps on the shelves stocked with different products:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "import cv2\n", - "%matplotlib inline\n", - "\n", - "plt.rcParams['figure.figsize'] = 10, 10\n", - "img = cv2.imread('sample.jpg')\n", - "\n", - "img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n", - "plt.imshow(img)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from dataprep import dataset_utils, pascalvoc_to_tfrecords\n", - "from importlib import reload\n", - "reload(dataset_utils)\n", - "\n", - "# Create directory for data files and model checkpoints. \n", - "\n", - "from os.path import expanduser\n", - "\n", - "data_dir = expanduser(\"~/azml_ssd_vgg\")\n", - "\n", - "dataset_utils.create_dir(data_dir) " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Verify that annotations and images are in the correct folders\n", - "\n", - "data_dir_images = os.path.join(data_dir, \"JPEGImages\")\n", - "data_dir_annotations = os.path.join(data_dir, \"Annotations\")\n", - "classes = [\"stockout\"]\n", - "\n", - "if not os.listdir(data_dir_images) or not os.listdir(data_dir_annotations):\n", - " print('JPEGImages or Annotations folder is empty. Please copy your images and annotations to these folders and rerun cell.')\n", - "\n", - "else:\n", - " images = glob.glob(os.path.join(data_dir_images, \"*.jpg\"))\n", - " annotations = glob.glob(os.path.join(data_dir_annotations, \"*.xml\"))\n", - " \n", - " # check for image and annotations files matching each other\n", - " \n", - " images, annotations = dataset_utils.check_labelmatch(images, annotations)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Split Into Training and Validation and Create TFRecord Datasets" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.model_selection import train_test_split\n", - "\n", - "train_images, test_images, \\\n", - " train_annotations, test_annotations = train_test_split(images, annotations, test_size = .2, random_state = 40)\n", - "\n", - "data_output_dir = os.path.join(data_dir, \"TFreccords\")\n", - "\n", - "pascalvoc_to_tfrecords.run(data_output_dir, classes, train_images, train_annotations, \"train\")\n", - "pascalvoc_to_tfrecords.run(data_output_dir, classes, test_images, test_annotations, \"test\")\n", - "\n", - "print(os.listdir(data_output_dir))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Set up and Run Training/Validation Loops" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Setup Training Data, Import the Model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from finetune.train import TrainVggSsd\n", - "from finetune.eval import EvalVggSsd\n", - "\n", - "ckpt_dir = data_dir\n", - "# this is the directory where the original model to be\n", - "# fine-tuned will be delivered and models saved as the training loop runs\n", - "\n", - "# get .tfrecord files created in the previous step\n", - "train_files = glob.glob(os.path.join(data_output_dir, \"train_*.tfrecord\"))\n", - "validation_files = glob.glob(os.path.join(data_output_dir, \"test_*.tfrecord\"))\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Training Parameters" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# run for these epochs\n", - "n_epochs = 6\n", - "# steps per training epoch\n", - "num_train_steps=3000\n", - "# batch size. \n", - "batch_size = 2\n", - "# steps to save as a checkpoint\n", - "steps_to_save=3000\n", - "# using Adam optimizer. These are the configurable parameters\n", - "learning_rate = 1e-4\n", - "learning_rate_decay_steps=3000\n", - "learning_rate_decay_value=0.96" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Validation Parameters" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "num_eval_steps=156\n", - "# number of classes. Includes the \"none\" (background) class\n", - "# cannot be more than 21\n", - "num_classes=2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Run Training Loop" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for _ in range(n_epochs):\n", - "\n", - " with TrainVggSsd(ckpt_dir, train_files, \n", - " num_steps=num_train_steps, \n", - " steps_to_save=steps_to_save, \n", - " batch_size = batch_size,\n", - " learning_rate=learning_rate,\n", - " learning_rate_decay_steps=learning_rate_decay_steps, \n", - " learning_rate_decay_value=learning_rate_decay_value) as trainer:\n", - " trainer.train()\n", - "\n", - " with EvalVggSsd(ckpt_dir, validation_files, \n", - " num_steps=num_eval_steps, \n", - " num_classes=num_classes) as evaluator:\n", - " evaluator.eval() " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Visualize Test Results" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "from finetune.inference import InferVggSsd\n", - "\n", - "plt.rcParams[\"figure.figsize\"] = 15, 15\n", - "infer = InferVggSsd(ckpt_dir, gpu=False)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%%time\n", - "classes, scores, boxes = infer.infer_file(test_images[5], visualize=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "authors": [ - { - "name": "v-borisk" - }, - { - "name": "v-zaper" - } - ], - "kernelspec": { - "display_name": "python 3.6 brain", - "language": "python", - "name": "brain" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.8" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/sample.jpg b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/sample.jpg deleted file mode 100644 index 9d0ab04d..00000000 Binary files a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/sample.jpg and /dev/null differ diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/sample.xml b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/sample.xml deleted file mode 100644 index 319a36d4..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/notebooks/sample.xml +++ /dev/null @@ -1,26 +0,0 @@ - - runeightft1 - 1555394321.8154433.jpg - E:/Image grocerydemostills/runeightft1/1555394321.8154433.jpg - - Unknown - - - 852 - 506 - 3 - - 0 - - stockout - Unspecified - 0 - 0 - - 660 - 201 - 712 - 294 - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/__init__.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/anchors/.__init__.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/anchors/.__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/anchors/generate_anchors.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/anchors/generate_anchors.py deleted file mode 100644 index f53914e9..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/anchors/generate_anchors.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright 2015 Paul Balanca. 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. -# ============================================================================== - -import numpy as np -import math -from model.ssd_vgg_300 import SSDNet, SSDParams - -_R_MEAN = 123. -_G_MEAN = 117. -_B_MEAN = 104. -EVAL_SIZE = (300, 300) - -defaults = SSDNet.default_params - -img_shape = defaults.img_shape -num_classes = defaults.num_classes -feat_layers = defaults.feat_layers -feat_shapes = defaults.feat_shapes -anchor_size_bounds = defaults.anchor_size_bounds -anchor_sizes = defaults.anchor_sizes -anchor_ratios = defaults.anchor_ratios -anchor_steps = defaults.anchor_steps -anchor_offset = defaults.anchor_offset -normalizations = defaults.normalizations -prior_scaling = defaults.prior_scaling - -def ssd_anchor_one_layer(img_shape, - feat_shape, - sizes, - ratios, - step, - offset=0.5, - dtype=np.float32): - """Computer SSD default anchor boxes for one feature layer. - - Determine the relative position grid of the centers, and the relative - width and height. - - Arguments: - feat_shape: Feature shape, used for computing relative position grids; - size: Absolute reference sizes; - ratios: Ratios to use on these features; - img_shape: Image shape, used for computing height, width relatively to the - former; - offset: Grid offset. - - Return: - y, x, h, w: Relative x and y grids, and height and width. - """ - # Compute the position grid: simple way. - # y, x = np.mgrid[0:feat_shape[0], 0:feat_shape[1]] - # y = (y.astype(dtype) + offset) / feat_shape[0] - # x = (x.astype(dtype) + offset) / feat_shape[1] - # Weird SSD-Caffe computation using steps values... - y, x = np.mgrid[0:feat_shape[0], 0:feat_shape[1]] - y = (y.astype(dtype) + offset) * step / img_shape[0] - x = (x.astype(dtype) + offset) * step / img_shape[1] - - # Expand dims to support easy broadcasting. - y = np.expand_dims(y, axis=-1) - x = np.expand_dims(x, axis=-1) - - # Compute relative height and width. - # Tries to follow the original implementation of SSD for the order. - num_anchors = len(sizes) + len(ratios) - h = np.zeros((num_anchors, ), dtype=dtype) - w = np.zeros((num_anchors, ), dtype=dtype) - # Add first anchor boxes with ratio=1. - h[0] = sizes[0] / img_shape[0] - w[0] = sizes[0] / img_shape[1] - di = 1 - if len(sizes) > 1: - h[1] = math.sqrt(sizes[0] * sizes[1]) / img_shape[0] - w[1] = math.sqrt(sizes[0] * sizes[1]) / img_shape[1] - di += 1 - for i, r in enumerate(ratios): - h[i+di] = sizes[0] / img_shape[0] / math.sqrt(r) - w[i+di] = sizes[0] / img_shape[1] * math.sqrt(r) - return y, x, h, w - - -def ssd_anchors_all_layers(img_shape = img_shape, - offset=0.5, - dtype=np.float32): - """Compute anchor boxes for all feature layers. - """ - layers_anchors = [] - for i, s in enumerate(feat_shapes): - anchor_bboxes = ssd_anchor_one_layer(img_shape, s, - anchor_sizes[i], - anchor_ratios[i], - anchor_steps[i], - offset=offset, dtype=dtype) - layers_anchors.append(anchor_bboxes) - return layers_anchors diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/dataprep/dataset_utils.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/dataprep/dataset_utils.py deleted file mode 100644 index d6a46056..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/dataprep/dataset_utils.py +++ /dev/null @@ -1,119 +0,0 @@ -import os -import sys -import tarfile - -from six.moves import urllib -import tensorflow as tf - -LABELS_FILENAME = 'labels.txt' - -import shutil -from os import path - -def check_labelmatch(images, annotations): - data_dir_images = os.path.split(images[0])[0] - data_dir_annot = os.path.split(annotations[0])[0] - - im_files = {os.path.splitext(os.path.split(f)[1])[0] for f in images} - annot_files = {os.path.splitext(os.path.split(f)[1])[0] for f in annotations} - - extra_ims = im_files.difference(annot_files) - extra_annots = annot_files.difference(im_files) - mismatch = len(extra_ims) > 0 or len(extra_annots) > 0 - - if mismatch: - print(f"The following files will be removed from the training process:") - - if len(extra_ims) > 0: - print(f"images without annotations: {extra_ims}") - - if len(extra_annots) > 0: - print(f"annotations without images: {extra_annots}") - - if not mismatch: - print(str(len(images)) + ' images found and ' + str(len(annotations)) + ' matching annotations found.' ) - return (images, annotations) - - im_files = im_files.difference(extra_ims) - annot_files = annot_files.difference(extra_annots) - - im_files = [os.path.join(data_dir_images, f+".jpg") for f in im_files] - annot_files = [os.path.join(data_dir_annot, f+".xml") for f in annot_files] - - return(im_files, annot_files) - -def create_dir(path): - try: - path_annotations = path + '/Annotations' - path_images = path + '/JPEGImages' - path_tfrec = path + '/TFreccords' - - os.makedirs(path_annotations) - os.makedirs(path_images) - os.makedirs(path_tfrec) - - except OSError: - print("Creation of folders in directory %s failed. Folders may already exist." % path) - else: - print("Successfully created Annotations, JPEGImages, and TFreccords folders at %s" % path) - - print('Please copy your annotation and image files to the Annotations and JPEGImages folders before moving to the next step') - - -def move_images(data_dir, train_images, train_annotations, - test_images, test_annotations): - - source = data_dir + '/' - - for image in train_images: - image = data_dir + '/' + image - dst = source + 'train/' + '/JPEGImages' - - if path.exists(image): - shutil.copy(image, dst) - - for image in test_images: - image = data_dir + '/' + image - dst = source + 'test/' + '/JPEGImages' - - if path.exists(image): - shutil.copy(image, dst) - - for annot in train_annotations: - annot = data_dir + '/' + annot - dst = source + 'train/' + '/Annotations' - - if path.exists(annot): - shutil.copy(annot, dst) - - for annot in test_annotations: - annot = data_dir + '/' + annot - dst = source + 'test/' + '/Annotations' - - if path.exists(annot): - shutil.copy(annot, dst) - - print('Images and annotations have been copied to directories: ' + source + 'train' + ' and ' + source + 'test') - -def int64_feature(value): - """Wrapper for inserting int64 features into Example proto. - """ - if not isinstance(value, list): - value = [value] - return tf.train.Feature(int64_list=tf.train.Int64List(value=value)) - - -def float_feature(value): - """Wrapper for inserting float features into Example proto. - """ - if not isinstance(value, list): - value = [value] - return tf.train.Feature(float_list=tf.train.FloatList(value=value)) - - -def bytes_feature(value): - """Wrapper for inserting bytes features into Example proto. - """ - if not isinstance(value, list): - value = [value] - return tf.train.Feature(bytes_list=tf.train.BytesList(value=value)) \ No newline at end of file diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/dataprep/pascalvoc_common.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/dataprep/pascalvoc_common.py deleted file mode 100644 index 61bca57d..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/dataprep/pascalvoc_common.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright 2015 Paul Balanca. 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. -# ============================================================================== -"""Provides data for the Pascal VOC Dataset (images + annotations). -""" -import os - -import tensorflow as tf -from dataprep import dataset_utils - -slim = tf.contrib.slim - -VOC_LABELS = { - 'none': (0, 'Background'), - 'aeroplane': (1, 'Vehicle'), - 'bicycle': (2, 'Vehicle'), - 'bird': (3, 'Animal'), - 'boat': (4, 'Vehicle'), - 'bottle': (5, 'Indoor'), - 'bus': (6, 'Vehicle'), - 'car': (7, 'Vehicle'), - 'cat': (8, 'Animal'), - 'chair': (9, 'Indoor'), - 'cow': (10, 'Animal'), - 'diningtable': (11, 'Indoor'), - 'dog': (12, 'Animal'), - 'horse': (13, 'Animal'), - 'motorbike': (14, 'Vehicle'), - 'person': (15, 'Person'), - 'pottedplant': (16, 'Indoor'), - 'sheep': (17, 'Animal'), - 'sofa': (18, 'Indoor'), - 'train': (19, 'Vehicle'), - 'tvmonitor': (20, 'Indoor'), -} - -def get_split(split_name, dataset_dir, file_pattern, reader, - split_to_sizes, items_to_descriptions, num_classes): - """Gets a dataset tuple with instructions for reading Pascal VOC dataset. - - Args: - split_name: A train/test split name. - dataset_dir: The base directory of the dataset sources. - file_pattern: The file pattern to use when matching the dataset sources. - It is assumed that the pattern contains a '%s' string so that the split - name can be inserted. - reader: The TensorFlow reader type. - - Returns: - A `Dataset` namedtuple. - - Raises: - ValueError: if `split_name` is not a valid train/test split. - """ - if split_name not in split_to_sizes: - raise ValueError('split name %s was not recognized.' % split_name) - file_pattern = os.path.join(dataset_dir, file_pattern % split_name) - - # Allowing None in the signature so that dataset_factory can use the default. - if reader is None: - reader = tf.TFRecordReader - # Features in Pascal VOC TFRecords. - keys_to_features = { - 'image/encoded': tf.FixedLenFeature((), tf.string, default_value=''), - 'image/format': tf.FixedLenFeature((), tf.string, default_value='jpeg'), - 'image/height': tf.FixedLenFeature([1], tf.int64), - 'image/width': tf.FixedLenFeature([1], tf.int64), - 'image/channels': tf.FixedLenFeature([1], tf.int64), - 'image/shape': tf.FixedLenFeature([3], tf.int64), - 'image/object/bbox/xmin': tf.VarLenFeature(dtype=tf.float32), - 'image/object/bbox/ymin': tf.VarLenFeature(dtype=tf.float32), - 'image/object/bbox/xmax': tf.VarLenFeature(dtype=tf.float32), - 'image/object/bbox/ymax': tf.VarLenFeature(dtype=tf.float32), - 'image/object/bbox/label': tf.VarLenFeature(dtype=tf.int64), - 'image/object/bbox/difficult': tf.VarLenFeature(dtype=tf.int64), - 'image/object/bbox/truncated': tf.VarLenFeature(dtype=tf.int64), - } - items_to_handlers = { - 'image': slim.tfexample_decoder.Image('image/encoded', 'image/format'), - 'shape': slim.tfexample_decoder.Tensor('image/shape'), - 'object/bbox': slim.tfexample_decoder.BoundingBox( - ['ymin', 'xmin', 'ymax', 'xmax'], 'image/object/bbox/'), - 'object/label': slim.tfexample_decoder.Tensor('image/object/bbox/label'), - 'object/difficult': slim.tfexample_decoder.Tensor('image/object/bbox/difficult'), - 'object/truncated': slim.tfexample_decoder.Tensor('image/object/bbox/truncated'), - } - decoder = slim.tfexample_decoder.TFExampleDecoder( - keys_to_features, items_to_handlers) - - labels_to_names = None - if dataset_utils.has_labels(dataset_dir): - labels_to_names = dataset_utils.read_label_file(dataset_dir) - - return slim.dataset.Dataset( - data_sources=file_pattern, - reader=reader, - decoder=decoder, - num_samples=split_to_sizes[split_name], - items_to_descriptions=items_to_descriptions, - num_classes=num_classes, - labels_to_names=labels_to_names) diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/dataprep/pascalvoc_to_tfrecords.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/dataprep/pascalvoc_to_tfrecords.py deleted file mode 100644 index 52112c97..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/dataprep/pascalvoc_to_tfrecords.py +++ /dev/null @@ -1,223 +0,0 @@ -# Copyright 2015 Paul Balanca. 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. -# ============================================================================== -"""Converts Pascal VOC data to TFRecords file format with Example protos. - -The raw Pascal VOC data set is expected to reside in JPEG files located in the -directory 'JPEGImages'. Similarly, bounding box annotations are supposed to be -stored in the 'Annotation directory' - -This TensorFlow script converts the training and evaluation data into -a sharded data set consisting of 1024 and 128 TFRecord files, respectively. - -Each validation TFRecord file contains ~500 records. Each training TFREcord -file contains ~1000 records. Each record within the TFRecord file is a -serialized Example proto. The Example proto contains the following fields: - - image/encoded: string containing JPEG encoded image in RGB colorspace - image/height: integer, image height in pixels - image/width: integer, image width in pixels - image/channels: integer, specifying the number of channels, always 3 - image/format: string, specifying the format, always'JPEG' - - - image/object/bbox/xmin: list of float specifying the 0+ human annotated - bounding boxes - image/object/bbox/xmax: list of float specifying the 0+ human annotated - bounding boxes - image/object/bbox/ymin: list of float specifying the 0+ human annotated - bounding boxes - image/object/bbox/ymax: list of float specifying the 0+ human annotated - bounding boxes - image/object/bbox/label: list of integer specifying the classification index. - image/object/bbox/label_text: list of string descriptions. - -Note that the length of xmin is identical to the length of xmax, ymin and ymax -for each example. -""" -import os -import sys -import random - -import numpy as np -import tensorflow as tf - -import xml.etree.ElementTree as ET - -from dataprep.dataset_utils import int64_feature, float_feature, bytes_feature - -# TFRecords conversion parameters. -RANDOM_SEED = 4242 -SAMPLES_PER_FILES = 100 - -def _set_voc_labels_map(class_list): - return dict(**{'none': 0}, **{cl: i + 1 for i, cl in enumerate(class_list)}) - -def _process_image(img_name, annot_name, class_list): - """Process a image and annotation file. - - Args: - img_name: string, path to an image file e.g., '/path/to/example.JPG'. - Returns: - image_buffer: string, JPEG encoding of RGB image. - height: integer, image height in pixels. - width: integer, image width in pixels. - """ - # Read the image file. - image_data = tf.gfile.FastGFile(img_name, 'rb').read() - class_dict = _set_voc_labels_map(class_list) - - # Read the XML annotation file. - filename = annot_name - tree = ET.parse(filename) - root = tree.getroot() - - # Image shape. - size = root.find('size') - shape = [int(size.find('height').text), - int(size.find('width').text), - int(size.find('depth').text)] - # Find annotations. - bboxes = [] - labels = [] - labels_text = [] - difficult = [] - truncated = [] - for obj in root.findall('object'): - label = obj.find('name').text - labels.append(class_dict[label]) - labels_text.append(label.encode('ascii')) - - if obj.find('difficult'): - difficult.append(int(obj.find('difficult').text)) - else: - difficult.append(0) - if obj.find('truncated'): - truncated.append(int(obj.find('truncated').text)) - else: - truncated.append(0) - - bbox = obj.find('bndbox') - bboxes.append((to_valid_range(float(bbox.find('ymin').text) / shape[0]), - to_valid_range(float(bbox.find('xmin').text) / shape[1]), - to_valid_range(float(bbox.find('ymax').text) / shape[0]), - to_valid_range(float(bbox.find('xmax').text) / shape[1]) - )) - return image_data, shape, np.clip(bboxes, a_min=0., a_max=1.), labels, labels_text, difficult, truncated - -def to_valid_range(v): - if v < 0.0: - return 0.0 - if v > 1.0: - return 1.0 - return v - - -def _convert_to_example(image_data, labels, labels_text, bboxes, shape, - difficult, truncated): - """Build an Example proto for an image example. - - Args: - image_data: string, JPEG encoding of RGB image; - labels: list of integers, identifier for the ground truth; - labels_text: list of strings, human-readable labels; - bboxes: list of bounding boxes; each box is a list of integers; - specifying [xmin, ymin, xmax, ymax]. All boxes are assumed to belong - to the same label as the image label. - shape: 3 integers, image shapes in pixels. - Returns: - Example proto - """ - xmin = [] - ymin = [] - xmax = [] - ymax = [] - for b in bboxes: - assert len(b) == 4 - # pylint: disable=expression-not-assigned - [l.append(point) for l, point in zip([ymin, xmin, ymax, xmax], b)] - # pylint: enable=expression-not-assigned - - image_format = b'JPEG' - example = tf.train.Example(features=tf.train.Features(feature={ - 'image/height': int64_feature(shape[0]), - 'image/width': int64_feature(shape[1]), - 'image/channels': int64_feature(shape[2]), - 'image/shape': int64_feature(shape), - 'image/object/bbox/xmin': float_feature(xmin), - 'image/object/bbox/xmax': float_feature(xmax), - 'image/object/bbox/ymin': float_feature(ymin), - 'image/object/bbox/ymax': float_feature(ymax), - 'image/object/bbox/label': int64_feature(labels), - 'image/object/bbox/label_text': bytes_feature(labels_text), - 'image/object/bbox/difficult': int64_feature(difficult), - 'image/object/bbox/truncated': int64_feature(truncated), - 'image/format': bytes_feature(image_format), - 'image/encoded': bytes_feature(image_data)})) - return example - - -def _add_to_tfrecord(img_name, annot_name, class_list, tfrecord_writer): - """Loads data from image and annotations files and add them to a TFRecord. - - Args: - dataset_dir: Dataset directory; - name: Image name to add to the TFRecord; - tfrecord_writer: The TFRecord writer to use for writing. - """ - image_data, shape, bboxes, labels, labels_text, difficult, truncated = \ - _process_image(img_name, annot_name, class_list) - - example = _convert_to_example(image_data, labels, labels_text, - bboxes, shape, difficult, truncated) - tfrecord_writer.write(example.SerializeToString()) - - -def _get_output_filename(output_dir, name, idx): - return os.path.join(output_dir, f"{name}_{idx:04d}.tfrecord") - -def run(output_dir, classes_list, images_list, annotations_list, output_name): - """Runs the conversion operation. - - Args: - output_dir: Output directory. - """ - - if not tf.gfile.Exists(output_dir): - tf.gfile.MakeDirs(output_dir) - - if(len(images_list) != len(annotations_list)): - raise ValueError("Images and annotations lists are of different legnths!") - - # Process dataset files. - fidx = 0 - i = 0 - im_annot = list(zip(images_list, annotations_list)) - - while i < len(im_annot): - # Open new TFRecord file. - tf_filename = _get_output_filename(output_dir, output_name, fidx) - with tf.python_io.TFRecordWriter(tf_filename) as tfrecord_writer: - j = 0 - while i < len(im_annot) and j < SAMPLES_PER_FILES: - sys.stdout.write('\r>> Converting image %d/%d' % (i+1, len(im_annot))) - sys.stdout.flush() - - img_name, annot_name = im_annot[i] - _add_to_tfrecord(img_name, annot_name, classes_list, tfrecord_writer) - i += 1 - j += 1 - fidx += 1 - - print('\nFinished converting the Pascal VOC dataset!') diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/__init__.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/parser.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/parser.py deleted file mode 100644 index daa56a65..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/parser.py +++ /dev/null @@ -1,65 +0,0 @@ -import tensorflow as tf -import numpy as np -import os - -from datautil.ssd_vgg_preprocessing import preprocess_for_train, preprocess_for_eval -from model import ssd_common -from tfutil import tf_utils - -features = { - 'image/encoded': tf.FixedLenFeature((), tf.string, default_value=''), - 'image/format': tf.FixedLenFeature((), tf.string, default_value='jpeg'), - 'image/height': tf.FixedLenFeature([1], tf.int64), - 'image/width': tf.FixedLenFeature([1], tf.int64), - 'image/channels': tf.FixedLenFeature([1], tf.int64), - 'image/shape': tf.FixedLenFeature([3], tf.int64), - 'image/object/bbox/xmin': tf.VarLenFeature(dtype=tf.float32), - 'image/object/bbox/ymin': tf.VarLenFeature(dtype=tf.float32), - 'image/object/bbox/xmax': tf.VarLenFeature(dtype=tf.float32), - 'image/object/bbox/ymax': tf.VarLenFeature(dtype=tf.float32), - 'image/object/bbox/label': tf.VarLenFeature(dtype=tf.int64), - 'image/object/bbox/difficult': tf.VarLenFeature(dtype=tf.int64), - 'image/object/bbox/truncated': tf.VarLenFeature(dtype=tf.int64), -} - - -def get_parser_func(anchors, num_classes, is_training, var_scope): - ''' - Dataset parser function for training and evaluation - - Arguments: - preprocess_fn - function that does preprocesing - ''' - - preprocess_fn = preprocess_for_train if is_training else preprocess_for_eval - - def parse_tfrec_data(example_proto): - with tf.variable_scope(var_scope): - parsed_features = tf.parse_single_example(example_proto, features) - - image_string = parsed_features['image/encoded'] - image_decoded = tf.image.decode_jpeg(image_string) - - labels = tf.sparse.to_dense(parsed_features['image/object/bbox/label']) - - xmin = tf.sparse.to_dense(parsed_features['image/object/bbox/xmin']) - xmax = tf.sparse.to_dense(parsed_features['image/object/bbox/xmax']) - ymin = tf.sparse.to_dense(parsed_features['image/object/bbox/ymin']) - ymax = tf.sparse.to_dense(parsed_features['image/object/bbox/ymax']) - bboxes = tf.stack([ymin, xmin, ymax, xmax], axis=1) - - if is_training: - image, labels, bboxes = preprocess_fn(image_decoded, labels, bboxes) - else: - image, labels, bboxes, _ = preprocess_fn(image_decoded, labels, bboxes) - - # ground truth encoding - # each of the returns is a litst of tensors - if is_training: - classes, localisations, scores = \ - ssd_common.tf_ssd_bboxes_encode(labels, bboxes, anchors, num_classes) - return tf_utils.reshape_list([image, classes, localisations, scores]) - else: - return tf_utils.reshape_list([image, labels, bboxes]) - - return parse_tfrec_data \ No newline at end of file diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/ssd_vgg_preprocessing.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/ssd_vgg_preprocessing.py deleted file mode 100644 index a0cf0249..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/ssd_vgg_preprocessing.py +++ /dev/null @@ -1,397 +0,0 @@ -# Copyright 2015 Paul Balanca. 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. -# ============================================================================== -"""Pre-processing images for SSD-type networks. -""" -from enum import Enum, IntEnum -import numpy as np - -import tensorflow as tf - -from tensorflow.python.ops import control_flow_ops - -import tfextended as tfe -from datautil import tf_image - -# Resizing strategies. -Resize = IntEnum('Resize', ('NONE', # Nothing! - 'CENTRAL_CROP', # Crop (and pad if necessary). - 'PAD_AND_RESIZE', # Pad, and resize to output shape. - 'WARP_RESIZE')) # Warp resize. - -# VGG mean parameters. -_R_MEAN = 123. -_G_MEAN = 117. -_B_MEAN = 104. - -# Some training pre-processing parameters. -BBOX_CROP_OVERLAP = 0.5 # Minimum overlap to keep a bbox after cropping. -MIN_OBJECT_COVERED = 0.25 -CROP_RATIO_RANGE = (0.6, 1.67) # Distortion ratio during cropping. -EVAL_SIZE = (300, 300) - - -def tf_image_whitened(image, means=[_R_MEAN, _G_MEAN, _B_MEAN]): - """Subtracts the given means from each image channel. - - Returns: - the centered image. - """ - if image.get_shape().ndims != 3: - raise ValueError('Input must be of size [height, width, C>0]') - - mean = tf.constant(means, dtype=image.dtype) - image = image - mean - return image - - -def tf_image_unwhitened(image, means=[_R_MEAN, _G_MEAN, _B_MEAN], to_int=True): - """Re-convert to original image distribution, and convert to int if - necessary. - - Returns: - Centered image. - """ - mean = tf.constant(means, dtype=image.dtype) - image = image + mean - if to_int: - image = tf.cast(image, tf.int32) - return image - - -def np_image_unwhitened(image, means=[_R_MEAN, _G_MEAN, _B_MEAN], to_int=True): - """Re-convert to original image distribution, and convert to int if - necessary. Numpy version. - - Returns: - Centered image. - """ - img = np.copy(image) - img += np.array(means, dtype=img.dtype) - if to_int: - img = img.astype(np.uint8) - return img - - -def tf_summary_image(image, bboxes, name='image', unwhitened=False): - """Add image with bounding boxes to summary. - """ - if unwhitened: - image = tf_image_unwhitened(image) - image = tf.expand_dims(image, 0) - bboxes = tf.expand_dims(bboxes, 0) - image_with_box = tf.image.draw_bounding_boxes(image, bboxes) - tf.summary.image(name, image_with_box) - - -def apply_with_random_selector(x, func, num_cases): - """Computes func(x, sel), with sel sampled from [0...num_cases-1]. - - Args: - x: input Tensor. - func: Python function to apply. - num_cases: Python int32, number of cases to sample sel from. - - Returns: - The result of func(x, sel), where func receives the value of the - selector as a python integer, but sel is sampled dynamically. - """ - sel = tf.random_uniform([], maxval=num_cases, dtype=tf.int32) - # Pass the real x only to one of the func calls. - return control_flow_ops.merge([ - func(control_flow_ops.switch(x, tf.equal(sel, case))[1], case) - for case in range(num_cases)])[0] - - -def distort_color(image, color_ordering=0, fast_mode=True, scope=None): - """Distort the color of a Tensor image. - - Each color distortion is non-commutative and thus ordering of the color ops - matters. Ideally we would randomly permute the ordering of the color ops. - Rather then adding that level of complication, we select a distinct ordering - of color ops for each preprocessing thread. - - Args: - image: 3-D Tensor containing single image in [0, 1]. - color_ordering: Python int, a type of distortion (valid values: 0-3). - fast_mode: Avoids slower ops (random_hue and random_contrast) - scope: Optional scope for name_scope. - Returns: - 3-D Tensor color-distorted image on range [0, 1] - Raises: - ValueError: if color_ordering not in [0, 3] - """ - with tf.name_scope(scope, 'distort_color', [image]): - if fast_mode: - if color_ordering == 0: - image = tf.image.random_brightness(image, max_delta=32. / 255.) - image = tf.image.random_saturation(image, lower=0.5, upper=1.5) - else: - image = tf.image.random_saturation(image, lower=0.5, upper=1.5) - image = tf.image.random_brightness(image, max_delta=32. / 255.) - else: - if color_ordering == 0: - image = tf.image.random_brightness(image, max_delta=32. / 255.) - image = tf.image.random_saturation(image, lower=0.5, upper=1.5) - image = tf.image.random_hue(image, max_delta=0.2) - image = tf.image.random_contrast(image, lower=0.5, upper=1.5) - elif color_ordering == 1: - image = tf.image.random_saturation(image, lower=0.5, upper=1.5) - image = tf.image.random_brightness(image, max_delta=32. / 255.) - image = tf.image.random_contrast(image, lower=0.5, upper=1.5) - image = tf.image.random_hue(image, max_delta=0.2) - elif color_ordering == 2: - image = tf.image.random_contrast(image, lower=0.5, upper=1.5) - image = tf.image.random_hue(image, max_delta=0.2) - image = tf.image.random_brightness(image, max_delta=32. / 255.) - image = tf.image.random_saturation(image, lower=0.5, upper=1.5) - elif color_ordering == 3: - image = tf.image.random_hue(image, max_delta=0.2) - image = tf.image.random_saturation(image, lower=0.5, upper=1.5) - image = tf.image.random_contrast(image, lower=0.5, upper=1.5) - image = tf.image.random_brightness(image, max_delta=32. / 255.) - else: - raise ValueError('color_ordering must be in [0, 3]') - # The random_* ops do not necessarily clamp. - return tf.clip_by_value(image, 0.0, 1.0) - - -def distorted_bounding_box_crop(image, - labels, - bboxes, - min_object_covered=0.3, - aspect_ratio_range=(0.9, 1.1), - area_range=(0.1, 1.0), - max_attempts=200, - clip_bboxes=True, - scope=None): - """Generates cropped_image using a one of the bboxes randomly distorted. - - See `tf.image.sample_distorted_bounding_box` for more documentation. - - Args: - image: 3-D Tensor of image (it will be converted to floats in [0, 1]). - bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords] - where each coordinate is [0, 1) and the coordinates are arranged - as [ymin, xmin, ymax, xmax]. If num_boxes is 0 then it would use the whole - image. - min_object_covered: An optional `float`. Defaults to `0.1`. The cropped - area of the image must contain at least this fraction of any bounding box - supplied. - aspect_ratio_range: An optional list of `floats`. The cropped area of the - image must have an aspect ratio = width / height within this range. - area_range: An optional list of `floats`. The cropped area of the image - must contain a fraction of the supplied image within in this range. - max_attempts: An optional `int`. Number of attempts at generating a cropped - region of the image of the specified constraints. After `max_attempts` - failures, return the entire image. - scope: Optional scope for name_scope. - Returns: - A tuple, a 3-D Tensor cropped_image and the distorted bbox - """ - with tf.name_scope(scope, 'distorted_bounding_box_crop', [image, bboxes]): - # Each bounding box has shape [1, num_boxes, box coords] and - # the coordinates are ordered [ymin, xmin, ymax, xmax]. - bbox_begin, bbox_size, distort_bbox = tf.image.sample_distorted_bounding_box( - tf.shape(image), - bounding_boxes=tf.expand_dims(bboxes, 0), - min_object_covered=min_object_covered, - aspect_ratio_range=aspect_ratio_range, - area_range=area_range, - max_attempts=max_attempts, - use_image_if_no_bounding_boxes=True) - distort_bbox = distort_bbox[0, 0] - - # Crop the image to the specified bounding box. - cropped_image = tf.slice(image, bbox_begin, bbox_size) - # Restore the shape since the dynamic slice loses 3rd dimension. - cropped_image.set_shape([None, None, 3]) - - # Update bounding boxes: resize and filter out. - bboxes = tfe.bboxes_resize(distort_bbox, bboxes) - labels, bboxes = tfe.bboxes_filter_overlap(labels, bboxes, - threshold=BBOX_CROP_OVERLAP, - assign_negative=False) - return cropped_image, labels, bboxes, distort_bbox - - -def preprocess_for_train(image, labels, bboxes, - out_shape = (300, 300), data_format='NHWC', - scope='ssd_preprocessing_train'): - """Preprocesses the given image for training. - - Note that the actual resizing scale is sampled from - [`resize_size_min`, `resize_size_max`]. - - Args: - image: A `Tensor` representing an image of arbitrary size. - output_height: The height of the image after preprocessing. - output_width: The width of the image after preprocessing. - resize_side_min: The lower bound for the smallest side of the image for - aspect-preserving resizing. - resize_side_max: The upper bound for the smallest side of the image for - aspect-preserving resizing. - - Returns: - A preprocessed image. - """ - fast_mode = False - with tf.name_scope(scope, 'ssd_preprocessing_train', [image, labels, bboxes]): - if image.get_shape().ndims != 3: - raise ValueError('Input must be of size [height, width, C>0]') - # Convert to float scaled [0, 1]. - if image.dtype != tf.float32: - image = tf.image.convert_image_dtype(image, dtype=tf.float32) - tf_summary_image(image, bboxes, 'image_with_bboxes') - - # # Remove DontCare labels. - # labels, bboxes = ssd_common.tf_bboxes_filter_labels(out_label, - # labels, - # bboxes) - - # Distort image and bounding boxes. - dst_image = image - dst_image, labels, bboxes, distort_bbox = \ - distorted_bounding_box_crop(image, labels, bboxes, - min_object_covered=MIN_OBJECT_COVERED, - aspect_ratio_range=CROP_RATIO_RANGE) - # Resize image to output size. - dst_image = tf_image.resize_image(dst_image, out_shape, - method=tf.image.ResizeMethod.BILINEAR, - align_corners=False) - tf_summary_image(dst_image, bboxes, 'image_shape_distorted') - - # Randomly flip the image horizontally. - dst_image, bboxes = tf_image.random_flip_left_right(dst_image, bboxes) - - # Randomly distort the colors. There are 4 ways to do it. - dst_image = apply_with_random_selector( - dst_image, - lambda x, ordering: distort_color(x, ordering, fast_mode), - num_cases=4) - tf_summary_image(dst_image, bboxes, 'image_color_distorted') - - # Rescale to VGG input scale. - image = dst_image * 255. - image = tf_image_whitened(image, [_R_MEAN, _G_MEAN, _B_MEAN]) - # Image data format. - if data_format == 'NCHW': - image = tf.transpose(image, perm=(2, 0, 1)) - return image, labels, bboxes - - -def preprocess_for_eval(image, labels, bboxes, - out_shape=EVAL_SIZE, data_format='NHWC', - difficults=None, resize=Resize.WARP_RESIZE, - scope='ssd_preprocessing_train'): - """Preprocess an image for evaluation. - - Args: - image: A `Tensor` representing an image of arbitrary size. - out_shape: Output shape after pre-processing (if resize != None) - resize: Resize strategy. - - Returns: - A preprocessed image. - """ - with tf.name_scope(scope): - if image.get_shape().ndims != 3: - raise ValueError('Input must be of size [height, width, C>0]') - - image = tf.cast(image, tf.float32) - image = tf_image_whitened(image, [_R_MEAN, _G_MEAN, _B_MEAN]) - - # Add image rectangle to bboxes. - bbox_img = tf.constant([[0., 0., 1., 1.]]) - if bboxes is None: - bboxes = bbox_img - else: - bboxes = tf.concat([bbox_img, bboxes], axis=0) - - if resize == Resize.NONE: - # No resizing... - pass - elif resize == Resize.CENTRAL_CROP: - # Central cropping of the image. - image, bboxes = tf_image.resize_image_bboxes_with_crop_or_pad( - image, bboxes, out_shape[0], out_shape[1]) - elif resize == Resize.PAD_AND_RESIZE: - # Resize image first: find the correct factor... - shape = tf.shape(image) - factor = tf.minimum(tf.to_double(1.0), - tf.minimum(tf.to_double(out_shape[0] / shape[0]), - tf.to_double(out_shape[1] / shape[1]))) - resize_shape = factor * tf.to_double(shape[0:2]) - resize_shape = tf.cast(tf.floor(resize_shape), tf.int32) - - image = tf_image.resize_image(image, resize_shape, - method=tf.image.ResizeMethod.BILINEAR, - align_corners=False) - # Pad to expected size. - image, bboxes = tf_image.resize_image_bboxes_with_crop_or_pad( - image, bboxes, out_shape[0], out_shape[1]) - elif resize == Resize.WARP_RESIZE: - # Warp resize of the image. - image = tf_image.resize_image(image, out_shape, - method=tf.image.ResizeMethod.BILINEAR, - align_corners=False) - - # Split back bounding boxes. - bbox_img = bboxes[0] - bboxes = bboxes[1:] - # Remove difficult boxes. - if difficults is not None: - mask = tf.logical_not(tf.cast(difficults, tf.bool)) - labels = tf.boolean_mask(labels, mask) - bboxes = tf.boolean_mask(bboxes, mask) - # Image data format. - if data_format == 'NCHW': - image = tf.transpose(image, perm=(2, 0, 1)) - return image, labels, bboxes, bbox_img - -def preprocess_image(image, - labels, - bboxes, - out_shape, - data_format, - is_training=False, - **kwargs): - """Pre-process an given image. - - Args: - image: A `Tensor` representing an image of arbitrary size. - output_height: The height of the image after preprocessing. - output_width: The width of the image after preprocessing. - is_training: `True` if we're preprocessing the image for training and - `False` otherwise. - resize_side_min: The lower bound for the smallest side of the image for - aspect-preserving resizing. If `is_training` is `False`, then this value - is used for rescaling. - resize_side_max: The upper bound for the smallest side of the image for - aspect-preserving resizing. If `is_training` is `False`, this value is - ignored. Otherwise, the resize side is sampled from - [resize_size_min, resize_size_max]. - - Returns: - A preprocessed image. - """ - if is_training: - return preprocess_for_train(image, labels, bboxes, - out_shape=out_shape, - data_format=data_format) - else: - return preprocess_for_eval(image, labels, bboxes, - out_shape=out_shape, - data_format=data_format, - **kwargs) diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/tf_image.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/tf_image.py deleted file mode 100644 index a9626266..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/datautil/tf_image.py +++ /dev/null @@ -1,306 +0,0 @@ -# Copyright 2015 The TensorFlow Authors and Paul Balanca. 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. -# ============================================================================== -"""Custom image operations. -Most of the following methods extend TensorFlow image library, and part of -the code is shameless copy-paste of the former! -""" -import tensorflow as tf - -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import ops -from tensorflow.python.framework import tensor_shape -from tensorflow.python.framework import tensor_util -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import check_ops -from tensorflow.python.ops import clip_ops -from tensorflow.python.ops import control_flow_ops -from tensorflow.python.ops import gen_image_ops -from tensorflow.python.ops import gen_nn_ops -from tensorflow.python.ops import string_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.ops import random_ops -from tensorflow.python.ops import variables - - -# =========================================================================== # -# Modification of TensorFlow image routines. -# =========================================================================== # -def _assert(cond, ex_type, msg): - """A polymorphic assert, works with tensors and boolean expressions. - If `cond` is not a tensor, behave like an ordinary assert statement, except - that a empty list is returned. If `cond` is a tensor, return a list - containing a single TensorFlow assert op. - Args: - cond: Something evaluates to a boolean value. May be a tensor. - ex_type: The exception class to use. - msg: The error message. - Returns: - A list, containing at most one assert op. - """ - if _is_tensor(cond): - return [control_flow_ops.Assert(cond, [msg])] - else: - if not cond: - raise ex_type(msg) - else: - return [] - - -def _is_tensor(x): - """Returns `True` if `x` is a symbolic tensor-like object. - Args: - x: A python object to check. - Returns: - `True` if `x` is a `tf.Tensor` or `tf.Variable`, otherwise `False`. - """ - return isinstance(x, (ops.Tensor, variables.Variable)) - - -def _ImageDimensions(image): - """Returns the dimensions of an image tensor. - Args: - image: A 3-D Tensor of shape `[height, width, channels]`. - Returns: - A list of `[height, width, channels]` corresponding to the dimensions of the - input image. Dimensions that are statically known are python integers, - otherwise they are integer scalar tensors. - """ - if image.get_shape().is_fully_defined(): - return image.get_shape().as_list() - else: - static_shape = image.get_shape().with_rank(3).as_list() - dynamic_shape = array_ops.unstack(array_ops.shape(image), 3) - return [s if s is not None else d - for s, d in zip(static_shape, dynamic_shape)] - - -def _Check3DImage(image, require_static=True): - """Assert that we are working with properly shaped image. - Args: - image: 3-D Tensor of shape [height, width, channels] - require_static: If `True`, requires that all dimensions of `image` are - known and non-zero. - Raises: - ValueError: if `image.shape` is not a 3-vector. - Returns: - An empty list, if `image` has fully defined dimensions. Otherwise, a list - containing an assert op is returned. - """ - try: - image_shape = image.get_shape().with_rank(3) - except ValueError: - raise ValueError("'image' must be three-dimensional.") - if require_static and not image_shape.is_fully_defined(): - raise ValueError("'image' must be fully defined.") - if any(x == 0 for x in image_shape): - raise ValueError("all dims of 'image.shape' must be > 0: %s" % - image_shape) - if not image_shape.is_fully_defined(): - return [check_ops.assert_positive(array_ops.shape(image), - ["all dims of 'image.shape' " - "must be > 0."])] - else: - return [] - - -def fix_image_flip_shape(image, result): - """Set the shape to 3 dimensional if we don't know anything else. - Args: - image: original image size - result: flipped or transformed image - Returns: - An image whose shape is at least None,None,None. - """ - image_shape = image.get_shape() - if image_shape == tensor_shape.unknown_shape(): - result.set_shape([None, None, None]) - else: - result.set_shape(image_shape) - return result - - -# =========================================================================== # -# Image + BBoxes methods: cropping, resizing, flipping, ... -# =========================================================================== # -def bboxes_crop_or_pad(bboxes, - height, width, - offset_y, offset_x, - target_height, target_width): - """Adapt bounding boxes to crop or pad operations. - Coordinates are always supposed to be relative to the image. - - Arguments: - bboxes: Tensor Nx4 with bboxes coordinates [y_min, x_min, y_max, x_max]; - height, width: Original image dimension; - offset_y, offset_x: Offset to apply, - negative if cropping, positive if padding; - target_height, target_width: Target dimension after cropping / padding. - """ - with tf.name_scope('bboxes_crop_or_pad'): - # Rescale bounding boxes in pixels. - scale = tf.cast(tf.stack([height, width, height, width]), bboxes.dtype) - bboxes = bboxes * scale - # Add offset. - offset = tf.cast(tf.stack([offset_y, offset_x, offset_y, offset_x]), bboxes.dtype) - bboxes = bboxes + offset - # Rescale to target dimension. - scale = tf.cast(tf.stack([target_height, target_width, - target_height, target_width]), bboxes.dtype) - bboxes = bboxes / scale - return bboxes - - -def resize_image_bboxes_with_crop_or_pad(image, bboxes, - target_height, target_width): - """Crops and/or pads an image to a target width and height. - Resizes an image to a target width and height by either centrally - cropping the image or padding it evenly with zeros. - - If `width` or `height` is greater than the specified `target_width` or - `target_height` respectively, this op centrally crops along that dimension. - If `width` or `height` is smaller than the specified `target_width` or - `target_height` respectively, this op centrally pads with 0 along that - dimension. - Args: - image: 3-D tensor of shape `[height, width, channels]` - target_height: Target height. - target_width: Target width. - Raises: - ValueError: if `target_height` or `target_width` are zero or negative. - Returns: - Cropped and/or padded image of shape - `[target_height, target_width, channels]` - """ - with tf.name_scope('resize_with_crop_or_pad'): - image = ops.convert_to_tensor(image, name='image') - - assert_ops = [] - assert_ops += _Check3DImage(image, require_static=False) - assert_ops += _assert(target_width > 0, ValueError, - 'target_width must be > 0.') - assert_ops += _assert(target_height > 0, ValueError, - 'target_height must be > 0.') - - image = control_flow_ops.with_dependencies(assert_ops, image) - # `crop_to_bounding_box` and `pad_to_bounding_box` have their own checks. - # Make sure our checks come first, so that error messages are clearer. - if _is_tensor(target_height): - target_height = control_flow_ops.with_dependencies( - assert_ops, target_height) - if _is_tensor(target_width): - target_width = control_flow_ops.with_dependencies(assert_ops, target_width) - - def max_(x, y): - if _is_tensor(x) or _is_tensor(y): - return math_ops.maximum(x, y) - else: - return max(x, y) - - def min_(x, y): - if _is_tensor(x) or _is_tensor(y): - return math_ops.minimum(x, y) - else: - return min(x, y) - - def equal_(x, y): - if _is_tensor(x) or _is_tensor(y): - return math_ops.equal(x, y) - else: - return x == y - - height, width, _ = _ImageDimensions(image) - width_diff = target_width - width - offset_crop_width = max_(-width_diff // 2, 0) - offset_pad_width = max_(width_diff // 2, 0) - - height_diff = target_height - height - offset_crop_height = max_(-height_diff // 2, 0) - offset_pad_height = max_(height_diff // 2, 0) - - # Maybe crop if needed. - height_crop = min_(target_height, height) - width_crop = min_(target_width, width) - cropped = tf.image.crop_to_bounding_box(image, offset_crop_height, offset_crop_width, - height_crop, width_crop) - bboxes = bboxes_crop_or_pad(bboxes, - height, width, - -offset_crop_height, -offset_crop_width, - height_crop, width_crop) - # Maybe pad if needed. - resized = tf.image.pad_to_bounding_box(cropped, offset_pad_height, offset_pad_width, - target_height, target_width) - bboxes = bboxes_crop_or_pad(bboxes, - height_crop, width_crop, - offset_pad_height, offset_pad_width, - target_height, target_width) - - # In theory all the checks below are redundant. - if resized.get_shape().ndims is None: - raise ValueError('resized contains no shape.') - - resized_height, resized_width, _ = _ImageDimensions(resized) - - assert_ops = [] - assert_ops += _assert(equal_(resized_height, target_height), ValueError, - 'resized height is not correct.') - assert_ops += _assert(equal_(resized_width, target_width), ValueError, - 'resized width is not correct.') - - resized = control_flow_ops.with_dependencies(assert_ops, resized) - return resized, bboxes - - -def resize_image(image, size, - method=tf.image.ResizeMethod.BILINEAR, - align_corners=False): - """Resize an image and bounding boxes. - """ - # Resize image. - with tf.name_scope('resize_image'): - height, width, channels = _ImageDimensions(image) - image = tf.expand_dims(image, 0) - image = tf.image.resize_images(image, size, - method, align_corners) - image = tf.reshape(image, tf.stack([size[0], size[1], channels])) - return image - - -def random_flip_left_right(image, bboxes, seed=None): - """Random flip left-right of an image and its bounding boxes. - """ - def flip_bboxes(bboxes): - """Flip bounding boxes coordinates. - """ - bboxes = tf.stack([bboxes[:, 0], 1 - bboxes[:, 3], - bboxes[:, 2], 1 - bboxes[:, 1]], axis=-1) - return bboxes - - # Random flip. Tensorflow implementation. - with tf.name_scope('random_flip_left_right'): - image = ops.convert_to_tensor(image, name='image') - _Check3DImage(image, require_static=False) - uniform_random = random_ops.random_uniform([], 0, 1.0, seed=seed) - mirror_cond = math_ops.less(uniform_random, .5) - # Flip image. - result = control_flow_ops.cond(mirror_cond, - lambda: array_ops.reverse_v2(image, [1]), - lambda: image) - # Flip bboxes. - bboxes = control_flow_ops.cond(mirror_cond, - lambda: flip_bboxes(bboxes), - lambda: bboxes) - return fix_image_flip_shape(image, result), bboxes - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/__init__.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/eval.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/eval.py deleted file mode 100644 index 6771ed54..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/eval.py +++ /dev/null @@ -1,159 +0,0 @@ -import tensorflow as tf -import numpy as np - -import os, sys, time - -from anchors import generate_anchors -from model import ssd_common, ssd_vgg_300 -from datautil.parser import get_parser_func -from datautil.ssd_vgg_preprocessing import preprocess_for_eval, preprocess_for_train -from tfutil import endpoints, tf_utils -import tfextended as tfe -from finetune.train_eval_base import TrainerBase - -class EvalVggSsd(TrainerBase): - ''' - Run fine-tuning - Have training and validation recordset files - ''' - - def __init__(self, ckpt_dir, validation_recordset_files, steps_to_save = 1000, num_steps = 1000, num_classes = 21, print_steps = 10): - - ''' - ckpt_dir - directory of checkpoint metagraph - train_recordset_files - list of files represetnting the recordset for training - validation_recordset_files - list of files representing validation recordset - ''' - super().__init__(ckpt_dir, validation_recordset_files, steps_to_save, num_steps, num_classes, print_steps, 1, is_training=False) - self.eval_classes = num_classes - - def get_eval_ops(self, b_labels, b_bboxes, predictions, localizations): - ''' - Create evaluation operation - ''' - b_difficults = tf.zeros(tf.shape(b_labels), dtype=tf.int64) - - # Performing post-processing on CPU: loop-intensive, usually more efficient. - with tf.device('/device:CPU:0'): - # Detected objects from SSD output. - detected_localizations = self.ssd_net.bboxes_decode(localizations, self.anchors) - - rscores, rbboxes = \ - self.ssd_net.detected_bboxes(predictions, detected_localizations, - select_threshold=0.01, - nms_threshold=0.45, - clipping_bbox=None, - top_k=400, - keep_top_k=20) - - # Compute TP and FP statistics. - num_gbboxes, tp, fp, rscores = \ - tfe.bboxes_matching_batch(rscores.keys(), rscores, rbboxes, - b_labels, b_bboxes, b_difficults, - matching_threshold=0.5) - - # =================================================================== # - # Evaluation metrics. - # =================================================================== # - dict_metrics = {} - metrics_scope = 'ssd_metrics_scope' - - # First add all losses. - for loss in tf.get_collection(tf.GraphKeys.LOSSES): - dict_metrics[loss.op.name] = tf.metrics.mean(loss, name=metrics_scope) - # Extra losses as well. - for loss in tf.get_collection('EXTRA_LOSSES'): - dict_metrics[loss.op.name] = tf.metrics.mean(loss, name=metrics_scope) - - # Add metrics to summaries and Print on screen. - for name, metric in dict_metrics.items(): - # summary_name = 'eval/%s' % name - summary_name = name - tf.summary.scalar(summary_name, metric[0]) - - # FP and TP metrics. - tp_fp_metric = tfe.streaming_tp_fp_arrays(num_gbboxes, tp, fp, rscores, name=metrics_scope) - - for c in tp_fp_metric[0].keys(): - dict_metrics['tp_fp_%s' % c] = (tp_fp_metric[0][c], - tp_fp_metric[1][c]) - - # Add to summaries precision/recall values. - aps_voc12 = {} - # TODO: We cut it short by the actual number of classes we have - for c in list(tp_fp_metric[0].keys())[:self.eval_classes - 1]: - # Precison and recall values. - prec, rec = tfe.precision_recall(*tp_fp_metric[0][c]) - - # Average precision VOC12. - v = tfe.average_precision_voc12(prec, rec) - summary_name = 'AP_VOC12/%s' % c - tf.summary.scalar(summary_name, v) - - aps_voc12[c] = v - - # Mean average precision VOC12. - summary_name = 'AP_VOC12/mAP' - mAP = tf.add_n(list(aps_voc12.values())) / len(aps_voc12) - tf.summary.scalar(summary_name, mAP) - - names_to_values, names_to_updates = tf.contrib.metrics.aggregate_metric_map(dict_metrics) - - # Split into values and updates ops. - return (names_to_values, names_to_updates, mAP) - - def eval(self): - - tf.logging.set_verbosity(tf.logging.INFO) - - # shorthand - sess = self.sess - - sess.run(self.iterator.initializer) - batch_data = self.iterator.get_next() - - # image, classes, scores, ground_truths are neatly packed into a flat list - # this is how we will slice it to extract the data we need: - # we will convert the flat list into a list of lists, where each sub-list - # is as long as each slice dimension - slice_shape = [1] * 3 - - b_image, b_labels, b_bboxes = tf_utils.reshape_list(batch_data, slice_shape) - - # network endpoints - predictions, localizations, _, _ = self.get_output_tensors(b_image) - - # branch to create evaluation operation - _, names_to_updates, mAP = \ - self.get_eval_ops(b_labels, b_bboxes, predictions, localizations) - - eval_update_ops = tf_utils.reshape_list(list(names_to_updates.values())) - - # summaries - summary_op = tf.summary.merge_all() - saver = tf.train.Saver() - - eval_writer = tf.summary.FileWriter(self.ckpt_dir + '/eval') - - # initialize globals - sess.run(tf.global_variables_initializer()) - - saver.restore(self.sess, self.ckpt_file) - sess.run(tf.local_variables_initializer()) - - tf.logging.info(f"Starting evaluation for {self.num_steps} steps") - cur_step = self.latest_ckpt_step - - for step in range(self.num_steps): - print(f"Evaluation step: {step + 1}", end='\r', flush=True) - _, summary = sess.run([eval_update_ops, summary_op]) - - if (step + 1) % self.print_steps == 0 or step == self.num_steps: - eval_writer.add_summary(summary, cur_step + step + 1) - - summary_final, mAP_val = sess.run([summary_op, mAP]) - - print(f"\nmAP: {mAP_val:.4f}") - - if (step + 1) % self.print_steps != 0: - eval_writer.add_summary(summary_final, self.num_steps + cur_step) \ No newline at end of file diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/inference.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/inference.py deleted file mode 100644 index d56bafea..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/inference.py +++ /dev/null @@ -1,95 +0,0 @@ -import tensorflow as tf - -import os, time - -from anchors import generate_anchors -from model import np_methods -from tfutil import endpoints, tf_utils -from datautil.ssd_vgg_preprocessing import preprocess_for_eval -import tfextended as tfe -from azureml.accel.models import SsdVgg - -class InferVggSsd: - ''' - Run fine-tuning - Have training and validation recordset files - ''' - - def __init__(self, ckpt_dir, ckpt_file=None, gpu=True): - - ''' - ckpt_dir - directory of checkpoint metagraph - ''' - - if gpu: - gpu_options = tf.GPUOptions(allow_growth=True) - config = tf.ConfigProto(log_device_placement=False, gpu_options=gpu_options) - else: - config = tf.ConfigProto(log_device_placement=False, device_count={'GPU': 0}) - - self.sess = tf.Session(config=config) - - ssd_net_graph = SsdVgg(ckpt_dir) - self.ckpt_dir = ssd_net_graph.model_path - - self.img_input = tf.placeholder(tf.uint8, shape=(None, None, 3)) - - # Evaluation pre-processing: resize to SSD net shape. - image_pre, _, _, self.bbox_img = preprocess_for_eval( - self.img_input, None, None, generate_anchors.img_shape, "NHWC") - self.image_4d = tf.expand_dims(image_pre, 0) - - # import the graph - ssd_net_graph.import_graph_def(self.image_4d, is_training=False) - - graph = tf.get_default_graph() - self.localizations = [graph.get_tensor_by_name(tensor_name) for tensor_name in endpoints.localizations_names] - self.predictions = [graph.get_tensor_by_name(tensor_name) for tensor_name in endpoints.predictions_names] - - # Restore SSD model. - self.sess.run(tf.global_variables_initializer()) - - if ckpt_file is None: - ssd_net_graph.restore_weights(self.sess) - else: - saver = tf.train.Saver() - saver.restore(self.sess, os.path.join(self.ckpt_dir, ckpt_file)) - - # SSD default anchor boxes. - self.ssd_anchors = generate_anchors.ssd_anchors_all_layers() - - - def close(self): - self.sess.close() - tf.reset_default_graph() - - def process_image(self, img, select_threshold=0.4, nms_threshold=.45, net_shape=(300, 300)): - # Run SSD network. - rpredictions, rlocalisations, rbbox_img = \ - self.sess.run([self.predictions, self.localizations, self.bbox_img], - feed_dict={self.img_input: img}) - # Get classes and bboxes from the net outputs. - rclasses, rscores, rbboxes = np_methods.ssd_bboxes_select( - rpredictions, rlocalisations, self.ssd_anchors, - select_threshold=select_threshold, img_shape=net_shape, num_classes=21, decode=True) - - rbboxes = np_methods.bboxes_clip(rbbox_img, rbboxes) - rclasses, rscores, rbboxes = np_methods.bboxes_sort(rclasses, rscores, rbboxes, top_k=400) - rclasses, rscores, rbboxes = np_methods.bboxes_nms(rclasses, rscores, rbboxes, nms_threshold=nms_threshold) - return rclasses, rscores, rbboxes - - def infer(self, img, visualize): - rclasses, rscores, rbboxes = self.process_image(img) - - if visualize: - from tfutil import visualization - visualization.plt_bboxes(img, rclasses, rscores, rbboxes) - - return rclasses, rscores, rbboxes - - def infer_file(self, im_file, visualize=False): - import cv2 - - img = cv2.imread(im_file) - img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) - return self.infer(img, visualize) \ No newline at end of file diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/metrics.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/metrics.py deleted file mode 100644 index e69de29b..00000000 diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/model_saver.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/model_saver.py deleted file mode 100644 index 2a172046..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/model_saver.py +++ /dev/null @@ -1,57 +0,0 @@ -import tensorflow as tf - -import os, time - -from azureml.accel.models import SsdVgg -import azureml.accel.models.utils as utils - -class SaverVggSsd: - ''' - Run fine-tuning - Have training and validation recordset files - ''' - - def __init__(self, ckpt_dir): - - ''' - ckpt_dir - directory of checkpoint metagraph - ''' - - config = tf.ConfigProto(log_device_placement=False, device_count={'GPU': 0}) - - self.sess = tf.Session(config=config) - - ssd_net_graph = SsdVgg(ckpt_dir, is_frozen=True) - self.ckpt_dir = ssd_net_graph.model_path - - self.in_images = tf.placeholder(tf.string) - self.image_tensors = utils.preprocess_array(self.in_images, output_width=300, output_height=300, - preserve_aspect_ratio=False) - - self.output_tensors = ssd_net_graph.import_graph_def(self.image_tensors, is_training=False) - - self.output_names = ssd_net_graph.output_tensor_list - self.input_name_str = self.in_images.name - - # Restore SSD model. - ssd_net_graph.restore_weights(self.sess) - - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.close() - - def close(self): - self.sess.close() - tf.reset_default_graph() - - def save_for_deployment(self, saved_path): - - output_map = {'out_{}'.format(i): output for i, output in enumerate(self.output_tensors)} - - tf.saved_model.simple_save(self.sess, - saved_path, - inputs={"images": self.in_images}, - outputs=output_map) \ No newline at end of file diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/train.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/train.py deleted file mode 100644 index b9b4e402..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/train.py +++ /dev/null @@ -1,144 +0,0 @@ -import tensorflow as tf -import numpy as np - -import os, sys, time, re - -from anchors import generate_anchors -from model import ssd_common, ssd_vgg_300 -from datautil.parser import get_parser_func -from datautil.ssd_vgg_preprocessing import preprocess_for_eval, preprocess_for_train -from tfutil import endpoints, tf_utils -import tfextended as tfe -from finetune.train_eval_base import TrainerBase - -class TrainVggSsd(TrainerBase): - ''' - Run fine-tuning - Have training and validation recordset files - ''' - - def __init__(self, ckpt_dir, train_recordset_files, - steps_to_save = 1000, num_steps = 1000, num_classes = 21, - print_steps = 10, batch_size = 2, - learning_rate = 1e-4, learning_rate_decay_steps=None, learning_rate_decay_value = None, - adam_beta1 = 0.9, adam_beta2 = 0.999, adam_epsilon = 1e-8): - - ''' - ckpt_dir - directory of checkpoint metagraph - train_recordset_files - list of files represetnting the recordset for training - validation_recordset_files - list of files representing validation recordset - ''' - - super().__init__(ckpt_dir, train_recordset_files, steps_to_save, num_steps, num_classes, print_steps, batch_size) - - # optimizer parameters - self.learning_rate = learning_rate - self.learning_rate_decay_steps = learning_rate_decay_steps - self.learning_rate_decay_value = learning_rate_decay_value - - if self.learning_rate <= 0 \ - or (self.learning_rate_decay_value is not None and self.learning_rate_decay_value <= 0) \ - or (self.learning_rate_decay_steps is not None and self.learning_rate_decay_steps <= 0) \ - or (self.learning_rate_decay_steps is None and self.learning_rate_decay_value is not None) \ - or (self.learning_rate_decay_steps is not None and self.learning_rate_decay_value is None): - raise ValueError("learning rate, learning rate steps, learning rate decay must be positive, \ - learning decay steps and value must be both present or both absent") - - self.adam_beta1 = adam_beta1 - self.adam_beta2 = adam_beta2 - self.adam_epsilon = adam_epsilon - - def get_optimizer(self, learning_rate): - optimizer = tf.train.AdamOptimizer( - learning_rate, - beta1=self.adam_beta1, - beta2=self.adam_beta2, - epsilon=self.adam_epsilon) - return optimizer - - def get_learning_rate(self, global_step): - ''' - Configure learning rate based on decay specifications - ''' - if self.learning_rate_decay_steps is None: - return tf.constant(self.learning_rate, name = 'fixed_learning_rate') - else: - return tf.train.exponential_decay(self.learning_rate, global_step, \ - self.learning_rate_decay_steps, self.learning_rate_decay_value, \ - staircase=True, name="exponential_decay_learning_rate") - - def train(self): - - tf.logging.set_verbosity(tf.logging.INFO) - - # shorthand - sess = self.sess - - batch_data = self.iterator.get_next() - - # image, classes, scores, ground_truths are neatly packed into a flat list - # this is how we will slice it to extract the data we need: - # we will convert the flat list into a list of lists, where each sub-list - # is as long as each slice dimension - slice_shape = [1] + [len(self.anchors)] * 3 - - b_image, b_classes, b_localizations, b_scores = tf_utils.reshape_list(batch_data, slice_shape) - # network endpoints - _, localizations, logits, bw_saver = self.get_output_tensors(b_image) - - variables_to_train = tf.trainable_variables() - sess.run(tf.initialize_variables(variables_to_train)) - - # add losses - total_loss = self.ssd_net.losses(logits, localizations, b_classes, b_localizations, b_scores) - tf.summary.scalar("total_loss", total_loss) - - global_step = tf.train.get_or_create_global_step() - learning_rate = self.get_learning_rate(global_step) - - # configure learning rate now that we have the global step - # add optimizer - optimizer = self.get_optimizer(learning_rate) - - tf.summary.scalar("learning_rate", learning_rate) - - grads_and_vars = optimizer.compute_gradients(total_loss, var_list=variables_to_train) - grad_updates = optimizer.apply_gradients(grads_and_vars, global_step=global_step) - - # initialize all the variables we should initialize - # weights will be restored right after - sess.run(tf.global_variables_initializer()) - - # after the first restore, we want global step in our checkpoint - saver = tf.train.Saver(variables_to_train + [global_step]) - if self.latest_ckpt_step == 0: - bw_saver.restore(sess, self.ckpt_file) - else: - saver.restore(sess, self.ckpt_file) - self.ckpt_file = os.path.join(self.ckpt_dir, self.ckpt_prefix) - - # summaries - train_summary_op = tf.summary.merge_all() - train_writer = tf.summary.FileWriter(self.ckpt_dir + '/train', tf.get_default_graph()) - - tf.logging.info(f"Starting training for {self.num_steps} steps") - - sess.run(self.iterator.initializer) - - # training loop - start = time.time() - - for _ in range(self.num_steps): - - loss, _, cur_step, summary = sess.run([total_loss, grad_updates, global_step, train_summary_op]) - cur_step += 1 - - if cur_step % self.print_steps == 0: - - print(f"{cur_step}: loss: {loss:.3f}, avg per step: {(time.time() - start) / self.print_steps:.3f} sec", end='\r', flush=True) - train_writer.add_summary(summary, cur_step + 1) - start = time.time() - - if cur_step % self.steps_to_save == 0: - saver.save(sess, self.ckpt_file, global_step=global_step) - print("\n") \ No newline at end of file diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/train_eval_base.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/train_eval_base.py deleted file mode 100644 index 340bd3e1..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/finetune/train_eval_base.py +++ /dev/null @@ -1,125 +0,0 @@ -import tensorflow as tf -import numpy as np - -import os, sys, time, glob, re - -from anchors import generate_anchors -from model import ssd_common, ssd_vgg_300 -from datautil.parser import get_parser_func -from datautil.ssd_vgg_preprocessing import preprocess_for_eval, preprocess_for_train -from tfutil import endpoints, tf_utils -import tfextended as tfe -from azureml.accel.models import SsdVgg - -slim = tf.contrib.slim - -class TrainerBase: - ''' - Run fine-tuning - Have training and validation recordset files - ''' - - def __init__(self, ckpt_dir, recordset_files, - steps_to_save = 1000, num_steps = 1000, num_classes = 21, print_steps = 10, batch_size=2, is_training=True): - - ''' - ckpt_dir - directory of checkpoint metagraph - recordset_files - list of files represetnting the recordset for training - validation_recordset_files - list of files representing validation recordset - ''' - - self.is_training = is_training - - # This will pull the model with its weights - # And seed the checkpoint - self.ssd_net_graph = SsdVgg(ckpt_dir) - self.ckpt_dir = self.ssd_net_graph.model_path - self.ckpt_file = tf.train.latest_checkpoint(self.ssd_net_graph.model_path) - - try: - self.latest_ckpt_step = int(re.findall("-[0-9]+$", self.ckpt_file)[0][1:]) - except: - self.latest_ckpt_step = 0 - - self.recordset = recordset_files - self.ckpt_prefix = os.path.split(self.ssd_net_graph.model_ref + "_bw")[1] - - self.pb_graph_path = os.path.join(self.ckpt_dir, self.ckpt_prefix + ".graph.pb") - #if self.is_training: - self.graph_file = os.path.join(self.ckpt_dir, self.ckpt_prefix + ".meta") - #else: - # self.graph_file = self.ckpt_file + ".meta" - - # anchors - self.anchors = generate_anchors.ssd_anchors_all_layers() - - # shuffle - self.n_shuffle = 1000 - self.num_steps = num_steps - - # num of classes - # REVIEW: this has to be 21! - self.num_classes = 21 - - # initialize data pipeline - self.batch_size = batch_size - self.iterator = None - self.prep_dataset_and_iterator() - - self.steps_to_save = steps_to_save - - self.print_steps = print_steps - # for losses etc - self.ssd_net = ssd_vgg_300.SSDNet() - - # input placeholder - self.input_tensor_name = self.ssd_net_graph.input_tensor_list[0] - - - def __enter__(self): - gpu_options = tf.GPUOptions(allow_growth=True) - config = tf.ConfigProto(log_device_placement=False, gpu_options=gpu_options) - - self.sess = tf.Session(config=config) - - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.sess.close() - tf.reset_default_graph() - - def prep_dataset_and_iterator(self): - ''' - Create datasets for training or validation - ''' - - var_scope = "training" if self.is_training else "eval" - - parse_func = get_parser_func(self.anchors, self.num_classes, self.is_training, var_scope) - - with tf.variable_scope(var_scope): - # data pipeline - dataset = tf.data.TFRecordDataset(self.recordset) - if self.is_training: - dataset = dataset.shuffle(self.n_shuffle) - dataset = dataset.map(parse_func) - dataset = dataset.repeat() - dataset = dataset.batch(self.batch_size) - dataset = dataset.prefetch(1) - - self.iterator = dataset.make_initializable_iterator() - - def get_output_tensors(self, image): - - is_training = tf.constant(self.is_training, dtype=tf.bool, shape=()) - input_map = {self.input_tensor_name: image, "is_training": is_training} - - saver = tf.train.import_meta_graph(self.graph_file, input_map=input_map) - graph = tf.get_default_graph() - - logits = [graph.get_tensor_by_name(tensor_name) for tensor_name in endpoints.logit_names] - localizations = [graph.get_tensor_by_name(tensor_name) for tensor_name in endpoints.localizations_names] - predictions = [graph.get_tensor_by_name(tensor_name) for tensor_name in endpoints.predictions_names] - - return predictions, localizations, logits, saver - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/__init__.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/custom_layers.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/custom_layers.py deleted file mode 100644 index 4939c872..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/custom_layers.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright 2015 Paul Balanca. 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. -# ============================================================================== -"""Implement some custom layers, not provided by TensorFlow. - -Trying to follow as much as possible the style/standards used in -tf.contrib.layers -""" -import tensorflow as tf - -from tensorflow.contrib.framework.python.ops import add_arg_scope -from tensorflow.contrib.layers.python.layers import initializers -from tensorflow.contrib.framework.python.ops import variables -from tensorflow.contrib.layers.python.layers import utils -from tensorflow.python.ops import nn -from tensorflow.python.ops import init_ops -from tensorflow.python.ops import variable_scope - - -def abs_smooth(x): - """Smoothed absolute function. Useful to compute an L1 smooth error. - - Define as: - x^2 / 2 if abs(x) < 1 - abs(x) - 0.5 if abs(x) > 1 - We use here a differentiable definition using min(x) and abs(x). Clearly - not optimal, but good enough for our purpose! - """ - absx = tf.abs(x) - minx = tf.minimum(absx, 1) - r = 0.5 * ((absx - 1) * minx + absx) - return r - - -@add_arg_scope -def l2_normalization( - inputs, - scaling=False, - scale_initializer=init_ops.ones_initializer(), - reuse=None, - variables_collections=None, - outputs_collections=None, - data_format='NHWC', - trainable=True, - scope=None): - """Implement L2 normalization on every feature (i.e. spatial normalization). - - Should be extended in some near future to other dimensions, providing a more - flexible normalization framework. - - Args: - inputs: a 4-D tensor with dimensions [batch_size, height, width, channels]. - scaling: whether or not to add a post scaling operation along the dimensions - which have been normalized. - scale_initializer: An initializer for the weights. - reuse: whether or not the layer and its variables should be reused. To be - able to reuse the layer scope must be given. - variables_collections: optional list of collections for all the variables or - a dictionary containing a different list of collection per variable. - outputs_collections: collection to add the outputs. - data_format: NHWC or NCHW data format. - trainable: If `True` also add variables to the graph collection - `GraphKeys.TRAINABLE_VARIABLES` (see tf.Variable). - scope: Optional scope for `variable_scope`. - Returns: - A `Tensor` representing the output of the operation. - """ - - with variable_scope.variable_scope( - scope, 'L2Normalization', [inputs], reuse=reuse) as sc: - inputs_shape = inputs.get_shape() - inputs_rank = inputs_shape.ndims - dtype = inputs.dtype.base_dtype - if data_format == 'NHWC': - # norm_dim = tf.range(1, inputs_rank-1) - norm_dim = tf.range(inputs_rank-1, inputs_rank) - params_shape = inputs_shape[-1:] - elif data_format == 'NCHW': - # norm_dim = tf.range(2, inputs_rank) - norm_dim = tf.range(1, 2) - params_shape = (inputs_shape[1]) - - # Normalize along spatial dimensions. - outputs = nn.l2_normalize(inputs, norm_dim, epsilon=1e-12) - # Additional scaling. - if scaling: - scale_collections = utils.get_variable_collections( - variables_collections, 'scale') - scale = variables.model_variable('gamma', - shape=params_shape, - dtype=dtype, - initializer=scale_initializer, - collections=scale_collections, - trainable=trainable) - if data_format == 'NHWC': - outputs = tf.multiply(outputs, scale) - elif data_format == 'NCHW': - scale = tf.expand_dims(scale, axis=-1) - scale = tf.expand_dims(scale, axis=-1) - outputs = tf.multiply(outputs, scale) - # outputs = tf.transpose(outputs, perm=(0, 2, 3, 1)) - - return utils.collect_named_outputs(outputs_collections, - sc.original_name_scope, outputs) - - -@add_arg_scope -def pad2d(inputs, - pad=(0, 0), - mode='CONSTANT', - data_format='NHWC', - trainable=True, - scope=None): - """2D Padding layer, adding a symmetric padding to H and W dimensions. - - Aims to mimic padding in Caffe and MXNet, helping the port of models to - TensorFlow. Tries to follow the naming convention of `tf.contrib.layers`. - - Args: - inputs: 4D input Tensor; - pad: 2-Tuple with padding values for H and W dimensions; - mode: Padding mode. C.f. `tf.pad` - data_format: NHWC or NCHW data format. - """ - with tf.name_scope(scope, 'pad2d', [inputs]): - # Padding shape. - if data_format == 'NHWC': - paddings = [[0, 0], [pad[0], pad[0]], [pad[1], pad[1]], [0, 0]] - elif data_format == 'NCHW': - paddings = [[0, 0], [0, 0], [pad[0], pad[0]], [pad[1], pad[1]]] - net = tf.pad(inputs, paddings, mode=mode) - return net - - -@add_arg_scope -def channel_to_last(inputs, - data_format='NHWC', - scope=None): - """Move the channel axis to the last dimension. Allows to - provide a single output format whatever the input data format. - - Args: - inputs: Input Tensor; - data_format: NHWC or NCHW. - Return: - Input in NHWC format. - """ - with tf.name_scope(scope, 'channel_to_last', [inputs]): - if data_format == 'NHWC': - net = inputs - elif data_format == 'NCHW': - net = tf.transpose(inputs, perm=(0, 2, 3, 1)) - return net diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/np_methods.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/np_methods.py deleted file mode 100644 index 7a021aa4..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/np_methods.py +++ /dev/null @@ -1,252 +0,0 @@ -# Copyright 2017 Paul Balanca. 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. -# ============================================================================== -"""Additional Numpy methods. Big mess of many things! -""" -import numpy as np - - -# =========================================================================== # -# Numpy implementations of SSD boxes functions. -# =========================================================================== # -def ssd_bboxes_decode(feat_localizations, - anchor_bboxes, - prior_scaling=[0.1, 0.1, 0.2, 0.2]): - """Compute the relative bounding boxes from the layer features and - reference anchor bounding boxes. - - Return: - numpy array Nx4: ymin, xmin, ymax, xmax - """ - # Reshape for easier broadcasting. - l_shape = feat_localizations.shape - feat_localizations = np.reshape(feat_localizations, - (-1, l_shape[-2], l_shape[-1])) - yref, xref, href, wref = anchor_bboxes - xref = np.reshape(xref, [-1, 1]) - yref = np.reshape(yref, [-1, 1]) - - # Compute center, height and width - cx = feat_localizations[:, :, 0] * wref * prior_scaling[0] + xref - cy = feat_localizations[:, :, 1] * href * prior_scaling[1] + yref - w = wref * np.exp(feat_localizations[:, :, 2] * prior_scaling[2]) - h = href * np.exp(feat_localizations[:, :, 3] * prior_scaling[3]) - # bboxes: ymin, xmin, xmax, ymax. - bboxes = np.zeros_like(feat_localizations) - bboxes[:, :, 0] = cy - h / 2. - bboxes[:, :, 1] = cx - w / 2. - bboxes[:, :, 2] = cy + h / 2. - bboxes[:, :, 3] = cx + w / 2. - # Back to original shape. - bboxes = np.reshape(bboxes, l_shape) - return bboxes - - -def ssd_bboxes_select_layer(predictions_layer, - localizations_layer, - anchors_layer, - select_threshold=0.5, - img_shape=(300, 300), - num_classes=21, - decode=True): - """Extract classes, scores and bounding boxes from features in one layer. - - Return: - classes, scores, bboxes: Numpy arrays... - """ - # First decode localizations features if necessary. - if decode: - localizations_layer = ssd_bboxes_decode(localizations_layer, anchors_layer) - - # Reshape features to: Batches x N x N_labels | 4. - p_shape = predictions_layer.shape - batch_size = p_shape[0] if len(p_shape) == 5 else 1 - predictions_layer = np.reshape(predictions_layer, - (batch_size, -1, p_shape[-1])) - l_shape = localizations_layer.shape - localizations_layer = np.reshape(localizations_layer, - (batch_size, -1, l_shape[-1])) - - # Boxes selection: use threshold or score > no-label criteria. - if select_threshold is None or select_threshold == 0: - # Class prediction and scores: assign 0. to 0-class - classes = np.argmax(predictions_layer, axis=2) - scores = np.amax(predictions_layer, axis=2) - mask = (classes > 0) - classes = classes[mask] - scores = scores[mask] - bboxes = localizations_layer[mask] - else: - sub_predictions = predictions_layer[:, :, 1:] - idxes = np.where(sub_predictions > select_threshold) - classes = idxes[-1]+1 - scores = sub_predictions[idxes] - bboxes = localizations_layer[idxes[:-1]] - - return classes, scores, bboxes - - -def ssd_bboxes_select(predictions_net, - localizations_net, - anchors_net, - select_threshold=0.5, - img_shape=(300, 300), - num_classes=21, - decode=True): - """Extract classes, scores and bounding boxes from network output layers. - - Return: - classes, scores, bboxes: Numpy arrays... - """ - l_classes = [] - l_scores = [] - l_bboxes = [] - # l_layers = [] - # l_idxes = [] - for i in range(len(predictions_net)): - classes, scores, bboxes = ssd_bboxes_select_layer( - predictions_net[i], localizations_net[i], anchors_net[i], - select_threshold, img_shape, num_classes, decode) - l_classes.append(classes) - l_scores.append(scores) - l_bboxes.append(bboxes) - # Debug information. - # l_layers.append(i) - # l_idxes.append((i, idxes)) - - classes = np.concatenate(l_classes, 0) - scores = np.concatenate(l_scores, 0) - bboxes = np.concatenate(l_bboxes, 0) - return classes, scores, bboxes - - -# =========================================================================== # -# Common functions for bboxes handling and selection. -# =========================================================================== # -def bboxes_sort(classes, scores, bboxes, top_k=400): - """Sort bounding boxes by decreasing order and keep only the top_k - """ - # if priority_inside: - # inside = (bboxes[:, 0] > margin) & (bboxes[:, 1] > margin) & \ - # (bboxes[:, 2] < 1-margin) & (bboxes[:, 3] < 1-margin) - # idxes = np.argsort(-scores) - # inside = inside[idxes] - # idxes = np.concatenate([idxes[inside], idxes[~inside]]) - idxes = np.argsort(-scores) - classes = classes[idxes][:top_k] - scores = scores[idxes][:top_k] - bboxes = bboxes[idxes][:top_k] - return classes, scores, bboxes - - -def bboxes_clip(bbox_ref, bboxes): - """Clip bounding boxes with respect to reference bbox. - """ - bboxes = np.copy(bboxes) - bboxes = np.transpose(bboxes) - bbox_ref = np.transpose(bbox_ref) - bboxes[0] = np.maximum(bboxes[0], bbox_ref[0]) - bboxes[1] = np.maximum(bboxes[1], bbox_ref[1]) - bboxes[2] = np.minimum(bboxes[2], bbox_ref[2]) - bboxes[3] = np.minimum(bboxes[3], bbox_ref[3]) - bboxes = np.transpose(bboxes) - return bboxes - - -def bboxes_resize(bbox_ref, bboxes): - """Resize bounding boxes based on a reference bounding box, - assuming that the latter is [0, 0, 1, 1] after transform. - """ - bboxes = np.copy(bboxes) - # Translate. - bboxes[:, 0] -= bbox_ref[0] - bboxes[:, 1] -= bbox_ref[1] - bboxes[:, 2] -= bbox_ref[0] - bboxes[:, 3] -= bbox_ref[1] - # Resize. - resize = [bbox_ref[2] - bbox_ref[0], bbox_ref[3] - bbox_ref[1]] - bboxes[:, 0] /= resize[0] - bboxes[:, 1] /= resize[1] - bboxes[:, 2] /= resize[0] - bboxes[:, 3] /= resize[1] - return bboxes - - -def bboxes_jaccard(bboxes1, bboxes2): - """Computing jaccard index between bboxes1 and bboxes2. - Note: bboxes1 and bboxes2 can be multi-dimensional, but should broacastable. - """ - bboxes1 = np.transpose(bboxes1) - bboxes2 = np.transpose(bboxes2) - # Intersection bbox and volume. - int_ymin = np.maximum(bboxes1[0], bboxes2[0]) - int_xmin = np.maximum(bboxes1[1], bboxes2[1]) - int_ymax = np.minimum(bboxes1[2], bboxes2[2]) - int_xmax = np.minimum(bboxes1[3], bboxes2[3]) - - int_h = np.maximum(int_ymax - int_ymin, 0.) - int_w = np.maximum(int_xmax - int_xmin, 0.) - int_vol = int_h * int_w - # Union volume. - vol1 = (bboxes1[2] - bboxes1[0]) * (bboxes1[3] - bboxes1[1]) - vol2 = (bboxes2[2] - bboxes2[0]) * (bboxes2[3] - bboxes2[1]) - jaccard = int_vol / (vol1 + vol2 - int_vol) - return jaccard - - -def bboxes_intersection(bboxes_ref, bboxes2): - """Computing jaccard index between bboxes1 and bboxes2. - Note: bboxes1 and bboxes2 can be multi-dimensional, but should broacastable. - """ - bboxes_ref = np.transpose(bboxes_ref) - bboxes2 = np.transpose(bboxes2) - # Intersection bbox and volume. - int_ymin = np.maximum(bboxes_ref[0], bboxes2[0]) - int_xmin = np.maximum(bboxes_ref[1], bboxes2[1]) - int_ymax = np.minimum(bboxes_ref[2], bboxes2[2]) - int_xmax = np.minimum(bboxes_ref[3], bboxes2[3]) - - int_h = np.maximum(int_ymax - int_ymin, 0.) - int_w = np.maximum(int_xmax - int_xmin, 0.) - int_vol = int_h * int_w - # Union volume. - vol = (bboxes_ref[2] - bboxes_ref[0]) * (bboxes_ref[3] - bboxes_ref[1]) - score = int_vol / vol - return score - - -def bboxes_nms(classes, scores, bboxes, nms_threshold=0.45): - """Apply non-maximum selection to bounding boxes. - """ - keep_bboxes = np.ones(scores.shape, dtype=np.bool) - for i in range(scores.size-1): - if keep_bboxes[i]: - # Computer overlap with bboxes which are following. - overlap = bboxes_jaccard(bboxes[i], bboxes[(i+1):]) - # Overlap threshold for keeping + checking part of the same class - keep_overlap = np.logical_or(overlap < nms_threshold, classes[(i+1):] != classes[i]) - keep_bboxes[(i+1):] = np.logical_and(keep_bboxes[(i+1):], keep_overlap) - - idxes = np.where(keep_bboxes) - return classes[idxes], scores[idxes], bboxes[idxes] - - -def bboxes_nms_fast(classes, scores, bboxes, threshold=0.45): - """Apply non-maximum selection to bounding boxes. - """ - pass - - - - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/ssd_common.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/ssd_common.py deleted file mode 100644 index 80896452..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/ssd_common.py +++ /dev/null @@ -1,408 +0,0 @@ -# Copyright 2015 Paul Balanca. 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. -# ============================================================================== -"""Shared function between different SSD implementations. -""" -import numpy as np -import tensorflow as tf -import tfextended as tfe - - -# =========================================================================== # -# TensorFlow implementation of boxes SSD encoding / decoding. -# =========================================================================== # -def tf_ssd_bboxes_encode_layer(labels, - bboxes, - anchors_layer, - num_classes, - ignore_threshold=0.5, - prior_scaling=[0.1, 0.1, 0.2, 0.2], - dtype=tf.float32): - """Encode groundtruth labels and bounding boxes using SSD anchors from - one layer. - - Arguments: - labels: 1D Tensor(int64) containing groundtruth labels; - bboxes: Nx4 Tensor(float) with bboxes relative coordinates; - anchors_layer: Numpy array with layer anchors; - matching_threshold: Threshold for positive match with groundtruth bboxes; - prior_scaling: Scaling of encoded coordinates. - - Return: - (target_labels, target_localizations, target_scores): Target Tensors. - """ - # Anchors coordinates and volume. - yref, xref, href, wref = anchors_layer - ymin = yref - href / 2. - xmin = xref - wref / 2. - ymax = yref + href / 2. - xmax = xref + wref / 2. - vol_anchors = (xmax - xmin) * (ymax - ymin) - - # Initialize tensors... - shape = (yref.shape[0], yref.shape[1], href.size) - feat_labels = tf.zeros(shape, dtype=tf.int64) - feat_scores = tf.zeros(shape, dtype=dtype) - - feat_ymin = tf.zeros(shape, dtype=dtype) - feat_xmin = tf.zeros(shape, dtype=dtype) - feat_ymax = tf.ones(shape, dtype=dtype) - feat_xmax = tf.ones(shape, dtype=dtype) - - def jaccard_with_anchors(bbox): - """Compute jaccard score between a box and the anchors. - """ - int_ymin = tf.maximum(ymin, bbox[0]) - int_xmin = tf.maximum(xmin, bbox[1]) - int_ymax = tf.minimum(ymax, bbox[2]) - int_xmax = tf.minimum(xmax, bbox[3]) - h = tf.maximum(int_ymax - int_ymin, 0.) - w = tf.maximum(int_xmax - int_xmin, 0.) - # Volumes. - inter_vol = h * w - union_vol = vol_anchors - inter_vol \ - + (bbox[2] - bbox[0]) * (bbox[3] - bbox[1]) - jaccard = tf.divide(inter_vol, union_vol) - return jaccard - - def intersection_with_anchors(bbox): - """Compute intersection between score a box and the anchors. - """ - int_ymin = tf.maximum(ymin, bbox[0]) - int_xmin = tf.maximum(xmin, bbox[1]) - int_ymax = tf.minimum(ymax, bbox[2]) - int_xmax = tf.minimum(xmax, bbox[3]) - h = tf.maximum(int_ymax - int_ymin, 0.) - w = tf.maximum(int_xmax - int_xmin, 0.) - inter_vol = h * w - scores = tf.divide(inter_vol, vol_anchors) - return scores - - def condition(i, feat_labels, feat_scores, - feat_ymin, feat_xmin, feat_ymax, feat_xmax): - """Condition: check label index. - """ - r = tf.less(i, tf.shape(labels)) - return r[0] - - def body(i, feat_labels, feat_scores, - feat_ymin, feat_xmin, feat_ymax, feat_xmax): - """Body: update feature labels, scores and bboxes. - Follow the original SSD paper for that purpose: - - assign values when jaccard > 0.5; - - only update if beat the score of other bboxes. - """ - # Jaccard score. - label = labels[i] - bbox = bboxes[i] - jaccard = jaccard_with_anchors(bbox) - # Mask: check threshold + scores + no annotations + num_classes. - mask = tf.greater(jaccard, feat_scores) - # mask = tf.logical_and(mask, tf.greater(jaccard, matching_threshold)) - mask = tf.logical_and(mask, feat_scores > -0.5) - mask = tf.logical_and(mask, label < num_classes) - imask = tf.cast(mask, tf.int64) - fmask = tf.cast(mask, dtype) - # Update values using mask. - feat_labels = imask * label + (1 - imask) * feat_labels - feat_scores = tf.where(mask, jaccard, feat_scores) - - feat_ymin = fmask * bbox[0] + (1 - fmask) * feat_ymin - feat_xmin = fmask * bbox[1] + (1 - fmask) * feat_xmin - feat_ymax = fmask * bbox[2] + (1 - fmask) * feat_ymax - feat_xmax = fmask * bbox[3] + (1 - fmask) * feat_xmax - - # Check no annotation label: ignore these anchors... - # interscts = intersection_with_anchors(bbox) - # mask = tf.logical_and(interscts > ignore_threshold, - # label == no_annotation_label) - # # Replace scores by -1. - # feat_scores = tf.where(mask, -tf.cast(mask, dtype), feat_scores) - - return [i+1, feat_labels, feat_scores, - feat_ymin, feat_xmin, feat_ymax, feat_xmax] - # Main loop definition. - i = 0 - [i, feat_labels, feat_scores, - feat_ymin, feat_xmin, - feat_ymax, feat_xmax] = tf.while_loop(condition, body, - [i, feat_labels, feat_scores, - feat_ymin, feat_xmin, - feat_ymax, feat_xmax]) - # Transform to center / size. - feat_cy = (feat_ymax + feat_ymin) / 2. - feat_cx = (feat_xmax + feat_xmin) / 2. - feat_h = feat_ymax - feat_ymin - feat_w = feat_xmax - feat_xmin - # Encode features. - feat_cy = (feat_cy - yref) / href / prior_scaling[0] - feat_cx = (feat_cx - xref) / wref / prior_scaling[1] - feat_h = tf.log(feat_h / href) / prior_scaling[2] - feat_w = tf.log(feat_w / wref) / prior_scaling[3] - # Use SSD ordering: x / y / w / h instead of ours. - feat_localizations = tf.stack([feat_cx, feat_cy, feat_w, feat_h], axis=-1) - return feat_labels, feat_localizations, feat_scores - - -def tf_ssd_bboxes_encode(labels, - bboxes, - anchors, - num_classes, - ignore_threshold=0.5, - prior_scaling=[0.1, 0.1, 0.2, 0.2], - dtype=tf.float32, - scope='ssd_bboxes_encode'): - """Encode groundtruth labels and bounding boxes using SSD net anchors. - Encoding boxes for all feature layers. - - Arguments: - labels: 1D Tensor(int64) containing groundtruth labels; - bboxes: Nx4 Tensor(float) with bboxes relative coordinates; - anchors: List of Numpy array with layer anchors; - matching_threshold: Threshold for positive match with groundtruth bboxes; - prior_scaling: Scaling of encoded coordinates. - - Return: - (target_labels, target_localizations, target_scores): - Each element is a list of target Tensors. - """ - with tf.name_scope(scope): - target_labels = [] - target_localizations = [] - target_scores = [] - for i, anchors_layer in enumerate(anchors): - with tf.name_scope('bboxes_encode_block_%i' % i): - t_labels, t_loc, t_scores = \ - tf_ssd_bboxes_encode_layer(labels, bboxes, anchors_layer, - num_classes, - ignore_threshold, - prior_scaling, dtype) - target_labels.append(t_labels) - target_localizations.append(t_loc) - target_scores.append(t_scores) - return target_labels, target_localizations, target_scores - - -def tf_ssd_bboxes_decode_layer(feat_localizations, - anchors_layer, - prior_scaling=[0.1, 0.1, 0.2, 0.2]): - """Compute the relative bounding boxes from the layer features and - reference anchor bounding boxes. - - Arguments: - feat_localizations: Tensor containing localization features. - anchors: List of numpy array containing anchor boxes. - - Return: - Tensor Nx4: ymin, xmin, ymax, xmax - """ - yref, xref, href, wref = anchors_layer - - # Compute center, height and width - cx = feat_localizations[:, :, :, :, 0] * wref * prior_scaling[0] + xref - cy = feat_localizations[:, :, :, :, 1] * href * prior_scaling[1] + yref - w = wref * tf.exp(feat_localizations[:, :, :, :, 2] * prior_scaling[2]) - h = href * tf.exp(feat_localizations[:, :, :, :, 3] * prior_scaling[3]) - # Boxes coordinates. - ymin = cy - h / 2. - xmin = cx - w / 2. - ymax = cy + h / 2. - xmax = cx + w / 2. - bboxes = tf.stack([ymin, xmin, ymax, xmax], axis=-1) - return bboxes - - -def tf_ssd_bboxes_decode(feat_localizations, - anchors, - prior_scaling=[0.1, 0.1, 0.2, 0.2], - scope='ssd_bboxes_decode'): - """Compute the relative bounding boxes from the SSD net features and - reference anchors bounding boxes. - - Arguments: - feat_localizations: List of Tensors containing localization features. - anchors: List of numpy array containing anchor boxes. - - Return: - List of Tensors Nx4: ymin, xmin, ymax, xmax - """ - with tf.name_scope(scope): - bboxes = [] - for i, anchors_layer in enumerate(anchors): - bboxes.append( - tf_ssd_bboxes_decode_layer(feat_localizations[i], - anchors_layer, - prior_scaling)) - return bboxes - - -# =========================================================================== # -# SSD boxes selection. -# =========================================================================== # -def tf_ssd_bboxes_select_layer(predictions_layer, localizations_layer, - select_threshold=None, - num_classes=21, - ignore_class=0, - scope=None): - """Extract classes, scores and bounding boxes from features in one layer. - Batch-compatible: inputs are supposed to have batch-type shapes. - - Args: - predictions_layer: A SSD prediction layer; - localizations_layer: A SSD localization layer; - select_threshold: Classification threshold for selecting a box. All boxes - under the threshold are set to 'zero'. If None, no threshold applied. - Return: - d_scores, d_bboxes: Dictionary of scores and bboxes Tensors of - size Batches X N x 1 | 4. Each key corresponding to a class. - """ - select_threshold = 0.0 if select_threshold is None else select_threshold - with tf.name_scope(scope, 'ssd_bboxes_select_layer', - [predictions_layer, localizations_layer]): - # Reshape features: Batches x N x N_labels | 4 - p_shape = tfe.get_shape(predictions_layer) - predictions_layer = tf.reshape(predictions_layer, - tf.stack([p_shape[0], -1, p_shape[-1]])) - l_shape = tfe.get_shape(localizations_layer) - localizations_layer = tf.reshape(localizations_layer, - tf.stack([l_shape[0], -1, l_shape[-1]])) - - d_scores = {} - d_bboxes = {} - for c in range(0, num_classes): - if c != ignore_class: - # Remove boxes under the threshold. - scores = predictions_layer[:, :, c] - fmask = tf.cast(tf.greater_equal(scores, select_threshold), scores.dtype) - scores = scores * fmask - bboxes = localizations_layer * tf.expand_dims(fmask, axis=-1) - # Append to dictionary. - d_scores[c] = scores - d_bboxes[c] = bboxes - - return d_scores, d_bboxes - - -def tf_ssd_bboxes_select(predictions_net, localizations_net, - select_threshold=None, - num_classes=21, - ignore_class=0, - scope=None): - """Extract classes, scores and bounding boxes from network output layers. - Batch-compatible: inputs are supposed to have batch-type shapes. - - Args: - predictions_net: List of SSD prediction layers; - localizations_net: List of localization layers; - select_threshold: Classification threshold for selecting a box. All boxes - under the threshold are set to 'zero'. If None, no threshold applied. - Return: - d_scores, d_bboxes: Dictionary of scores and bboxes Tensors of - size Batches X N x 1 | 4. Each key corresponding to a class. - """ - with tf.name_scope(scope, 'ssd_bboxes_select', - [predictions_net, localizations_net]): - l_scores = [] - l_bboxes = [] - for i in range(len(predictions_net)): - scores, bboxes = tf_ssd_bboxes_select_layer(predictions_net[i], - localizations_net[i], - select_threshold, - num_classes, - ignore_class) - l_scores.append(scores) - l_bboxes.append(bboxes) - # Concat results. - d_scores = {} - d_bboxes = {} - for c in l_scores[0].keys(): - ls = [s[c] for s in l_scores] - lb = [b[c] for b in l_bboxes] - d_scores[c] = tf.concat(ls, axis=1) - d_bboxes[c] = tf.concat(lb, axis=1) - return d_scores, d_bboxes - - -def tf_ssd_bboxes_select_layer_all_classes(predictions_layer, localizations_layer, - select_threshold=None): - """Extract classes, scores and bounding boxes from features in one layer. - Batch-compatible: inputs are supposed to have batch-type shapes. - - Args: - predictions_layer: A SSD prediction layer; - localizations_layer: A SSD localization layer; - select_threshold: Classification threshold for selecting a box. If None, - select boxes whose classification score is higher than 'no class'. - Return: - classes, scores, bboxes: Input Tensors. - """ - # Reshape features: Batches x N x N_labels | 4 - p_shape = tfe.get_shape(predictions_layer) - predictions_layer = tf.reshape(predictions_layer, - tf.stack([p_shape[0], -1, p_shape[-1]])) - l_shape = tfe.get_shape(localizations_layer) - localizations_layer = tf.reshape(localizations_layer, - tf.stack([l_shape[0], -1, l_shape[-1]])) - # Boxes selection: use threshold or score > no-label criteria. - if select_threshold is None or select_threshold == 0: - # Class prediction and scores: assign 0. to 0-class - classes = tf.argmax(predictions_layer, axis=2) - scores = tf.reduce_max(predictions_layer, axis=2) - scores = scores * tf.cast(classes > 0, scores.dtype) - else: - sub_predictions = predictions_layer[:, :, 1:] - classes = tf.argmax(sub_predictions, axis=2) + 1 - scores = tf.reduce_max(sub_predictions, axis=2) - # Only keep predictions higher than threshold. - mask = tf.greater(scores, select_threshold) - classes = classes * tf.cast(mask, classes.dtype) - scores = scores * tf.cast(mask, scores.dtype) - # Assume localization layer already decoded. - bboxes = localizations_layer - return classes, scores, bboxes - - -def tf_ssd_bboxes_select_all_classes(predictions_net, localizations_net, - select_threshold=None, - scope=None): - """Extract classes, scores and bounding boxes from network output layers. - Batch-compatible: inputs are supposed to have batch-type shapes. - - Args: - predictions_net: List of SSD prediction layers; - localizations_net: List of localization layers; - select_threshold: Classification threshold for selecting a box. If None, - select boxes whose classification score is higher than 'no class'. - Return: - classes, scores, bboxes: Tensors. - """ - with tf.name_scope(scope, 'ssd_bboxes_select', - [predictions_net, localizations_net]): - l_classes = [] - l_scores = [] - l_bboxes = [] - for i in range(len(predictions_net)): - classes, scores, bboxes = \ - tf_ssd_bboxes_select_layer_all_classes(predictions_net[i], - localizations_net[i], - select_threshold) - l_classes.append(classes) - l_scores.append(scores) - l_bboxes.append(bboxes) - - classes = tf.concat(l_classes, axis=1) - scores = tf.concat(l_scores, axis=1) - bboxes = tf.concat(l_bboxes, axis=1) - return classes, scores, bboxes - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/ssd_vgg_300.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/ssd_vgg_300.py deleted file mode 100644 index 0b5d63ef..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/model/ssd_vgg_300.py +++ /dev/null @@ -1,660 +0,0 @@ -# Copyright 2016 Paul Balanca. 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. -# ============================================================================== -"""Definition of 300 VGG-based SSD network. - -This model was initially introduced in: -SSD: Single Shot MultiBox Detector -Wei Liu, Dragomir Anguelov, Dumitru Erhan, Christian Szegedy, Scott Reed, -Cheng-Yang Fu, Alexander C. Berg -https://arxiv.org/abs/1512.02325 - -Two variants of the model are defined: the 300x300 and 512x512 models, the -latter obtaining a slightly better accuracy on Pascal VOC. - -Usage: - with slim.arg_scope(ssd_vgg.ssd_vgg()): - outputs, end_points = ssd_vgg.ssd_vgg(inputs) - -This network port of the original Caffe model. The padding in TF and Caffe -is slightly different, and can lead to severe accuracy drop if not taken care -in a correct way! - -In Caffe, the output size of convolution and pooling layers are computing as -following: h_o = (h_i + 2 * pad_h - kernel_h) / stride_h + 1 - -Nevertheless, there is a subtle difference between both for stride > 1. In -the case of convolution: - top_size = floor((bottom_size + 2*pad - kernel_size) / stride) + 1 -whereas for pooling: - top_size = ceil((bottom_size + 2*pad - kernel_size) / stride) + 1 -Hence implicitely allowing some additional padding even if pad = 0. This -behaviour explains why pooling with stride and kernel of size 2 are behaving -the same way in TensorFlow and Caffe. - -Nevertheless, this is not the case anymore for other kernel sizes, hence -motivating the use of special padding layer for controlling these side-effects. - -@@ssd_vgg_300 -""" -import math -from collections import namedtuple - -import numpy as np -import tensorflow as tf - -import tfextended as tfe -from model import custom_layers, ssd_common - -slim = tf.contrib.slim - - -# =========================================================================== # -# SSD class definition. -# =========================================================================== # -SSDParams = namedtuple('SSDParameters', ['img_shape', - 'num_classes', - 'no_annotation_label', - 'feat_layers', - 'feat_shapes', - 'anchor_size_bounds', - 'anchor_sizes', - 'anchor_ratios', - 'anchor_steps', - 'anchor_offset', - 'normalizations', - 'prior_scaling' - ]) - - -class SSDNet(object): - """Implementation of the SSD VGG-based 300 network. - - The default features layers with 300x300 image input are: - conv4 ==> 38 x 38 - conv7 ==> 19 x 19 - conv8 ==> 10 x 10 - conv9 ==> 5 x 5 - conv10 ==> 3 x 3 - conv11 ==> 1 x 1 - The default image size used to train this network is 300x300. - """ - default_params = SSDParams( - img_shape=(300, 300), - num_classes=21, - no_annotation_label=21, - feat_layers=['block4', 'block7', 'block8', 'block9', 'block10', 'block11'], - feat_shapes=[(37, 37), (19, 19), (10, 10), (5, 5), (3, 3), (1, 1)], - anchor_size_bounds=[0.15, 0.90], - # anchor_size_bounds=[0.20, 0.90], - anchor_sizes=[(21., 45.), - (45., 99.), - (99., 153.), - (153., 207.), - (207., 261.), - (261., 315.)], - # anchor_sizes=[(30., 60.), - # (60., 111.), - # (111., 162.), - # (162., 213.), - # (213., 264.), - # (264., 315.)], - anchor_ratios=[[2, .5], - [2, .5, 3, 1./3], - [2, .5, 3, 1./3], - [2, .5, 3, 1./3], - [2, .5], - [2, .5]], - anchor_steps=[8, 16, 32, 64, 100, 300], - anchor_offset=0.5, - normalizations=[20, -1, -1, -1, -1, -1], - prior_scaling=[0.1, 0.1, 0.2, 0.2] - ) - - def __init__(self, params=None): - """Init the SSD net with some parameters. Use the default ones - if none provided. - """ - if isinstance(params, SSDParams): - self.params = params - else: - self.params = SSDNet.default_params - - # ======================================================================= # - def net(self, inputs, - is_training=True, - update_feat_shapes=True, - dropout_keep_prob=0.5, - prediction_fn=slim.softmax, - reuse=None, - scope='ssd_300_vgg'): - """SSD network definition. - """ - r = ssd_net(inputs, - num_classes=self.params.num_classes, - feat_layers=self.params.feat_layers, - anchor_sizes=self.params.anchor_sizes, - anchor_ratios=self.params.anchor_ratios, - normalizations=self.params.normalizations, - is_training=is_training, - dropout_keep_prob=dropout_keep_prob, - prediction_fn=prediction_fn, - reuse=reuse, - scope=scope) - # Update feature shapes (try at least!) - if update_feat_shapes: - shapes = ssd_feat_shapes_from_net(r[0], self.params.feat_shapes) - self.params = self.params._replace(feat_shapes=shapes) - return r - - def arg_scope(self, weight_decay=0.0005, data_format='NHWC'): - """Network arg_scope. - """ - return ssd_arg_scope(weight_decay, data_format=data_format) - - def arg_scope_caffe(self, caffe_scope): - """Caffe arg_scope used for weights importing. - """ - return ssd_arg_scope_caffe(caffe_scope) - - # ======================================================================= # - def update_feature_shapes(self, predictions): - """Update feature shapes from predictions collection (Tensor or Numpy - array). - """ - shapes = ssd_feat_shapes_from_net(predictions, self.params.feat_shapes) - self.params = self.params._replace(feat_shapes=shapes) - - def anchors(self, img_shape, dtype=np.float32): - """Compute the default anchor boxes, given an image shape. - """ - return ssd_anchors_all_layers(img_shape, - self.params.feat_shapes, - self.params.anchor_sizes, - self.params.anchor_ratios, - self.params.anchor_steps, - self.params.anchor_offset, - dtype) - - def bboxes_encode(self, labels, bboxes, anchors, - scope=None): - """Encode labels and bounding boxes. - """ - return ssd_common.tf_ssd_bboxes_encode( - labels, bboxes, anchors, - self.params.num_classes, - ignore_threshold=0.5, - prior_scaling=self.params.prior_scaling, - scope=scope) - - def bboxes_decode(self, feat_localizations, anchors, - scope='ssd_bboxes_decode'): - """Encode labels and bounding boxes. - """ - return ssd_common.tf_ssd_bboxes_decode( - feat_localizations, anchors, - prior_scaling=self.params.prior_scaling, - scope=scope) - - def detected_bboxes(self, predictions, localisations, - select_threshold=None, nms_threshold=0.5, - clipping_bbox=None, top_k=400, keep_top_k=200): - """Get the detected bounding boxes from the SSD network output. - """ - # Select top_k bboxes from predictions, and clip - rscores, rbboxes = \ - ssd_common.tf_ssd_bboxes_select(predictions, localisations, - select_threshold=select_threshold, - num_classes=self.params.num_classes) - rscores, rbboxes = \ - tfe.bboxes_sort(rscores, rbboxes, top_k=top_k) - # Apply NMS algorithm. - rscores, rbboxes = \ - tfe.bboxes_nms_batch(rscores, rbboxes, - nms_threshold=nms_threshold, - keep_top_k=keep_top_k) - if clipping_bbox is not None: - rbboxes = tfe.bboxes_clip(clipping_bbox, rbboxes) - return rscores, rbboxes - - def losses(self, logits, localisations, - gclasses, glocalisations, gscores, - match_threshold=0.5, - negative_ratio=3., - alpha=1., - label_smoothing=0., - scope='ssd_losses'): - """Define the SSD network losses. - """ - return ssd_losses(logits, localisations, - gclasses, glocalisations, gscores, - match_threshold=match_threshold, - negative_ratio=negative_ratio, - alpha=alpha, - label_smoothing=label_smoothing, - scope=scope) - - -# =========================================================================== # -# SSD tools... -# =========================================================================== # -def ssd_size_bounds_to_values(size_bounds, - n_feat_layers, - img_shape=(300, 300)): - """Compute the reference sizes of the anchor boxes from relative bounds. - The absolute values are measured in pixels, based on the network - default size (300 pixels). - - This function follows the computation performed in the original - implementation of SSD in Caffe. - - Return: - list of list containing the absolute sizes at each scale. For each scale, - the ratios only apply to the first value. - """ - assert img_shape[0] == img_shape[1] - - img_size = img_shape[0] - min_ratio = int(size_bounds[0] * 100) - max_ratio = int(size_bounds[1] * 100) - step = int(math.floor((max_ratio - min_ratio) / (n_feat_layers - 2))) - # Start with the following smallest sizes. - sizes = [[img_size * size_bounds[0] / 2, img_size * size_bounds[0]]] - for ratio in range(min_ratio, max_ratio + 1, step): - sizes.append((img_size * ratio / 100., - img_size * (ratio + step) / 100.)) - return sizes - - -def ssd_feat_shapes_from_net(predictions, default_shapes=None): - """Try to obtain the feature shapes from the prediction layers. The latter - can be either a Tensor or Numpy ndarray. - - Return: - list of feature shapes. Default values if predictions shape not fully - determined. - """ - feat_shapes = [] - for l in predictions: - # Get the shape, from either a np array or a tensor. - if isinstance(l, np.ndarray): - shape = l.shape - else: - shape = l.get_shape().as_list() - shape = shape[1:4] - # Problem: undetermined shape... - if None in shape: - return default_shapes - else: - feat_shapes.append(shape) - return feat_shapes - - -def ssd_anchor_one_layer(img_shape, - feat_shape, - sizes, - ratios, - step, - offset=0.5, - dtype=np.float32): - """Computer SSD default anchor boxes for one feature layer. - - Determine the relative position grid of the centers, and the relative - width and height. - - Arguments: - feat_shape: Feature shape, used for computing relative position grids; - size: Absolute reference sizes; - ratios: Ratios to use on these features; - img_shape: Image shape, used for computing height, width relatively to the - former; - offset: Grid offset. - - Return: - y, x, h, w: Relative x and y grids, and height and width. - """ - # Compute the position grid: simple way. - # y, x = np.mgrid[0:feat_shape[0], 0:feat_shape[1]] - # y = (y.astype(dtype) + offset) / feat_shape[0] - # x = (x.astype(dtype) + offset) / feat_shape[1] - # Weird SSD-Caffe computation using steps values... - y, x = np.mgrid[0:feat_shape[0], 0:feat_shape[1]] - y = (y.astype(dtype) + offset) * step / img_shape[0] - x = (x.astype(dtype) + offset) * step / img_shape[1] - - # Expand dims to support easy broadcasting. - y = np.expand_dims(y, axis=-1) - x = np.expand_dims(x, axis=-1) - - # Compute relative height and width. - # Tries to follow the original implementation of SSD for the order. - num_anchors = len(sizes) + len(ratios) - h = np.zeros((num_anchors, ), dtype=dtype) - w = np.zeros((num_anchors, ), dtype=dtype) - # Add first anchor boxes with ratio=1. - h[0] = sizes[0] / img_shape[0] - w[0] = sizes[0] / img_shape[1] - di = 1 - if len(sizes) > 1: - h[1] = math.sqrt(sizes[0] * sizes[1]) / img_shape[0] - w[1] = math.sqrt(sizes[0] * sizes[1]) / img_shape[1] - di += 1 - for i, r in enumerate(ratios): - h[i+di] = sizes[0] / img_shape[0] / math.sqrt(r) - w[i+di] = sizes[0] / img_shape[1] * math.sqrt(r) - return y, x, h, w - - -def ssd_anchors_all_layers(img_shape, - layers_shape, - anchor_sizes, - anchor_ratios, - anchor_steps, - offset=0.5, - dtype=np.float32): - """Compute anchor boxes for all feature layers. - """ - layers_anchors = [] - for i, s in enumerate(layers_shape): - anchor_bboxes = ssd_anchor_one_layer(img_shape, s, - anchor_sizes[i], - anchor_ratios[i], - anchor_steps[i], - offset=offset, dtype=dtype) - layers_anchors.append(anchor_bboxes) - return layers_anchors - - -# =========================================================================== # -# Functional definition of VGG-based SSD 300. -# =========================================================================== # -def tensor_shape(x, rank=3): - """Returns the dimensions of a tensor. - Args: - image: A N-D Tensor of shape. - Returns: - A list of dimensions. Dimensions that are statically known are python - integers,otherwise they are integer scalar tensors. - """ - if x.get_shape().is_fully_defined(): - return x.get_shape().as_list() - else: - static_shape = x.get_shape().with_rank(rank).as_list() - dynamic_shape = tf.unstack(tf.shape(x), rank) - return [s if s is not None else d - for s, d in zip(static_shape, dynamic_shape)] - - -def ssd_multibox_layer(inputs, - num_classes, - sizes, - ratios=[1], - normalization=-1, - bn_normalization=False): - """Construct a multibox layer, return a class and localization predictions. - """ - net = inputs - if normalization > 0: - net = custom_layers.l2_normalization(net, scaling=True) - # Number of anchors. - num_anchors = len(sizes) + len(ratios) - - # Location. - num_loc_pred = num_anchors * 4 - loc_pred = slim.conv2d(net, num_loc_pred, [3, 3], activation_fn=None, - scope='conv_loc') - loc_pred = custom_layers.channel_to_last(loc_pred) - loc_pred = tf.reshape(loc_pred, - tensor_shape(loc_pred, 4)[:-1]+[num_anchors, 4]) - # Class prediction. - num_cls_pred = num_anchors * num_classes - cls_pred = slim.conv2d(net, num_cls_pred, [3, 3], activation_fn=None, - scope='conv_cls') - cls_pred = custom_layers.channel_to_last(cls_pred) - cls_pred = tf.reshape(cls_pred, - tensor_shape(cls_pred, 4)[:-1]+[num_anchors, num_classes]) - return cls_pred, loc_pred - - -def ssd_net(inputs, - num_classes=SSDNet.default_params.num_classes, - feat_layers=SSDNet.default_params.feat_layers, - anchor_sizes=SSDNet.default_params.anchor_sizes, - anchor_ratios=SSDNet.default_params.anchor_ratios, - normalizations=SSDNet.default_params.normalizations, - is_training=True, - dropout_keep_prob=0.5, - prediction_fn=slim.softmax, - reuse=None, - scope='ssd_300_vgg'): - """SSD net definition. - """ - # if data_format == 'NCHW': - # inputs = tf.transpose(inputs, perm=(0, 3, 1, 2)) - - # End_points collect relevant activations for external use. - end_points = {} - with tf.variable_scope(scope, 'ssd_300_vgg', [inputs], reuse=reuse): - # Original VGG-16 blocks. - net = slim.repeat(inputs, 2, slim.conv2d, 64, [3, 3], scope='conv1') - end_points['block1'] = net - net = slim.max_pool2d(net, [2, 2], scope='pool1') - # Block 2. - net = slim.repeat(net, 2, slim.conv2d, 128, [3, 3], scope='conv2') - end_points['block2'] = net - net = slim.max_pool2d(net, [2, 2], scope='pool2') - # Block 3. - net = slim.repeat(net, 3, slim.conv2d, 256, [3, 3], scope='conv3') - end_points['block3'] = net - net = slim.max_pool2d(net, [2, 2], scope='pool3') - # Block 4. - net = slim.repeat(net, 3, slim.conv2d, 512, [3, 3], scope='conv4') - end_points['block4'] = net - net = slim.max_pool2d(net, [2, 2], scope='pool4') - # Block 5. - net = slim.repeat(net, 3, slim.conv2d, 512, [3, 3], scope='conv5') - end_points['block5'] = net - net = slim.max_pool2d(net, [3, 3], stride=1, scope='pool5') - - # Additional SSD blocks. - # Block 6: let's dilate the hell out of it! - net = slim.conv2d(net, 1024, [3, 3], rate=6, scope='conv6') - end_points['block6'] = net - net = tf.layers.dropout(net, rate=dropout_keep_prob, training=is_training) - # Block 7: 1x1 conv. Because the fuck. - net = slim.conv2d(net, 1024, [1, 1], scope='conv7') - end_points['block7'] = net - net = tf.layers.dropout(net, rate=dropout_keep_prob, training=is_training) - - # Block 8/9/10/11: 1x1 and 3x3 convolutions stride 2 (except lasts). - end_point = 'block8' - with tf.variable_scope(end_point): - net = slim.conv2d(net, 256, [1, 1], scope='conv1x1') - net = custom_layers.pad2d(net, pad=(1, 1)) - net = slim.conv2d(net, 512, [3, 3], stride=2, scope='conv3x3', padding='VALID') - end_points[end_point] = net - end_point = 'block9' - with tf.variable_scope(end_point): - net = slim.conv2d(net, 128, [1, 1], scope='conv1x1') - net = custom_layers.pad2d(net, pad=(1, 1)) - net = slim.conv2d(net, 256, [3, 3], stride=2, scope='conv3x3', padding='VALID') - end_points[end_point] = net - end_point = 'block10' - with tf.variable_scope(end_point): - net = slim.conv2d(net, 128, [1, 1], scope='conv1x1') - net = slim.conv2d(net, 256, [3, 3], scope='conv3x3', padding='VALID') - end_points[end_point] = net - end_point = 'block11' - with tf.variable_scope(end_point): - net = slim.conv2d(net, 128, [1, 1], scope='conv1x1') - net = slim.conv2d(net, 256, [3, 3], scope='conv3x3', padding='VALID') - end_points[end_point] = net - - # Prediction and localisations layers. - predictions = [] - logits = [] - localisations = [] - for i, layer in enumerate(feat_layers): - with tf.variable_scope(layer + '_box'): - p, l = ssd_multibox_layer(end_points[layer], - num_classes, - anchor_sizes[i], - anchor_ratios[i], - normalizations[i]) - predictions.append(prediction_fn(p)) - logits.append(p) - localisations.append(l) - - return predictions, localisations, logits, end_points -ssd_net.default_image_size = 300 - - -def ssd_arg_scope(weight_decay=0.0005, data_format='NHWC'): - """Defines the VGG arg scope. - - Args: - weight_decay: The l2 regularization coefficient. - - Returns: - An arg_scope. - """ - with slim.arg_scope([slim.conv2d, slim.fully_connected], - activation_fn=tf.nn.relu, - weights_regularizer=slim.l2_regularizer(weight_decay), - weights_initializer=tf.contrib.layers.xavier_initializer(), - biases_initializer=tf.zeros_initializer()): - with slim.arg_scope([slim.conv2d, slim.max_pool2d], - padding='SAME', - data_format=data_format): - with slim.arg_scope([custom_layers.pad2d, - custom_layers.l2_normalization, - custom_layers.channel_to_last], - data_format=data_format) as sc: - return sc - - -# =========================================================================== # -# Caffe scope: importing weights at initialization. -# =========================================================================== # -def ssd_arg_scope_caffe(caffe_scope): - """Caffe scope definition. - - Args: - caffe_scope: Caffe scope object with loaded weights. - - Returns: - An arg_scope. - """ - # Default network arg scope. - with slim.arg_scope([slim.conv2d], - activation_fn=tf.nn.relu, - weights_initializer=caffe_scope.conv_weights_init(), - biases_initializer=caffe_scope.conv_biases_init()): - with slim.arg_scope([slim.fully_connected], - activation_fn=tf.nn.relu): - with slim.arg_scope([custom_layers.l2_normalization], - scale_initializer=caffe_scope.l2_norm_scale_init()): - with slim.arg_scope([slim.conv2d, slim.max_pool2d], - padding='SAME') as sc: - return sc - - -# =========================================================================== # -# SSD loss function. -# =========================================================================== # -def ssd_losses(logits, localisations, - gclasses, glocalisations, gscores, - match_threshold=0.5, - negative_ratio=3., - alpha=1., - label_smoothing=0., - device='/cpu:0', - scope=None): - with tf.name_scope(scope, 'ssd_losses'): - lshape = tfe.get_shape(logits[0], 5) - num_classes = lshape[-1] - batch_size = lshape[0] - - # Flatten out all vectors! - flogits = [] - fgclasses = [] - fgscores = [] - flocalisations = [] - fglocalisations = [] - for i in range(len(logits)): - flogits.append(tf.reshape(logits[i], [-1, num_classes])) - fgclasses.append(tf.reshape(gclasses[i], [-1])) - fgscores.append(tf.reshape(gscores[i], [-1])) - flocalisations.append(tf.reshape(localisations[i], [-1, 4])) - fglocalisations.append(tf.reshape(glocalisations[i], [-1, 4])) - # And concat the crap! - logits = tf.concat(flogits, axis=0) - gclasses = tf.concat(fgclasses, axis=0) - gscores = tf.concat(fgscores, axis=0) - localisations = tf.concat(flocalisations, axis=0) - glocalisations = tf.concat(fglocalisations, axis=0) - dtype = logits.dtype - - # Compute positive matching mask... - pmask = gscores > match_threshold - fpmask = tf.cast(pmask, dtype) - n_positives = tf.reduce_sum(fpmask) - - # Hard negative mining... - no_classes = tf.cast(pmask, tf.int32) - predictions = slim.softmax(logits) - nmask = tf.logical_and(tf.logical_not(pmask), - gscores > -0.5) - fnmask = tf.cast(nmask, dtype) - nvalues = tf.where(nmask, - predictions[:, 0], - 1. - fnmask) - nvalues_flat = tf.reshape(nvalues, [-1]) - # Number of negative entries to select. - max_neg_entries = tf.cast(tf.reduce_sum(fnmask), tf.int32) - n_neg = tf.cast(negative_ratio * n_positives, tf.int32) + batch_size - n_neg = tf.minimum(n_neg, max_neg_entries) - - val, idxes = tf.nn.top_k(-nvalues_flat, k=n_neg) - max_hard_pred = -val[-1] - # Final negative mask. - nmask = tf.logical_and(nmask, nvalues < max_hard_pred) - fnmask = tf.cast(nmask, dtype) - - batch_float = tf.cast(batch_size, tf.float32) - - # Add cross-entropy loss. - with tf.name_scope('cross_entropy_pos'): - cross_entropy_pos_loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, - labels=gclasses) - cross_entropy_pos_loss = tf.divide(tf.reduce_sum(cross_entropy_pos_loss * fpmask), batch_float, name='value') - tf.losses.add_loss(cross_entropy_pos_loss) - - with tf.name_scope('cross_entropy_neg'): - cross_entropy_neg_loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, - labels=no_classes) - cross_entropy_neg_loss = tf.divide(tf.reduce_sum(cross_entropy_neg_loss * fnmask), batch_float, name='value') - tf.losses.add_loss(cross_entropy_neg_loss) - - # Add localization loss: smooth L1, L2, ... - with tf.name_scope('localization'): - # Weights Tensor: positive mask + random negative. - weights = tf.expand_dims(alpha * fpmask, axis=-1) - localization_loss = custom_layers.abs_smooth(localisations - glocalisations) - localization_loss = tf.divide(tf.reduce_sum(localization_loss * weights), batch_float, name='value') - tf.losses.add_loss(localization_loss) - - regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) - all_losses = [cross_entropy_neg_loss, cross_entropy_pos_loss, localization_loss] + (regularization_losses if regularization_losses else []) - return tf.add_n(all_losses) \ No newline at end of file diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/__init__.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/__init__.py deleted file mode 100644 index 3ba75b6a..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2017 Paul Balanca. 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. -# ============================================================================== -"""TF Extended: additional metrics. -""" - -# pylint: disable=unused-import,line-too-long,g-importing-member,wildcard-import -from tfextended.metrics import * -from tfextended.tensors import * -from tfextended.bboxes import * -from tfextended.image import * -from tfextended.math import * - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/bboxes.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/bboxes.py deleted file mode 100644 index 0689b295..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/bboxes.py +++ /dev/null @@ -1,508 +0,0 @@ -# Copyright 2017 Paul Balanca. 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. -# ============================================================================== -"""TF Extended: additional bounding boxes methods. -""" -import numpy as np -import tensorflow as tf - -from tfextended import tensors as tfe_tensors -from tfextended import math as tfe_math - - -# =========================================================================== # -# Standard boxes algorithms. -# =========================================================================== # -def bboxes_sort_all_classes(classes, scores, bboxes, top_k=400, scope=None): - """Sort bounding boxes by decreasing order and keep only the top_k. - Assume the input Tensors mix-up objects with different classes. - Assume a batch-type input. - - Args: - classes: Batch x N Tensor containing integer classes. - scores: Batch x N Tensor containing float scores. - bboxes: Batch x N x 4 Tensor containing boxes coordinates. - top_k: Top_k boxes to keep. - Return: - classes, scores, bboxes: Sorted tensors of shape Batch x Top_k. - """ - with tf.name_scope(scope, 'bboxes_sort', [classes, scores, bboxes]): - scores, idxes = tf.nn.top_k(scores, k=top_k, sorted=True) - - # Trick to be able to use tf.gather: map for each element in the batch. - def fn_gather(classes, bboxes, idxes): - cl = tf.gather(classes, idxes) - bb = tf.gather(bboxes, idxes) - return [cl, bb] - r = tf.map_fn(lambda x: fn_gather(x[0], x[1], x[2]), - [classes, bboxes, idxes], - dtype=[classes.dtype, bboxes.dtype], - parallel_iterations=10, - back_prop=False, - swap_memory=False, - infer_shape=True) - classes = r[0] - bboxes = r[1] - return classes, scores, bboxes - - -def bboxes_sort(scores, bboxes, top_k=400, scope=None): - """Sort bounding boxes by decreasing order and keep only the top_k. - If inputs are dictionnaries, assume every key is a different class. - Assume a batch-type input. - - Args: - scores: Batch x N Tensor/Dictionary containing float scores. - bboxes: Batch x N x 4 Tensor/Dictionary containing boxes coordinates. - top_k: Top_k boxes to keep. - Return: - scores, bboxes: Sorted Tensors/Dictionaries of shape Batch x Top_k x 1|4. - """ - # Dictionaries as inputs. - if isinstance(scores, dict) or isinstance(bboxes, dict): - with tf.name_scope(scope, 'bboxes_sort_dict'): - d_scores = {} - d_bboxes = {} - for c in scores.keys(): - s, b = bboxes_sort(scores[c], bboxes[c], top_k=top_k) - d_scores[c] = s - d_bboxes[c] = b - return d_scores, d_bboxes - - # Tensors inputs. - with tf.name_scope(scope, 'bboxes_sort', [scores, bboxes]): - # Sort scores... - scores, idxes = tf.nn.top_k(scores, k=top_k, sorted=True) - - # Trick to be able to use tf.gather: map for each element in the first dim. - def fn_gather(bboxes, idxes): - bb = tf.gather(bboxes, idxes) - return [bb] - r = tf.map_fn(lambda x: fn_gather(x[0], x[1]), - [bboxes, idxes], - dtype=[bboxes.dtype], - parallel_iterations=10, - back_prop=False, - swap_memory=False, - infer_shape=True) - bboxes = r[0] - return scores, bboxes - - -def bboxes_clip(bbox_ref, bboxes, scope=None): - """Clip bounding boxes to a reference box. - Batch-compatible if the first dimension of `bbox_ref` and `bboxes` - can be broadcasted. - - Args: - bbox_ref: Reference bounding box. Nx4 or 4 shaped-Tensor; - bboxes: Bounding boxes to clip. Nx4 or 4 shaped-Tensor or dictionary. - Return: - Clipped bboxes. - """ - # Bboxes is dictionary. - if isinstance(bboxes, dict): - with tf.name_scope(scope, 'bboxes_clip_dict'): - d_bboxes = {} - for c in bboxes.keys(): - d_bboxes[c] = bboxes_clip(bbox_ref, bboxes[c]) - return d_bboxes - - # Tensors inputs. - with tf.name_scope(scope, 'bboxes_clip'): - # Easier with transposed bboxes. Especially for broadcasting. - bbox_ref = tf.transpose(bbox_ref) - bboxes = tf.transpose(bboxes) - # Intersection bboxes and reference bbox. - ymin = tf.maximum(bboxes[0], bbox_ref[0]) - xmin = tf.maximum(bboxes[1], bbox_ref[1]) - ymax = tf.minimum(bboxes[2], bbox_ref[2]) - xmax = tf.minimum(bboxes[3], bbox_ref[3]) - # Double check! Empty boxes when no-intersection. - ymin = tf.minimum(ymin, ymax) - xmin = tf.minimum(xmin, xmax) - bboxes = tf.transpose(tf.stack([ymin, xmin, ymax, xmax], axis=0)) - return bboxes - - -def bboxes_resize(bbox_ref, bboxes, name=None): - """Resize bounding boxes based on a reference bounding box, - assuming that the latter is [0, 0, 1, 1] after transform. Useful for - updating a collection of boxes after cropping an image. - """ - # Bboxes is dictionary. - if isinstance(bboxes, dict): - with tf.name_scope(name, 'bboxes_resize_dict'): - d_bboxes = {} - for c in bboxes.keys(): - d_bboxes[c] = bboxes_resize(bbox_ref, bboxes[c]) - return d_bboxes - - # Tensors inputs. - with tf.name_scope(name, 'bboxes_resize'): - # Translate. - v = tf.stack([bbox_ref[0], bbox_ref[1], bbox_ref[0], bbox_ref[1]]) - bboxes = bboxes - v - # Scale. - s = tf.stack([bbox_ref[2] - bbox_ref[0], - bbox_ref[3] - bbox_ref[1], - bbox_ref[2] - bbox_ref[0], - bbox_ref[3] - bbox_ref[1]]) - bboxes = bboxes / s - return bboxes - - -def bboxes_nms(scores, bboxes, nms_threshold=0.5, keep_top_k=200, scope=None): - """Apply non-maximum selection to bounding boxes. In comparison to TF - implementation, use classes information for matching. - Should only be used on single-entries. Use batch version otherwise. - - Args: - scores: N Tensor containing float scores. - bboxes: N x 4 Tensor containing boxes coordinates. - nms_threshold: Matching threshold in NMS algorithm; - keep_top_k: Number of total object to keep after NMS. - Return: - classes, scores, bboxes Tensors, sorted by score. - Padded with zero if necessary. - """ - with tf.name_scope(scope, 'bboxes_nms_single', [scores, bboxes]): - # Apply NMS algorithm. - idxes = tf.image.non_max_suppression(bboxes, scores, - keep_top_k, nms_threshold) - scores = tf.gather(scores, idxes) - bboxes = tf.gather(bboxes, idxes) - # Pad results. - scores = tfe_tensors.pad_axis(scores, 0, keep_top_k, axis=0) - bboxes = tfe_tensors.pad_axis(bboxes, 0, keep_top_k, axis=0) - return scores, bboxes - - -def bboxes_nms_batch(scores, bboxes, nms_threshold=0.5, keep_top_k=200, - scope=None): - """Apply non-maximum selection to bounding boxes. In comparison to TF - implementation, use classes information for matching. - Use only on batched-inputs. Use zero-padding in order to batch output - results. - - Args: - scores: Batch x N Tensor/Dictionary containing float scores. - bboxes: Batch x N x 4 Tensor/Dictionary containing boxes coordinates. - nms_threshold: Matching threshold in NMS algorithm; - keep_top_k: Number of total object to keep after NMS. - Return: - scores, bboxes Tensors/Dictionaries, sorted by score. - Padded with zero if necessary. - """ - # Dictionaries as inputs. - if isinstance(scores, dict) or isinstance(bboxes, dict): - with tf.name_scope(scope, 'bboxes_nms_batch_dict'): - d_scores = {} - d_bboxes = {} - for c in scores.keys(): - s, b = bboxes_nms_batch(scores[c], bboxes[c], - nms_threshold=nms_threshold, - keep_top_k=keep_top_k) - d_scores[c] = s - d_bboxes[c] = b - return d_scores, d_bboxes - - # Tensors inputs. - with tf.name_scope(scope, 'bboxes_nms_batch'): - r = tf.map_fn(lambda x: bboxes_nms(x[0], x[1], - nms_threshold, keep_top_k), - (scores, bboxes), - dtype=(scores.dtype, bboxes.dtype), - parallel_iterations=10, - back_prop=False, - swap_memory=False, - infer_shape=True) - scores, bboxes = r - return scores, bboxes - - -# def bboxes_fast_nms(classes, scores, bboxes, -# nms_threshold=0.5, eta=3., num_classes=21, -# pad_output=True, scope=None): -# with tf.name_scope(scope, 'bboxes_fast_nms', -# [classes, scores, bboxes]): - -# nms_classes = tf.zeros((0,), dtype=classes.dtype) -# nms_scores = tf.zeros((0,), dtype=scores.dtype) -# nms_bboxes = tf.zeros((0, 4), dtype=bboxes.dtype) - - -def bboxes_matching(label, scores, bboxes, - glabels, gbboxes, gdifficults, - matching_threshold=0.5, scope=None): - """Matching a collection of detected boxes with groundtruth values. - Does not accept batched-inputs. - The algorithm goes as follows: for every detected box, check - if one grountruth box is matching. If none, then considered as False Positive. - If the grountruth box is already matched with another one, it also counts - as a False Positive. We refer the Pascal VOC documentation for the details. - - Args: - rclasses, rscores, rbboxes: N(x4) Tensors. Detected objects, sorted by score; - glabels, gbboxes: Groundtruth bounding boxes. May be zero padded, hence - zero-class objects are ignored. - matching_threshold: Threshold for a positive match. - Return: Tuple of: - n_gbboxes: Scalar Tensor with number of groundtruth boxes (may difer from - size because of zero padding). - tp_match: (N,)-shaped boolean Tensor containing with True Positives. - fp_match: (N,)-shaped boolean Tensor containing with False Positives. - """ - with tf.name_scope(scope, 'bboxes_matching_single', - [scores, bboxes, glabels, gbboxes]): - rsize = tf.size(scores) - rshape = tf.shape(scores) - rlabel = tf.cast(label, glabels.dtype) - # Number of groundtruth boxes. - gdifficults = tf.cast(gdifficults, tf.bool) - n_gbboxes = tf.count_nonzero(tf.logical_and(tf.equal(glabels, label), - tf.logical_not(gdifficults))) - # Grountruth matching arrays. - gmatch = tf.zeros(tf.shape(glabels), dtype=tf.bool) - grange = tf.range(tf.size(glabels), dtype=tf.int32) - # True/False positive matching TensorArrays. - sdtype = tf.bool - ta_tp_bool = tf.TensorArray(sdtype, size=rsize, dynamic_size=False, infer_shape=True) - ta_fp_bool = tf.TensorArray(sdtype, size=rsize, dynamic_size=False, infer_shape=True) - - # Loop over returned objects. - def m_condition(i, ta_tp, ta_fp, gmatch): - r = tf.less(i, rsize) - return r - - def m_body(i, ta_tp, ta_fp, gmatch): - # Jaccard score with groundtruth bboxes. - rbbox = bboxes[i] - jaccard = bboxes_jaccard(rbbox, gbboxes) - jaccard = jaccard * tf.cast(tf.equal(glabels, rlabel), dtype=jaccard.dtype) - - # Best fit, checking it's above threshold. - idxmax = tf.cast(tf.argmax(jaccard, axis=0), tf.int32) - jcdmax = jaccard[idxmax] - match = jcdmax > matching_threshold - existing_match = gmatch[idxmax] - not_difficult = tf.logical_not(gdifficults[idxmax]) - - # TP: match & no previous match and FP: previous match | no match. - # If difficult: no record, i.e FP=False and TP=False. - tp = tf.logical_and(not_difficult, - tf.logical_and(match, tf.logical_not(existing_match))) - ta_tp = ta_tp.write(i, tp) - fp = tf.logical_and(not_difficult, - tf.logical_or(existing_match, tf.logical_not(match))) - ta_fp = ta_fp.write(i, fp) - # Update grountruth match. - mask = tf.logical_and(tf.equal(grange, idxmax), - tf.logical_and(not_difficult, match)) - gmatch = tf.logical_or(gmatch, mask) - - return [i+1, ta_tp, ta_fp, gmatch] - # Main loop definition. - i = 0 - [i, ta_tp_bool, ta_fp_bool, gmatch] = \ - tf.while_loop(m_condition, m_body, - [i, ta_tp_bool, ta_fp_bool, gmatch], - parallel_iterations=1, - back_prop=False) - # TensorArrays to Tensors and reshape. - tp_match = tf.reshape(ta_tp_bool.stack(), rshape) - fp_match = tf.reshape(ta_fp_bool.stack(), rshape) - - # Some debugging information... - # tp_match = tf.Print(tp_match, - # [n_gbboxes, - # tf.reduce_sum(tf.cast(tp_match, tf.int64)), - # tf.reduce_sum(tf.cast(fp_match, tf.int64)), - # tf.reduce_sum(tf.cast(gmatch, tf.int64))], - # 'Matching (NG, TP, FP, GM): ') - return n_gbboxes, tp_match, fp_match - - -def bboxes_matching_batch(labels, scores, bboxes, - glabels, gbboxes, gdifficults, - matching_threshold=0.5, scope=None): - """Matching a collection of detected boxes with groundtruth values. - Batched-inputs version. - - Args: - rclasses, rscores, rbboxes: BxN(x4) Tensors. Detected objects, sorted by score; - glabels, gbboxes: Groundtruth bounding boxes. May be zero padded, hence - zero-class objects are ignored. - matching_threshold: Threshold for a positive match. - Return: Tuple or Dictionaries with: - n_gbboxes: Scalar Tensor with number of groundtruth boxes (may difer from - size because of zero padding). - tp: (B, N)-shaped boolean Tensor containing with True Positives. - fp: (B, N)-shaped boolean Tensor containing with False Positives. - """ - # Dictionaries as inputs. - if isinstance(scores, dict) or isinstance(bboxes, dict): - with tf.name_scope(scope, 'bboxes_matching_batch_dict'): - d_n_gbboxes = {} - d_tp = {} - d_fp = {} - for c in labels: - n, tp, fp, _ = bboxes_matching_batch(c, scores[c], bboxes[c], - glabels, gbboxes, gdifficults, - matching_threshold) - d_n_gbboxes[c] = n - d_tp[c] = tp - d_fp[c] = fp - return d_n_gbboxes, d_tp, d_fp, scores - - with tf.name_scope(scope, 'bboxes_matching_batch', - [scores, bboxes, glabels, gbboxes]): - r = tf.map_fn(lambda x: bboxes_matching(labels, x[0], x[1], - x[2], x[3], x[4], - matching_threshold), - (scores, bboxes, glabels, gbboxes, gdifficults), - dtype=(tf.int64, tf.bool, tf.bool), - parallel_iterations=10, - back_prop=False, - swap_memory=True, - infer_shape=True) - return r[0], r[1], r[2], scores - - -# =========================================================================== # -# Some filteting methods. -# =========================================================================== # -def bboxes_filter_center(labels, bboxes, margins=[0., 0., 0., 0.], - scope=None): - """Filter out bounding boxes whose center are not in - the rectangle [0, 0, 1, 1] + margins. The margin Tensor - can be used to enforce or loosen this condition. - - Return: - labels, bboxes: Filtered elements. - """ - with tf.name_scope(scope, 'bboxes_filter', [labels, bboxes]): - cy = (bboxes[:, 0] + bboxes[:, 2]) / 2. - cx = (bboxes[:, 1] + bboxes[:, 3]) / 2. - mask = tf.greater(cy, margins[0]) - mask = tf.logical_and(mask, tf.greater(cx, margins[1])) - mask = tf.logical_and(mask, tf.less(cx, 1. + margins[2])) - mask = tf.logical_and(mask, tf.less(cx, 1. + margins[3])) - # Boolean masking... - labels = tf.boolean_mask(labels, mask) - bboxes = tf.boolean_mask(bboxes, mask) - return labels, bboxes - - -def bboxes_filter_overlap(labels, bboxes, - threshold=0.5, assign_negative=False, - scope=None): - """Filter out bounding boxes based on (relative )overlap with reference - box [0, 0, 1, 1]. Remove completely bounding boxes, or assign negative - labels to the one outside (useful for latter processing...). - - Return: - labels, bboxes: Filtered (or newly assigned) elements. - """ - with tf.name_scope(scope, 'bboxes_filter', [labels, bboxes]): - scores = bboxes_intersection(tf.constant([0, 0, 1, 1], bboxes.dtype), - bboxes) - mask = scores > threshold - if assign_negative: - labels = tf.where(mask, labels, -labels) - # bboxes = tf.where(mask, bboxes, bboxes) - else: - labels = tf.boolean_mask(labels, mask) - bboxes = tf.boolean_mask(bboxes, mask) - return labels, bboxes - - -def bboxes_filter_labels(labels, bboxes, - out_labels=[], num_classes=np.inf, - scope=None): - """Filter out labels from a collection. Typically used to get - of DontCare elements. Also remove elements based on the number of classes. - - Return: - labels, bboxes: Filtered elements. - """ - with tf.name_scope(scope, 'bboxes_filter_labels', [labels, bboxes]): - mask = tf.greater_equal(labels, num_classes) - for l in labels: - mask = tf.logical_and(mask, tf.not_equal(labels, l)) - labels = tf.boolean_mask(labels, mask) - bboxes = tf.boolean_mask(bboxes, mask) - return labels, bboxes - - -# =========================================================================== # -# Standard boxes computation. -# =========================================================================== # -def bboxes_jaccard(bbox_ref, bboxes, name=None): - """Compute jaccard score between a reference box and a collection - of bounding boxes. - - Args: - bbox_ref: (N, 4) or (4,) Tensor with reference bounding box(es). - bboxes: (N, 4) Tensor, collection of bounding boxes. - Return: - (N,) Tensor with Jaccard scores. - """ - with tf.name_scope(name, 'bboxes_jaccard'): - # Should be more efficient to first transpose. - bboxes = tf.transpose(bboxes) - bbox_ref = tf.transpose(bbox_ref) - # Intersection bbox and volume. - int_ymin = tf.maximum(bboxes[0], bbox_ref[0]) - int_xmin = tf.maximum(bboxes[1], bbox_ref[1]) - int_ymax = tf.minimum(bboxes[2], bbox_ref[2]) - int_xmax = tf.minimum(bboxes[3], bbox_ref[3]) - h = tf.maximum(int_ymax - int_ymin, 0.) - w = tf.maximum(int_xmax - int_xmin, 0.) - # Volumes. - inter_vol = h * w - union_vol = -inter_vol \ - + (bboxes[2] - bboxes[0]) * (bboxes[3] - bboxes[1]) \ - + (bbox_ref[2] - bbox_ref[0]) * (bbox_ref[3] - bbox_ref[1]) - jaccard = tfe_math.safe_divide(inter_vol, union_vol, 'jaccard') - return jaccard - - -def bboxes_intersection(bbox_ref, bboxes, name=None): - """Compute relative intersection between a reference box and a - collection of bounding boxes. Namely, compute the quotient between - intersection area and box area. - - Args: - bbox_ref: (N, 4) or (4,) Tensor with reference bounding box(es). - bboxes: (N, 4) Tensor, collection of bounding boxes. - Return: - (N,) Tensor with relative intersection. - """ - with tf.name_scope(name, 'bboxes_intersection'): - # Should be more efficient to first transpose. - bboxes = tf.transpose(bboxes) - bbox_ref = tf.transpose(bbox_ref) - # Intersection bbox and volume. - int_ymin = tf.maximum(bboxes[0], bbox_ref[0]) - int_xmin = tf.maximum(bboxes[1], bbox_ref[1]) - int_ymax = tf.minimum(bboxes[2], bbox_ref[2]) - int_xmax = tf.minimum(bboxes[3], bbox_ref[3]) - h = tf.maximum(int_ymax - int_ymin, 0.) - w = tf.maximum(int_xmax - int_xmin, 0.) - # Volumes. - inter_vol = h * w - bboxes_vol = (bboxes[2] - bboxes[0]) * (bboxes[3] - bboxes[1]) - scores = tfe_math.safe_divide(inter_vol, bboxes_vol, 'intersection') - return scores diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/image.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/image.py deleted file mode 100644 index e69de29b..00000000 diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/math.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/math.py deleted file mode 100644 index 2e5359c5..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/math.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2017 Paul Balanca. 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. -# ============================================================================== -"""TF Extended: additional math functions. -""" -import tensorflow as tf - -from tensorflow.python.framework import ops - -def safe_divide(numerator, denominator, name): - """Divides two values, returning 0 if the denominator is <= 0. - Args: - numerator: A real `Tensor`. - denominator: A real `Tensor`, with dtype matching `numerator`. - name: Name for the returned op. - Returns: - 0 if `denominator` <= 0, else `numerator` / `denominator` - """ - return tf.where( - tf.greater(denominator, 0), - tf.divide(numerator, denominator), - tf.zeros_like(numerator), - name=name) - - -def cummax(x, reverse=False, name=None): - """Compute the cumulative maximum of the tensor `x` along `axis`. This - operation is similar to the more classic `cumsum`. Only support 1D Tensor - for now. - - Args: - x: A `Tensor`. Must be one of the following types: `float32`, `float64`, - `int64`, `int32`, `uint8`, `uint16`, `int16`, `int8`, `complex64`, - `complex128`, `qint8`, `quint8`, `qint32`, `half`. - axis: A `Tensor` of type `int32` (default: 0). - reverse: A `bool` (default: False). - name: A name for the operation (optional). - Returns: - A `Tensor`. Has the same type as `x`. - """ - with ops.name_scope(name, "Cummax", [x]) as name: - x = ops.convert_to_tensor(x, name="x") - # Not very optimal: should directly integrate reverse into tf.scan. - if reverse: - x = tf.reverse(x, axis=[0]) - # 'Accumlating' maximum: ensure it is always increasing. - cmax = tf.scan(tf.maximum, x, - initializer=None, parallel_iterations=1, - back_prop=False, swap_memory=False) - if reverse: - cmax = tf.reverse(cmax, axis=[0]) - return cmax diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/metrics.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/metrics.py deleted file mode 100644 index 42895291..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/metrics.py +++ /dev/null @@ -1,397 +0,0 @@ -# Copyright 2017 Paul Balanca. 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. -# ============================================================================== -"""TF Extended: additional metrics. -""" -import tensorflow as tf -import numpy as np - -from tensorflow.contrib.framework.python.ops import variables as contrib_variables -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import ops -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.ops import nn -from tensorflow.python.ops import state_ops -from tensorflow.python.ops import variable_scope -from tensorflow.python.ops import variables - -from tfextended import math as tfe_math - - -# =========================================================================== # -# TensorFlow utils -# =========================================================================== # -def _create_local(name, shape, collections=None, validate_shape=False, - dtype=dtypes.float32): - """Creates a new local variable. - Args: - name: The name of the new or existing variable. - shape: Shape of the new or existing variable. - collections: A list of collection names to which the Variable will be added. - validate_shape: Whether to validate the shape of the variable. - dtype: Data type of the variables. - Returns: - The created variable. - """ - # Make sure local variables are added to tf.GraphKeys.LOCAL_VARIABLES - collections = list(collections or []) - collections += [ops.GraphKeys.LOCAL_VARIABLES] - return tf.Variable( - initial_value=array_ops.zeros(shape, dtype=dtype), - name=name, - trainable=False, - collections=collections, - validate_shape=validate_shape) - - -def _safe_div(numerator, denominator, name): - """Divides two values, returning 0 if the denominator is <= 0. - Args: - numerator: A real `Tensor`. - denominator: A real `Tensor`, with dtype matching `numerator`. - name: Name for the returned op. - Returns: - 0 if `denominator` <= 0, else `numerator` / `denominator` - """ - return tf.where( - tf.math.greater(denominator, 0), - tf.math.divide(numerator, denominator), - tf.zeros_like(numerator), - name=name) - - -def _broadcast_weights(weights, values): - """Broadcast `weights` to the same shape as `values`. - This returns a version of `weights` following the same broadcast rules as - `mul(weights, values)`. When computing a weighted average, use this function - to broadcast `weights` before summing them; e.g., - `reduce_sum(w * v) / reduce_sum(_broadcast_weights(w, v))`. - Args: - weights: `Tensor` whose shape is broadcastable to `values`. - values: `Tensor` of any shape. - Returns: - `weights` broadcast to `values` shape. - """ - weights_shape = weights.get_shape() - values_shape = values.get_shape() - if(weights_shape.is_fully_defined() and - values_shape.is_fully_defined() and - weights_shape.is_compatible_with(values_shape)): - return weights - return tf.math.multiply( - weights, array_ops.ones_like(values), name='broadcast_weights') - - -# =========================================================================== # -# TF Extended metrics: TP and FP arrays. -# =========================================================================== # -def precision_recall(num_gbboxes, num_detections, tp, fp, scores, - dtype=tf.float64, scope=None): - """Compute precision and recall from scores, true positives and false - positives booleans arrays - """ - # Input dictionaries: dict outputs as streaming metrics. - if isinstance(scores, dict): - d_precision = {} - d_recall = {} - for c in num_gbboxes.keys(): - scope = 'precision_recall_%s' % c - p, r = precision_recall(num_gbboxes[c], num_detections[c], - tp[c], fp[c], scores[c], - dtype, scope) - d_precision[c] = p - d_recall[c] = r - return d_precision, d_recall - - # Sort by score. - with tf.name_scope(scope, 'precision_recall', - [num_gbboxes, num_detections, tp, fp, scores]): - # Sort detections by score. - scores, idxes = tf.nn.top_k(scores, k=num_detections, sorted=True) - tp = tf.gather(tp, idxes) - fp = tf.gather(fp, idxes) - # Computer recall and precision. - tp = tf.cumsum(tf.cast(tp, dtype), axis=0) - fp = tf.cumsum(tf.cast(fp, dtype), axis=0) - recall = _safe_div(tp, tf.cast(num_gbboxes, dtype), 'recall') - precision = _safe_div(tp, tp + fp, 'precision') - return tf.tuple([precision, recall]) - - -def streaming_tp_fp_arrays(num_gbboxes, tp, fp, scores, - remove_zero_scores=True, - metrics_collections=None, - updates_collections=None, - name=None): - """Streaming computation of True and False Positive arrays. This metrics - also keeps track of scores and number of grountruth objects. - """ - # Input dictionaries: dict outputs as streaming metrics. - if isinstance(scores, dict) or isinstance(fp, dict): - d_values = {} - d_update_ops = {} - for c in num_gbboxes.keys(): - scope = 'streaming_tp_fp_%s' % c - v, up = streaming_tp_fp_arrays(num_gbboxes[c], tp[c], fp[c], scores[c], - remove_zero_scores, - metrics_collections, - updates_collections, - name=scope) - d_values[c] = v - d_update_ops[c] = up - return d_values, d_update_ops - - # Input Tensors... - with variable_scope.variable_scope(name, 'streaming_tp_fp', - [num_gbboxes, tp, fp, scores]): - num_gbboxes = tf.cast(num_gbboxes, dtype=tf.int64) - scores = tf.cast(scores, dtype=tf.float32) - stype = tf.bool - tp = tf.cast(tp, stype) - fp = tf.cast(fp, stype) - # Reshape TP and FP tensors and clean away 0 class values. - scores = tf.reshape(scores, [-1]) - tp = tf.reshape(tp, [-1]) - fp = tf.reshape(fp, [-1]) - # Remove TP and FP both false. - mask = tf.logical_or(tp, fp) - if remove_zero_scores: - rm_threshold = 1e-4 - mask = tf.logical_and(mask, tf.greater(scores, rm_threshold)) - scores = tf.boolean_mask(scores, mask) - tp = tf.boolean_mask(tp, mask) - fp = tf.boolean_mask(fp, mask) - - # Local variables accumlating information over batches. - v_nobjects = _create_local('v_num_gbboxes', shape=[], dtype=tf.int64) - v_ndetections = _create_local('v_num_detections', shape=[], dtype=tf.int32) - v_scores = _create_local('v_scores', shape=[0, ]) - v_tp = _create_local('v_tp', shape=[0, ], dtype=stype) - v_fp = _create_local('v_fp', shape=[0, ], dtype=stype) - - # Update operations. - nobjects_op = state_ops.assign_add(v_nobjects, - tf.reduce_sum(num_gbboxes)) - ndetections_op = state_ops.assign_add(v_ndetections, - tf.size(scores, out_type=tf.int32)) - scores_op = state_ops.assign(v_scores, tf.concat([v_scores, scores], axis=0), - validate_shape=False) - tp_op = state_ops.assign(v_tp, tf.concat([v_tp, tp], axis=0), - validate_shape=False) - fp_op = state_ops.assign(v_fp, tf.concat([v_fp, fp], axis=0), - validate_shape=False) - - # Value and update ops. - val = (v_nobjects, v_ndetections, v_tp, v_fp, v_scores) - with ops.control_dependencies([nobjects_op, ndetections_op, - scores_op, tp_op, fp_op]): - update_op = (nobjects_op, ndetections_op, tp_op, fp_op, scores_op) - - if metrics_collections: - ops.add_to_collections(metrics_collections, val) - if updates_collections: - ops.add_to_collections(updates_collections, update_op) - return val, update_op - - -# =========================================================================== # -# Average precision computations. -# =========================================================================== # -def average_precision_voc12(precision, recall, name=None): - """Compute (interpolated) average precision from precision and recall Tensors. - - The implementation follows Pascal 2012 and ILSVRC guidelines. - See also: https://sanchom.wordpress.com/tag/average-precision/ - """ - with tf.name_scope(name, 'average_precision_voc12', [precision, recall]): - # Convert to float64 to decrease error on Riemann sums. - precision = tf.cast(precision, dtype=tf.float64) - recall = tf.cast(recall, dtype=tf.float64) - - # Add bounds values to precision and recall. - precision = tf.concat([[0.], precision, [0.]], axis=0) - recall = tf.concat([[0.], recall, [1.]], axis=0) - # Ensures precision is increasing in reverse order. - precision = tfe_math.cummax(precision, reverse=True) - - # Riemann sums for estimating the integral. - # mean_pre = (precision[1:] + precision[:-1]) / 2. - mean_pre = precision[1:] - diff_rec = recall[1:] - recall[:-1] - ap = tf.reduce_sum(mean_pre * diff_rec) - return ap - - -def average_precision_voc07(precision, recall, name=None): - """Compute (interpolated) average precision from precision and recall Tensors. - - The implementation follows Pascal 2007 guidelines. - See also: https://sanchom.wordpress.com/tag/average-precision/ - """ - with tf.name_scope(name, 'average_precision_voc07', [precision, recall]): - # Convert to float64 to decrease error on cumulated sums. - precision = tf.cast(precision, dtype=tf.float64) - recall = tf.cast(recall, dtype=tf.float64) - # Add zero-limit value to avoid any boundary problem... - precision = tf.concat([precision, [0.]], axis=0) - recall = tf.concat([recall, [np.inf]], axis=0) - - # Split the integral into 10 bins. - l_aps = [] - for t in np.arange(0., 1.1, 0.1): - mask = tf.greater_equal(recall, t) - v = tf.reduce_max(tf.boolean_mask(precision, mask)) - l_aps.append(v / 11.) - ap = tf.add_n(l_aps) - return ap - - -def precision_recall_values(xvals, precision, recall, name=None): - """Compute values on the precision/recall curve. - - Args: - x: Python list of floats; - precision: 1D Tensor decreasing. - recall: 1D Tensor increasing. - Return: - list of precision values. - """ - with ops.name_scope(name, "precision_recall_values", - [precision, recall]) as name: - # Add bounds values to precision and recall. - precision = tf.concat([[0.], precision, [0.]], axis=0) - recall = tf.concat([[0.], recall, [1.]], axis=0) - precision = tfe_math.cummax(precision, reverse=True) - - prec_values = [] - for x in xvals: - mask = tf.less_equal(recall, x) - val = tf.reduce_min(tf.boolean_mask(precision, mask)) - prec_values.append(val) - return tf.tuple(prec_values) - - -# =========================================================================== # -# TF Extended metrics: old stuff! -# =========================================================================== # -def _precision_recall(n_gbboxes, n_detections, scores, tp, fp, scope=None): - """Compute precision and recall from scores, true positives and false - positives booleans arrays - """ - # Sort by score. - with tf.name_scope(scope, 'prec_rec', [n_gbboxes, scores, tp, fp]): - # Sort detections by score. - scores, idxes = tf.nn.top_k(scores, k=n_detections, sorted=True) - tp = tf.gather(tp, idxes) - fp = tf.gather(fp, idxes) - # Computer recall and precision. - dtype = tf.float64 - tp = tf.cumsum(tf.cast(tp, dtype), axis=0) - fp = tf.cumsum(tf.cast(fp, dtype), axis=0) - recall = _safe_div(tp, tf.cast(n_gbboxes, dtype), 'recall') - precision = _safe_div(tp, tp + fp, 'precision') - - return tf.tuple([precision, recall]) - - -def streaming_precision_recall_arrays(n_gbboxes, rclasses, rscores, - tp_tensor, fp_tensor, - remove_zero_labels=True, - metrics_collections=None, - updates_collections=None, - name=None): - """Streaming computation of precision / recall arrays. This metrics - keeps tracks of boolean True positives and False positives arrays. - """ - with variable_scope.variable_scope(name, 'stream_precision_recall', - [n_gbboxes, rclasses, tp_tensor, fp_tensor]): - n_gbboxes = tf.cast(n_gbboxes, tf.int64) - rclasses = tf.cast(rclasses, tf.int64) - rscores = tf.cast(rscores, tf.float) - - stype = tf.int32 - tp_tensor = tf.cast(tp_tensor, stype) - fp_tensor = tf.cast(fp_tensor, stype) - - # Reshape TP and FP tensors and clean away 0 class values. - rclasses = tf.reshape(rclasses, [-1]) - rscores = tf.reshape(rscores, [-1]) - tp_tensor = tf.reshape(tp_tensor, [-1]) - fp_tensor = tf.reshape(fp_tensor, [-1]) - if remove_zero_labels: - mask = tf.greater(rclasses, 0) - rclasses = tf.boolean_mask(rclasses, mask) - rscores = tf.boolean_mask(rscores, mask) - tp_tensor = tf.boolean_mask(tp_tensor, mask) - fp_tensor = tf.boolean_mask(fp_tensor, mask) - - # Local variables accumlating information over batches. - v_nobjects = _create_local('v_nobjects', shape=[], dtype=tf.int64) - v_ndetections = _create_local('v_ndetections', shape=[], dtype=tf.int32) - v_scores = _create_local('v_scores', shape=[0, ]) - v_tp = _create_local('v_tp', shape=[0, ], dtype=stype) - v_fp = _create_local('v_fp', shape=[0, ], dtype=stype) - - # Update operations. - nobjects_op = state_ops.assign_add(v_nobjects, - tf.reduce_sum(n_gbboxes)) - ndetections_op = state_ops.assign_add(v_ndetections, - tf.size(rscores, out_type=tf.int32)) - scores_op = state_ops.assign(v_scores, tf.concat([v_scores, rscores], axis=0), - validate_shape=False) - tp_op = state_ops.assign(v_tp, tf.concat([v_tp, tp_tensor], axis=0), - validate_shape=False) - fp_op = state_ops.assign(v_fp, tf.concat([v_fp, fp_tensor], axis=0), - validate_shape=False) - - # Precision and recall computations. - # r = _precision_recall(nobjects_op, scores_op, tp_op, fp_op, 'value') - r = _precision_recall(v_nobjects, v_ndetections, v_scores, - v_tp, v_fp, 'value') - - with ops.control_dependencies([nobjects_op, ndetections_op, - scores_op, tp_op, fp_op]): - update_op = _precision_recall(nobjects_op, ndetections_op, - scores_op, tp_op, fp_op, 'update_op') - - # update_op = tf.Print(update_op, - # [tf.reduce_sum(tf.cast(mask, tf.int64)), - # tf.reduce_sum(tf.cast(mask2, tf.int64)), - # tf.reduce_min(rscores), - # tf.reduce_sum(n_gbboxes)], - # 'Metric: ') - # Some debugging stuff! - # update_op = tf.Print(update_op, - # [tf.shape(tp_op), - # tf.reduce_sum(tf.cast(tp_op, tf.int64), axis=0)], - # 'TP and FP shape: ') - # update_op[0] = tf.Print(update_op, - # [nobjects_op], - # '# Groundtruth bboxes: ') - # update_op = tf.Print(update_op, - # [update_op[0][0], - # update_op[0][-1], - # tf.reduce_min(update_op[0]), - # tf.reduce_max(update_op[0]), - # tf.reduce_min(update_op[1]), - # tf.reduce_max(update_op[1])], - # 'Precision and recall :') - - if metrics_collections: - ops.add_to_collections(metrics_collections, r) - if updates_collections: - ops.add_to_collections(updates_collections, update_op) - return r, update_op - diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/tensors.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/tensors.py deleted file mode 100644 index f2d561bc..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfextended/tensors.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright 2017 Paul Balanca. 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. -# ============================================================================== -"""TF Extended: additional tensors operations. -""" -import tensorflow as tf - -from tensorflow.contrib.framework.python.ops import variables as contrib_variables -from tensorflow.contrib.metrics.python.ops import set_ops -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import ops -from tensorflow.python.framework import sparse_tensor -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import check_ops -from tensorflow.python.ops import control_flow_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.ops import nn -from tensorflow.python.ops import state_ops -from tensorflow.python.ops import variable_scope -from tensorflow.python.ops import variables - - -def get_shape(x, rank=None): - """Returns the dimensions of a Tensor as list of integers or scale tensors. - - Args: - x: N-d Tensor; - rank: Rank of the Tensor. If None, will try to guess it. - Returns: - A list of `[d1, d2, ..., dN]` corresponding to the dimensions of the - input tensor. Dimensions that are statically known are python integers, - otherwise they are integer scalar tensors. - """ - if x.get_shape().is_fully_defined(): - return x.get_shape().as_list() - else: - static_shape = x.get_shape() - if rank is None: - static_shape = static_shape.as_list() - rank = len(static_shape) - else: - static_shape = x.get_shape().with_rank(rank).as_list() - dynamic_shape = tf.unstack(tf.shape(x), rank) - return [s if s is not None else d - for s, d in zip(static_shape, dynamic_shape)] - - -def pad_axis(x, offset, size, axis=0, name=None): - """Pad a tensor on an axis, with a given offset and output size. - The tensor is padded with zero (i.e. CONSTANT mode). Note that the if the - `size` is smaller than existing size + `offset`, the output tensor - was the latter dimension. - - Args: - x: Tensor to pad; - offset: Offset to add on the dimension chosen; - size: Final size of the dimension. - Return: - Padded tensor whose dimension on `axis` is `size`, or greater if - the input vector was larger. - """ - with tf.name_scope(name, 'pad_axis'): - shape = get_shape(x) - rank = len(shape) - # Padding description. - new_size = tf.maximum(size-offset-shape[axis], 0) - pad1 = tf.stack([0]*axis + [offset] + [0]*(rank-axis-1)) - pad2 = tf.stack([0]*axis + [new_size] + [0]*(rank-axis-1)) - paddings = tf.stack([pad1, pad2], axis=1) - x = tf.pad(x, paddings, mode='CONSTANT') - # Reshape, to get fully defined shape if possible. - # TODO: fix with tf.slice - shape[axis] = size - x = tf.reshape(x, tf.stack(shape)) - return x - - -# def select_at_index(idx, val, t): -# """Return a tensor. -# """ -# idx = tf.expand_dims(tf.expand_dims(idx, 0), 0) -# val = tf.expand_dims(val, 0) -# t = t + tf.scatter_nd(idx, val, tf.shape(t)) -# return t diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/__init__.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/endpoints.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/endpoints.py deleted file mode 100644 index c6a46df4..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/endpoints.py +++ /dev/null @@ -1,20 +0,0 @@ -''' -Endpoint names to look for in the graph -''' - -from anchors import generate_anchors - -feat_layers = generate_anchors.feat_layers -sub_feats = [''] -localizations_names = [f'ssd_300_vgg/{feature}_box/Reshape:0' for feature in feat_layers] - -predictions_names = ['ssd_300_vgg/softmax/Reshape_1:0'] \ - + [f'ssd_300_vgg/softmax_{n}/Reshape_1:0' for n in range(1, len(feat_layers))] - -logit_names = [f'ssd_300_vgg/{feature}_box/Reshape_1:0' for feature in feat_layers] - -endpoint_names = ['ssd_300_vgg/conv1/conv1_2/Relu:0'] \ - + [f'ssd_300_vgg/conv{n}/conv{n}_3/Relu:0' for n in range(4, 6)] \ - + [f'ssd_300_vgg/conv{n}/conv{n}_{n}/Relu:0' for n in range(2, 4)] \ - + [f'ssd_300_vgg/conv{n}/Relu:0' for n in range(6, 8)] \ - + [f'ssd_300_vgg/{feature}/conv3x3/Relu:0' for feature in feat_layers if feature != 'block4' and feature != 'block7'] \ No newline at end of file diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/tf_utils.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/tf_utils.py deleted file mode 100644 index a17fa3c1..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/tf_utils.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright 2016 Paul Balanca. 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. -# ============================================================================= -"""Diverse TensorFlow utils, for training, evaluation and so on! -""" -import os - -import tensorflow as tf - -# =========================================================================== # -# General tools. -# =========================================================================== # -def reshape_list(l, shape=None): - """Reshape list of (list): 1D to 2D or the other way around. - - Args: - l: List or List of list. - shape: 1D or 2D shape. - Return - Reshaped list. - """ - r = [] - if shape is None: - # Flatten everything. - for a in l: - if isinstance(a, (list, tuple)): - r = r + list(a) - else: - r.append(a) - else: - # Reshape to list of list. - i = 0 - for s in shape: - if s == 1: - r.append(l[i]) - else: - r.append(l[i:i+s]) - i += s - return r - -def configure_learning_rate(flags, num_samples_per_epoch, global_step): - """Configures the learning rate. - - Args: - num_samples_per_epoch: The number of samples in each epoch of training. - global_step: The global_step tensor. - Returns: - A `Tensor` representing the learning rate. - """ - decay_steps = int(num_samples_per_epoch / flags.batch_size * - flags.num_epochs_per_decay) - - if flags.learning_rate_decay_type == 'exponential': - return tf.train.exponential_decay(flags.learning_rate, - global_step, - decay_steps, - flags.learning_rate_decay_factor, - staircase=True, - name='exponential_decay_learning_rate') - elif flags.learning_rate_decay_type == 'fixed': - return tf.constant(flags.learning_rate, name='fixed_learning_rate') - elif flags.learning_rate_decay_type == 'polynomial': - return tf.train.polynomial_decay(flags.learning_rate, - global_step, - decay_steps, - flags.end_learning_rate, - power=1.0, - cycle=False, - name='polynomial_decay_learning_rate') - else: - raise ValueError('learning_rate_decay_type [%s] was not recognized', - flags.learning_rate_decay_type) - - -def configure_optimizer(flags, learning_rate): - """Configures the optimizer used for training. - - Args: - learning_rate: A scalar or `Tensor` learning rate. - Returns: - An instance of an optimizer. - """ - if flags.optimizer == 'adadelta': - optimizer = tf.train.AdadeltaOptimizer( - learning_rate, - rho=flags.adadelta_rho, - epsilon=flags.opt_epsilon) - elif flags.optimizer == 'adagrad': - optimizer = tf.train.AdagradOptimizer( - learning_rate, - initial_accumulator_value=flags.adagrad_initial_accumulator_value) - elif flags.optimizer == 'adam': - optimizer = tf.train.AdamOptimizer( - learning_rate, - beta1=flags.adam_beta1, - beta2=flags.adam_beta2, - epsilon=flags.opt_epsilon) - elif flags.optimizer == 'ftrl': - optimizer = tf.train.FtrlOptimizer( - learning_rate, - learning_rate_power=flags.ftrl_learning_rate_power, - initial_accumulator_value=flags.ftrl_initial_accumulator_value, - l1_regularization_strength=flags.ftrl_l1, - l2_regularization_strength=flags.ftrl_l2) - elif flags.optimizer == 'momentum': - optimizer = tf.train.MomentumOptimizer( - learning_rate, - momentum=flags.momentum, - name='Momentum') - elif flags.optimizer == 'rmsprop': - optimizer = tf.train.RMSPropOptimizer( - learning_rate, - decay=flags.rmsprop_decay, - momentum=flags.rmsprop_momentum, - epsilon=flags.opt_epsilon) - elif flags.optimizer == 'sgd': - optimizer = tf.train.GradientDescentOptimizer(learning_rate) - else: - raise ValueError('Optimizer [%s] was not recognized', flags.optimizer) - return optimizer - - -def update_model_scope(var, ckpt_scope, new_scope): - return var.op.name.replace(new_scope,'vgg_16') - - -def get_variables_to_train(flags): - """Returns a list of variables to train. - - Returns: - A list of variables to train by the optimizer. - """ - if flags.trainable_scopes is None: - return tf.trainable_variables() - else: - scopes = [scope.strip() for scope in flags.trainable_scopes.split(',')] - - variables_to_train = [] - for scope in scopes: - variables = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope) - variables_to_train.extend(variables) - return variables_to_train - - -# =========================================================================== # -# Evaluation utils. -# =========================================================================== # diff --git a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/visualization.py b/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/visualization.py deleted file mode 100644 index 227655d2..00000000 --- a/how-to-use-azureml/deployment/accelerated-models/finetune-ssd-vgg/tfssd/tfutil/visualization.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2017 Paul Balanca. 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. -# ============================================================================== -import cv2 -import random - -import matplotlib.pyplot as plt -import matplotlib.image as mpimg -import matplotlib.cm as mpcm - - -# =========================================================================== # -# Some colormaps. -# =========================================================================== # -def colors_subselect(colors, num_classes=21): - dt = len(colors) // num_classes - sub_colors = [] - for i in range(num_classes): - color = colors[i*dt] - if isinstance(color[0], float): - sub_colors.append([int(c * 255) for c in color]) - else: - sub_colors.append([c for c in color]) - return sub_colors - -colors_plasma = colors_subselect(mpcm.plasma.colors, num_classes=21) -colors_tableau = [(255, 255, 255), (31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120), - (44, 160, 44), (152, 223, 138), (214, 39, 40), (255, 152, 150), - (148, 103, 189), (197, 176, 213), (140, 86, 75), (196, 156, 148), - (227, 119, 194), (247, 182, 210), (127, 127, 127), (199, 199, 199), - (188, 189, 34), (219, 219, 141), (23, 190, 207), (158, 218, 229)] - - -# =========================================================================== # -# OpenCV drawing. -# =========================================================================== # -def draw_lines(img, lines, color=[255, 0, 0], thickness=2): - """Draw a collection of lines on an image. - """ - for line in lines: - for x1, y1, x2, y2 in line: - cv2.line(img, (x1, y1), (x2, y2), color, thickness) - - -def draw_rectangle(img, p1, p2, color=[255, 0, 0], thickness=2): - cv2.rectangle(img, p1[::-1], p2[::-1], color, thickness) - - -def draw_bbox(img, bbox, shape, label, color=[255, 0, 0], thickness=2): - p1 = (int(bbox[0] * shape[0]), int(bbox[1] * shape[1])) - p2 = (int(bbox[2] * shape[0]), int(bbox[3] * shape[1])) - cv2.rectangle(img, p1[::-1], p2[::-1], color, thickness) - p1 = (p1[0]+15, p1[1]) - cv2.putText(img, str(label), p1[::-1], cv2.FONT_HERSHEY_DUPLEX, 0.5, color, 1) - - -def bboxes_draw_on_img(img, classes, scores, bboxes, colors, thickness=2): - shape = img.shape - for i in range(bboxes.shape[0]): - bbox = bboxes[i] - color = colors[classes[i]] - # Draw bounding box... - p1 = (int(bbox[0] * shape[0]), int(bbox[1] * shape[1])) - p2 = (int(bbox[2] * shape[0]), int(bbox[3] * shape[1])) - cv2.rectangle(img, p1[::-1], p2[::-1], color, thickness) - # Draw text... - s = '%s/%.3f' % (classes[i], scores[i]) - p1 = (p1[0]-5, p1[1]) - cv2.putText(img, s, p1[::-1], cv2.FONT_HERSHEY_DUPLEX, 0.4, color, 1) - - -# =========================================================================== # -# Matplotlib show... -# =========================================================================== # -def plt_bboxes(img, classes, scores, bboxes, figsize=(10,10), linewidth=1.5): - """Visualize bounding boxes. Largely inspired by SSD-MXNET! - """ - fig = plt.figure(figsize=figsize) - plt.imshow(img) - height = img.shape[0] - width = img.shape[1] - colors = dict() - for i in range(classes.shape[0]): - cls_id = int(classes[i]) - if cls_id >= 0: - score = scores[i] - if cls_id not in colors: - colors[cls_id] = (random.random(), random.random(), random.random()) - ymin = int(bboxes[i, 0] * height) - xmin = int(bboxes[i, 1] * width) - ymax = int(bboxes[i, 2] * height) - xmax = int(bboxes[i, 3] * width) - rect = plt.Rectangle((xmin, ymin), xmax - xmin, - ymax - ymin, fill=False, - edgecolor=colors[cls_id], - linewidth=linewidth) - plt.gca().add_patch(rect) - class_name = str(cls_id) - plt.gca().text(xmin, ymin - 2, - '{:s} | {:.3f}'.format(class_name, score), - bbox=dict(facecolor=colors[cls_id], alpha=0.5), - fontsize=12, color='white') - plt.show()