mipbkhn commited on
Commit
7537fbd
1 Parent(s): beb1bca
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ rsna-pneumonia-detection-challenge/
2
+ rsna-pneumonia-detection-challenge.zip
3
+ data/
.gradioignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ rsna-pneumonia-detection-challenge/
2
+ rsna-pneumonia-detection-challenge.zip
3
+ data/
README.md CHANGED
@@ -1,10 +1,10 @@
1
  ---
2
- title: PneumoniaDetectionPublic
3
- emoji: 🦀
4
- colorFrom: red
5
- colorTo: pink
6
  sdk: gradio
7
- sdk_version: 3.41.2
8
  app_file: app.py
9
  pinned: false
10
  ---
 
1
  ---
2
+ title: Pneumonia Detection
3
+ emoji: 📈
4
+ colorFrom: blue
5
+ colorTo: indigo
6
  sdk: gradio
7
+ sdk_version: 3.29.0
8
  app_file: app.py
9
  pinned: false
10
  ---
app.ipynb ADDED
@@ -0,0 +1,446 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "87345732-d868-473b-b1a1-5c25839ce25b",
7
+ "metadata": {
8
+ "id": "87345732-d868-473b-b1a1-5c25839ce25b"
9
+ },
10
+ "outputs": [],
11
+ "source": [
12
+ "import gradio\n",
13
+ "from fastai.vision.all import *"
14
+ ]
15
+ },
16
+ {
17
+ "cell_type": "code",
18
+ "execution_count": 2,
19
+ "id": "5409c6a7-5cae-42bb-8335-587a04471f22",
20
+ "metadata": {
21
+ "id": "5409c6a7-5cae-42bb-8335-587a04471f22"
22
+ },
23
+ "outputs": [],
24
+ "source": [
25
+ "MODELS_PATH = Path(\"./models\")\n",
26
+ "EXAMPLES_PATH = Path('./examples')"
27
+ ]
28
+ },
29
+ {
30
+ "cell_type": "code",
31
+ "execution_count": 3,
32
+ "id": "c6ad64e8-f163-4472-b2f0-c0aa50ead4d8",
33
+ "metadata": {
34
+ "id": "c6ad64e8-f163-4472-b2f0-c0aa50ead4d8"
35
+ },
36
+ "outputs": [],
37
+ "source": [
38
+ "learn = load_learner(MODELS_PATH/'model.pkl')"
39
+ ]
40
+ },
41
+ {
42
+ "cell_type": "code",
43
+ "execution_count": 4,
44
+ "id": "d1370d20-fd51-4512-bd28-5f170d216c7b",
45
+ "metadata": {
46
+ "id": "d1370d20-fd51-4512-bd28-5f170d216c7b",
47
+ "outputId": "a6b86c72-7763-43fa-a04d-ba8c2e94793f"
48
+ },
49
+ "outputs": [
50
+ {
51
+ "data": {
52
+ "text/plain": [
53
+ "['Negative', 'Positive']"
54
+ ]
55
+ },
56
+ "execution_count": 4,
57
+ "metadata": {},
58
+ "output_type": "execute_result"
59
+ }
60
+ ],
61
+ "source": [
62
+ "labels = learn.dls.vocab\n",
63
+ "labels"
64
+ ]
65
+ },
66
+ {
67
+ "cell_type": "code",
68
+ "execution_count": 5,
69
+ "id": "a360dd6b-75a9-43e5-b91d-c6963ea462ea",
70
+ "metadata": {
71
+ "id": "a360dd6b-75a9-43e5-b91d-c6963ea462ea"
72
+ },
73
+ "outputs": [],
74
+ "source": [
75
+ "def predict(img):\n",
76
+ " img = PILImage.create(img)\n",
77
+ " _pred, _pred_w_idx, probs = learn.predict(img)\n",
78
+ " labels_probs = {labels[i]: float(probs[i]) for i, _ in enumerate(labels)}\n",
79
+ " return labels_probs"
80
+ ]
81
+ },
82
+ {
83
+ "cell_type": "code",
84
+ "execution_count": 6,
85
+ "id": "febc7266-8587-4530-811b-f2fa9117dcd5",
86
+ "metadata": {
87
+ "id": "febc7266-8587-4530-811b-f2fa9117dcd5"
88
+ },
89
+ "outputs": [],
90
+ "source": [
91
+ "with open('gradio_article.md') as f:\n",
92
+ " article = f.read()"
93
+ ]
94
+ },
95
+ {
96
+ "cell_type": "code",
97
+ "execution_count": 7,
98
+ "id": "8fd4ffb4-11ca-4b25-999c-cde2a4e236b4",
99
+ "metadata": {
100
+ "id": "8fd4ffb4-11ca-4b25-999c-cde2a4e236b4",
101
+ "outputId": "254d01cb-835b-4710-f415-f7f3d56ab0bd"
102
+ },
103
+ "outputs": [],
104
+ "source": [
105
+ "interface_options = {\n",
106
+ " \"title\": \"RSNA Pneumonia Detection\",\n",
107
+ " \"description\": \"An algorithm that automatically detects potential pneumonia cases\",\n",
108
+ " \"article\": article,\n",
109
+ " \"examples\": [f'{EXAMPLES_PATH}/{f.name}' for f in EXAMPLES_PATH.iterdir()],\n",
110
+ " \"layout\": \"horizontal\",\n",
111
+ " \"theme\": \"default\",\n",
112
+ "}\n",
113
+ "\n",
114
+ "demo_options = {\n",
115
+ " \"inline\": False,\n",
116
+ " \"inbrowser\": True,\n",
117
+ " \"share\": False,\n",
118
+ " \"show_error\": True,\n",
119
+ " \"server_name\": \"0.0.0.0\",\n",
120
+ " \"server_port\": 9999,\n",
121
+ " \"enable_queue\": True,\n",
122
+ "}\n",
123
+ "\n",
124
+ "# demo = gradio.Interface(fn=predict,\n",
125
+ "# inputs=gradio.inputs.Image(shape=(512, 512)),\n",
126
+ "# outputs=gradio.outputs.Label(num_top_classes=5),\n",
127
+ "# **interface_options)\n",
128
+ "\n",
129
+ "# demo.launch(**demo_options)"
130
+ ]
131
+ },
132
+ {
133
+ "cell_type": "code",
134
+ "execution_count": 109,
135
+ "id": "38ed16c9",
136
+ "metadata": {},
137
+ "outputs": [],
138
+ "source": [
139
+ "examples = [f'{EXAMPLES_PATH}/{f.name}' for f in EXAMPLES_PATH.iterdir()]\n",
140
+ "from random import choice\n",
141
+ "\n",
142
+ "example = choice(examples)\n",
143
+ "img = PILImage.create(example)\n"
144
+ ]
145
+ },
146
+ {
147
+ "cell_type": "code",
148
+ "execution_count": 110,
149
+ "id": "81974150",
150
+ "metadata": {},
151
+ "outputs": [
152
+ {
153
+ "data": {
154
+ "text/plain": [
155
+ "'Positive'"
156
+ ]
157
+ },
158
+ "execution_count": 110,
159
+ "metadata": {},
160
+ "output_type": "execute_result"
161
+ }
162
+ ],
163
+ "source": [
164
+ "x, = first(learn.dls.test_dl([img]))\n",
165
+ "with torch.no_grad():\n",
166
+ " output = learn.model.eval()(x)\n",
167
+ "cls = int(output.argmax())\n",
168
+ "learn.dls.vocab[cls]"
169
+ ]
170
+ },
171
+ {
172
+ "cell_type": "code",
173
+ "execution_count": 111,
174
+ "id": "fdad2f6f",
175
+ "metadata": {},
176
+ "outputs": [
177
+ {
178
+ "data": {
179
+ "image/png": "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",
180
+ "text/plain": [
181
+ "<Figure size 432x288 with 1 Axes>"
182
+ ]
183
+ },
184
+ "metadata": {
185
+ "needs_background": "light"
186
+ },
187
+ "output_type": "display_data"
188
+ }
189
+ ],
190
+ "source": [
191
+ "class Hook():\n",
192
+ " def __init__(self, m):\n",
193
+ " self.hook = m.register_forward_hook(self.hook_func) \n",
194
+ " def hook_func(self, m, i, o): self.stored = o.detach().clone()\n",
195
+ " def __enter__(self, *args): return self\n",
196
+ " def __exit__(self, *args): self.hook.remove()\n",
197
+ "\n",
198
+ "class HookBwd():\n",
199
+ " def __init__(self, m):\n",
200
+ " self.hook = m.register_backward_hook(self.hook_func) \n",
201
+ " def hook_func(self, m, gi, go): self.stored = go[0].detach().clone()\n",
202
+ " def __enter__(self, *args): return self\n",
203
+ " def __exit__(self, *args): self.hook.remove()\n",
204
+ "\n",
205
+ "x_dec = TensorImage(learn.dls.train.decode((x,))[0][0])\n",
206
+ "with HookBwd(learn.model[0].model.layer4) as hookg:\n",
207
+ " with Hook(learn.model[0].model.layer4]) as hook:\n",
208
+ " output = learn.model.eval()(x)\n",
209
+ " act = hook.stored\n",
210
+ " output[0,cls].backward()\n",
211
+ " grad = hookg.stored\n",
212
+ "\n",
213
+ "w = grad[0].mean(dim=[1,2], keepdim=True)\n",
214
+ "cam_map = (w * act[0]).sum(0)\n",
215
+ "\n",
216
+ "_,ax = plt.subplots()\n",
217
+ "x_dec.show(ctx=ax)\n",
218
+ "ax.imshow(cam_map.detach().cpu(), alpha=0.7, extent=(0,128,128,0),\n",
219
+ " interpolation='bilinear', cmap='magma');"
220
+ ]
221
+ },
222
+ {
223
+ "cell_type": "code",
224
+ "execution_count": 49,
225
+ "id": "942067b5",
226
+ "metadata": {},
227
+ "outputs": [
228
+ {
229
+ "data": {
230
+ "text/plain": [
231
+ "Sequential(\n",
232
+ " (0): Bottleneck(\n",
233
+ " (conv1): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
234
+ " (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
235
+ " (act1): ReLU(inplace=True)\n",
236
+ " (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
237
+ " (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
238
+ " (drop_block): Identity()\n",
239
+ " (act2): ReLU(inplace=True)\n",
240
+ " (aa): Identity()\n",
241
+ " (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
242
+ " (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
243
+ " (act3): ReLU(inplace=True)\n",
244
+ " (downsample): Sequential(\n",
245
+ " (0): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
246
+ " (1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
247
+ " )\n",
248
+ " )\n",
249
+ " (1): Bottleneck(\n",
250
+ " (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
251
+ " (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
252
+ " (act1): ReLU(inplace=True)\n",
253
+ " (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
254
+ " (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
255
+ " (drop_block): Identity()\n",
256
+ " (act2): ReLU(inplace=True)\n",
257
+ " (aa): Identity()\n",
258
+ " (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
259
+ " (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
260
+ " (act3): ReLU(inplace=True)\n",
261
+ " )\n",
262
+ " (2): Bottleneck(\n",
263
+ " (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
264
+ " (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
265
+ " (act1): ReLU(inplace=True)\n",
266
+ " (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
267
+ " (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
268
+ " (drop_block): Identity()\n",
269
+ " (act2): ReLU(inplace=True)\n",
270
+ " (aa): Identity()\n",
271
+ " (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
272
+ " (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
273
+ " (act3): ReLU(inplace=True)\n",
274
+ " )\n",
275
+ ")"
276
+ ]
277
+ },
278
+ "execution_count": 49,
279
+ "metadata": {},
280
+ "output_type": "execute_result"
281
+ }
282
+ ],
283
+ "source": [
284
+ "learn.model[0].model.layer4"
285
+ ]
286
+ },
287
+ {
288
+ "cell_type": "code",
289
+ "execution_count": 17,
290
+ "id": "bd6fc5be",
291
+ "metadata": {},
292
+ "outputs": [
293
+ {
294
+ "name": "stderr",
295
+ "output_type": "stream",
296
+ "text": [
297
+ "/tmp/ipykernel_365035/2218158489.py:29: GradioDeprecationWarning: Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your component from gradio.components\n",
298
+ " inputs=gradio.inputs.Image(shape=(512, 512)),\n",
299
+ "/tmp/ipykernel_365035/2218158489.py:29: GradioDeprecationWarning: `optional` parameter is deprecated, and it has no effect\n",
300
+ " inputs=gradio.inputs.Image(shape=(512, 512)),\n",
301
+ "/tmp/ipykernel_365035/2218158489.py:30: GradioDeprecationWarning: Usage of gradio.outputs is deprecated, and will not be supported in the future, please import your components from gradio.components\n",
302
+ " outputs=[gradio.outputs.Label(num_top_classes=5, label=\"Detected Class\"),\n",
303
+ "/tmp/ipykernel_365035/2218158489.py:30: GradioUnusedKwargWarning: You have unused kwarg parameters in Label, please remove them: {'type': 'auto'}\n",
304
+ " outputs=[gradio.outputs.Label(num_top_classes=5, label=\"Detected Class\"),\n",
305
+ "/tmp/ipykernel_365035/2218158489.py:31: GradioDeprecationWarning: Usage of gradio.outputs is deprecated, and will not be supported in the future, please import your components from gradio.components\n",
306
+ " gradio.outputs.Image(type=\"filepath\", label=\"GradCAM\")],\n",
307
+ "/tmp/ipykernel_365035/2218158489.py:28: GradioDeprecationWarning: `layout` parameter is deprecated, and it has no effect\n",
308
+ " demo = gradio.Interface(fn=predict,\n",
309
+ "/tmp/ipykernel_365035/2218158489.py:34: GradioDeprecationWarning: The `enable_queue` parameter has been deprecated. Please use the `.queue()` method instead.\n",
310
+ " demo.launch(**demo_options)\n"
311
+ ]
312
+ },
313
+ {
314
+ "name": "stdout",
315
+ "output_type": "stream",
316
+ "text": [
317
+ "Running on local URL: http://0.0.0.0:9999\n",
318
+ "\n",
319
+ "To create a public link, set `share=True` in `launch()`.\n"
320
+ ]
321
+ },
322
+ {
323
+ "data": {
324
+ "text/plain": []
325
+ },
326
+ "execution_count": 17,
327
+ "metadata": {},
328
+ "output_type": "execute_result"
329
+ },
330
+ {
331
+ "data": {
332
+ "text/html": [
333
+ "\n",
334
+ "<style>\n",
335
+ " /* Turns off some styling */\n",
336
+ " progress {\n",
337
+ " /* gets rid of default border in Firefox and Opera. */\n",
338
+ " border: none;\n",
339
+ " /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
340
+ " background-size: auto;\n",
341
+ " }\n",
342
+ " progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
343
+ " background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
344
+ " }\n",
345
+ " .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
346
+ " background: #F44336;\n",
347
+ " }\n",
348
+ "</style>\n"
349
+ ],
350
+ "text/plain": [
351
+ "<IPython.core.display.HTML object>"
352
+ ]
353
+ },
354
+ "metadata": {},
355
+ "output_type": "display_data"
356
+ },
357
+ {
358
+ "data": {
359
+ "text/html": [],
360
+ "text/plain": [
361
+ "<IPython.core.display.HTML object>"
362
+ ]
363
+ },
364
+ "metadata": {},
365
+ "output_type": "display_data"
366
+ },
367
+ {
368
+ "name": "stderr",
369
+ "output_type": "stream",
370
+ "text": [
371
+ "/opt/conda/lib/python3.8/site-packages/torch/nn/modules/module.py:1052: UserWarning: Using a non-full backward hook when the forward contains multiple autograd Nodes is deprecated and will be removed in future versions. This hook will be missing some grad_input. Please use register_full_backward_hook to get the documented behavior.\n",
372
+ " warnings.warn(\"Using a non-full backward hook when the forward contains multiple autograd Nodes \"\n"
373
+ ]
374
+ }
375
+ ],
376
+ "source": [
377
+ "def predict(img):\n",
378
+ " img = PILImage.create(img)\n",
379
+ " _pred, _pred_w_idx, probs = learn.predict(img)\n",
380
+ " labels_probs = {labels[i]: float(probs[i]) for i, _ in enumerate(labels)}\n",
381
+ "\n",
382
+ "\n",
383
+ " x, = first(learn.dls.test_dl([img]))\n",
384
+ " x_dec = TensorImage(learn.dls.train.decode((x,))[0][0])\n",
385
+ " with HookBwd(learn.model[0].model.layer4) as hookg:\n",
386
+ " with Hook(learn.model[0].model.layer4) as hook:\n",
387
+ " output = learn.model.eval()(x)\n",
388
+ " act = hook.stored\n",
389
+ " output[0,cls].backward()\n",
390
+ " grad = hookg.stored\n",
391
+ "\n",
392
+ " w = grad[0].mean(dim=[1,2], keepdim=True)\n",
393
+ " cam_map = (w * act[0]).sum(0)\n",
394
+ "\n",
395
+ " _,ax = plt.subplots()\n",
396
+ " x_dec.show(ctx=ax)\n",
397
+ " ax.imshow(cam_map.detach().cpu(), alpha=0.7, extent=(0,128,128,0),\n",
398
+ " interpolation='bilinear', cmap='magma');\n",
399
+ " plt.savefig(\"gradcam.jpg\", format=\"jpg\")\n",
400
+ " plt.close()\n",
401
+ " \n",
402
+ " return labels_probs, Path(\"gradcam.jpg\")\n",
403
+ "\n",
404
+ "demo = gradio.Interface(fn=predict,\n",
405
+ " inputs=gradio.inputs.Image(shape=(512, 512)),\n",
406
+ " outputs=[gradio.outputs.Label(num_top_classes=5, label=\"Detected Class\"),\n",
407
+ " gradio.outputs.Image(type=\"filepath\", label=\"GradCAM\")],\n",
408
+ " **interface_options)\n",
409
+ "\n",
410
+ "demo.launch(**demo_options)"
411
+ ]
412
+ },
413
+ {
414
+ "cell_type": "code",
415
+ "execution_count": null,
416
+ "id": "67eb0978",
417
+ "metadata": {},
418
+ "outputs": [],
419
+ "source": []
420
+ }
421
+ ],
422
+ "metadata": {
423
+ "colab": {
424
+ "provenance": []
425
+ },
426
+ "kernelspec": {
427
+ "display_name": "Python 3 (ipykernel)",
428
+ "language": "python",
429
+ "name": "python3"
430
+ },
431
+ "language_info": {
432
+ "codemirror_mode": {
433
+ "name": "ipython",
434
+ "version": 3
435
+ },
436
+ "file_extension": ".py",
437
+ "mimetype": "text/x-python",
438
+ "name": "python",
439
+ "nbconvert_exporter": "python",
440
+ "pygments_lexer": "ipython3",
441
+ "version": "3.7.0"
442
+ }
443
+ },
444
+ "nbformat": 4,
445
+ "nbformat_minor": 5
446
+ }
app.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio
2
+ from fastai.vision.all import *
3
+
4
+ MODELS_PATH = Path('./models')
5
+ EXAMPLES_PATH = Path('./examples')
6
+
7
+ learn = load_learner(MODELS_PATH/'model.pkl')
8
+ labels = learn.dls.vocab
9
+
10
+ class Hook():
11
+ def __init__(self, m):
12
+ self.hook = m.register_forward_hook(self.hook_func)
13
+ def hook_func(self, m, i, o): self.stored = o.detach().clone()
14
+ def __enter__(self, *args): return self
15
+ def __exit__(self, *args): self.hook.remove()
16
+
17
+ class HookBwd():
18
+ def __init__(self, m):
19
+ self.hook = m.register_backward_hook(self.hook_func)
20
+ def hook_func(self, m, gi, go): self.stored = go[0].detach().clone()
21
+ def __enter__(self, *args): return self
22
+ def __exit__(self, *args): self.hook.remove()
23
+
24
+ def predict(img):
25
+ img = PILImage.create(img)
26
+ _pred, _pred_w_idx, probs = learn.predict(img)
27
+ labels_probs = {labels[i]: float(probs[i]) for i, _ in enumerate(labels)}
28
+
29
+ x, = first(learn.dls.test_dl([img]))
30
+ with torch.no_grad():
31
+ output = learn.model.eval()(x)
32
+ cls = int(output.argmax())
33
+
34
+ x_dec = TensorImage(learn.dls.train.decode((x,))[0][0])
35
+ with HookBwd(learn.model[0].model.layer4) as hookg:
36
+ with Hook(learn.model[0].model.layer4) as hook:
37
+ output = learn.model.eval()(x)
38
+ act = hook.stored
39
+ output[0,cls].backward()
40
+ grad = hookg.stored
41
+
42
+ w = grad[0].mean(dim=[1,2], keepdim=True)
43
+ cam_map = (w * act[0]).sum(0)
44
+
45
+ _,ax = plt.subplots()
46
+ x_dec.show(ctx=ax)
47
+ ax.imshow(cam_map.detach().cpu(), alpha=0.7, extent=(0,128,128,0),
48
+ interpolation='bilinear', cmap='magma');
49
+ if os.path.exists("gradcam.jpg"):
50
+ os.remove("gradcam.jpg")
51
+ plt.savefig("gradcam.jpg", format="jpg", bbox_inches='tight')
52
+ plt.close()
53
+
54
+ if learn.dls.vocab[cls] == "Negative":
55
+ img.save("gradcam.jpg", format="JPEG")
56
+
57
+ return labels_probs, Path("gradcam.jpg")
58
+
59
+ with open('gradio_article.md') as f:
60
+ article = f.read()
61
+
62
+ interface_options = {
63
+ "title": "RSNA Pneumonia Detection",
64
+ "description": "An algorithm that automatically detects potential pneumonia cases. Upload an image or select from the examples below.",
65
+ "examples": [f'{EXAMPLES_PATH}/{f.name}' for f in EXAMPLES_PATH.iterdir()],
66
+ "article": article,
67
+ "layout": "horizontal",
68
+ "theme": "default",
69
+ }
70
+
71
+ demo = gradio.Interface(fn=predict,
72
+ inputs=gradio.inputs.Image(shape=(512, 512), label="Chest X-ray"),
73
+ outputs=[gradio.outputs.Label(num_top_classes=5, label="Detected Class"),
74
+ gradio.outputs.Image(type="filepath", label="GradCAM")],
75
+ **interface_options)
76
+
77
+ launch_options = {
78
+ "enable_queue": True,
79
+ "share": False,
80
+ }
81
+
82
+ demo.launch(**launch_options)
examples/00.jpg ADDED
examples/00a85be6-6eb0-421d-8acf-ff2dc0007e8a.jpg ADDED
examples/00c.jpg ADDED
examples/00dd08bb-b7ea-4617-801e-02b3051c3475.jpg ADDED
examples/00ddefb9-d94e-4e86-b945-970be30483d7.jpg ADDED
examples/7342f4bc-2ce8-4d13-b820-7d90f8804a1b.jpg ADDED
examples/7471b0e8-8f55-4ced-b8e4-18a7554a0ebe.jpg ADDED
examples/7507bb99-a8cf-48c8-a4dd-859ad26e9e1a.jpg ADDED
examples/8888.jpg ADDED
gradcam.jpg ADDED
gradio_article.md ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ ## Description
3
+ Here, I present a compelling algorithm designed to identify crucial visual markers of pneumonia in medical images. The focus of this demonstration revolves around autonomously recognizing lung opacity regions within chest radiographs.
4
+
5
+ The Challenge:
6
+ The task at hand involves crafting an algorithm capable of autonomously pinpointing areas of lung opacity within chest radiographs – a critical step in detecting pneumonia indicators. This challenge carries substantial significance in the context of medical diagnosis and patient care.
7
+
8
+ Addressing a Global Health Concern:
9
+ Pneumonia remains a significant global health concern, accounting for over 15% of child deaths under the age of 5 worldwide. In a single year, 920,000 children lost their lives due to pneumonia in this age group. The impact is evident even in developed nations like the United States, where pneumonia resulted in over 500,000 emergency department visits and more than 50,000 deaths in a single year, ranking among the top 10 causes of mortality.
10
+
11
+ [![alt text](https://storage.googleapis.com/kaggle-media/competitions/rsna/Kaggle_Banner.jpg)](link_url)
12
+
13
+ Navigating Diagnostic Complexity:
14
+ Accurate diagnosis of pneumonia is a complex task, necessitating careful analysis of chest radiographs by specialized experts. These radiographs often exhibit regions of heightened opacity, indicating potential pneumonia presence. However, distinguishing pneumonia from other lung-related conditions such as edema, bleeding, and atelectasis poses a significant challenge. Moreover, opacity can arise from conditions beyond lung issues, such as pleural effusion. Accurate diagnosis often involves comparing multiple radiographs over time, along with clinical data.
15
+
16
+ Unraveling Radiograph Interpretation:
17
+ Chest radiographs are fundamental diagnostic tools, but their interpretation is influenced by variables like patient positioning and breath depth. This complexity is compounded by the sheer volume of images that medical professionals review during each shift.
models/model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2bb70727874cb1bdc7de8d8e83b7b8d649cadf075b146b74eb67763b23be94ae
3
+ size 103381781
models/tmpozvoncd2/_tmp.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e6a170a3f28026a1c0b5a9e97be4dbd0f78a87c3220f575d6b17244240d62d92
3
+ size 102828397
predictions.csv ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ patientId,PredictionString
2
+ 0004cfab-14fd-4e49-80ba-63a80b6bddd6,0.5 0 0 100 100
3
+ 00313ee0-9eaa-42f4-b0ab-c148ed3241cd,
4
+ 00322d4d-1c29-4943-afc9-b6754be640eb,0.8 10 10 50 50 0.75 100 100 5 5
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ fastai==2.7.12
2
+ gradio==3.39.0
3
+ typing_extensions==4.7.1
4
+ timm
train01.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
train02.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
train03_wbbox.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
train04_jpg.ipynb ADDED
The diff for this file is too large to render. See raw diff