Spaces:
Sleeping
Sleeping
| # ββ Gradio μ€μΉ ββββββββββββββββββββββββββ | |
| import gradio as gr | |
| import torch | |
| import torch.nn as nn | |
| import torchvision.transforms as transforms | |
| from PIL import Image | |
| from datasets import load_dataset | |
| # ββ ν΄λμ€ μ΄λ¦ κ°μ Έμ€κΈ° ββββββββββββββββββ | |
| dataset = load_dataset("food101", split="train[:1%]") | |
| class_names = dataset.features['label'].names | |
| # ββ λͺ¨λΈ μ μ (λκ°μ΄ λΆμ¬λ£κΈ°) βββββββββββ | |
| class BottleneckBlock(nn.Module): | |
| expansion = 4 | |
| def __init__(self, in_channels, mid_channels, stride=1): | |
| super().__init__() | |
| self.conv1 = nn.Conv2d(in_channels, mid_channels, kernel_size=1, bias=False) | |
| self.bn1 = nn.BatchNorm2d(mid_channels) | |
| self.conv2 = nn.Conv2d(mid_channels, mid_channels, kernel_size=3, | |
| stride=stride, padding=1, bias=False) | |
| self.bn2 = nn.BatchNorm2d(mid_channels) | |
| self.conv3 = nn.Conv2d(mid_channels, mid_channels * self.expansion, | |
| kernel_size=1, bias=False) | |
| self.bn3 = nn.BatchNorm2d(mid_channels * self.expansion) | |
| self.relu = nn.ReLU(inplace=True) | |
| self.shortcut = nn.Sequential() | |
| if stride != 1 or in_channels != mid_channels * self.expansion: | |
| self.shortcut = nn.Sequential( | |
| nn.Conv2d(in_channels, mid_channels * self.expansion, | |
| kernel_size=1, stride=stride, bias=False), | |
| nn.BatchNorm2d(mid_channels * self.expansion) | |
| ) | |
| def forward(self, x): | |
| identity = x | |
| out = self.relu(self.bn1(self.conv1(x))) | |
| out = self.relu(self.bn2(self.conv2(out))) | |
| out = self.bn3(self.conv3(out)) | |
| out += self.shortcut(identity) | |
| out = self.relu(out) | |
| return out | |
| class ResNet50(nn.Module): | |
| def __init__(self, num_classes=101): | |
| super().__init__() | |
| self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False) | |
| self.bn1 = nn.BatchNorm2d(64) | |
| self.relu = nn.ReLU(inplace=True) | |
| self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) | |
| self.layer1 = self._make_layer( 64, 64, blocks=3, stride=1) | |
| self.layer2 = self._make_layer(256, 128, blocks=4, stride=2) | |
| self.layer3 = self._make_layer(512, 256, blocks=6, stride=2) | |
| self.layer4 = self._make_layer(1024, 512, blocks=3, stride=2) | |
| self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) | |
| self.fc = nn.Linear(2048, num_classes) | |
| def _make_layer(self, in_channels, mid_channels, blocks, stride): | |
| layers = [BottleneckBlock(in_channels, mid_channels, stride=stride)] | |
| for _ in range(1, blocks): | |
| layers.append(BottleneckBlock(mid_channels * 4, mid_channels)) | |
| return nn.Sequential(*layers) | |
| def forward(self, x): | |
| x = self.maxpool(self.relu(self.bn1(self.conv1(x)))) | |
| x = self.layer1(x) | |
| x = self.layer2(x) | |
| x = self.layer3(x) | |
| x = self.layer4(x) | |
| x = self.avgpool(x) | |
| x = torch.flatten(x, 1) | |
| x = self.fc(x) | |
| return x | |
| # ββ λͺ¨λΈ λΆλ¬μ€κΈ° βββββββββββββββββββββββββ | |
| device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') | |
| model = ResNet50(num_classes=101) | |
| model.load_state_dict( | |
| torch.load('resnet50_food101.pth', map_location=device) | |
| ) | |
| model = model.to(device) | |
| model.eval() | |
| # ββ μ μ²λ¦¬ ββββββββββββββββββββββββββββββββ | |
| transform = transforms.Compose([ | |
| transforms.Resize((224, 224)), | |
| transforms.ToTensor(), | |
| transforms.Normalize( | |
| mean=[0.485, 0.456, 0.406], | |
| std=[0.229, 0.224, 0.225] | |
| ) | |
| ]) | |
| # ββ μμΈ‘ ν¨μ βββββββββββββββββββββββββββββ | |
| def predict(image): | |
| # PIL μ΄λ―Έμ§ β ν μ λ³ν | |
| img_tensor = transform(image).unsqueeze(0).to(device) | |
| # unsqueeze(0) = (3,224,224) β (1,3,224,224) λ°°μΉ μ°¨μ μΆκ° | |
| with torch.no_grad(): | |
| output = model(img_tensor) | |
| probs = torch.softmax(output, dim=1) # μ μ β νλ₯ | |
| top5 = probs.topk(5) # μμ 5κ° | |
| # κ²°κ³Ό λμ λλ¦¬λ‘ λ°ν | |
| result = {} | |
| for i in range(5): | |
| label = class_names[top5.indices[0][i].item()] | |
| prob = top5.values[0][i].item() | |
| result[label] = prob | |
| return result | |
| # ββ Gradio μΈν°νμ΄μ€ ββββββββββββββββββββββ | |
| demo = gr.Interface( | |
| fn=predict, # μμΈ‘ ν¨μ | |
| inputs=gr.Image(type="pil"), # μ λ ₯: μ΄λ―Έμ§ | |
| outputs=gr.Label(num_top_classes=5), # μΆλ ₯: μμ 5κ° ν΄λμ€ | |
| title="π Food-101 λΆλ₯κΈ°", | |
| description="μμ μ¬μ§μ μ¬λ¦¬λ©΄ μ΄λ€ μμμΈμ§ λ§μΆ°μ€μ! (101κ°μ§ μμ λΆλ₯)", | |
| examples=[], # μμ μ΄λ―Έμ§ (μμΌλ©΄ μΆκ°) | |
| ) | |
| demo.launch() |