Skip to content

Commit 9bb732e

Browse files
committed
merge with master and resolve conflicts
2 parents 813892f + 0141800 commit 9bb732e

16 files changed

Lines changed: 1251 additions & 21 deletions

guide/02-api-overview/release-notes.ipynb

Lines changed: 154 additions & 0 deletions
Large diffs are not rendered by default.

guide/14-deep-learning/geospatial-deep-learning.ipynb

Lines changed: 96 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# How single-shot detector (SSD) works?"
8+
]
9+
},
10+
{
11+
"cell_type": "markdown",
12+
"metadata": {},
13+
"source": [
14+
"## Image classification and object detection"
15+
]
16+
},
17+
{
18+
"cell_type": "markdown",
19+
"metadata": {},
20+
"source": [
21+
"Image classification in computer vision takes an image and predicts the object in an image, while object detection not only predicts the object but also finds their location in terms of bounding boxes. For example, when we build a swimming pool classifier, we take an input image and predict whether it contains a pool, while an object detection model would also tell us the location of the pool.\n",
22+
"\n",
23+
"<img src=\"../../static/img/classVdetection.png\" height=\"500\" width=\"500\">\n",
24+
"<center>Figure 1. Difference between classification and object detection</center>"
25+
]
26+
},
27+
{
28+
"cell_type": "markdown",
29+
"metadata": {},
30+
"source": [
31+
"For illustrative purpose, assuming there is at most one class and one object in an image, the output of an object detection model should include:\n",
32+
"- Probablity that there is an object, \n",
33+
"- Height of the bounding box, \n",
34+
"- Width of the bounding box, \n",
35+
"- Horizontal coordinate of the center point of the bounding box,\n",
36+
"- Vertical coordinate of the center point of the bounding box.\n",
37+
"\n",
38+
"This is just one of the conventions of specifying output. Different models and implementations may have different formats, but the idea is the same, which is to output the probablity and the location of the object."
39+
]
40+
},
41+
{
42+
"cell_type": "markdown",
43+
"metadata": {},
44+
"source": [
45+
"## Why sliding window approach wouldn't work?"
46+
]
47+
},
48+
{
49+
"cell_type": "markdown",
50+
"metadata": {},
51+
"source": [
52+
"It's natural to think of building an object detection model on the top of an image classification model. Once we have a good image classifier, a simple way to detect objects is to slide a 'window' across the image and classify whether the image in that window (cropped out region of the image) is of the desired type. Sounds simple! Well, there are at least two problems: \n",
53+
"- (1) How do you know the **size of the window** so that it always contains the object? Different types of objects (palm tree and swimming pool), even the same type of objects (e.g. a small building and a large buidling) can be of varying sizes as well. \n",
54+
"- (2) **Aspect ratio** (the ratio of height to width of a bounding box). A lot of objects can be present in various shapes like a building footprint will have a different aspect ratio than a palm tree.\n",
55+
"\n",
56+
"To solve these problems, we would have to try out different sizes/shapes of sliding window, which is very computationally intensive, especially with deep neural network. \n",
57+
"\n",
58+
"<img src=\"../../static/img/slidingwindow.gif\" height=\"500\" width=\"500\">\n",
59+
"<center>Figure 2. Example of sliding window approach</center>"
60+
]
61+
},
62+
{
63+
"cell_type": "markdown",
64+
"metadata": {},
65+
"source": [
66+
"In practice, there are two types of mainstream object detection algorithms. Algorithms like R-CNN and Fast(er) R-CNN use a two-step approach - first to identify regions where objects are expected to be found and then detect objects only in those regions using convnet. On the other hand, algorithms like YOLO (You Only Look Once) [1] and SSD (Single-Shot Detector) [2] use a fully convolutional approach in which the network is able to find all objects within an image in one pass (hence ‘single-shot’ or ‘look once’) through the convnet. The region proposal algorithms usually have slightly better accuracy but slower to run, while single-shot algorithms are more efficient and has as good accuracy and that's what we are going to focus on in this section."
67+
]
68+
},
69+
{
70+
"cell_type": "markdown",
71+
"metadata": {},
72+
"source": [
73+
"> To follow the guide below, we assume that you have some basic understanding of the convolutional neural networks (CNN) concept. You can refresh your CNN knowledge by going through this short paper “[A guide to convolution arithmetic for deep learning](https://arxiv.org/pdf/1603.07285.pdf)”."
74+
]
75+
},
76+
{
77+
"cell_type": "markdown",
78+
"metadata": {},
79+
"source": [
80+
"## Single-Shot Detector (SSD)"
81+
]
82+
},
83+
{
84+
"cell_type": "markdown",
85+
"metadata": {},
86+
"source": [
87+
"SSD has two components: a __backbone__ model and __SSD head__. _Backbone_ model usually is a pre-trained image classification network as a feature extractor. This is typically a network like ResNet trained on ImageNet from which the final fully connected classification layer has been removed. We are thus left with a deep neural network that is able to extract semantic meaning from the input image while preserving the spatial structure of the image albeit at a lower resolution. For ResNet34, the backbone results in a 256 7x7 feature maps for an input image. We will explain what feature and feature map are later on. The _SSD head_ is just one or more convolutional layers added to this backbone and the outputs are interpreted as the bounding boxes and classes of objects in the spatial location of the final layers activations. \n",
88+
"\n",
89+
"In the figure below, the first few layers (white boxes) are the backbone, the last few layers (blue boxes) represent the SSD head.\n",
90+
"<img src=\"https://cdn-images-1.medium.com/max/1000/1*GmJiirxTSuSVrh-r7gtJdA.png\">\n",
91+
"<center>Figure 3. Architecture of a convolutional neural network with a SSD detector [2]</center>"
92+
]
93+
},
94+
{
95+
"cell_type": "markdown",
96+
"metadata": {},
97+
"source": [
98+
"Next, let's go through the important concepts/parameters in SSD."
99+
]
100+
},
101+
{
102+
"cell_type": "markdown",
103+
"metadata": {},
104+
"source": [
105+
"### Grid cell\n",
106+
"\n",
107+
"Instead of using sliding window, SSD divides the image using a grid and have each grid cell be responsible for detecting objects in that region of the image. Detection objects simply means predicting the class and location of an object within that region. If no object is present, we consider it as the background class and the location is ignored. For instance, we could use a 4x4 grid in the example below. Each grid cell is able to output the position and shape of the object it contains.\n",
108+
"\n",
109+
"<img src=\"../../static/img/gridcell.png\" height=\"300\" width=\"300\">\n",
110+
"<center>Figure 4. Example of a 4x4 grid</center>\n",
111+
"\n",
112+
"Now you might be wondering what if there are multiple objects in one grid cell or we need to detect multiple objects of different shapes. There is where anchor box and receptive field come into play."
113+
]
114+
},
115+
{
116+
"cell_type": "markdown",
117+
"metadata": {},
118+
"source": [
119+
"### Anchor box\n",
120+
"\n",
121+
"Each grid cell in SSD can be assigned with multiple anchor/prior boxes. These anchor boxes are pre-defined and each one is responsible for a size and shape within a grid cell. For example, the swimming pool in the image below corresponds to the taller anchor box while the building corresponds to the wider box.\n",
122+
"\n",
123+
"<img src=\"../../static/img/anchorbox.png\" height=\"480\" width=\"480\">\n",
124+
"<center>Figure 5. Example of two anchor boxes</center>\n",
125+
"\n",
126+
"\n",
127+
"SSD uses a matching phase while training, to match the appropriate anchor box with the bounding boxes of each ground truth object within an image. Essentially, the anchor box with the highest degree of overlap with an object is responsible for predicting that object’s class and its location. This property is used for training the network and for predicting the detected objects and their locations once the network has been trained. In practice, each anchor box is specified by an aspect ratio and a zoom level.\n",
128+
"\n",
129+
"#### Aspect ratio\n",
130+
"\n",
131+
"Not all objects are square in shape. Some are longer and some are wider, by varying degrees. The SSD architecture allows pre-defined aspect ratios of the anchor boxes to account for this. The ratios parameter can be used to specify the different aspect ratios of the anchor boxes associates with each grid cell at each zoom/scale level.\n",
132+
"\n",
133+
"<img src=\"../../static/img/aspect_ratio.png\" height=\"350\" width=\"350\">\n",
134+
"<center>Figure 6. The bounding box of building 1 is higher, while the bouding box for building 2 is wider</center>\n",
135+
"\n",
136+
"\n",
137+
"#### Zoom level\n",
138+
"\n",
139+
"It is not necessary for the anchor boxes to have the same size as the grid cell. We might be interested in finding smaller or larger objects within a grid cell. The zooms parameter is used to specify how much the anchor boxes need to be scaled up or down with respect to each grid cell. Just like what we have seen in the anchor box example, the size of building is generally larger than swimming pool.\n"
140+
]
141+
},
142+
{
143+
"cell_type": "markdown",
144+
"metadata": {},
145+
"source": [
146+
"### Receptive Field\n",
147+
"\n",
148+
"Receptive field is defined as __the region in the input space that a particular CNN’s feature is looking at (i.e. be affected by)__. We will use \"feature\" and \"activation\" interchangeably here and treat them as the linear combination (sometimes applying an activation function after that to increase non-linearity) of the previous layer at the corresponding location [3]. Because of the the convolution operation, features at different layers represent different sizes of region in the input image. As it goes deeper, the size represented by a feature gets larger. In this example below, we start with the bottom layer (5x5) and then apply a convolution that results in the middle layer (3x3) where one feature (green pixel) represents a 3x3 region of the input layer (bottom layer). And then apply the convolution to middle layer and get the top layer (2x2) where each feature corresponds to a 7x7 region on the input image. These kind of green and orange 2D array are also called __feature maps__ which refer to a set of features created by applying the same feature extractor at different locations of the input map in a sliding window fastion. Features in the same feature map have the same receptive field and look for the same pattern but at different locations. This creates the spatial invariance of ConvNet.\n",
149+
"<img src=\"../../static/img/receptive1.png\" height=\"500\" width=\"500\">\n",
150+
"<center>Figure 7. Visualizing CNN feature maps and receptive field</center>\n",
151+
"\n",
152+
"Receptive field is the central premise of the SSD architecture as it enables us to detect objects at different scales and output a tighter bounding box. Why? As you might still remember, the ResNet34 backbone outputs a 256 7x7 feature maps for an input image. If we specify a 4x4 grid, the simplest approach is just to apply a convolution to this feature map and convert it to 4x4. This approach can actually work to some extent and is exatcly the idea of YOLO (You Only Look Once). The extra step taken by SSD is that it applies more convolutional layers to the backbone feature map and has each of these convolution layers output a object detection results. __As earlier layers bearing smaller receptive field can represent smaller sized objects, predictions from earlier layers help in dealing with smaller sized objects__.\n",
153+
"\n",
154+
"Because of this, SSD allows us to define __a hierarchy of grid cells__ at different layers. For example, we could use a 4x4 grid to find smaller objects, a 2x2 grid to find mid sized objects and a 1x1 grid to find objects that cover the entire image. "
155+
]
156+
},
157+
{
158+
"cell_type": "markdown",
159+
"metadata": {},
160+
"source": [
161+
"## SSD implementation in `arcgis.learn`\n",
162+
"\n",
163+
"Armed with these fundamental concepts, we are now ready to define a SSD model. `arcgis.learn` allows us to define a SSD architecture just through a single line of code. For example:\n",
164+
"\n",
165+
" ssd = SingleShotDetector(data, grids=[4], zooms=[1.0], ratios=[[1.0, 1.0]])\n",
166+
"\n",
167+
"The grids parameter specifies the size of the grid cell, in this case 4x4. Additionally, we are specifying a zoom level of 1.0 and aspect ratio of 1.0:1.0. What this essentially means is that the network will create an anchor box for each grid cell, which is the same size as the grid cell (zoom level of 1.0) and is square in shape with an aspect ratio of 1.0:1.0. The output activations along the depth of the final feature map are used to shift and scale (within a reasonable limit) this anchor box so it can approach the actual bounding box of the object even if it doesn’t exactly match with the anchor box. \n",
168+
"\n",
169+
"For more information about the API, please go to the [API reference](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.learn.html#singleshotdetector)."
170+
]
171+
},
172+
{
173+
"cell_type": "markdown",
174+
"metadata": {},
175+
"source": [
176+
"## References\n",
177+
"- [1] Joseph Redmon, Santosh Divvala, Ross Girshick, Ali Farhadi: “You Only Look Once: Unified, Real-Time Object Detection”, 2015; <a href='https://arxiv.org/abs/1506.02640'>arXiv:1506.02640</a>.\n",
178+
"- [2] Wei Liu, Dragomir Anguelov, Dumitru Erhan, Christian Szegedy, Scott Reed, Cheng-Yang Fu: “SSD: Single Shot MultiBox Detector”, 2016; <a href='http://arxiv.org/abs/1512.02325'>arXiv:1512.02325</a>.\n",
179+
"- [3] Zeiler, Matthew D., and Rob Fergus. \"Visualizing and understanding convolutional networks.\" In European conference on computer vision, pp. 818-833. springer, Cham, 2014.\n",
180+
"- [4] Dang Ha The Hien. A guide to receptive field arithmetic for Convolutional Neural Networks. https://medium.com/mlreview/a-guide-to-receptive-field-arithmetic-for-convolutional-neural-networks-e0f514068807"
181+
]
182+
}
183+
],
184+
"metadata": {
185+
"kernelspec": {
186+
"display_name": "Python 3",
187+
"language": "python",
188+
"name": "python3"
189+
},
190+
"language_info": {
191+
"codemirror_mode": {
192+
"name": "ipython",
193+
"version": 3
194+
},
195+
"file_extension": ".py",
196+
"mimetype": "text/x-python",
197+
"name": "python",
198+
"nbconvert_exporter": "python",
199+
"pygments_lexer": "ipython3",
200+
"version": "3.7.2"
201+
},
202+
"toc": {
203+
"base_numbering": 1,
204+
"nav_menu": {},
205+
"number_sections": true,
206+
"sideBar": true,
207+
"skip_h1_title": false,
208+
"title_cell": "Table of Contents",
209+
"title_sidebar": "Contents",
210+
"toc_cell": false,
211+
"toc_position": {},
212+
"toc_section_display": true,
213+
"toc_window_display": false
214+
}
215+
},
216+
"nbformat": 4,
217+
"nbformat_minor": 2
218+
}

