arpandesign commited on
Commit
12c7f66
·
verified ·
1 Parent(s): 16849c3

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -0
app.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import random
3
+ from PIL import Image, ImageEnhance
4
+ import torch
5
+ from glob import glob
6
+ from torch import nn
7
+ from torchvision import transforms
8
+
9
+ def predict_number(custom_image: Image.Image):
10
+
11
+ custom_image = ImageEnhance.Contrast(custom_image.convert("L")).enhance(5.0).point(lambda p: 255 if p > 128 else 0).resize((28, 28))
12
+
13
+ transform = transforms.Compose([
14
+ transforms.ToTensor(),
15
+ ])
16
+
17
+ model_0.eval()
18
+ with torch.inference_mode():
19
+ pred = torch.softmax(model_0(transform(custom_image).unsqueeze(0).to(device)), dim=1)
20
+
21
+ class_names = list("0123456789")
22
+ return {class_names[i]: float(pred[0][i]) for i in range(len(class_names))}
23
+
24
+ class NumberClassifier(nn.Module):
25
+
26
+ def __init__(self, input_shape: int, hidden_units: int, output_shape: int) -> None:
27
+ super().__init__()
28
+ self.conv_block_1 = nn.Sequential(
29
+ nn.Conv2d(in_channels=input_shape,
30
+ out_channels=hidden_units,
31
+ kernel_size=2, # how big is the square that's going over the image?
32
+ stride=1, # default
33
+ ), # options = "valid" (no padding) or "same" (output has same shape as input) or int for specific number
34
+ nn.ReLU(),
35
+ nn.Conv2d(in_channels=hidden_units,
36
+ out_channels=hidden_units,
37
+ kernel_size=2,
38
+ stride=1,
39
+ ),
40
+ nn.ReLU(),
41
+ nn.MaxPool2d(kernel_size=2,
42
+ stride=2) # default stride value is same as kernel_size
43
+ )
44
+ self.conv_block_2 = nn.Sequential(
45
+ nn.Conv2d(hidden_units, hidden_units, kernel_size=2),
46
+ nn.ReLU(),
47
+ nn.Conv2d(hidden_units, hidden_units, kernel_size=2),
48
+ nn.ReLU(),
49
+ nn.MaxPool2d(2)
50
+ )
51
+ self.classifier = nn.Sequential(
52
+ nn.Flatten(),
53
+ # Where did this in_features shape come from?
54
+ # It's because each layer of our network compresses and changes the shape of our input data.
55
+ nn.Linear(in_features=hidden_units*5*5,
56
+ out_features=output_shape)
57
+ )
58
+
59
+ def forward(self, x: torch.Tensor):
60
+ x = self.conv_block_1(x)
61
+ # print(x.shape)
62
+ x = self.conv_block_2(x)
63
+ # print(x.shape)
64
+ x = self.classifier(x)
65
+ # print(x.shape)
66
+ return x
67
+ # return self.classifier(self.conv_block_2(self.conv_block_1(x))) # <- leverage the benefits of operator fusion
68
+
69
+ device = "cuda" if torch.cuda.is_available() else "cpu"
70
+ torch.manual_seed(42)
71
+ model_0 = NumberClassifier(input_shape=1, # number of color channels (3 for RGB)
72
+ hidden_units=10,
73
+ output_shape=10).to(device)
74
+
75
+ model_0.load_state_dict(torch.load("/home/arpan/torchenv_learning/models/pytorch_num_classifier_final_model_with_EMNIST.pth"))
76
+
77
+
78
+ title = "Number Classifier Minimal"
79
+ description = "An Image feature extractor computer vision model to classify images of handwritten digits."
80
+ article = "Created at [09. PyTorch Model Deployment](https://www.learnpytorch.io/09_pytorch_model_deployment/)."
81
+ example_list = [[str(filepath)] for filepath in random.sample(glob("/home/arpan/torchenv_learning/showcase_dataset/*"), k=25)]
82
+ example_list
83
+
84
+
85
+ demo = gr.Interface(fn=predict_number,
86
+ inputs=gr.Image(type="pil"),
87
+ outputs=[gr.Label(num_top_classes=10, label="Predictions")],
88
+ examples=example_list,
89
+ title=title,
90
+ description=description,
91
+ article=article)
92
+
93
+
94
+ demo.launch(debug=True, share=True)