wgpubs commited on
Commit
4ad6955
1 Parent(s): 5c02b50

initial commit

Browse files
.gitattributes CHANGED
@@ -26,4 +26,3 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
26
  *.zstandard filter=lfs diff=lfs merge=lfs -text
27
  *tfevents* filter=lfs diff=lfs merge=lfs -text
28
  *.pkl filter=lfs diff=lfs merge=lfs -text
29
- models/*.pkl filter=lfs diff=lfs merge=lfs -text
26
  *.zstandard filter=lfs diff=lfs merge=lfs -text
27
  *tfevents* filter=lfs diff=lfs merge=lfs -text
28
  *.pkl filter=lfs diff=lfs merge=lfs -text
 
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ data/
2
+ models/
3
+ gardio_queue.db
app.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastai.vision.all import *
2
+ from fastcore.all import *
3
+ import gradio as gr
4
+
5
+ data_path = Path("./data")
6
+ models_path = Path("./models")
7
+ examples_path = Path("./nbs/examples")
8
+
9
+ # code required for serving predictions
10
+ def is_marvel(img):
11
+ return 1.0 if img.parent.name.lower().startswith("marvel") else 0.0
12
+
13
+
14
+ inf_learn = load_learner(models_path / "export.pkl")
15
+
16
+
17
+ def predict(img):
18
+ pred, _, _ = inf_learn.predict(img)
19
+ return f"{pred[0]*100:.2f}%"
20
+
21
+
22
+ # define our Gradio Interface instance and launch it
23
+ with open("gradio_article.md") as f:
24
+ article = f.read()
25
+
26
+ interface_config = {
27
+ "title": "Is it a Marvel Character?",
28
+ "description": "For those wanting to make sure they are rooting on the right heroes. Based on Jeremy Howards ['Is it a bird? Creating a model from your own data'](https://www.kaggle.com/code/jhoward/is-it-a-bird-creating-a-model-from-your-own-data)",
29
+ "article": article,
30
+ "examples": [f"{examples_path}/{f.name}" for f in examples_path.iterdir()],
31
+ "interpretation": None,
32
+ "layout": "horizontal",
33
+ "allow_flagging": "never",
34
+ }
35
+
36
+ demo = gr.Interface(
37
+ fn=predict,
38
+ inputs=gr.inputs.Image(shape=(512, 512)),
39
+ outputs=gr.outputs.Textbox(label="Marvel character probability"),
40
+ **interface_config,
41
+ )
42
+
43
+ demo.launch()
gradio_article.md ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Objective
2
+
3
+ Inspired by Vishnu's excellent [Marvel Character classifier](https://notebookse.jarvislabs.ai/jY5fsv-S9jKoQQrgd1dsoJuCDt6pTg6ZjBpNK9afxLIGInQv4OlHVuTMHqOPh2LU/), this model is designed to thwart adversarial attacks by DC fans who can only dream of their characters being brought into the superior Marvel universe.
4
+
5
+ ## Dataset
6
+
7
+ The dataset is composed of roughly 200 Marvel and 200 DC character images fetched from https://duckduckgo.com/ using the code in
8
+ Jeremy Howard's ['Is it a bird? Creating a model from your own data'](https://www.kaggle.com/code/jhoward/is-it-a-bird-creating-a-model-from-your-own-data) Kaggle notebook.
9
+
10
+ ## Training
11
+ With minimal modifications to our `DataBlock` and parameters passed to fastai's `vision_learner`, this model demonstrates how we can turn the multi-classification example
12
+ Jeremy presented in session 1 of the 2022 fastai course into a regression task. These changes include:
13
+
14
+ 1. Creating a labeling function that returns a float, 0.0 if it is a DC character and 1.0 if it is a Marvel character
15
+
16
+ ```
17
+ def is_marvel(img):
18
+ return 1. if img.parent.name.lower().startswith("marvel") else 0.
19
+ ```
20
+
21
+ 2. Updating our `DataBlock`to use a `RegressionBlock` for our targets, and then assigning our labeling function above to the `get_y` argument.
22
+
23
+ ```
24
+ blocks=(ImageBlock, RegressionBlock)
25
+ ```
26
+
27
+ 3. Updating our call to `vision_learner` to use a regression friendly metric like RMSE, as well as specifying a `y_range` to constrain our predictions to the expected range of between 0 and 1.
28
+
29
+ ```
30
+ learn = vision_learner(dls, resnet18, metrics=rmse, y_range=(0, 1))
31
+ ```
32
+
33
+ We'll start with a pre-trained `ResNet18` model which we'll train by calling `Learner.fine_tune()` and a learning rate of `1e-3`. This will train the classification head of the model (e.g., it will update the completely randomized weights dedicated to predicting a value) for 1 epoch, and then train all the model weights for 3 epochs. The final results of this process are included below.
34
+
35
+
36
+ Training the classification head only:
37
+ | epoch | train_loss | valid_loss | rmse | time |
38
+ |-------|---------------|---------------|---------------|-------|
39
+ | 0 | 0.344505 | 0.324276 | 0.569452 | 00:02 |
40
+
41
+
42
+ Training the entire model:
43
+ | epoch | train_loss | valid_loss | rmse | time |
44
+ |-------|---------------|---------------|---------------|-------|
45
+ | 0 | 0.303813 | 0.292256 | 0.540607 | 00:02 |
46
+ | 1 | 0.250147 | 0.272003 | 0.521539 | 00:01 |
47
+ | 2 | 0.223758 | 0.270610 | 0.520202 | 00:01 |
48
+
49
+ ## Examples
50
+
51
+ Example Marvel and DC character images from the dataset above are provided as examples for this demo. Feel free to upload your own Marvel, DC, and/or whatever else images to see whether you got a hero worth rooting for (or one to avoid).
hf_space_create.png ADDED
nbs/examples/dc1.jpg ADDED
nbs/examples/dc2.jpg ADDED
nbs/examples/dc3.jpg ADDED
nbs/examples/dc4.jpg ADDED
nbs/examples/dc5.jpg ADDED
nbs/examples/marvel1.jpg ADDED
nbs/examples/marvel2.jpg ADDED
nbs/examples/marvel3.jpg ADDED
nbs/examples/marvel4.png ADDED
nbs/examples/marvel5.jpg ADDED
nbs/gradio.ipynb ADDED
@@ -0,0 +1,523 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# Marvel Character Probability Model: Gradio Inference Demo"
8
+ ]
9
+ },
10
+ {
11
+ "cell_type": "markdown",
12
+ "metadata": {},
13
+ "source": [
14
+ "The objective is simple: Thwart adverserial attacks from DC fans who may want to abuse the wonderful [Marvel Character classifier](https://notebookse.jarvislabs.ai/jY5fsv-S9jKoQQrgd1dsoJuCDt6pTg6ZjBpNK9afxLIGInQv4OlHVuTMHqOPh2LU/) in hopes of having DC characters classified as part of the Marvel universe (the unspoken obession of every DC fan).\n",
15
+ "\n",
16
+ "**Gradio** allows us to create a web application for our ML model that can be used directly or embedded in another application (e.g., Hugging Face Spaces).\n",
17
+ "\n",
18
+ "Two resources were fundamental is helping me figure out how to make this critical model available to the world via Gradio and Hugging Face Spaces. The are:\n",
19
+ "\n",
20
+ "1. [\"Gradio + HuggingFace Spaces: A Tutorial\"](https://tmabraham.github.io/blog/gradio_hf_spaces_tutorial) by Tanishq Abraham\n",
21
+ "2. [\"Food Image Classifier\"](https://huggingface.co/spaces/suvash/food-101-resnet50) by Suvash\n"
22
+ ]
23
+ },
24
+ {
25
+ "cell_type": "code",
26
+ "execution_count": 1,
27
+ "metadata": {},
28
+ "outputs": [
29
+ {
30
+ "name": "stderr",
31
+ "output_type": "stream",
32
+ "text": [
33
+ "/home/wgilliam/miniconda3/envs/fastexamples/lib/python3.9/site-packages/paramiko/transport.py:236: CryptographyDeprecationWarning: Blowfish has been deprecated\n",
34
+ " \"class\": algorithms.Blowfish,\n"
35
+ ]
36
+ }
37
+ ],
38
+ "source": [
39
+ "from fastai.vision.all import *\n",
40
+ "from fastcore.all import *\n",
41
+ "import gradio as gr\n"
42
+ ]
43
+ },
44
+ {
45
+ "cell_type": "markdown",
46
+ "metadata": {},
47
+ "source": [
48
+ "## Setup/Configuration"
49
+ ]
50
+ },
51
+ {
52
+ "cell_type": "code",
53
+ "execution_count": 32,
54
+ "metadata": {},
55
+ "outputs": [],
56
+ "source": [
57
+ "data_path = Path(\"../data\")\n",
58
+ "models_path = Path(\"../models\")\n",
59
+ "examples_path = Path(\"./examples\")\n"
60
+ ]
61
+ },
62
+ {
63
+ "cell_type": "markdown",
64
+ "metadata": {},
65
+ "source": [
66
+ "## Utilities"
67
+ ]
68
+ },
69
+ {
70
+ "cell_type": "code",
71
+ "execution_count": 33,
72
+ "metadata": {},
73
+ "outputs": [],
74
+ "source": [
75
+ "def is_marvel(img):\n",
76
+ " return 1.0 if img.parent.name.lower().startswith(\"marvel\") else 0.0\n"
77
+ ]
78
+ },
79
+ {
80
+ "cell_type": "markdown",
81
+ "metadata": {},
82
+ "source": [
83
+ "## Step 1: Inference"
84
+ ]
85
+ },
86
+ {
87
+ "cell_type": "markdown",
88
+ "metadata": {},
89
+ "source": [
90
+ "We start by loading our exported learner from the [training notebook](train.ipynb) via `load_learner`. \n",
91
+ "\n",
92
+ "`load_learner` returns a `Learner` that knows all about our data transformations and training bits, allowing us to use it for item or batch inference without any additional code."
93
+ ]
94
+ },
95
+ {
96
+ "cell_type": "code",
97
+ "execution_count": 34,
98
+ "metadata": {},
99
+ "outputs": [],
100
+ "source": [
101
+ "inf_learn = load_learner(models_path / \"export.pkl\")\n"
102
+ ]
103
+ },
104
+ {
105
+ "cell_type": "markdown",
106
+ "metadata": {},
107
+ "source": [
108
+ "We'll modify our `predict` method here so that it returns the probability of the image being a Marvel character as a string"
109
+ ]
110
+ },
111
+ {
112
+ "cell_type": "code",
113
+ "execution_count": 35,
114
+ "metadata": {},
115
+ "outputs": [],
116
+ "source": [
117
+ "def predict(img):\n",
118
+ " pred, _, _ = inf_learn.predict(img)\n",
119
+ " return f\"{pred[0]*100:.2f}%\"\n"
120
+ ]
121
+ },
122
+ {
123
+ "cell_type": "markdown",
124
+ "metadata": {},
125
+ "source": [
126
+ "... and we'll test things to ensure our predictions look good"
127
+ ]
128
+ },
129
+ {
130
+ "cell_type": "code",
131
+ "execution_count": 36,
132
+ "metadata": {},
133
+ "outputs": [
134
+ {
135
+ "data": {
136
+ "text/html": [
137
+ "\n",
138
+ "<style>\n",
139
+ " /* Turns off some styling */\n",
140
+ " progress {\n",
141
+ " /* gets rid of default border in Firefox and Opera. */\n",
142
+ " border: none;\n",
143
+ " /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
144
+ " background-size: auto;\n",
145
+ " }\n",
146
+ " .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
147
+ " background: #F44336;\n",
148
+ " }\n",
149
+ "</style>\n"
150
+ ],
151
+ "text/plain": [
152
+ "<IPython.core.display.HTML object>"
153
+ ]
154
+ },
155
+ "metadata": {},
156
+ "output_type": "display_data"
157
+ },
158
+ {
159
+ "data": {
160
+ "text/html": [],
161
+ "text/plain": [
162
+ "<IPython.core.display.HTML object>"
163
+ ]
164
+ },
165
+ "metadata": {},
166
+ "output_type": "display_data"
167
+ },
168
+ {
169
+ "name": "stdout",
170
+ "output_type": "stream",
171
+ "text": [
172
+ "Marvel character probability: 41.55%\n"
173
+ ]
174
+ },
175
+ {
176
+ "data": {
177
+ "image/png": "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",
178
+ "text/plain": [
179
+ "<PIL.Image.Image image mode=RGB size=130x256>"
180
+ ]
181
+ },
182
+ "execution_count": 36,
183
+ "metadata": {},
184
+ "output_type": "execute_result"
185
+ }
186
+ ],
187
+ "source": [
188
+ "test_img = PILImage.create(data_path / \"_marvel_example.jpg\")\n",
189
+ "res = predict(test_img)\n",
190
+ "\n",
191
+ "print(f\"Marvel character probability: {res}\")\n",
192
+ "test_img.to_thumb(256, 256)\n"
193
+ ]
194
+ },
195
+ {
196
+ "cell_type": "markdown",
197
+ "metadata": {},
198
+ "source": [
199
+ "## Step 2: Gradio\n",
200
+ "\n",
201
+ "See Tanishq's article [\"Gradio + HuggingFace Spaces: A Tutorial\"](https://tmabraham.github.io/blog/gradio_hf_spaces_tutorial) for more detail on how Gradio can be configured to demo just about any ML model imaginable. I present here a bare minimum explanation of how it works and of the settings used in this particular demo."
202
+ ]
203
+ },
204
+ {
205
+ "cell_type": "markdown",
206
+ "metadata": {},
207
+ "source": [
208
+ "We'll start by including a markdown file with information about our demo (e.g., objective, dataset, training procedure, results, etc...). This information will appear at the bottom of your gradio demo (assed to the `article` parameter of `gradio.Interface()`)"
209
+ ]
210
+ },
211
+ {
212
+ "cell_type": "code",
213
+ "execution_count": 37,
214
+ "metadata": {},
215
+ "outputs": [],
216
+ "source": [
217
+ "with open(\"../gradio_article.md\") as f:\n",
218
+ " article = f.read()\n"
219
+ ]
220
+ },
221
+ {
222
+ "cell_type": "markdown",
223
+ "metadata": {},
224
+ "source": [
225
+ "The UI is ***defined*** via a call to `gradio.Interface()`. \n",
226
+ "\n",
227
+ "Here's a description of the parameters used in this demo:\n",
228
+ "\n",
229
+ "- `title` (str): The title of your demo (appears at the top)\n",
230
+ "- `description` (str): The description of your demo (appears beneath the title and is markup/HTML friendly)\n",
231
+ "- `article` (markdown file): Markdown with explanatory information about your demo (appears at the bottom)\n",
232
+ "- `examples` (str/list): Location of pre-defined examples users can use in your demo\n",
233
+ "- `interpretation` (callabel/str): A function that returns an interpretation for the prediction (options: \"unalighed\", \"horizontal\", \"vertical\")\n",
234
+ "- `layout` (str): You can specify either \"horizontal\" or \"vertical\"\n",
235
+ "- `allow_flagging` (str): Controls if/how users can flag predictions (options: \"never\", \"auto\", \"manual\") \n",
236
+ "\n",
237
+ "See the [docs](https://gradio.app/docs/#interface) for more info.\n",
238
+ "\n",
239
+ "Given the below, we can see/use our demo straight from out notebook!"
240
+ ]
241
+ },
242
+ {
243
+ "cell_type": "code",
244
+ "execution_count": 38,
245
+ "metadata": {},
246
+ "outputs": [],
247
+ "source": [
248
+ "interface_config = {\n",
249
+ " \"title\": \"Is it a Marvel Character?\",\n",
250
+ " \"description\": \"For those wanting to make sure they are rooting on the right heroes. Based on Jeremy Howards ['Is it a bird? Creating a model from your own data'](https://www.kaggle.com/code/jhoward/is-it-a-bird-creating-a-model-from-your-own-data)\",\n",
251
+ " \"article\": article,\n",
252
+ " \"examples\": [f\"{examples_path}/{f.name}\" for f in examples_path.iterdir()],\n",
253
+ " \"interpretation\": None,\n",
254
+ " \"layout\": \"horizontal\",\n",
255
+ " \"allow_flagging\": \"never\",\n",
256
+ "}\n",
257
+ "\n",
258
+ "demo = gr.Interface(\n",
259
+ " fn=predict,\n",
260
+ " inputs=gr.inputs.Image(shape=(512, 512)),\n",
261
+ " outputs=gr.outputs.Textbox(label=\"Marvel character probability\"),\n",
262
+ " **interface_config,\n",
263
+ ")\n"
264
+ ]
265
+ },
266
+ {
267
+ "cell_type": "markdown",
268
+ "metadata": {},
269
+ "source": [
270
+ "The UI is ***launched*** via a call to `gradio.Interface` instance's `launch()` method. \n",
271
+ "\n",
272
+ "Here's a description of the parameters used in this demo:\n",
273
+ "\n",
274
+ "- `inline` (bool): If `True`, will display the interface in your Juypter notebook\n",
275
+ "- `inbrowser` (bool): If `True`, will launch the demo in a new browser tab\n",
276
+ "- `share` (bool): If `True`, will create a shareable link you can use to access your demo on the web\n",
277
+ "- `show_error` (bool): If `True`, errors in the interface will be included in the browser's console log\n",
278
+ "- `enable_queue` (bool): Controls how requests are processed (**Note: Set to `True` for request that will take a long time**)\n",
279
+ "\n",
280
+ "See the [docs](https://gradio.app/docs/#launch) for more info."
281
+ ]
282
+ },
283
+ {
284
+ "cell_type": "code",
285
+ "execution_count": 39,
286
+ "metadata": {},
287
+ "outputs": [
288
+ {
289
+ "name": "stdout",
290
+ "output_type": "stream",
291
+ "text": [
292
+ "Running on local URL: http://127.0.0.1:7863/\n",
293
+ "Running on public URL: https://55030.gradio.app\n",
294
+ "\n",
295
+ "This share link expires in 72 hours. For free permanent hosting, check out Spaces (https://huggingface.co/spaces)\n"
296
+ ]
297
+ },
298
+ {
299
+ "data": {
300
+ "text/html": [
301
+ "\n",
302
+ " <iframe\n",
303
+ " width=\"900\"\n",
304
+ " height=\"500\"\n",
305
+ " src=\"https://55030.gradio.app\"\n",
306
+ " frameborder=\"0\"\n",
307
+ " allowfullscreen\n",
308
+ " \n",
309
+ " ></iframe>\n",
310
+ " "
311
+ ],
312
+ "text/plain": [
313
+ "<IPython.lib.display.IFrame at 0x7efb8444e190>"
314
+ ]
315
+ },
316
+ "metadata": {},
317
+ "output_type": "display_data"
318
+ },
319
+ {
320
+ "data": {
321
+ "text/plain": [
322
+ "(<fastapi.applications.FastAPI at 0x7efbdecab100>,\n",
323
+ " 'http://127.0.0.1:7863/',\n",
324
+ " 'https://55030.gradio.app')"
325
+ ]
326
+ },
327
+ "execution_count": 39,
328
+ "metadata": {},
329
+ "output_type": "execute_result"
330
+ },
331
+ {
332
+ "data": {
333
+ "text/html": [
334
+ "\n",
335
+ "<style>\n",
336
+ " /* Turns off some styling */\n",
337
+ " progress {\n",
338
+ " /* gets rid of default border in Firefox and Opera. */\n",
339
+ " border: none;\n",
340
+ " /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
341
+ " background-size: auto;\n",
342
+ " }\n",
343
+ " .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
344
+ " background: #F44336;\n",
345
+ " }\n",
346
+ "</style>\n"
347
+ ],
348
+ "text/plain": [
349
+ "<IPython.core.display.HTML object>"
350
+ ]
351
+ },
352
+ "metadata": {},
353
+ "output_type": "display_data"
354
+ },
355
+ {
356
+ "data": {
357
+ "text/html": [],
358
+ "text/plain": [
359
+ "<IPython.core.display.HTML object>"
360
+ ]
361
+ },
362
+ "metadata": {},
363
+ "output_type": "display_data"
364
+ }
365
+ ],
366
+ "source": [
367
+ "demo_config = {\n",
368
+ " \"inline\": True,\n",
369
+ " \"inbrowser\": False,\n",
370
+ " \"share\": True,\n",
371
+ " \"show_error\": True,\n",
372
+ " \"enable_queue\": True,\n",
373
+ "}\n",
374
+ "\n",
375
+ "demo.launch(**demo_config)\n"
376
+ ]
377
+ },
378
+ {
379
+ "cell_type": "markdown",
380
+ "metadata": {},
381
+ "source": [
382
+ "Once we got things working, we need to put all the above into an `app.py` file like so:\n",
383
+ "\n"
384
+ ]
385
+ },
386
+ {
387
+ "cell_type": "markdown",
388
+ "metadata": {},
389
+ "source": [
390
+ "## Step 3: Deploy\n",
391
+ "\n",
392
+ "We'll be deploying our Gradio demo to [HuggingFace Spaces](https://huggingface.co/spaces), which Tanishq desrbies like this:\n",
393
+ "\n",
394
+ "> ... a free-to-use platform for hosting machine learning demos and apps [providing] a CPU environment with 16 GB RAM and 8 cores [and support for both] Gradio and Streamlit platforms.\n",
395
+ "\n",
396
+ "Here's how its done ..."
397
+ ]
398
+ },
399
+ {
400
+ "cell_type": "markdown",
401
+ "metadata": {},
402
+ "source": [
403
+ "### Create your \"Space\"\n",
404
+ "\n",
405
+ "We start by creating a new space on the aptly named [\"Create a new Space\"](https://huggingface.co/new-space) page.\n",
406
+ "\n",
407
+ "I'll be using my favorite \"License\", wtfpl and setting this up for use on the fastai organization hosted on Hugging Face. I'm naming the space so folks will know it derives from lessons learned in the first session of the 2022 fastai course.\n",
408
+ "\n",
409
+ "![](hf_space_create.png)\n"
410
+ ]
411
+ },
412
+ {
413
+ "cell_type": "markdown",
414
+ "metadata": {},
415
+ "source": [
416
+ "### Define your `app.py`\n",
417
+ "\n",
418
+ "Spaces are organized as a git repo that contains an `app.py` file with all your inference and interface configuration information. This contents of this file look like this:\n",
419
+ "\n",
420
+ "```python\n",
421
+ "from fastai.vision.all import *\n",
422
+ "from fastcore.all import *\n",
423
+ "import gradio as gr\n",
424
+ "\n",
425
+ "data_path = Path(\"./data\")\n",
426
+ "models_path = Path(\"./models\")\n",
427
+ "examples_path = Path(\"./examples\")\n",
428
+ "\n",
429
+ "\n",
430
+ "def is_marvel(img):\n",
431
+ " return 1.0 if img.parent.name.lower().startswith(\"marvel\") else 0.0\n",
432
+ "\n",
433
+ "\n",
434
+ "inf_learn = load_learner(models_path / \"export.pkl\")\n",
435
+ "\n",
436
+ "\n",
437
+ "def predict(img):\n",
438
+ " pred, _, _ = inf_learn.predict(img)\n",
439
+ " return f\"{pred[0]*100:.2f}%\"\n",
440
+ "\n",
441
+ "\n",
442
+ "with open(\"gradio_article.md\") as f:\n",
443
+ " article = f.read()\n",
444
+ "\n",
445
+ "interface_config = {\n",
446
+ " \"title\": \"Is it a Marvel Character?\",\n",
447
+ " \"description\": \"For those wanting to make sure they are rooting on the right heroes. Based on Jeremy Howards ['Is it a bird? Creating a model from your own data'](https://www.kaggle.com/code/jhoward/is-it-a-bird-creating-a-model-from-your-own-data)\",\n",
448
+ " \"article\": article,\n",
449
+ " \"examples\": [f\"{examples_path}/{f.name}\" for f in examples_path.iterdir()],\n",
450
+ " \"interpretation\": None,\n",
451
+ " \"layout\": \"horizontal\",\n",
452
+ " \"allow_flagging\": \"never\",\n",
453
+ "}\n",
454
+ "\n",
455
+ "demo = gr.Interface(\n",
456
+ " fn=predict,\n",
457
+ " inputs=gr.inputs.Image(shape=(512, 512)),\n",
458
+ " outputs=gr.outputs.Textbox(label=\"Marvel character probability\"),\n",
459
+ " **interface_config,\n",
460
+ ")\n",
461
+ "\n",
462
+ "demo_config = {\n",
463
+ " \"inline\": True,\n",
464
+ " \"inbrowser\": False,\n",
465
+ " \"share\": True,\n",
466
+ " \"show_error\": True,\n",
467
+ " \"enable_queue\": True,\n",
468
+ "}\n",
469
+ "\n",
470
+ "demo.launch()\n",
471
+ "```\n"
472
+ ]
473
+ },
474
+ {
475
+ "cell_type": "markdown",
476
+ "metadata": {},
477
+ "source": [
478
+ "### Define a `requirements.txt`\n",
479
+ "\n",
480
+ "We'll also include a `requirements.txt` file with the libraries required for our demo like so:\n",
481
+ "\n",
482
+ "```\n",
483
+ "fastai\n",
484
+ "gradio\n",
485
+ "```"
486
+ ]
487
+ },
488
+ {
489
+ "cell_type": "code",
490
+ "execution_count": null,
491
+ "metadata": {},
492
+ "outputs": [],
493
+ "source": [
494
+ "\n"
495
+ ]
496
+ }
497
+ ],
498
+ "metadata": {
499
+ "interpreter": {
500
+ "hash": "8d7a979f659379f6312caf3993ac2ab4b165620bf8bd7cd5a3069321dc3c91fd"
501
+ },
502
+ "kernelspec": {
503
+ "display_name": "Python 3.9.12 ('fastexamples')",
504
+ "language": "python",
505
+ "name": "python3"
506
+ },
507
+ "language_info": {
508
+ "codemirror_mode": {
509
+ "name": "ipython",
510
+ "version": 3
511
+ },
512
+ "file_extension": ".py",
513
+ "mimetype": "text/x-python",
514
+ "name": "python",
515
+ "nbconvert_exporter": "python",
516
+ "pygments_lexer": "ipython3",
517
+ "version": "3.9.12"
518
+ },
519
+ "orig_nbformat": 4
520
+ },
521
+ "nbformat": 4,
522
+ "nbformat_minor": 2
523
+ }
nbs/gradio_queue.db ADDED
Binary file (32.8 kB). View file
nbs/train.ipynb ADDED
The diff for this file is too large to render. See raw diff
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
1
+ fastai==2.6.0
2
+ gradio