guide/14-deep-learning/object-detection.ipynb

Lines changed: 739 additions & 0 deletions
Large diffs are not rendered by default.

misc/_common.py

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,40 @@
11
from arcgis.gis import GIS
2-
import datetime
32

43
"""accounts to keep from user/groups/items deletion"""
5-
ignore_accounts = ['andrew', 'andrew.chapkowski', 'apulver', 'dvitale', 'david.vitale',
4+
ignore_accounts_online = ['DavidJVitale', 'yjiang_geosaurus', 'amani_geosaurus', 'api_data_owner',
5+
'bmajor_geosaurus', 'rsingh_geosaurus', 'rohitgeo', 'andrew887',
6+
'cwhitmore_geosaurus', 'ArcGISPyAPIBot', 'jyaist_geosaurus', 'cpeng_geosaurus']
7+
8+
ignore_accounts_playground = ['andrew', 'andrew.chapkowski', 'apulver', 'dvitale', 'david.vitale',
69
'atma.mani', 'john.yaist', 'bill.major', 'YJiang',
710
'rohit.singh', 'rohitgeo', 'gbochenek_python',
811
'system_publisher', 'admin', 'portaladmin',
912
'Demo_User', 'First_User', 'Second_User',
1013
'api_data_owner', 'arcgis_python', 'temp_execution']
1114

1215
"""accounts that you want to delete groups and items, but keep user"""
13-
target_accounts = ['arcgis_python']
16+
target_accounts_online = ['arcgis_python']
17+
target_accounts_playground = ['arcgis_python']
18+
19+
"""data to publish"""
20+
data_paths = [r'\\archive\crdata\Geosaurus_datasets\data_prep\csv\Trailheads.csv']
1421

1522
"""create GIS connection via admin credentials"""
16-
# gis = GIS(profile='your_entp_admin_profile', verify_cert=False)
17-
gis = GIS("https://pythonapi.playground.esri.com/portal","temp_execution", "temp_execution123")
23+
gis_online = GIS(profile="your_online_admin_profile")
24+
gis_playground = GIS(profile='your_ent_admin_profile')
1825

1926

2027
def delete_depending_items(dependent_item):
2128
"""deletes the item's depending items, and then the item"""
22-
depending_items = dependent_item.dependent_to()
23-
if depending_items['list']:
24-
for item in depending_items['list']:
25-
delete_depending_items(item)
29+
depending_items = None
30+
try:
31+
depending_items = dependent_item.dependent_to()
32+
if depending_items['list']:
33+
for item in depending_items['list']:
34+
delete_depending_items(item)
35+
except:
36+
print("=== could not get item list %s" % dependent_item.homepage)
37+
2638
if dependent_item.protected:
2739
dependent_item.protect(False)
2840
try:
@@ -42,7 +54,7 @@ def delete_items(user):
4254
print("=== finished deleting items owned by " + user.username)
4355

4456

45-
def delete_groups(user):
57+
def delete_groups(gis, user):
4658
"""deletes the user groups, and removes user from groups where user is a member of"""
4759
groups_for_deletion = gis.groups.get('query=owner:' + user.username)
4860
if groups_for_deletion is not None:
@@ -63,28 +75,35 @@ def delete_groups(user):
6375
print("=== finished deleting groups owned by " + user.username)
6476

6577

66-
def delete_for_users():
78+
def delete_for_users(gis, ignore_accounts, target_accounts):
6779
"""deletes items and groups for users in target_accounts, and ignore others"""
6880
for user in gis.users.search():
6981
if user.username not in ignore_accounts and not user.username.startswith("esri_"):
7082
print("-*-*-*-*-*-*-Delete groups & items & user for %s -*-*-*-*-*-" % user.username)
7183
delete_items(user)
72-
delete_groups(user)
84+
delete_groups(gis, user)
7385
try:
7486
user.delete()
7587
except:
7688
print("could not delete user %s" % user.username)
77-
7889
elif user.username in target_accounts:
7990
print("-*-*-*-*-*-*-Delete groups & items for %s -*-*-*-*-*-*-*-*-" % user.username)
8091
delete_items(user)
81-
delete_groups(user)
92+
delete_groups(gis, user)
8293

8394
else:
8495
print("-*-*-*-*-*-*-*-*-No Delete for %s -*-*-*-*-*-*-*-*-*-*-" % user.username)
8596

8697

87-
def clean_up_location_tracking():
98+
def publish_data(gis, paths):
99+
"""publish sample data"""
100+
for path in paths:
101+
item = gis.content.add({}, path)
102+
item.share(everyone=True)
103+
lyr = item.publish()
104+
105+
106+
def clean_up_location_tracking(gis):
88107
# disable location tracking
89108
if gis.admin.location_tracking.status != "disabled":
90109
gis.admin.location_tracking.disable()
@@ -96,7 +115,7 @@ def clean_up_location_tracking():
96115
break
97116

98117

99-
def setup_tracker_user():
118+
def setup_tracker_user(gis):
100119
# create the track_viewer account
101120
tracker_demo = gis.users.get('tracker_demo')
102121
if tracker_demo is None:

misc/setup.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
print("-*-*-*-*-*-*-*-*-*-*-*Setup begins*-*-*-*-*-*-*-*-*-*-*-*-*-")
44

5-
clean_up_location_tracking()
6-
delete_for_users()
7-
setup_tracker_user()
5+
clean_up_location_tracking(gis_playground)
6+
delete_for_users(gis_online, ignore_accounts_online, target_accounts_online)
7+
delete_for_users(gis_playground, ignore_accounts_playground, target_accounts_playground)
8+
setup_tracker_user(gis_playground)
9+
# publish_data(gis_online, data_paths)
810

911
print("-*-*-*-*-*-*-*-*-*-*-*Setup ends*-*-*-*-*-*-*-*-*-*-*-*-*-*-")

misc/teardown.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
print("-*-*-*-*-*-*-*-*-*-*-*Teardown begins*-*-*-*-*-*-*-*-*-*-*-*-")
44

5-
clean_up_location_tracking()
6-
delete_for_users()
5+
clean_up_location_tracking(gis_playground)
6+
delete_for_users(gis_online, ignore_accounts_online, target_accounts_online)
7+
delete_for_users(gis_playground, ignore_accounts_playground, target_accounts_playground)
8+
# publish_data(gis_online, data_paths)
79

810
print("-*-*-*-*-*-*-*-*-*-*-*Teardown ends*-*-*-*-*-*-*-*-*-*-*-*-*-")

static/img/anchorbox.png

1.09 MB
Loading

static/img/aspect_ratio.png

1.11 MB
Loading

static/img/cat.png

330 KB
Loading

0 commit comments

Comments
 (0)