Spaces:
Running
Running
added prediction functionality to app and updated dockerfile
Browse files- .dockerignore +1 -0
- Dockerfile +3 -1
- app.py +78 -0
- download_model.py +7 -0
- shinyapp/app.py +0 -20
.dockerignore
CHANGED
@@ -1,3 +1,4 @@
|
|
1 |
*.git
|
2 |
**/__pycache__
|
|
|
3 |
venv
|
|
|
1 |
*.git
|
2 |
**/__pycache__
|
3 |
+
*.pt
|
4 |
venv
|
Dockerfile
CHANGED
@@ -12,6 +12,8 @@ RUN pip install --upgrade pip \
|
|
12 |
|
13 |
COPY . .
|
14 |
|
|
|
|
|
15 |
EXPOSE 3000
|
16 |
|
17 |
-
CMD ["shiny", "run", "
|
|
|
12 |
|
13 |
COPY . .
|
14 |
|
15 |
+
RUN python download_model.py
|
16 |
+
|
17 |
EXPOSE 3000
|
18 |
|
19 |
+
CMD ["shiny", "run", "app.py", "-h", "0.0.0.0", "-p", "3000"]
|
app.py
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from shiny import App, reactive, render, ui
|
2 |
+
from shiny.types import ImgData
|
3 |
+
|
4 |
+
from PIL import Image
|
5 |
+
|
6 |
+
import torch
|
7 |
+
import torchvision.transforms as transforms
|
8 |
+
import modules.model as model
|
9 |
+
|
10 |
+
def forward_prop(image_path):
|
11 |
+
imsize = 128
|
12 |
+
classes = ('Female', 'Male')
|
13 |
+
modelsave_name = 'model_parameters.pt'
|
14 |
+
|
15 |
+
if torch.backends.mps.is_available():
|
16 |
+
device = torch.device('mps')
|
17 |
+
device_name = 'Apple Silicon GPU'
|
18 |
+
elif torch.cuda.is_available():
|
19 |
+
device = torch.device('cuda')
|
20 |
+
device_name = 'CUDA'
|
21 |
+
else:
|
22 |
+
device = torch.device('cpu')
|
23 |
+
device_name = 'CPU'
|
24 |
+
|
25 |
+
torch.set_default_device(device)
|
26 |
+
|
27 |
+
resnet = model.resnetModel_128()
|
28 |
+
resnet.load_state_dict(torch.load(modelsave_name, map_location=device))
|
29 |
+
resnet.eval()
|
30 |
+
|
31 |
+
loader = transforms.Compose([
|
32 |
+
transforms.Resize([imsize, imsize]),
|
33 |
+
transforms.Grayscale(1),
|
34 |
+
transforms.ToTensor(),
|
35 |
+
transforms.Normalize(0, 1)
|
36 |
+
])
|
37 |
+
|
38 |
+
image = Image.open(image_path).convert('RGB')
|
39 |
+
image_tensor = loader(image)
|
40 |
+
image_tensor = image_tensor.unsqueeze(0)
|
41 |
+
|
42 |
+
X = image_tensor.to(device)
|
43 |
+
y_pred = resnet.forward(X)
|
44 |
+
predicted = torch.max(y_pred.data,1)[1]
|
45 |
+
|
46 |
+
return f'Prediction: {classes[predicted]} with weight {y_pred[0][predicted].item()}. Predicted using {device_name}.'
|
47 |
+
|
48 |
+
|
49 |
+
app_ui = ui.page_fluid(
|
50 |
+
ui.panel_title('Image Uploader'),
|
51 |
+
ui.input_file('image', 'Image', accept=['.png', '.jpg', '.jpeg']),
|
52 |
+
ui.output_image('show_image'),
|
53 |
+
ui.input_action_button('predict_gender', 'Predict'),
|
54 |
+
ui.output_text('prediction')
|
55 |
+
)
|
56 |
+
|
57 |
+
def server(input, output, session):
|
58 |
+
@render.image
|
59 |
+
def show_image():
|
60 |
+
if input.image() is None:
|
61 |
+
return None
|
62 |
+
|
63 |
+
image_path = input.image()[0]['datapath']
|
64 |
+
img: ImgData = {'src': image_path}
|
65 |
+
return img
|
66 |
+
|
67 |
+
@render.text
|
68 |
+
@reactive.event(input.predict_gender)
|
69 |
+
def prediction():
|
70 |
+
if input.image() is None:
|
71 |
+
return None
|
72 |
+
|
73 |
+
image_path = input.image()[0]['datapath']
|
74 |
+
prediction = forward_prop(image_path)
|
75 |
+
|
76 |
+
return prediction
|
77 |
+
|
78 |
+
app = App(app_ui, server)
|
download_model.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import gdown
|
3 |
+
|
4 |
+
modelsave_name = 'model_parameters.pt'
|
5 |
+
if os.path.isfile(modelsave_name) == False:
|
6 |
+
url = 'https://drive.google.com/file/d/1_mYn2LrhG080Xvt26tWBtJ8U_0F2E1-s/view?usp=sharing'
|
7 |
+
gdown.download(url, output=modelsave_name, fuzzy=True)
|
shinyapp/app.py
DELETED
@@ -1,20 +0,0 @@
|
|
1 |
-
from shiny import App, render, ui
|
2 |
-
from shiny.types import ImgData
|
3 |
-
|
4 |
-
app_ui = ui.page_fluid(
|
5 |
-
ui.panel_title('Image Uploader'),
|
6 |
-
ui.input_file('image', 'Image', multiple=True, accept=['.png', '.jpg', '.jpeg']),
|
7 |
-
ui.output_image('show_image')
|
8 |
-
)
|
9 |
-
|
10 |
-
def server(input, output, session):
|
11 |
-
@render.image
|
12 |
-
def show_image():
|
13 |
-
if input.image() is None:
|
14 |
-
return None
|
15 |
-
|
16 |
-
image_path = input.image()[0]['datapath']
|
17 |
-
img: ImgData = {'src': image_path}
|
18 |
-
return img
|
19 |
-
|
20 |
-
app = App(app_ui, server)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|