Spaces:
Runtime error
Runtime error
Commit ·
0f83c3b
0
Parent(s):
Initial commit
Browse files- .dockerignore +16 -0
- .gitattributes +5 -0
- .gitignore +10 -0
- Dockerfile +21 -0
- README.md +25 -0
- index.html +102 -0
- main.py +78 -0
- model_training.ipynb +1688 -0
- models/best_model.pth +3 -0
- models/int8_model.onnx +3 -0
- models/onnx_model.onnx +3 -0
- requirements.txt +6 -0
- static/logo.png +3 -0
- static/script.js +244 -0
- static/style.css +186 -0
- test_images/bekon.jpg +3 -0
- test_images/burger_drwala.png +3 -0
- test_images/jajecznica_z_brokulem.jpg +3 -0
- test_images/kotelty_z_ziemniakami.jpeg +3 -0
- test_images/mini_pizza_salami.jpg +3 -0
- test_images/miska_salaty.jpg +3 -0
- test_images/owsianka_z_owocami.jpg +3 -0
- test_images/pizza_slice.jpg +3 -0
- test_images/spaghetti-bolognese.jpg +3 -0
- test_images/stek_z_warzywami.jpg +3 -0
- test_images/super_bowl.png +3 -0
.dockerignore
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Cache Pythona
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.pyc
|
| 4 |
+
|
| 5 |
+
# środowisko badawcze
|
| 6 |
+
*.ipynb
|
| 7 |
+
*.pth
|
| 8 |
+
.git/
|
| 9 |
+
.gitignore
|
| 10 |
+
|
| 11 |
+
# dataset
|
| 12 |
+
food_dataset/
|
| 13 |
+
|
| 14 |
+
# Pliki konfiguracyjne edytora
|
| 15 |
+
.vscode/
|
| 16 |
+
.idea/
|
.gitattributes
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Cache Pythona
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.pyc
|
| 4 |
+
|
| 5 |
+
# dataset
|
| 6 |
+
food_dataset/
|
| 7 |
+
|
| 8 |
+
# Pliki konfiguracyjne edytora
|
| 9 |
+
.vscode/
|
| 10 |
+
.idea/
|
Dockerfile
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 1. Bierzemy Linuxa z gotowym Pythonem 3.10
|
| 2 |
+
FROM python:3.10-bullseye
|
| 3 |
+
|
| 4 |
+
# 2. Tworzymy folder /app wewnątrz kontenera i tam wchodzimy
|
| 5 |
+
WORKDIR /app
|
| 6 |
+
|
| 7 |
+
# 3. Kopiujemy TYLKO plik z listą bibliotek
|
| 8 |
+
COPY requirements.txt .
|
| 9 |
+
|
| 10 |
+
# 4. Instalujemy biblioteki (Docker to zapamięta w cache)
|
| 11 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 12 |
+
|
| 13 |
+
# 5. Kopiujemy całą resztę naszych plików (main.py, index.html, static, modele ONNX)
|
| 14 |
+
COPY . .
|
| 15 |
+
|
| 16 |
+
# 6. Mówimy Dockerowi, że nasza aplikacja będzie gadać przez port 7860
|
| 17 |
+
EXPOSE 7860
|
| 18 |
+
|
| 19 |
+
# 7. Komenda, która odpali się SAMOCZYNNIE po uruchomieniu kontenera
|
| 20 |
+
# Zwróć uwagę na "0.0.0.0" - to wymóg Dockera, żeby wypuścić sygnał na zewnątrz kontenera!
|
| 21 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
|
README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
### Testy inferencji modeli
|
| 2 |
+
|
| 3 |
+
Testy zostały przeprowadzone z inferencją na CPU.
|
| 4 |
+
|
| 5 |
+
| Model | Błąd MAE [KCAL] | Błąd MAE [FAT] | Błąd MAE [CARB] | Błąd MAE [PROTEIN] | Średni czas Inferencji |
|
| 6 |
+
| :--- | :--- | :--- | :--- | :--- | :--- |
|
| 7 |
+
| **PyTorch** | 63.28 | 3.878 | 8.389 | 5.317 | 40.70 ms |
|
| 8 |
+
| **ONNX** | 63.28 | 3.878 | 8.389 | 5.317 | **6.65 ms** |
|
| 9 |
+
| **ONNX INT8** | 92.687 | 5.910 | 10.404 | 7.359 | 41.38 ms |
|
| 10 |
+
|
| 11 |
+
> Najlepszy model ONNX FP32 (bez kwantyzacji), najkrótszy czas inferencji + najlepsze rezultaty, model ten zostanie użyty w API projektu
|
| 12 |
+
|
| 13 |
+
### Uruchomienie projektu (Docker)
|
| 14 |
+
|
| 15 |
+
1. Zbudowanie obrazku Dockera:
|
| 16 |
+
|
| 17 |
+
`docker build -t food-macro-app .`
|
| 18 |
+
|
| 19 |
+
2. Uruchomienie kontenera:
|
| 20 |
+
|
| 21 |
+
`docker run -p 7860:7860 food-macro-app`
|
| 22 |
+
|
| 23 |
+
3. W przeglądarce przejść na adres:
|
| 24 |
+
|
| 25 |
+
`localhost:7860`
|
index.html
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="pl">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>AI Food Macro | Panel MLOps</title>
|
| 7 |
+
<link rel="icon" type="image/jpeg" href="/static/logo.png">
|
| 8 |
+
<link rel="stylesheet" href="/static/style.css">
|
| 9 |
+
</head>
|
| 10 |
+
<body>
|
| 11 |
+
|
| 12 |
+
<button class="toggle-btn" id="btnTest" onclick="openSidebar('test')">🗂️ Dataset</button>
|
| 13 |
+
<button class="toggle-btn" id="btnExternal" onclick="openSidebar('external')">🌍 Spoza Datasetu</button>
|
| 14 |
+
<button class="toggle-btn" id="btnUser" onclick="openSidebar('user')">👤 Użytkownik</button>
|
| 15 |
+
|
| 16 |
+
<div class="main-panel" id="mainPanel">
|
| 17 |
+
<div class="container">
|
| 18 |
+
<h1>AI Food Macro</h1>
|
| 19 |
+
<p id="modeIndicator" class="mode-indicator">Tryb: Nowe zdjęcie</p>
|
| 20 |
+
|
| 21 |
+
<label class="custom-file-upload">
|
| 22 |
+
<input type="file" id="imageInput" accept="image/*" onchange="previewNewImage(event)">
|
| 23 |
+
📸 Kliknij, aby wgrać własne zdjęcie
|
| 24 |
+
</label>
|
| 25 |
+
|
| 26 |
+
<img id="preview" src="" alt="Podgląd zdjęcia">
|
| 27 |
+
|
| 28 |
+
<button id="analyzeBtn" onclick="analyzeImage()" disabled>Analizuj Makro</button>
|
| 29 |
+
|
| 30 |
+
<div class="results" id="resultsPanel">
|
| 31 |
+
<table>
|
| 32 |
+
<thead>
|
| 33 |
+
<tr>
|
| 34 |
+
<th class="emoji-col"></th>
|
| 35 |
+
<th>Makro</th>
|
| 36 |
+
<th>Model</th>
|
| 37 |
+
<th class="truth-col">Prawda</th>
|
| 38 |
+
<th class="truth-col">Błąd</th>
|
| 39 |
+
</tr>
|
| 40 |
+
</thead>
|
| 41 |
+
<tbody>
|
| 42 |
+
<tr>
|
| 43 |
+
<td class="emoji-col">🔥</td>
|
| 44 |
+
<td>Kalorie</td>
|
| 45 |
+
<td class="val-model" id="res-kcal">0 kcal</td>
|
| 46 |
+
<td class="val-truth truth-col" id="truth-kcal">-</td>
|
| 47 |
+
<td class="val-diff truth-col" id="diff-kcal">-</td>
|
| 48 |
+
</tr>
|
| 49 |
+
<tr>
|
| 50 |
+
<td class="emoji-col">🍗</td>
|
| 51 |
+
<td>Białko</td>
|
| 52 |
+
<td class="val-model" id="res-protein">0 g</td>
|
| 53 |
+
<td class="val-truth truth-col" id="truth-protein">-</td>
|
| 54 |
+
<td class="val-diff truth-col" id="diff-protein">-</td>
|
| 55 |
+
</tr>
|
| 56 |
+
<tr>
|
| 57 |
+
<td class="emoji-col">🥑</td>
|
| 58 |
+
<td>Tłuszcz</td>
|
| 59 |
+
<td class="val-model" id="res-fat">0 g</td>
|
| 60 |
+
<td class="val-truth truth-col" id="truth-fat">-</td>
|
| 61 |
+
<td class="val-diff truth-col" id="diff-fat">-</td>
|
| 62 |
+
</tr>
|
| 63 |
+
<tr>
|
| 64 |
+
<td class="emoji-col">🍞</td>
|
| 65 |
+
<td>Węgle</td>
|
| 66 |
+
<td class="val-model" id="res-carb">0 g</td>
|
| 67 |
+
<td class="val-truth truth-col" id="truth-carb">-</td>
|
| 68 |
+
<td class="val-diff truth-col" id="diff-carb">-</td>
|
| 69 |
+
</tr>
|
| 70 |
+
</tbody>
|
| 71 |
+
</table>
|
| 72 |
+
</div>
|
| 73 |
+
</div>
|
| 74 |
+
</div>
|
| 75 |
+
|
| 76 |
+
<div class="sidebar" id="sidebar">
|
| 77 |
+
<h2 id="sidebarTitle">Panel</h2>
|
| 78 |
+
<p id="sidebarDesc"></p>
|
| 79 |
+
|
| 80 |
+
<div id="mealsList"></div>
|
| 81 |
+
|
| 82 |
+
<div class="add-meal-form" id="addMealForm" style="display: none;">
|
| 83 |
+
<h3>Dodaj do bazy</h3>
|
| 84 |
+
<input type="text" id="newMealName" placeholder="Nazwa (np. Płatki)">
|
| 85 |
+
<label class="form-label">Zdjęcie Ground Truth:</label>
|
| 86 |
+
<input type="file" id="newMealImage" class="form-file">
|
| 87 |
+
|
| 88 |
+
<div class="form-row">
|
| 89 |
+
<input type="number" id="newMealKcal" placeholder="Kcal">
|
| 90 |
+
<input type="number" id="newMealP" placeholder="Białko(g)">
|
| 91 |
+
</div>
|
| 92 |
+
<div class="form-row">
|
| 93 |
+
<input type="number" id="newMealF" placeholder="Tłuszcz(g)">
|
| 94 |
+
<input type="number" id="newMealC" placeholder="Węgle(g)">
|
| 95 |
+
</div>
|
| 96 |
+
<button onclick="addUserMeal()" class="btn-save">➕ Zapisz</button>
|
| 97 |
+
</div>
|
| 98 |
+
</div>
|
| 99 |
+
|
| 100 |
+
<script src="/static/script.js"></script>
|
| 101 |
+
</body>
|
| 102 |
+
</html>
|
main.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, UploadFile, File
|
| 2 |
+
from fastapi.responses import FileResponse
|
| 3 |
+
from fastapi.staticfiles import StaticFiles
|
| 4 |
+
import onnxruntime as ort
|
| 5 |
+
import numpy as np
|
| 6 |
+
from PIL import Image
|
| 7 |
+
import io
|
| 8 |
+
import os
|
| 9 |
+
|
| 10 |
+
# inicjalizacja aplikacji webowej
|
| 11 |
+
app = FastAPI(title="AI Food Macro API", version="1.0")
|
| 12 |
+
|
| 13 |
+
os.makedirs("models", exist_ok=True)
|
| 14 |
+
os.makedirs("static", exist_ok=True)
|
| 15 |
+
os.makedirs("test_images", exist_ok=True)
|
| 16 |
+
|
| 17 |
+
app.mount("/models", StaticFiles(directory="models"), name="models")
|
| 18 |
+
app.mount("/static", StaticFiles(directory="static"), name="static")
|
| 19 |
+
app.mount("/test_images", StaticFiles(directory="test_images"), name="test_images")
|
| 20 |
+
|
| 21 |
+
# załadowanie modelu na start serwera
|
| 22 |
+
print("Ładowanie silnika ONNX na CPU...")
|
| 23 |
+
session = ort.InferenceSession("models/onnx_model.onnx", providers=["CPUExecutionProvider"])
|
| 24 |
+
input_name = session.get_inputs()[0].name
|
| 25 |
+
|
| 26 |
+
# maksyma wyciągnięte ze zbioru treningowego (max_factors)
|
| 27 |
+
# Maksima -> Kcal: 3943.325195, Tłuszcz: 106.343002, Węgle: 844.568604, Białko: 143.492493
|
| 28 |
+
MAX_FACTORS = np.array([3943.325195, 106.343002, 844.568604, 143.492493])
|
| 29 |
+
|
| 30 |
+
def preprocess_image(image: Image.Image) -> np.ndarray:
|
| 31 |
+
"""
|
| 32 |
+
Ręczna transformacja zdjęcia (zastępuje transform.Compose z Pytorcha)
|
| 33 |
+
"""
|
| 34 |
+
img = image.convert('RGB').resize((224, 224), Image.Resampling.LANCZOS)
|
| 35 |
+
|
| 36 |
+
img_data = np.array(img).astype(np.float32) / 255.0
|
| 37 |
+
|
| 38 |
+
# standaryzacja ImageNet
|
| 39 |
+
mean = np.array([0.485, 0.456, 0.406], dtype=np.float32)
|
| 40 |
+
std = np.array([0.229, 0.224, 0.225], dtype=np.float32)
|
| 41 |
+
img_data = (img_data - mean) / std
|
| 42 |
+
|
| 43 |
+
# zmiana ułożenia osi z [Wysokość, Szerokość, Kanały] na [Kanały, Wysokość, Szerokość]
|
| 44 |
+
img_data = np.transpose(img_data, (2, 0, 1))
|
| 45 |
+
|
| 46 |
+
# dodanie wymiaru batcha [1, 3, 224, 224]
|
| 47 |
+
img_data = np.expand_dims(img_data, axis=0)
|
| 48 |
+
|
| 49 |
+
return img_data
|
| 50 |
+
|
| 51 |
+
# GŁÓWNY ENDPOINT
|
| 52 |
+
@app.post("/predict-macro")
|
| 53 |
+
async def predict_macro(file: UploadFile = File(...)):
|
| 54 |
+
# odbiór pliku od użytkownika i wczytanie do RAM
|
| 55 |
+
contents = await file.read()
|
| 56 |
+
image = Image.open(io.BytesIO(contents))
|
| 57 |
+
|
| 58 |
+
# MLOps: Transformacja -> ONNS -> Odwrócenie skali
|
| 59 |
+
input_data = preprocess_image(image)
|
| 60 |
+
raw_output = session.run(None, {input_name: input_data})[0][0]
|
| 61 |
+
|
| 62 |
+
predicted_macro = raw_output * MAX_FACTORS
|
| 63 |
+
|
| 64 |
+
return {
|
| 65 |
+
"status": "success",
|
| 66 |
+
"filename": file.filename,
|
| 67 |
+
"predictions": {
|
| 68 |
+
"kcal": round(float(predicted_macro[0]), 0),
|
| 69 |
+
"fat_g": round(float(predicted_macro[1]), 0),
|
| 70 |
+
"carb_g": round(float(predicted_macro[2]), 0),
|
| 71 |
+
"protein_g": round(float(predicted_macro[3]), 0),
|
| 72 |
+
}
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
# Obsługuje główną strone
|
| 76 |
+
@app.get("/")
|
| 77 |
+
async def serve_frontend():
|
| 78 |
+
return FileResponse("index.html")
|
model_training.ipynb
ADDED
|
@@ -0,0 +1,1688 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"metadata": {
|
| 6 |
+
"id": "sjuMnYjkDZXT"
|
| 7 |
+
},
|
| 8 |
+
"source": [
|
| 9 |
+
"# Temat: ***Klasyfikacja makro składników posiłków***\n",
|
| 10 |
+
"\n",
|
| 11 |
+
"Dataset: https://huggingface.co/datasets/mmathys/food-nutrients"
|
| 12 |
+
]
|
| 13 |
+
},
|
| 14 |
+
{
|
| 15 |
+
"cell_type": "markdown",
|
| 16 |
+
"metadata": {},
|
| 17 |
+
"source": [
|
| 18 |
+
"## Przygotowanie datasetu"
|
| 19 |
+
]
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
"cell_type": "markdown",
|
| 23 |
+
"metadata": {
|
| 24 |
+
"id": "VkAX_NjlIPbd"
|
| 25 |
+
},
|
| 26 |
+
"source": [
|
| 27 |
+
"Importy"
|
| 28 |
+
]
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
"cell_type": "code",
|
| 32 |
+
"execution_count": 1,
|
| 33 |
+
"metadata": {
|
| 34 |
+
"id": "nWdktah-DUro"
|
| 35 |
+
},
|
| 36 |
+
"outputs": [],
|
| 37 |
+
"source": [
|
| 38 |
+
"import torch\n",
|
| 39 |
+
"import torch.nn as nn\n",
|
| 40 |
+
"import torchvision.models as models\n",
|
| 41 |
+
"import torch.optim as optim\n",
|
| 42 |
+
"import time\n",
|
| 43 |
+
"import pandas as pd\n",
|
| 44 |
+
"import numpy as np\n",
|
| 45 |
+
"import onnxruntime as ort\n",
|
| 46 |
+
"\n",
|
| 47 |
+
"from torchvision import transforms\n",
|
| 48 |
+
"from datasets import load_dataset, load_from_disk\n",
|
| 49 |
+
"from torch.utils.data import Dataset, DataLoader\n",
|
| 50 |
+
"from tabulate import tabulate\n",
|
| 51 |
+
"from onnxruntime.quantization import quantize_dynamic, QuantType"
|
| 52 |
+
]
|
| 53 |
+
},
|
| 54 |
+
{
|
| 55 |
+
"cell_type": "markdown",
|
| 56 |
+
"metadata": {
|
| 57 |
+
"id": "Vn9Q92Z5IQue"
|
| 58 |
+
},
|
| 59 |
+
"source": [
|
| 60 |
+
"Pobranie datasetu z hugging face lub wczytanie z dysku"
|
| 61 |
+
]
|
| 62 |
+
},
|
| 63 |
+
{
|
| 64 |
+
"cell_type": "code",
|
| 65 |
+
"execution_count": null,
|
| 66 |
+
"metadata": {
|
| 67 |
+
"id": "Wu-oDqOoD4hf"
|
| 68 |
+
},
|
| 69 |
+
"outputs": [],
|
| 70 |
+
"source": [
|
| 71 |
+
"# pobranie z hugging face\n",
|
| 72 |
+
"# dataset = load_dataset(\"mmathys/food-nutrients\", revision=\"refs/convert/parquet\")\n",
|
| 73 |
+
"\n",
|
| 74 |
+
"# wczytanie z dysku Google\n",
|
| 75 |
+
"split_dataset = load_from_disk('/content/drive/MyDrive/food_dataset') # <- ścieżka do datasetu"
|
| 76 |
+
]
|
| 77 |
+
},
|
| 78 |
+
{
|
| 79 |
+
"cell_type": "markdown",
|
| 80 |
+
"metadata": {
|
| 81 |
+
"id": "k-lO8jVeyHCt"
|
| 82 |
+
},
|
| 83 |
+
"source": [
|
| 84 |
+
"Podzielenie datasetu"
|
| 85 |
+
]
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"cell_type": "code",
|
| 89 |
+
"execution_count": 3,
|
| 90 |
+
"metadata": {
|
| 91 |
+
"colab": {
|
| 92 |
+
"base_uri": "https://localhost:8080/",
|
| 93 |
+
"height": 223,
|
| 94 |
+
"referenced_widgets": [
|
| 95 |
+
"d3a8e790b1cf4b7b81cd14ced76c8b21",
|
| 96 |
+
"ffb88d550f134522bef235e4562e7703",
|
| 97 |
+
"ceb341ce3bbd4501a6a4571e5f90ef97",
|
| 98 |
+
"8afbb9695a364f87a5d8cb9179d0d797",
|
| 99 |
+
"e003619d59ca4e82bcffc06e674496de",
|
| 100 |
+
"c07a874cdc4a48b8bf3b1d8e8a89b6eb",
|
| 101 |
+
"0b6b96bd67fb4b1e86f85c64a03bed6e",
|
| 102 |
+
"58bd7fa138dd49fdba81c7aaaae7ee18",
|
| 103 |
+
"930be0d638704282bb2d152017e426b4",
|
| 104 |
+
"39505a3dd9fb4d4d9e0a87b196d34dcf",
|
| 105 |
+
"ef1da96b7eb9459cbe3137fa21d954a9",
|
| 106 |
+
"383d49a8573b4edaa8112bb3f1b0fdf5",
|
| 107 |
+
"3f30729bea374230be2518f856932d75",
|
| 108 |
+
"285067ea372542b0b33884ac9f673bdf",
|
| 109 |
+
"d87645ce5d2c443cab2d67adae2a59f3",
|
| 110 |
+
"0f2e8d3ced844f87a7716241727a05bb",
|
| 111 |
+
"6a9109178b124b658333522102e1d3d5",
|
| 112 |
+
"f606ffa8c38a4875bc02a8013e66eb9f",
|
| 113 |
+
"da60736bf83a40dba607d1790b18e1ec",
|
| 114 |
+
"50b0bf64a56140d7bce17eebacd4b458",
|
| 115 |
+
"fe58601fb3d14dddb4c6172693b89707",
|
| 116 |
+
"fb15837db0f64e0fbf057a1d8af5f8e7"
|
| 117 |
+
]
|
| 118 |
+
},
|
| 119 |
+
"id": "qlInHE5Yxo_z",
|
| 120 |
+
"outputId": "2a09b347-c42b-45e1-a6f5-1df372595cc5"
|
| 121 |
+
},
|
| 122 |
+
"outputs": [
|
| 123 |
+
{
|
| 124 |
+
"name": "stdout",
|
| 125 |
+
"output_type": "stream",
|
| 126 |
+
"text": [
|
| 127 |
+
"Zdjęcia treningowe: 2608\n",
|
| 128 |
+
"Zdjęcia testowe: 652\n",
|
| 129 |
+
"\n",
|
| 130 |
+
"Dataset({\n",
|
| 131 |
+
" features: ['image', 'id', 'split', 'ingredients', 'total_calories', 'total_mass', 'total_fat', 'total_carb', 'total_protein'],\n",
|
| 132 |
+
" num_rows: 2608\n",
|
| 133 |
+
"})\n"
|
| 134 |
+
]
|
| 135 |
+
}
|
| 136 |
+
],
|
| 137 |
+
"source": [
|
| 138 |
+
"# split_dataset = dataset['test'].train_test_split(test_size=0.2, seed=42)\n",
|
| 139 |
+
"\n",
|
| 140 |
+
"# zapisanie datasetu na dysku Google\n",
|
| 141 |
+
"# split_dataset.save_to_disk('/content/drive/MyDrive/food_dataset')\n",
|
| 142 |
+
"\n",
|
| 143 |
+
"print(f\"Zdjęcia treningowe: {len(split_dataset['train'])}\")\n",
|
| 144 |
+
"print(f\"Zdjęcia testowe: {len(split_dataset['test'])}\")\n",
|
| 145 |
+
"print(f\"\\n{split_dataset['train']}\")"
|
| 146 |
+
]
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"cell_type": "markdown",
|
| 150 |
+
"metadata": {},
|
| 151 |
+
"source": [
|
| 152 |
+
"Wyznaczenie max wartości w celu skalowania wartości"
|
| 153 |
+
]
|
| 154 |
+
},
|
| 155 |
+
{
|
| 156 |
+
"cell_type": "code",
|
| 157 |
+
"execution_count": 4,
|
| 158 |
+
"metadata": {},
|
| 159 |
+
"outputs": [
|
| 160 |
+
{
|
| 161 |
+
"name": "stdout",
|
| 162 |
+
"output_type": "stream",
|
| 163 |
+
"text": [
|
| 164 |
+
"Maksima -> Kcal: 3943.325195, Tłuszcz: 106.343002, Węgle: 844.568604, Białko: 143.492493\n"
|
| 165 |
+
]
|
| 166 |
+
}
|
| 167 |
+
],
|
| 168 |
+
"source": [
|
| 169 |
+
"train_features = split_dataset['train']\n",
|
| 170 |
+
"\n",
|
| 171 |
+
"max_kcal = max(train_features['total_calories'])\n",
|
| 172 |
+
"max_fat = max(train_features['total_fat'])\n",
|
| 173 |
+
"max_carb = max(train_features['total_carb'])\n",
|
| 174 |
+
"max_protein = max(train_features['total_protein'])\n",
|
| 175 |
+
"\n",
|
| 176 |
+
"print(f\"Maksima -> Kcal: {max_kcal}, Tłuszcz: {max_fat}, Węgle: {max_carb}, Białko: {max_protein}\")\n",
|
| 177 |
+
"\n",
|
| 178 |
+
"max_factors = np.array([max_kcal, max_fat, max_carb, max_protein])"
|
| 179 |
+
]
|
| 180 |
+
},
|
| 181 |
+
{
|
| 182 |
+
"cell_type": "markdown",
|
| 183 |
+
"metadata": {
|
| 184 |
+
"id": "_qVBt7epIXLo"
|
| 185 |
+
},
|
| 186 |
+
"source": [
|
| 187 |
+
"Klasa Dataset"
|
| 188 |
+
]
|
| 189 |
+
},
|
| 190 |
+
{
|
| 191 |
+
"cell_type": "code",
|
| 192 |
+
"execution_count": 5,
|
| 193 |
+
"metadata": {
|
| 194 |
+
"colab": {
|
| 195 |
+
"base_uri": "https://localhost:8080/"
|
| 196 |
+
},
|
| 197 |
+
"id": "JMXGulIJII75",
|
| 198 |
+
"outputId": "2827e9dc-56dd-48d5-ec62-9ae6a9f9d8d3"
|
| 199 |
+
},
|
| 200 |
+
"outputs": [
|
| 201 |
+
{
|
| 202 |
+
"name": "stdout",
|
| 203 |
+
"output_type": "stream",
|
| 204 |
+
"text": [
|
| 205 |
+
"Kształt: torch.Size([3, 224, 224])\n",
|
| 206 |
+
"Wartości: tensor([0.0469, 0.0075, 0.0469, 0.0264])\n"
|
| 207 |
+
]
|
| 208 |
+
}
|
| 209 |
+
],
|
| 210 |
+
"source": [
|
| 211 |
+
"data_transforms = transforms.Compose([\n",
|
| 212 |
+
" transforms.Resize((224, 224)),\n",
|
| 213 |
+
" transforms.ToTensor(),\n",
|
| 214 |
+
" transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # standardowe wartości dla ImageNet\n",
|
| 215 |
+
"])\n",
|
| 216 |
+
"\n",
|
| 217 |
+
"class FoodNutrientDataset(Dataset):\n",
|
| 218 |
+
" def __init__(self, hf_dataset, transform=None):\n",
|
| 219 |
+
" self.hf_dataset = hf_dataset\n",
|
| 220 |
+
" self.transform = transform\n",
|
| 221 |
+
"\n",
|
| 222 |
+
" def __len__(self):\n",
|
| 223 |
+
" return len(self.hf_dataset)\n",
|
| 224 |
+
"\n",
|
| 225 |
+
" def __getitem__(self, idx):\n",
|
| 226 |
+
" item = self.hf_dataset[idx]\n",
|
| 227 |
+
"\n",
|
| 228 |
+
" image = item['image'].convert(\"RGB\")\n",
|
| 229 |
+
"\n",
|
| 230 |
+
" if self.transform:\n",
|
| 231 |
+
" image = self.transform(image)\n",
|
| 232 |
+
"\n",
|
| 233 |
+
" # nazwy kluczy\n",
|
| 234 |
+
" kcal = float(item['total_calories']) / max_kcal\n",
|
| 235 |
+
" fat = float(item['total_fat']) / max_fat\n",
|
| 236 |
+
" carbs = float(item['total_carb']) / max_carb\n",
|
| 237 |
+
" protein = float(item['total_protein']) / max_protein\n",
|
| 238 |
+
"\n",
|
| 239 |
+
" targets = torch.tensor([kcal, fat, carbs, protein], dtype=torch.float32)\n",
|
| 240 |
+
"\n",
|
| 241 |
+
" return image, targets\n",
|
| 242 |
+
"\n",
|
| 243 |
+
"# instancje\n",
|
| 244 |
+
"train_dataset = FoodNutrientDataset(split_dataset['train'], transform=data_transforms)\n",
|
| 245 |
+
"test_dataset = FoodNutrientDataset(split_dataset['test'], transform=data_transforms)\n",
|
| 246 |
+
"\n",
|
| 247 |
+
"test_img, test_target = train_dataset[0]\n",
|
| 248 |
+
"print(f\"Kształt: {test_img.shape}\")\n",
|
| 249 |
+
"print(f\"Wartości: {test_target}\")"
|
| 250 |
+
]
|
| 251 |
+
},
|
| 252 |
+
{
|
| 253 |
+
"cell_type": "markdown",
|
| 254 |
+
"metadata": {
|
| 255 |
+
"id": "Xr60ZnxMBdy2"
|
| 256 |
+
},
|
| 257 |
+
"source": [
|
| 258 |
+
"Przygotowanie paczek (DataLoaders)"
|
| 259 |
+
]
|
| 260 |
+
},
|
| 261 |
+
{
|
| 262 |
+
"cell_type": "code",
|
| 263 |
+
"execution_count": 6,
|
| 264 |
+
"metadata": {
|
| 265 |
+
"id": "3sbGbwsbBc4i"
|
| 266 |
+
},
|
| 267 |
+
"outputs": [],
|
| 268 |
+
"source": [
|
| 269 |
+
"train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\n",
|
| 270 |
+
"test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)"
|
| 271 |
+
]
|
| 272 |
+
},
|
| 273 |
+
{
|
| 274 |
+
"cell_type": "markdown",
|
| 275 |
+
"metadata": {
|
| 276 |
+
"id": "ioO4y_QLCy2g"
|
| 277 |
+
},
|
| 278 |
+
"source": [
|
| 279 |
+
"## Transfer Learning"
|
| 280 |
+
]
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"cell_type": "markdown",
|
| 284 |
+
"metadata": {
|
| 285 |
+
"id": "auclJzeYEKcz"
|
| 286 |
+
},
|
| 287 |
+
"source": [
|
| 288 |
+
"Pobranie modelu MobileNetV2 i przerobienie na model do regresji"
|
| 289 |
+
]
|
| 290 |
+
},
|
| 291 |
+
{
|
| 292 |
+
"cell_type": "code",
|
| 293 |
+
"execution_count": 26,
|
| 294 |
+
"metadata": {
|
| 295 |
+
"colab": {
|
| 296 |
+
"base_uri": "https://localhost:8080/"
|
| 297 |
+
},
|
| 298 |
+
"id": "W1TA6bKxEJsD",
|
| 299 |
+
"outputId": "13a6e7e7-1a59-4940-c519-97539ddd0d4a"
|
| 300 |
+
},
|
| 301 |
+
"outputs": [
|
| 302 |
+
{
|
| 303 |
+
"name": "stdout",
|
| 304 |
+
"output_type": "stream",
|
| 305 |
+
"text": [
|
| 306 |
+
"Załadowano model na cuda\n"
|
| 307 |
+
]
|
| 308 |
+
}
|
| 309 |
+
],
|
| 310 |
+
"source": [
|
| 311 |
+
"weights = models.MobileNet_V2_Weights.DEFAULT\n",
|
| 312 |
+
"model = models.mobilenet_v2(weights=weights)\n",
|
| 313 |
+
"\n",
|
| 314 |
+
"# zamrożenie wszystkich warstw\n",
|
| 315 |
+
"for param in model.parameters():\n",
|
| 316 |
+
" param.requires_grad = False\n",
|
| 317 |
+
"\n",
|
| 318 |
+
"# odmrożenie 3 bloków features\n",
|
| 319 |
+
"for param in model.features[-3:].parameters():\n",
|
| 320 |
+
" param.requires_grad = True\n",
|
| 321 |
+
"\n",
|
| 322 |
+
"# podmiana ostatniej warstwy\n",
|
| 323 |
+
"# 4 wyjścia [Kalorie, Białko, Tłuszcz, Węglowodany]\n",
|
| 324 |
+
"num_ftrs = model.classifier[1].in_features\n",
|
| 325 |
+
"model.classifier[1] = nn.Sequential(\n",
|
| 326 |
+
" nn.Linear(num_ftrs, 256),\n",
|
| 327 |
+
" nn.ReLU(),\n",
|
| 328 |
+
" nn.Dropout(0.3),\n",
|
| 329 |
+
" nn.Linear(256, 4),\n",
|
| 330 |
+
" nn.ReLU()\n",
|
| 331 |
+
")\n",
|
| 332 |
+
"\n",
|
| 333 |
+
"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
|
| 334 |
+
"model = model.to(device)\n",
|
| 335 |
+
"\n",
|
| 336 |
+
"print(f\"Załadowano model na {device}\")\n",
|
| 337 |
+
"\n",
|
| 338 |
+
"# funkcja straty\n",
|
| 339 |
+
"# criterion = nn.MSELoss()\n",
|
| 340 |
+
"criterion = nn.HuberLoss(delta=50.0)\n",
|
| 341 |
+
"\n",
|
| 342 |
+
"# optimalizator (tylko dla nowych warstw)\n",
|
| 343 |
+
"optimizer = optim.Adam([\n",
|
| 344 |
+
" {'params': model.features[-3:].parameters(), 'lr': 0.0001},\n",
|
| 345 |
+
" {'params': model.classifier[1].parameters(), 'lr': 0.001}\n",
|
| 346 |
+
" ])\n",
|
| 347 |
+
"\n",
|
| 348 |
+
"# scheduler\n",
|
| 349 |
+
"scheduler = optim.lr_scheduler.ReduceLROnPlateau(\n",
|
| 350 |
+
" optimizer, mode='min', factor=0.5, patience=5\n",
|
| 351 |
+
")"
|
| 352 |
+
]
|
| 353 |
+
},
|
| 354 |
+
{
|
| 355 |
+
"cell_type": "markdown",
|
| 356 |
+
"metadata": {
|
| 357 |
+
"id": "cnv-fMaNDeTl"
|
| 358 |
+
},
|
| 359 |
+
"source": [
|
| 360 |
+
"Trening"
|
| 361 |
+
]
|
| 362 |
+
},
|
| 363 |
+
{
|
| 364 |
+
"cell_type": "code",
|
| 365 |
+
"execution_count": null,
|
| 366 |
+
"metadata": {
|
| 367 |
+
"colab": {
|
| 368 |
+
"base_uri": "https://localhost:8080/"
|
| 369 |
+
},
|
| 370 |
+
"id": "dcAtp2g_C0Ed",
|
| 371 |
+
"outputId": "f1276175-bd07-4c7a-bdad-46aee7d8a23f"
|
| 372 |
+
},
|
| 373 |
+
"outputs": [
|
| 374 |
+
{
|
| 375 |
+
"name": "stdout",
|
| 376 |
+
"output_type": "stream",
|
| 377 |
+
"text": [
|
| 378 |
+
"Rozpoczynam trening...\n",
|
| 379 |
+
"Epoka [1/100]...\n",
|
| 380 |
+
"Czas: 56.2s | Błąd treningowy (RMSE): 178.188561 | Błąd testowy (RMSE): 168.004262\n",
|
| 381 |
+
"Epoka [2/100]...\n",
|
| 382 |
+
"Czas: 55.8s | Błąd treningowy (RMSE): 169.397108 | Błąd testowy (RMSE): 167.980771\n",
|
| 383 |
+
"Epoka [3/100]...\n",
|
| 384 |
+
"Czas: 57.2s | Błąd treningowy (RMSE): 169.361251 | Błąd testowy (RMSE): 167.961045\n",
|
| 385 |
+
"Epoka [4/100]...\n",
|
| 386 |
+
"Czas: 57.3s | Błąd treningowy (RMSE): 169.332773 | Błąd testowy (RMSE): 167.945894\n",
|
| 387 |
+
"Epoka [5/100]...\n",
|
| 388 |
+
"Czas: 58.7s | Błąd treningowy (RMSE): 169.325557 | Błąd testowy (RMSE): 167.939000\n",
|
| 389 |
+
"Epoka [6/100]...\n",
|
| 390 |
+
"Czas: 54.9s | Błąd treningowy (RMSE): 169.225351 | Błąd testowy (RMSE): 167.864880\n",
|
| 391 |
+
"Epoka [7/100]...\n",
|
| 392 |
+
"Czas: 56.5s | Błąd treningowy (RMSE): 164.112868 | Błąd testowy (RMSE): 99.558664\n",
|
| 393 |
+
"Epoka [8/100]...\n",
|
| 394 |
+
"Czas: 56.1s | Błąd treningowy (RMSE): 77.103902 | Błąd testowy (RMSE): 52.589928\n",
|
| 395 |
+
"Epoka [9/100]...\n",
|
| 396 |
+
"Czas: 55.9s | Błąd treningowy (RMSE): 64.033303 | Błąd testowy (RMSE): 52.435742\n",
|
| 397 |
+
"Epoka [10/100]...\n",
|
| 398 |
+
"Czas: 56.5s | Błąd treningowy (RMSE): 57.499566 | Błąd testowy (RMSE): 58.920475\n",
|
| 399 |
+
"Epoka [11/100]...\n",
|
| 400 |
+
"Czas: 57.8s | Błąd treningowy (RMSE): 57.538209 | Błąd testowy (RMSE): 52.279127\n",
|
| 401 |
+
"Epoka [12/100]...\n",
|
| 402 |
+
"Czas: 59.0s | Błąd treningowy (RMSE): 57.607072 | Błąd testowy (RMSE): 50.357450\n",
|
| 403 |
+
"Epoka [13/100]...\n",
|
| 404 |
+
"Czas: 56.0s | Błąd treningowy (RMSE): 56.605721 | Błąd testowy (RMSE): 51.868502\n",
|
| 405 |
+
"Epoka [14/100]...\n",
|
| 406 |
+
"Czas: 55.6s | Błąd treningowy (RMSE): 53.386503 | Błąd testowy (RMSE): 58.271139\n",
|
| 407 |
+
"Epoka [15/100]...\n",
|
| 408 |
+
"Czas: 53.1s | Błąd treningowy (RMSE): 54.221051 | Błąd testowy (RMSE): 53.148526\n",
|
| 409 |
+
"Epoka [16/100]...\n",
|
| 410 |
+
"Czas: 52.7s | Błąd treningowy (RMSE): 52.917060 | Błąd testowy (RMSE): 52.019663\n",
|
| 411 |
+
"Epoka [17/100]...\n",
|
| 412 |
+
"Czas: 52.0s | Błąd treningowy (RMSE): 52.992275 | Błąd testowy (RMSE): 48.665368\n",
|
| 413 |
+
"Epoka [18/100]...\n",
|
| 414 |
+
"Czas: 52.5s | Błąd treningowy (RMSE): 50.237864 | Błąd testowy (RMSE): 50.677346\n",
|
| 415 |
+
"Epoka [19/100]...\n",
|
| 416 |
+
"Czas: 57.8s | Błąd treningowy (RMSE): 46.434908 | Błąd testowy (RMSE): 50.953815\n",
|
| 417 |
+
"Epoka [20/100]...\n",
|
| 418 |
+
"Czas: 56.9s | Błąd treningowy (RMSE): 45.531937 | Błąd testowy (RMSE): 49.074650\n",
|
| 419 |
+
"Epoka [21/100]...\n",
|
| 420 |
+
"Czas: 55.8s | Błąd treningowy (RMSE): 44.728347 | Błąd testowy (RMSE): 51.778983\n",
|
| 421 |
+
"Epoka [22/100]...\n",
|
| 422 |
+
"Czas: 56.5s | Błąd treningowy (RMSE): 41.428644 | Błąd testowy (RMSE): 48.853425\n",
|
| 423 |
+
"Epoka [23/100]...\n",
|
| 424 |
+
"Czas: 59.5s | Błąd treningowy (RMSE): 47.100133 | Błąd testowy (RMSE): 49.450177\n",
|
| 425 |
+
"Epoka [24/100]...\n",
|
| 426 |
+
"Czas: 56.7s | Błąd treningowy (RMSE): 41.668273 | Błąd testowy (RMSE): 50.537118\n",
|
| 427 |
+
"Epoka [25/100]...\n",
|
| 428 |
+
"Czas: 57.4s | Błąd treningowy (RMSE): 38.992410 | Błąd testowy (RMSE): 48.851822\n",
|
| 429 |
+
"Epoka [26/100]...\n",
|
| 430 |
+
"Czas: 54.1s | Błąd treningowy (RMSE): 41.042813 | Błąd testowy (RMSE): 48.137097\n",
|
| 431 |
+
"Epoka [27/100]...\n",
|
| 432 |
+
"Czas: 54.0s | Błąd treningowy (RMSE): 46.796708 | Błąd testowy (RMSE): 49.257832\n",
|
| 433 |
+
"Epoka [28/100]...\n",
|
| 434 |
+
"Czas: 54.0s | Błąd treningowy (RMSE): 46.009532 | Błąd testowy (RMSE): 47.618421\n",
|
| 435 |
+
"Epoka [29/100]...\n",
|
| 436 |
+
"Czas: 53.8s | Błąd treningowy (RMSE): 37.545192 | Błąd testowy (RMSE): 50.782361\n",
|
| 437 |
+
"Epoka [30/100]...\n",
|
| 438 |
+
"Czas: 54.5s | Błąd treningowy (RMSE): 37.893514 | Błąd testowy (RMSE): 47.197283\n",
|
| 439 |
+
"Epoka [31/100]...\n",
|
| 440 |
+
"Czas: 52.6s | Błąd treningowy (RMSE): 39.940901 | Błąd testowy (RMSE): 46.907932\n",
|
| 441 |
+
"Epoka [32/100]...\n",
|
| 442 |
+
"Czas: 54.1s | Błąd treningowy (RMSE): 37.930065 | Błąd testowy (RMSE): 47.868895\n",
|
| 443 |
+
"Epoka [33/100]...\n",
|
| 444 |
+
"Czas: 53.5s | Błąd treningowy (RMSE): 34.407337 | Błąd testowy (RMSE): 49.043571\n",
|
| 445 |
+
"Epoka [34/100]...\n",
|
| 446 |
+
"Czas: 53.1s | Błąd treningowy (RMSE): 34.219125 | Błąd testowy (RMSE): 47.288172\n",
|
| 447 |
+
"Epoka [35/100]...\n",
|
| 448 |
+
"Czas: 52.1s | Błąd treningowy (RMSE): 35.117653 | Błąd testowy (RMSE): 45.491266\n",
|
| 449 |
+
"Epoka [36/100]...\n",
|
| 450 |
+
"Czas: 51.4s | Błąd treningowy (RMSE): 33.759862 | Błąd testowy (RMSE): 48.359096\n",
|
| 451 |
+
"Epoka [37/100]...\n",
|
| 452 |
+
"Czas: 51.1s | Błąd treningowy (RMSE): 42.132784 | Błąd testowy (RMSE): 48.234712\n",
|
| 453 |
+
"Epoka [38/100]...\n",
|
| 454 |
+
"Czas: 51.1s | Błąd treningowy (RMSE): 36.024418 | Błąd testowy (RMSE): 46.255143\n",
|
| 455 |
+
"Epoka [39/100]...\n",
|
| 456 |
+
"Czas: 51.0s | Błąd treningowy (RMSE): 34.478403 | Błąd testowy (RMSE): 46.288933\n",
|
| 457 |
+
"Epoka [40/100]...\n",
|
| 458 |
+
"Czas: 51.3s | Błąd treningowy (RMSE): 33.229815 | Błąd testowy (RMSE): 46.113043\n",
|
| 459 |
+
"Epoka [41/100]...\n",
|
| 460 |
+
"Czas: 51.1s | Błąd treningowy (RMSE): 33.600531 | Błąd testowy (RMSE): 44.267916\n",
|
| 461 |
+
"Epoka [42/100]...\n",
|
| 462 |
+
"Czas: 51.4s | Błąd treningowy (RMSE): 34.830769 | Błąd testowy (RMSE): 45.718961\n",
|
| 463 |
+
"Epoka [43/100]...\n",
|
| 464 |
+
"Czas: 51.1s | Błąd treningowy (RMSE): 40.249838 | Błąd testowy (RMSE): 47.888996\n",
|
| 465 |
+
"Epoka [44/100]...\n",
|
| 466 |
+
"Czas: 51.1s | Błąd treningowy (RMSE): 43.058492 | Błąd testowy (RMSE): 45.792097\n",
|
| 467 |
+
"Epoka [45/100]...\n",
|
| 468 |
+
"Czas: 51.1s | Błąd treningowy (RMSE): 38.675054 | Błąd testowy (RMSE): 45.848031\n",
|
| 469 |
+
"Epoka [46/100]...\n",
|
| 470 |
+
"Czas: 51.0s | Błąd treningowy (RMSE): 31.439777 | Błąd testowy (RMSE): 46.967925\n",
|
| 471 |
+
"Epoka [47/100]...\n",
|
| 472 |
+
"Czas: 51.0s | Błąd treningowy (RMSE): 33.378058 | Błąd testowy (RMSE): 46.117315\n",
|
| 473 |
+
"Epoka [48/100]...\n",
|
| 474 |
+
"Czas: 51.2s | Błąd treningowy (RMSE): 31.249257 | Błąd testowy (RMSE): 46.905557\n",
|
| 475 |
+
"Epoka [49/100]...\n",
|
| 476 |
+
"Czas: 50.8s | Błąd treningowy (RMSE): 31.615665 | Błąd testowy (RMSE): 47.424634\n",
|
| 477 |
+
"Epoka [50/100]...\n",
|
| 478 |
+
"Czas: 51.0s | Błąd treningowy (RMSE): 30.728995 | Błąd testowy (RMSE): 47.000143\n",
|
| 479 |
+
"Epoka [51/100]...\n",
|
| 480 |
+
"Czas: 51.0s | Błąd treningowy (RMSE): 29.675208 | Błąd testowy (RMSE): 45.689271\n",
|
| 481 |
+
"Epoka [52/100]...\n",
|
| 482 |
+
"Czas: 51.0s | Błąd treningowy (RMSE): 32.260185 | Błąd testowy (RMSE): 45.121416\n",
|
| 483 |
+
"Epoka [53/100]...\n",
|
| 484 |
+
"Czas: 50.7s | Błąd treningowy (RMSE): 30.568070 | Błąd testowy (RMSE): 46.054914\n",
|
| 485 |
+
"Epoka [54/100]...\n",
|
| 486 |
+
"Czas: 50.9s | Błąd treningowy (RMSE): 31.322373 | Błąd testowy (RMSE): 46.634195\n",
|
| 487 |
+
"Epoka [55/100]...\n",
|
| 488 |
+
"Czas: 51.1s | Błąd treningowy (RMSE): 29.367186 | Błąd testowy (RMSE): 46.658814\n",
|
| 489 |
+
"Epoka [56/100]...\n",
|
| 490 |
+
"Czas: 51.6s | Błąd treningowy (RMSE): 30.754483 | Błąd testowy (RMSE): 45.815291\n",
|
| 491 |
+
"Epoka [57/100]...\n",
|
| 492 |
+
"Czas: 51.4s | Błąd treningowy (RMSE): 29.166818 | Błąd testowy (RMSE): 45.661158\n",
|
| 493 |
+
"Epoka [58/100]...\n",
|
| 494 |
+
"Czas: 52.6s | Błąd treningowy (RMSE): 30.426733 | Błąd testowy (RMSE): 46.018076\n",
|
| 495 |
+
"Epoka [59/100]...\n",
|
| 496 |
+
"Czas: 51.7s | Błąd treningowy (RMSE): 32.292654 | Błąd testowy (RMSE): 46.141985\n",
|
| 497 |
+
"Epoka [60/100]...\n",
|
| 498 |
+
"Czas: 51.1s | Błąd treningowy (RMSE): 29.627590 | Błąd testowy (RMSE): 45.483171\n",
|
| 499 |
+
"Epoka [61/100]...\n",
|
| 500 |
+
"Czas: 51.1s | Błąd treningowy (RMSE): 27.022041 | Błąd testowy (RMSE): 45.479725\n",
|
| 501 |
+
"Epoka [62/100]...\n",
|
| 502 |
+
"Czas: 51.4s | Błąd treningowy (RMSE): 28.119333 | Błąd testowy (RMSE): 45.083476\n",
|
| 503 |
+
"Epoka [63/100]...\n",
|
| 504 |
+
"Czas: 51.4s | Błąd treningowy (RMSE): 29.978329 | Błąd testowy (RMSE): 45.417601\n",
|
| 505 |
+
"Epoka [64/100]...\n",
|
| 506 |
+
"Czas: 51.4s | Błąd treningowy (RMSE): 35.413107 | Błąd testowy (RMSE): 45.002775\n",
|
| 507 |
+
"Epoka [65/100]...\n",
|
| 508 |
+
"Czas: 51.8s | Błąd treningowy (RMSE): 28.598748 | Błąd testowy (RMSE): 45.098285\n",
|
| 509 |
+
"Epoka [66/100]...\n",
|
| 510 |
+
"Czas: 51.3s | Błąd treningowy (RMSE): 27.512637 | Błąd testowy (RMSE): 45.033344\n",
|
| 511 |
+
"Epoka [67/100]...\n",
|
| 512 |
+
"Czas: 51.4s | Błąd treningowy (RMSE): 30.729560 | Błąd testowy (RMSE): 44.926249\n",
|
| 513 |
+
"Epoka [68/100]...\n",
|
| 514 |
+
"Czas: 52.3s | Błąd treningowy (RMSE): 27.634430 | Błąd testowy (RMSE): 44.983803\n",
|
| 515 |
+
"Epoka [69/100]...\n",
|
| 516 |
+
"Czas: 52.3s | Błąd treningowy (RMSE): 27.527840 | Błąd testowy (RMSE): 45.067444\n",
|
| 517 |
+
"Epoka [70/100]...\n",
|
| 518 |
+
"Czas: 51.3s | Błąd treningowy (RMSE): 32.309510 | Błąd testowy (RMSE): 45.459961\n",
|
| 519 |
+
"Epoka [71/100]...\n",
|
| 520 |
+
"Czas: 52.8s | Błąd treningowy (RMSE): 28.036586 | Błąd testowy (RMSE): 45.506729\n",
|
| 521 |
+
"Epoka [72/100]...\n",
|
| 522 |
+
"Czas: 51.6s | Błąd treningowy (RMSE): 27.291661 | Błąd testowy (RMSE): 45.453879\n",
|
| 523 |
+
"Epoka [73/100]...\n",
|
| 524 |
+
"Czas: 52.5s | Błąd treningowy (RMSE): 29.256362 | Błąd testowy (RMSE): 45.413326\n",
|
| 525 |
+
"Epoka [74/100]...\n",
|
| 526 |
+
"Czas: 51.4s | Błąd treningowy (RMSE): 28.189695 | Błąd testowy (RMSE): 45.519797\n",
|
| 527 |
+
"Epoka [75/100]...\n",
|
| 528 |
+
"Czas: 50.9s | Błąd treningowy (RMSE): 29.568075 | Błąd testowy (RMSE): 44.883508\n",
|
| 529 |
+
"Epoka [76/100]...\n",
|
| 530 |
+
"Czas: 50.9s | Błąd treningowy (RMSE): 29.721016 | Błąd testowy (RMSE): 45.545479\n",
|
| 531 |
+
"Epoka [77/100]...\n",
|
| 532 |
+
"Czas: 50.9s | Błąd treningowy (RMSE): 27.339565 | Błąd testowy (RMSE): 45.704246\n",
|
| 533 |
+
"Epoka [78/100]...\n",
|
| 534 |
+
"Czas: 50.8s | Błąd treningowy (RMSE): 30.446479 | Błąd testowy (RMSE): 45.286802\n",
|
| 535 |
+
"Epoka [79/100]...\n",
|
| 536 |
+
"Czas: 51.1s | Błąd treningowy (RMSE): 26.813800 | Błąd testowy (RMSE): 45.080516\n",
|
| 537 |
+
"Epoka [80/100]...\n",
|
| 538 |
+
"Czas: 51.3s | Błąd treningowy (RMSE): 37.333608 | Błąd testowy (RMSE): 45.825647\n",
|
| 539 |
+
"Epoka [81/100]...\n",
|
| 540 |
+
"Czas: 51.3s | Błąd treningowy (RMSE): 29.171336 | Błąd testowy (RMSE): 45.950801\n",
|
| 541 |
+
"Epoka [82/100]...\n",
|
| 542 |
+
"Czas: 51.0s | Błąd treningowy (RMSE): 27.917753 | Błąd testowy (RMSE): 45.960414\n",
|
| 543 |
+
"Epoka [83/100]...\n",
|
| 544 |
+
"Czas: 50.9s | Błąd treningowy (RMSE): 29.808054 | Błąd testowy (RMSE): 45.165492\n",
|
| 545 |
+
"Epoka [84/100]...\n",
|
| 546 |
+
"Czas: 51.0s | Błąd treningowy (RMSE): 28.590885 | Błąd testowy (RMSE): 45.355686\n",
|
| 547 |
+
"Epoka [85/100]...\n",
|
| 548 |
+
"Czas: 50.6s | Błąd treningowy (RMSE): 26.703351 | Błąd testowy (RMSE): 45.299842\n",
|
| 549 |
+
"Epoka [86/100]...\n",
|
| 550 |
+
"Czas: 50.6s | Błąd treningowy (RMSE): 27.528077 | Błąd testowy (RMSE): 45.696952\n",
|
| 551 |
+
"Epoka [87/100]...\n",
|
| 552 |
+
"Czas: 50.8s | Błąd treningowy (RMSE): 28.112270 | Błąd testowy (RMSE): 45.012691\n",
|
| 553 |
+
"Epoka [88/100]...\n",
|
| 554 |
+
"Czas: 50.6s | Błąd treningowy (RMSE): 28.337286 | Błąd testowy (RMSE): 45.180012\n",
|
| 555 |
+
"Epoka [89/100]...\n",
|
| 556 |
+
"Czas: 50.6s | Błąd treningowy (RMSE): 30.984244 | Błąd testowy (RMSE): 45.622681\n",
|
| 557 |
+
"Epoka [90/100]...\n",
|
| 558 |
+
"Czas: 50.6s | Błąd treningowy (RMSE): 26.309565 | Błąd testowy (RMSE): 45.704545\n",
|
| 559 |
+
"Epoka [91/100]...\n",
|
| 560 |
+
"Czas: 50.8s | Błąd treningowy (RMSE): 31.285457 | Błąd testowy (RMSE): 45.885330\n",
|
| 561 |
+
"Epoka [92/100]...\n",
|
| 562 |
+
"Czas: 50.4s | Błąd treningowy (RMSE): 27.869966 | Błąd testowy (RMSE): 45.417818\n",
|
| 563 |
+
"Epoka [93/100]...\n",
|
| 564 |
+
"Czas: 50.6s | Błąd treningowy (RMSE): 26.787253 | Błąd testowy (RMSE): 45.865132\n",
|
| 565 |
+
"Epoka [94/100]...\n",
|
| 566 |
+
"Czas: 50.5s | Błąd treningowy (RMSE): 27.359251 | Błąd testowy (RMSE): 45.640092\n",
|
| 567 |
+
"Epoka [95/100]...\n",
|
| 568 |
+
"Czas: 50.6s | Błąd treningowy (RMSE): 27.103805 | Błąd testowy (RMSE): 46.633001\n",
|
| 569 |
+
"Epoka [96/100]...\n",
|
| 570 |
+
"Czas: 50.5s | Błąd treningowy (RMSE): 31.908320 | Błąd testowy (RMSE): 45.638081\n",
|
| 571 |
+
"Epoka [97/100]...\n",
|
| 572 |
+
"Czas: 50.5s | Błąd treningowy (RMSE): 27.385738 | Błąd testowy (RMSE): 45.925380\n",
|
| 573 |
+
"Epoka [98/100]...\n",
|
| 574 |
+
"Czas: 50.4s | Błąd treningowy (RMSE): 29.219606 | Błąd testowy (RMSE): 45.558900\n",
|
| 575 |
+
"Epoka [99/100]...\n",
|
| 576 |
+
"Czas: 50.5s | Błąd treningowy (RMSE): 28.252443 | Błąd testowy (RMSE): 45.398595\n",
|
| 577 |
+
"Epoka [100/100]...\n",
|
| 578 |
+
"Czas: 50.7s | Błąd treningowy (RMSE): 27.743260 | Błąd testowy (RMSE): 45.271798\n",
|
| 579 |
+
"Trening zakończony.\n",
|
| 580 |
+
"Najlepszy model z loss 44.267916 zapisano w 'best_model.pth'\n"
|
| 581 |
+
]
|
| 582 |
+
}
|
| 583 |
+
],
|
| 584 |
+
"source": [
|
| 585 |
+
"# metryki do raportowania\n",
|
| 586 |
+
"metric_fn = nn.MSELoss()\n",
|
| 587 |
+
"\n",
|
| 588 |
+
"print(\"Rozpoczynam trening...\")\n",
|
| 589 |
+
"\n",
|
| 590 |
+
"num_epochs = 100\n",
|
| 591 |
+
"best_test_rmse = float('inf')\n",
|
| 592 |
+
"max_factors = torch.tensor([max_kcal, max_fat, max_carb, max_protein], dtype=torch.float32).to(device)\n",
|
| 593 |
+
"\n",
|
| 594 |
+
"for epoch in range(num_epochs):\n",
|
| 595 |
+
" print(f\"Epoka [{epoch+1}/{num_epochs}]...\")\n",
|
| 596 |
+
" start_time = time.time()\n",
|
| 597 |
+
"\n",
|
| 598 |
+
" # trening\n",
|
| 599 |
+
" model.train()\n",
|
| 600 |
+
" train_loss = 0.0\n",
|
| 601 |
+
"\n",
|
| 602 |
+
" for images, targets in train_loader:\n",
|
| 603 |
+
" images = images.to(device)\n",
|
| 604 |
+
" targets = targets.to(device)\n",
|
| 605 |
+
"\n",
|
| 606 |
+
" optimizer.zero_grad()\n",
|
| 607 |
+
"\n",
|
| 608 |
+
" outputs = model(images)\n",
|
| 609 |
+
" loss = criterion(outputs, targets)\n",
|
| 610 |
+
" loss.backward()\n",
|
| 611 |
+
" optimizer.step()\n",
|
| 612 |
+
"\n",
|
| 613 |
+
" # odwrócenie skalowania do wyliczenia błędu\n",
|
| 614 |
+
" with torch.no_grad():\n",
|
| 615 |
+
" unscaled_outputs = outputs * max_factors\n",
|
| 616 |
+
" unscaled_targets = targets * max_factors\n",
|
| 617 |
+
" real_mse = metric_fn(unscaled_outputs, unscaled_targets)\n",
|
| 618 |
+
" train_loss += real_mse.item() * images.size(0)\n",
|
| 619 |
+
"\n",
|
| 620 |
+
" epoch_train_rmse = (train_loss / len(train_loader.dataset)) ** 0.5\n",
|
| 621 |
+
"\n",
|
| 622 |
+
" # testy\n",
|
| 623 |
+
" model.eval()\n",
|
| 624 |
+
" test_loss = 0.0\n",
|
| 625 |
+
"\n",
|
| 626 |
+
" with torch.no_grad():\n",
|
| 627 |
+
" for images, targets in test_loader:\n",
|
| 628 |
+
" images = images.to(device)\n",
|
| 629 |
+
" targets = targets.to(device)\n",
|
| 630 |
+
"\n",
|
| 631 |
+
" outputs = model(images)\n",
|
| 632 |
+
"\n",
|
| 633 |
+
" unscaled_outputs = outputs * max_factors\n",
|
| 634 |
+
" unscaled_targets = targets * max_factors\n",
|
| 635 |
+
"\n",
|
| 636 |
+
" real_mse = metric_fn(unscaled_outputs, unscaled_targets)\n",
|
| 637 |
+
" test_loss += real_mse.item() * images.size(0)\n",
|
| 638 |
+
"\n",
|
| 639 |
+
" epoch_test_rmse = (test_loss / len(test_loader.dataset)) ** 0.5\n",
|
| 640 |
+
"\n",
|
| 641 |
+
" # automatyczne obniżenie learning_rate w przypadku stagnacji przez 5 epok\n",
|
| 642 |
+
" scheduler.step(epoch_test_rmse) \n",
|
| 643 |
+
"\n",
|
| 644 |
+
" end_time = time.time()\n",
|
| 645 |
+
"\n",
|
| 646 |
+
" print(f\"Czas: {end_time - start_time:.1f}s | \"\n",
|
| 647 |
+
" f\"Błąd treningowy (RMSE): {epoch_train_rmse:.6f} | \"\n",
|
| 648 |
+
" f\"Błąd testowy (RMSE): {epoch_test_rmse:.6f}\"\n",
|
| 649 |
+
" )\n",
|
| 650 |
+
"\n",
|
| 651 |
+
" if epoch_test_rmse < best_test_rmse:\n",
|
| 652 |
+
" best_test_rmse = epoch_test_rmse\n",
|
| 653 |
+
" torch.save(model.state_dict(), \"models/best_model.pth\")\n",
|
| 654 |
+
"\n",
|
| 655 |
+
"print(\"Trening zakończony.\")\n",
|
| 656 |
+
"print(f\"Najlepszy model z loss {best_test_rmse:.6f} zapisano w 'best_model.pth'\")"
|
| 657 |
+
]
|
| 658 |
+
},
|
| 659 |
+
{
|
| 660 |
+
"cell_type": "markdown",
|
| 661 |
+
"metadata": {},
|
| 662 |
+
"source": [
|
| 663 |
+
"## Testy inferencji modeli\n",
|
| 664 |
+
"#### Model bazowy: **MobileNetV2**\n",
|
| 665 |
+
"\n",
|
| 666 |
+
"Inferencja na CPU\n",
|
| 667 |
+
"- model PyTorch\n",
|
| 668 |
+
"- model ONNX\n",
|
| 669 |
+
"- model ONNX kwantyzowany do INT8"
|
| 670 |
+
]
|
| 671 |
+
},
|
| 672 |
+
{
|
| 673 |
+
"cell_type": "markdown",
|
| 674 |
+
"metadata": {},
|
| 675 |
+
"source": [
|
| 676 |
+
"Funkcja do inferencji modelu PyTorch"
|
| 677 |
+
]
|
| 678 |
+
},
|
| 679 |
+
{
|
| 680 |
+
"cell_type": "code",
|
| 681 |
+
"execution_count": 7,
|
| 682 |
+
"metadata": {},
|
| 683 |
+
"outputs": [],
|
| 684 |
+
"source": [
|
| 685 |
+
"# funkcja do inferencji modelu\n",
|
| 686 |
+
"def inference_model(model, test_dataset, max_factors, name):\n",
|
| 687 |
+
" print(f\"\\nRozpoczynam testowanie modelu {name}...\")\n",
|
| 688 |
+
" model.eval()\n",
|
| 689 |
+
"\n",
|
| 690 |
+
" diff_all = []\n",
|
| 691 |
+
" inference_times = []\n",
|
| 692 |
+
"\n",
|
| 693 |
+
" for i in range(len(test_dataset)):\n",
|
| 694 |
+
" test_image, test_result = test_dataset[i]\n",
|
| 695 |
+
" test_image_batch = test_image.unsqueeze(0).to(device)\n",
|
| 696 |
+
"\n",
|
| 697 |
+
" # INFERENCJA\n",
|
| 698 |
+
" start_time_pt = time.perf_counter() # start\n",
|
| 699 |
+
"\n",
|
| 700 |
+
" with torch.no_grad():\n",
|
| 701 |
+
" raw_output = model(test_image_batch).numpy() # predykcja\n",
|
| 702 |
+
"\n",
|
| 703 |
+
" end_time_pt = time.perf_counter() # koniec\n",
|
| 704 |
+
" inference_time = (end_time_pt - start_time_pt) * 1000\n",
|
| 705 |
+
" inference_times.append(inference_time)\n",
|
| 706 |
+
"\n",
|
| 707 |
+
" predicted = raw_output[0] * max_factors\n",
|
| 708 |
+
" real_target = test_result.numpy() * max_factors\n",
|
| 709 |
+
"\n",
|
| 710 |
+
" diff = np.abs(predicted - real_target)\n",
|
| 711 |
+
" diff_all.append(diff)\n",
|
| 712 |
+
"\n",
|
| 713 |
+
" mean_diff = np.nanmean(np.array(diff_all), axis=0)\n",
|
| 714 |
+
" mean_inference = np.mean(inference_times)\n",
|
| 715 |
+
"\n",
|
| 716 |
+
" print(f\"\\n=== WYNIKI INFERENCJI [{name}] ===\")\n",
|
| 717 |
+
" df = pd.DataFrame([\n",
|
| 718 |
+
" [\"Średni błąd (MAE)\"] + [f\"{v:.3f}\" for v in mean_diff] + [f\"{mean_inference:.2f} ms\"]\n",
|
| 719 |
+
" ])\n",
|
| 720 |
+
"\n",
|
| 721 |
+
" headers = [\"\", \"[KCAL]\", \"[FAT]\", \"[CARB]\", \"[PROTEIN]\", \"Średni czas Inferencji\"]\n",
|
| 722 |
+
"\n",
|
| 723 |
+
"\n",
|
| 724 |
+
" print(tabulate(df, headers=headers, tablefmt='grid', showindex=False))\n"
|
| 725 |
+
]
|
| 726 |
+
},
|
| 727 |
+
{
|
| 728 |
+
"cell_type": "markdown",
|
| 729 |
+
"metadata": {},
|
| 730 |
+
"source": [
|
| 731 |
+
"PyTorch (CPU) MobileNetV2"
|
| 732 |
+
]
|
| 733 |
+
},
|
| 734 |
+
{
|
| 735 |
+
"cell_type": "code",
|
| 736 |
+
"execution_count": 9,
|
| 737 |
+
"metadata": {},
|
| 738 |
+
"outputs": [
|
| 739 |
+
{
|
| 740 |
+
"name": "stdout",
|
| 741 |
+
"output_type": "stream",
|
| 742 |
+
"text": [
|
| 743 |
+
"Załadowano model z pliku na cpu\n"
|
| 744 |
+
]
|
| 745 |
+
},
|
| 746 |
+
{
|
| 747 |
+
"name": "stderr",
|
| 748 |
+
"output_type": "stream",
|
| 749 |
+
"text": [
|
| 750 |
+
"C:\\Users\\Kacper\\AppData\\Local\\Temp\\ipykernel_12660\\1426864496.py:18: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",
|
| 751 |
+
" model_mobilenet.load_state_dict(torch.load('models/best_model.pth', map_location=device))\n"
|
| 752 |
+
]
|
| 753 |
+
}
|
| 754 |
+
],
|
| 755 |
+
"source": [
|
| 756 |
+
"# stworzenie pustego modelu\n",
|
| 757 |
+
"model_mobilenet = models.mobilenet_v2()\n",
|
| 758 |
+
"\n",
|
| 759 |
+
"# podmiana ostatniej warstwy\n",
|
| 760 |
+
"# 4 wyjścia [Kalorie, Białko, Tłuszcz, Węglowodany]\n",
|
| 761 |
+
"num_ftrs = model_mobilenet.classifier[1].in_features\n",
|
| 762 |
+
"model_mobilenet.classifier[1] = nn.Sequential(\n",
|
| 763 |
+
" nn.Linear(num_ftrs, 256),\n",
|
| 764 |
+
" nn.ReLU(),\n",
|
| 765 |
+
" nn.Dropout(0.3),\n",
|
| 766 |
+
" nn.Linear(256, 4),\n",
|
| 767 |
+
" nn.ReLU()\n",
|
| 768 |
+
")\n",
|
| 769 |
+
"\n",
|
| 770 |
+
"device = \"cpu\"\n",
|
| 771 |
+
"model_mobilenet = model_mobilenet.to(device)\n",
|
| 772 |
+
"\n",
|
| 773 |
+
"model_mobilenet.load_state_dict(torch.load('models/best_model.pth', map_location=device))\n",
|
| 774 |
+
"\n",
|
| 775 |
+
"print(f\"Załadowano model z pliku na {device}\")"
|
| 776 |
+
]
|
| 777 |
+
},
|
| 778 |
+
{
|
| 779 |
+
"cell_type": "markdown",
|
| 780 |
+
"metadata": {},
|
| 781 |
+
"source": [
|
| 782 |
+
"ONNX MobileNetV2 + kwantyzacja do INT8"
|
| 783 |
+
]
|
| 784 |
+
},
|
| 785 |
+
{
|
| 786 |
+
"cell_type": "code",
|
| 787 |
+
"execution_count": null,
|
| 788 |
+
"metadata": {},
|
| 789 |
+
"outputs": [
|
| 790 |
+
{
|
| 791 |
+
"name": "stdout",
|
| 792 |
+
"output_type": "stream",
|
| 793 |
+
"text": [
|
| 794 |
+
"Zapisano model ONNX (onnx_model.onnx)\n"
|
| 795 |
+
]
|
| 796 |
+
},
|
| 797 |
+
{
|
| 798 |
+
"name": "stderr",
|
| 799 |
+
"output_type": "stream",
|
| 800 |
+
"text": [
|
| 801 |
+
"WARNING:root:Please consider to run pre-processing before quantization. Refer to example: https://github.com/microsoft/onnxruntime-inference-examples/blob/main/quantization/image_classification/cpu/ReadMe.md \n"
|
| 802 |
+
]
|
| 803 |
+
},
|
| 804 |
+
{
|
| 805 |
+
"name": "stdout",
|
| 806 |
+
"output_type": "stream",
|
| 807 |
+
"text": [
|
| 808 |
+
"Zapisano skwantyzowany model ONNX INT8 (int8_model.onnx)\n"
|
| 809 |
+
]
|
| 810 |
+
}
|
| 811 |
+
],
|
| 812 |
+
"source": [
|
| 813 |
+
"# atrapa danych\n",
|
| 814 |
+
"dummy_input = torch.randn(1, 3, 224, 224).to('cpu')\n",
|
| 815 |
+
"\n",
|
| 816 |
+
"# użyty model z PyTorch\n",
|
| 817 |
+
"model_mobilenet.to('cpu')\n",
|
| 818 |
+
"model_mobilenet.eval()\n",
|
| 819 |
+
"\n",
|
| 820 |
+
"# EXPORT DO FORMATU ONNX\n",
|
| 821 |
+
"onnx_model_path = \"models/onnx_model.onnx\"\n",
|
| 822 |
+
"\n",
|
| 823 |
+
"torch.onnx.export(\n",
|
| 824 |
+
" model_mobilenet, # model PyTorch\n",
|
| 825 |
+
" dummy_input, # atrapa wejścia\n",
|
| 826 |
+
" onnx_model_path, # ścieżka do zapisu\n",
|
| 827 |
+
" export_params=True, # zapisz wyuczone wagi\n",
|
| 828 |
+
" opset_version=14, # wersja standardu ONNX\n",
|
| 829 |
+
" do_constant_folding=True, # optymalizacja matematyczna grafu\n",
|
| 830 |
+
" input_names=['input'], # nazwa wejścia\n",
|
| 831 |
+
" output_names=['output'], # nazwa wyjścia\n",
|
| 832 |
+
" dynamic_axes={ # pozwala na wrzucenie wielu zdjęć naraz\n",
|
| 833 |
+
" 'input': {0: 'batch_size'},\n",
|
| 834 |
+
" 'output': {0: 'batch_size'}\n",
|
| 835 |
+
" }\n",
|
| 836 |
+
")\n",
|
| 837 |
+
"print(f\"Zapisano model ONNX ({onnx_model_path})\")\n",
|
| 838 |
+
"\n",
|
| 839 |
+
"# KWANTYZACJA DO INT8\n",
|
| 840 |
+
"quantized_model_path = \"int8_model.onnx\"\n",
|
| 841 |
+
"\n",
|
| 842 |
+
"# kwantyzacja ucina precyzje wag, zmniejszając wage modelu i przyspieszając inferencje na procesorze\n",
|
| 843 |
+
"quantize_dynamic(\n",
|
| 844 |
+
" model_input=onnx_model_path, # ścieżka modelu który chcemy kwantyzować\n",
|
| 845 |
+
" model_output=quantized_model_path, # ścieżka do zapisu\n",
|
| 846 |
+
" weight_type=QuantType.QUInt8 # precyzja wag\n",
|
| 847 |
+
")\n",
|
| 848 |
+
"print(f\"Zapisano skwantyzowany model ONNX INT8 ({quantized_model_path})\")"
|
| 849 |
+
]
|
| 850 |
+
},
|
| 851 |
+
{
|
| 852 |
+
"cell_type": "markdown",
|
| 853 |
+
"metadata": {},
|
| 854 |
+
"source": [
|
| 855 |
+
"Funkcja do inferencji modelu ONNX"
|
| 856 |
+
]
|
| 857 |
+
},
|
| 858 |
+
{
|
| 859 |
+
"cell_type": "code",
|
| 860 |
+
"execution_count": 10,
|
| 861 |
+
"metadata": {},
|
| 862 |
+
"outputs": [],
|
| 863 |
+
"source": [
|
| 864 |
+
"def inference_model_onnx(onnx_path, test_dataset, max_factors, name):\n",
|
| 865 |
+
" # załadowanie silnika ONNX\n",
|
| 866 |
+
" session = ort.InferenceSession(onnx_path, providers=['CPUExecutionProvider'])\n",
|
| 867 |
+
"\n",
|
| 868 |
+
" # nazwa wejścia definiowana przy exporcie\n",
|
| 869 |
+
" input_name = session.get_inputs()[0].name\n",
|
| 870 |
+
"\n",
|
| 871 |
+
" print(f\"\\nRozpoczynam testowanie modelu {name}...\")\n",
|
| 872 |
+
"\n",
|
| 873 |
+
" diff_all = []\n",
|
| 874 |
+
" inference_times = []\n",
|
| 875 |
+
"\n",
|
| 876 |
+
" for i in range(len(test_dataset)):\n",
|
| 877 |
+
" test_image, test_result = test_dataset[i]\n",
|
| 878 |
+
" test_image_batch = test_image.unsqueeze(0).numpy() # numpy() kluczowe\n",
|
| 879 |
+
"\n",
|
| 880 |
+
" # INFERENCJA\n",
|
| 881 |
+
" start_time = time.perf_counter() # start\n",
|
| 882 |
+
"\n",
|
| 883 |
+
" raw_output = session.run(None, {input_name: test_image_batch})[0]\n",
|
| 884 |
+
"\n",
|
| 885 |
+
" end_time = time.perf_counter() # koniec\n",
|
| 886 |
+
" inference_time = (end_time - start_time) * 1000\n",
|
| 887 |
+
" inference_times.append(inference_time)\n",
|
| 888 |
+
"\n",
|
| 889 |
+
" predicted = raw_output[0] * max_factors\n",
|
| 890 |
+
" real_target = test_result.numpy() * max_factors\n",
|
| 891 |
+
"\n",
|
| 892 |
+
" diff = np.abs(predicted - real_target)\n",
|
| 893 |
+
" diff_all.append(diff)\n",
|
| 894 |
+
"\n",
|
| 895 |
+
" mean_diff = np.nanmean(np.array(diff_all), axis=0)\n",
|
| 896 |
+
" mean_inference = np.mean(inference_times)\n",
|
| 897 |
+
"\n",
|
| 898 |
+
" print(f\"\\n=== WYNIKI INFERENCJI [{name}] ===\")\n",
|
| 899 |
+
" df = pd.DataFrame([\n",
|
| 900 |
+
" [\"Średni błąd (MAE)\"] + [f\"{v:.3f}\" for v in mean_diff] + [f\"{mean_inference:.2f} ms\"]\n",
|
| 901 |
+
" ])\n",
|
| 902 |
+
"\n",
|
| 903 |
+
" headers = [\"\", \"[KCAL]\", \"[FAT]\", \"[CARB]\", \"[PROTEIN]\", \"Średni czas Inferencji\"]\n",
|
| 904 |
+
"\n",
|
| 905 |
+
"\n",
|
| 906 |
+
" print(tabulate(df, headers=headers, tablefmt='grid', showindex=False))\n",
|
| 907 |
+
" "
|
| 908 |
+
]
|
| 909 |
+
},
|
| 910 |
+
{
|
| 911 |
+
"cell_type": "markdown",
|
| 912 |
+
"metadata": {},
|
| 913 |
+
"source": [
|
| 914 |
+
"### TEST INFERENCJI"
|
| 915 |
+
]
|
| 916 |
+
},
|
| 917 |
+
{
|
| 918 |
+
"cell_type": "code",
|
| 919 |
+
"execution_count": 11,
|
| 920 |
+
"metadata": {},
|
| 921 |
+
"outputs": [
|
| 922 |
+
{
|
| 923 |
+
"name": "stdout",
|
| 924 |
+
"output_type": "stream",
|
| 925 |
+
"text": [
|
| 926 |
+
"\n",
|
| 927 |
+
"Rozpoczynam testowanie modelu PyTorch [CPU]...\n",
|
| 928 |
+
"\n",
|
| 929 |
+
"=== WYNIKI INFERENCJI [PyTorch [CPU]] ===\n",
|
| 930 |
+
"+-------------------+----------+---------+----------+-------------+--------------------------+\n",
|
| 931 |
+
"| | [KCAL] | [FAT] | [CARB] | [PROTEIN] | Średni czas Inferencji |\n",
|
| 932 |
+
"+===================+==========+=========+==========+=============+==========================+\n",
|
| 933 |
+
"| Średni błąd (MAE) | 63.28 | 3.878 | 8.389 | 5.317 | 40.70 ms |\n",
|
| 934 |
+
"+-------------------+----------+---------+----------+-------------+--------------------------+\n",
|
| 935 |
+
"\n",
|
| 936 |
+
"Rozpoczynam testowanie modelu ONNX [CPU]...\n",
|
| 937 |
+
"\n",
|
| 938 |
+
"=== WYNIKI INFERENCJI [ONNX [CPU]] ===\n",
|
| 939 |
+
"+-------------------+----------+---------+----------+-------------+--------------------------+\n",
|
| 940 |
+
"| | [KCAL] | [FAT] | [CARB] | [PROTEIN] | Średni czas Inferencji |\n",
|
| 941 |
+
"+===================+==========+=========+==========+=============+==========================+\n",
|
| 942 |
+
"| Średni błąd (MAE) | 63.28 | 3.878 | 8.389 | 5.317 | 6.65 ms |\n",
|
| 943 |
+
"+-------------------+----------+---------+----------+-------------+--------------------------+\n",
|
| 944 |
+
"\n",
|
| 945 |
+
"Rozpoczynam testowanie modelu ONNX INT8 [CPU]...\n",
|
| 946 |
+
"\n",
|
| 947 |
+
"=== WYNIKI INFERENCJI [ONNX INT8 [CPU]] ===\n",
|
| 948 |
+
"+-------------------+----------+---------+----------+-------------+--------------------------+\n",
|
| 949 |
+
"| | [KCAL] | [FAT] | [CARB] | [PROTEIN] | Średni czas Inferencji |\n",
|
| 950 |
+
"+===================+==========+=========+==========+=============+==========================+\n",
|
| 951 |
+
"| Średni błąd (MAE) | 92.687 | 5.91 | 10.404 | 7.359 | 41.38 ms |\n",
|
| 952 |
+
"+-------------------+----------+---------+----------+-------------+--------------------------+\n"
|
| 953 |
+
]
|
| 954 |
+
}
|
| 955 |
+
],
|
| 956 |
+
"source": [
|
| 957 |
+
"inference_model(model_mobilenet, test_dataset, max_factors, \"PyTorch [CPU]\")\n",
|
| 958 |
+
"\n",
|
| 959 |
+
"inference_model_onnx(\"models/onnx_model.onnx\", test_dataset, max_factors, \"ONNX [CPU]\")\n",
|
| 960 |
+
"\n",
|
| 961 |
+
"inference_model_onnx(\"models/int8_model.onnx\", test_dataset, max_factors, \"ONNX INT8 [CPU]\")"
|
| 962 |
+
]
|
| 963 |
+
},
|
| 964 |
+
{
|
| 965 |
+
"cell_type": "markdown",
|
| 966 |
+
"metadata": {},
|
| 967 |
+
"source": [
|
| 968 |
+
"#### Wniosek\n",
|
| 969 |
+
"\n",
|
| 970 |
+
"Najlepszy model to **ONNX (bez kwantyzacji)**, osiągnął on najkrótszy czas inferencji (6 ms) + najlepsze rezultaty (takie same jak czysty PyTorch), model ten zostanie wykorzystany do realizacji API projektu."
|
| 971 |
+
]
|
| 972 |
+
}
|
| 973 |
+
],
|
| 974 |
+
"metadata": {
|
| 975 |
+
"accelerator": "GPU",
|
| 976 |
+
"colab": {
|
| 977 |
+
"gpuType": "T4",
|
| 978 |
+
"provenance": []
|
| 979 |
+
},
|
| 980 |
+
"kernelspec": {
|
| 981 |
+
"display_name": "food_ml",
|
| 982 |
+
"language": "python",
|
| 983 |
+
"name": "python3"
|
| 984 |
+
},
|
| 985 |
+
"language_info": {
|
| 986 |
+
"codemirror_mode": {
|
| 987 |
+
"name": "ipython",
|
| 988 |
+
"version": 3
|
| 989 |
+
},
|
| 990 |
+
"file_extension": ".py",
|
| 991 |
+
"mimetype": "text/x-python",
|
| 992 |
+
"name": "python",
|
| 993 |
+
"nbconvert_exporter": "python",
|
| 994 |
+
"pygments_lexer": "ipython3",
|
| 995 |
+
"version": "3.10.20"
|
| 996 |
+
},
|
| 997 |
+
"widgets": {
|
| 998 |
+
"application/vnd.jupyter.widget-state+json": {
|
| 999 |
+
"0b6b96bd67fb4b1e86f85c64a03bed6e": {
|
| 1000 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1001 |
+
"model_module_version": "1.5.0",
|
| 1002 |
+
"model_name": "DescriptionStyleModel",
|
| 1003 |
+
"state": {
|
| 1004 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1005 |
+
"_model_module_version": "1.5.0",
|
| 1006 |
+
"_model_name": "DescriptionStyleModel",
|
| 1007 |
+
"_view_count": null,
|
| 1008 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1009 |
+
"_view_module_version": "1.2.0",
|
| 1010 |
+
"_view_name": "StyleView",
|
| 1011 |
+
"description_width": ""
|
| 1012 |
+
}
|
| 1013 |
+
},
|
| 1014 |
+
"0f2e8d3ced844f87a7716241727a05bb": {
|
| 1015 |
+
"model_module": "@jupyter-widgets/base",
|
| 1016 |
+
"model_module_version": "1.2.0",
|
| 1017 |
+
"model_name": "LayoutModel",
|
| 1018 |
+
"state": {
|
| 1019 |
+
"_model_module": "@jupyter-widgets/base",
|
| 1020 |
+
"_model_module_version": "1.2.0",
|
| 1021 |
+
"_model_name": "LayoutModel",
|
| 1022 |
+
"_view_count": null,
|
| 1023 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1024 |
+
"_view_module_version": "1.2.0",
|
| 1025 |
+
"_view_name": "LayoutView",
|
| 1026 |
+
"align_content": null,
|
| 1027 |
+
"align_items": null,
|
| 1028 |
+
"align_self": null,
|
| 1029 |
+
"border": null,
|
| 1030 |
+
"bottom": null,
|
| 1031 |
+
"display": null,
|
| 1032 |
+
"flex": null,
|
| 1033 |
+
"flex_flow": null,
|
| 1034 |
+
"grid_area": null,
|
| 1035 |
+
"grid_auto_columns": null,
|
| 1036 |
+
"grid_auto_flow": null,
|
| 1037 |
+
"grid_auto_rows": null,
|
| 1038 |
+
"grid_column": null,
|
| 1039 |
+
"grid_gap": null,
|
| 1040 |
+
"grid_row": null,
|
| 1041 |
+
"grid_template_areas": null,
|
| 1042 |
+
"grid_template_columns": null,
|
| 1043 |
+
"grid_template_rows": null,
|
| 1044 |
+
"height": null,
|
| 1045 |
+
"justify_content": null,
|
| 1046 |
+
"justify_items": null,
|
| 1047 |
+
"left": null,
|
| 1048 |
+
"margin": null,
|
| 1049 |
+
"max_height": null,
|
| 1050 |
+
"max_width": null,
|
| 1051 |
+
"min_height": null,
|
| 1052 |
+
"min_width": null,
|
| 1053 |
+
"object_fit": null,
|
| 1054 |
+
"object_position": null,
|
| 1055 |
+
"order": null,
|
| 1056 |
+
"overflow": null,
|
| 1057 |
+
"overflow_x": null,
|
| 1058 |
+
"overflow_y": null,
|
| 1059 |
+
"padding": null,
|
| 1060 |
+
"right": null,
|
| 1061 |
+
"top": null,
|
| 1062 |
+
"visibility": null,
|
| 1063 |
+
"width": null
|
| 1064 |
+
}
|
| 1065 |
+
},
|
| 1066 |
+
"285067ea372542b0b33884ac9f673bdf": {
|
| 1067 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1068 |
+
"model_module_version": "1.5.0",
|
| 1069 |
+
"model_name": "FloatProgressModel",
|
| 1070 |
+
"state": {
|
| 1071 |
+
"_dom_classes": [],
|
| 1072 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1073 |
+
"_model_module_version": "1.5.0",
|
| 1074 |
+
"_model_name": "FloatProgressModel",
|
| 1075 |
+
"_view_count": null,
|
| 1076 |
+
"_view_module": "@jupyter-widgets/controls",
|
| 1077 |
+
"_view_module_version": "1.5.0",
|
| 1078 |
+
"_view_name": "ProgressView",
|
| 1079 |
+
"bar_style": "success",
|
| 1080 |
+
"description": "",
|
| 1081 |
+
"description_tooltip": null,
|
| 1082 |
+
"layout": "IPY_MODEL_da60736bf83a40dba607d1790b18e1ec",
|
| 1083 |
+
"max": 652,
|
| 1084 |
+
"min": 0,
|
| 1085 |
+
"orientation": "horizontal",
|
| 1086 |
+
"style": "IPY_MODEL_50b0bf64a56140d7bce17eebacd4b458",
|
| 1087 |
+
"value": 652
|
| 1088 |
+
}
|
| 1089 |
+
},
|
| 1090 |
+
"383d49a8573b4edaa8112bb3f1b0fdf5": {
|
| 1091 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1092 |
+
"model_module_version": "1.5.0",
|
| 1093 |
+
"model_name": "HBoxModel",
|
| 1094 |
+
"state": {
|
| 1095 |
+
"_dom_classes": [],
|
| 1096 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1097 |
+
"_model_module_version": "1.5.0",
|
| 1098 |
+
"_model_name": "HBoxModel",
|
| 1099 |
+
"_view_count": null,
|
| 1100 |
+
"_view_module": "@jupyter-widgets/controls",
|
| 1101 |
+
"_view_module_version": "1.5.0",
|
| 1102 |
+
"_view_name": "HBoxView",
|
| 1103 |
+
"box_style": "",
|
| 1104 |
+
"children": [
|
| 1105 |
+
"IPY_MODEL_3f30729bea374230be2518f856932d75",
|
| 1106 |
+
"IPY_MODEL_285067ea372542b0b33884ac9f673bdf",
|
| 1107 |
+
"IPY_MODEL_d87645ce5d2c443cab2d67adae2a59f3"
|
| 1108 |
+
],
|
| 1109 |
+
"layout": "IPY_MODEL_0f2e8d3ced844f87a7716241727a05bb"
|
| 1110 |
+
}
|
| 1111 |
+
},
|
| 1112 |
+
"39505a3dd9fb4d4d9e0a87b196d34dcf": {
|
| 1113 |
+
"model_module": "@jupyter-widgets/base",
|
| 1114 |
+
"model_module_version": "1.2.0",
|
| 1115 |
+
"model_name": "LayoutModel",
|
| 1116 |
+
"state": {
|
| 1117 |
+
"_model_module": "@jupyter-widgets/base",
|
| 1118 |
+
"_model_module_version": "1.2.0",
|
| 1119 |
+
"_model_name": "LayoutModel",
|
| 1120 |
+
"_view_count": null,
|
| 1121 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1122 |
+
"_view_module_version": "1.2.0",
|
| 1123 |
+
"_view_name": "LayoutView",
|
| 1124 |
+
"align_content": null,
|
| 1125 |
+
"align_items": null,
|
| 1126 |
+
"align_self": null,
|
| 1127 |
+
"border": null,
|
| 1128 |
+
"bottom": null,
|
| 1129 |
+
"display": null,
|
| 1130 |
+
"flex": null,
|
| 1131 |
+
"flex_flow": null,
|
| 1132 |
+
"grid_area": null,
|
| 1133 |
+
"grid_auto_columns": null,
|
| 1134 |
+
"grid_auto_flow": null,
|
| 1135 |
+
"grid_auto_rows": null,
|
| 1136 |
+
"grid_column": null,
|
| 1137 |
+
"grid_gap": null,
|
| 1138 |
+
"grid_row": null,
|
| 1139 |
+
"grid_template_areas": null,
|
| 1140 |
+
"grid_template_columns": null,
|
| 1141 |
+
"grid_template_rows": null,
|
| 1142 |
+
"height": null,
|
| 1143 |
+
"justify_content": null,
|
| 1144 |
+
"justify_items": null,
|
| 1145 |
+
"left": null,
|
| 1146 |
+
"margin": null,
|
| 1147 |
+
"max_height": null,
|
| 1148 |
+
"max_width": null,
|
| 1149 |
+
"min_height": null,
|
| 1150 |
+
"min_width": null,
|
| 1151 |
+
"object_fit": null,
|
| 1152 |
+
"object_position": null,
|
| 1153 |
+
"order": null,
|
| 1154 |
+
"overflow": null,
|
| 1155 |
+
"overflow_x": null,
|
| 1156 |
+
"overflow_y": null,
|
| 1157 |
+
"padding": null,
|
| 1158 |
+
"right": null,
|
| 1159 |
+
"top": null,
|
| 1160 |
+
"visibility": null,
|
| 1161 |
+
"width": null
|
| 1162 |
+
}
|
| 1163 |
+
},
|
| 1164 |
+
"3f30729bea374230be2518f856932d75": {
|
| 1165 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1166 |
+
"model_module_version": "1.5.0",
|
| 1167 |
+
"model_name": "HTMLModel",
|
| 1168 |
+
"state": {
|
| 1169 |
+
"_dom_classes": [],
|
| 1170 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1171 |
+
"_model_module_version": "1.5.0",
|
| 1172 |
+
"_model_name": "HTMLModel",
|
| 1173 |
+
"_view_count": null,
|
| 1174 |
+
"_view_module": "@jupyter-widgets/controls",
|
| 1175 |
+
"_view_module_version": "1.5.0",
|
| 1176 |
+
"_view_name": "HTMLView",
|
| 1177 |
+
"description": "",
|
| 1178 |
+
"description_tooltip": null,
|
| 1179 |
+
"layout": "IPY_MODEL_6a9109178b124b658333522102e1d3d5",
|
| 1180 |
+
"placeholder": "",
|
| 1181 |
+
"style": "IPY_MODEL_f606ffa8c38a4875bc02a8013e66eb9f",
|
| 1182 |
+
"value": "Saving the dataset (1/1 shards): 100%"
|
| 1183 |
+
}
|
| 1184 |
+
},
|
| 1185 |
+
"50b0bf64a56140d7bce17eebacd4b458": {
|
| 1186 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1187 |
+
"model_module_version": "1.5.0",
|
| 1188 |
+
"model_name": "ProgressStyleModel",
|
| 1189 |
+
"state": {
|
| 1190 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1191 |
+
"_model_module_version": "1.5.0",
|
| 1192 |
+
"_model_name": "ProgressStyleModel",
|
| 1193 |
+
"_view_count": null,
|
| 1194 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1195 |
+
"_view_module_version": "1.2.0",
|
| 1196 |
+
"_view_name": "StyleView",
|
| 1197 |
+
"bar_color": null,
|
| 1198 |
+
"description_width": ""
|
| 1199 |
+
}
|
| 1200 |
+
},
|
| 1201 |
+
"58bd7fa138dd49fdba81c7aaaae7ee18": {
|
| 1202 |
+
"model_module": "@jupyter-widgets/base",
|
| 1203 |
+
"model_module_version": "1.2.0",
|
| 1204 |
+
"model_name": "LayoutModel",
|
| 1205 |
+
"state": {
|
| 1206 |
+
"_model_module": "@jupyter-widgets/base",
|
| 1207 |
+
"_model_module_version": "1.2.0",
|
| 1208 |
+
"_model_name": "LayoutModel",
|
| 1209 |
+
"_view_count": null,
|
| 1210 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1211 |
+
"_view_module_version": "1.2.0",
|
| 1212 |
+
"_view_name": "LayoutView",
|
| 1213 |
+
"align_content": null,
|
| 1214 |
+
"align_items": null,
|
| 1215 |
+
"align_self": null,
|
| 1216 |
+
"border": null,
|
| 1217 |
+
"bottom": null,
|
| 1218 |
+
"display": null,
|
| 1219 |
+
"flex": null,
|
| 1220 |
+
"flex_flow": null,
|
| 1221 |
+
"grid_area": null,
|
| 1222 |
+
"grid_auto_columns": null,
|
| 1223 |
+
"grid_auto_flow": null,
|
| 1224 |
+
"grid_auto_rows": null,
|
| 1225 |
+
"grid_column": null,
|
| 1226 |
+
"grid_gap": null,
|
| 1227 |
+
"grid_row": null,
|
| 1228 |
+
"grid_template_areas": null,
|
| 1229 |
+
"grid_template_columns": null,
|
| 1230 |
+
"grid_template_rows": null,
|
| 1231 |
+
"height": null,
|
| 1232 |
+
"justify_content": null,
|
| 1233 |
+
"justify_items": null,
|
| 1234 |
+
"left": null,
|
| 1235 |
+
"margin": null,
|
| 1236 |
+
"max_height": null,
|
| 1237 |
+
"max_width": null,
|
| 1238 |
+
"min_height": null,
|
| 1239 |
+
"min_width": null,
|
| 1240 |
+
"object_fit": null,
|
| 1241 |
+
"object_position": null,
|
| 1242 |
+
"order": null,
|
| 1243 |
+
"overflow": null,
|
| 1244 |
+
"overflow_x": null,
|
| 1245 |
+
"overflow_y": null,
|
| 1246 |
+
"padding": null,
|
| 1247 |
+
"right": null,
|
| 1248 |
+
"top": null,
|
| 1249 |
+
"visibility": null,
|
| 1250 |
+
"width": null
|
| 1251 |
+
}
|
| 1252 |
+
},
|
| 1253 |
+
"6a9109178b124b658333522102e1d3d5": {
|
| 1254 |
+
"model_module": "@jupyter-widgets/base",
|
| 1255 |
+
"model_module_version": "1.2.0",
|
| 1256 |
+
"model_name": "LayoutModel",
|
| 1257 |
+
"state": {
|
| 1258 |
+
"_model_module": "@jupyter-widgets/base",
|
| 1259 |
+
"_model_module_version": "1.2.0",
|
| 1260 |
+
"_model_name": "LayoutModel",
|
| 1261 |
+
"_view_count": null,
|
| 1262 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1263 |
+
"_view_module_version": "1.2.0",
|
| 1264 |
+
"_view_name": "LayoutView",
|
| 1265 |
+
"align_content": null,
|
| 1266 |
+
"align_items": null,
|
| 1267 |
+
"align_self": null,
|
| 1268 |
+
"border": null,
|
| 1269 |
+
"bottom": null,
|
| 1270 |
+
"display": null,
|
| 1271 |
+
"flex": null,
|
| 1272 |
+
"flex_flow": null,
|
| 1273 |
+
"grid_area": null,
|
| 1274 |
+
"grid_auto_columns": null,
|
| 1275 |
+
"grid_auto_flow": null,
|
| 1276 |
+
"grid_auto_rows": null,
|
| 1277 |
+
"grid_column": null,
|
| 1278 |
+
"grid_gap": null,
|
| 1279 |
+
"grid_row": null,
|
| 1280 |
+
"grid_template_areas": null,
|
| 1281 |
+
"grid_template_columns": null,
|
| 1282 |
+
"grid_template_rows": null,
|
| 1283 |
+
"height": null,
|
| 1284 |
+
"justify_content": null,
|
| 1285 |
+
"justify_items": null,
|
| 1286 |
+
"left": null,
|
| 1287 |
+
"margin": null,
|
| 1288 |
+
"max_height": null,
|
| 1289 |
+
"max_width": null,
|
| 1290 |
+
"min_height": null,
|
| 1291 |
+
"min_width": null,
|
| 1292 |
+
"object_fit": null,
|
| 1293 |
+
"object_position": null,
|
| 1294 |
+
"order": null,
|
| 1295 |
+
"overflow": null,
|
| 1296 |
+
"overflow_x": null,
|
| 1297 |
+
"overflow_y": null,
|
| 1298 |
+
"padding": null,
|
| 1299 |
+
"right": null,
|
| 1300 |
+
"top": null,
|
| 1301 |
+
"visibility": null,
|
| 1302 |
+
"width": null
|
| 1303 |
+
}
|
| 1304 |
+
},
|
| 1305 |
+
"8afbb9695a364f87a5d8cb9179d0d797": {
|
| 1306 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1307 |
+
"model_module_version": "1.5.0",
|
| 1308 |
+
"model_name": "HTMLModel",
|
| 1309 |
+
"state": {
|
| 1310 |
+
"_dom_classes": [],
|
| 1311 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1312 |
+
"_model_module_version": "1.5.0",
|
| 1313 |
+
"_model_name": "HTMLModel",
|
| 1314 |
+
"_view_count": null,
|
| 1315 |
+
"_view_module": "@jupyter-widgets/controls",
|
| 1316 |
+
"_view_module_version": "1.5.0",
|
| 1317 |
+
"_view_name": "HTMLView",
|
| 1318 |
+
"description": "",
|
| 1319 |
+
"description_tooltip": null,
|
| 1320 |
+
"layout": "IPY_MODEL_39505a3dd9fb4d4d9e0a87b196d34dcf",
|
| 1321 |
+
"placeholder": "",
|
| 1322 |
+
"style": "IPY_MODEL_ef1da96b7eb9459cbe3137fa21d954a9",
|
| 1323 |
+
"value": " 2608/2608 [00:18<00:00, 140.10 examples/s]"
|
| 1324 |
+
}
|
| 1325 |
+
},
|
| 1326 |
+
"930be0d638704282bb2d152017e426b4": {
|
| 1327 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1328 |
+
"model_module_version": "1.5.0",
|
| 1329 |
+
"model_name": "ProgressStyleModel",
|
| 1330 |
+
"state": {
|
| 1331 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1332 |
+
"_model_module_version": "1.5.0",
|
| 1333 |
+
"_model_name": "ProgressStyleModel",
|
| 1334 |
+
"_view_count": null,
|
| 1335 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1336 |
+
"_view_module_version": "1.2.0",
|
| 1337 |
+
"_view_name": "StyleView",
|
| 1338 |
+
"bar_color": null,
|
| 1339 |
+
"description_width": ""
|
| 1340 |
+
}
|
| 1341 |
+
},
|
| 1342 |
+
"c07a874cdc4a48b8bf3b1d8e8a89b6eb": {
|
| 1343 |
+
"model_module": "@jupyter-widgets/base",
|
| 1344 |
+
"model_module_version": "1.2.0",
|
| 1345 |
+
"model_name": "LayoutModel",
|
| 1346 |
+
"state": {
|
| 1347 |
+
"_model_module": "@jupyter-widgets/base",
|
| 1348 |
+
"_model_module_version": "1.2.0",
|
| 1349 |
+
"_model_name": "LayoutModel",
|
| 1350 |
+
"_view_count": null,
|
| 1351 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1352 |
+
"_view_module_version": "1.2.0",
|
| 1353 |
+
"_view_name": "LayoutView",
|
| 1354 |
+
"align_content": null,
|
| 1355 |
+
"align_items": null,
|
| 1356 |
+
"align_self": null,
|
| 1357 |
+
"border": null,
|
| 1358 |
+
"bottom": null,
|
| 1359 |
+
"display": null,
|
| 1360 |
+
"flex": null,
|
| 1361 |
+
"flex_flow": null,
|
| 1362 |
+
"grid_area": null,
|
| 1363 |
+
"grid_auto_columns": null,
|
| 1364 |
+
"grid_auto_flow": null,
|
| 1365 |
+
"grid_auto_rows": null,
|
| 1366 |
+
"grid_column": null,
|
| 1367 |
+
"grid_gap": null,
|
| 1368 |
+
"grid_row": null,
|
| 1369 |
+
"grid_template_areas": null,
|
| 1370 |
+
"grid_template_columns": null,
|
| 1371 |
+
"grid_template_rows": null,
|
| 1372 |
+
"height": null,
|
| 1373 |
+
"justify_content": null,
|
| 1374 |
+
"justify_items": null,
|
| 1375 |
+
"left": null,
|
| 1376 |
+
"margin": null,
|
| 1377 |
+
"max_height": null,
|
| 1378 |
+
"max_width": null,
|
| 1379 |
+
"min_height": null,
|
| 1380 |
+
"min_width": null,
|
| 1381 |
+
"object_fit": null,
|
| 1382 |
+
"object_position": null,
|
| 1383 |
+
"order": null,
|
| 1384 |
+
"overflow": null,
|
| 1385 |
+
"overflow_x": null,
|
| 1386 |
+
"overflow_y": null,
|
| 1387 |
+
"padding": null,
|
| 1388 |
+
"right": null,
|
| 1389 |
+
"top": null,
|
| 1390 |
+
"visibility": null,
|
| 1391 |
+
"width": null
|
| 1392 |
+
}
|
| 1393 |
+
},
|
| 1394 |
+
"ceb341ce3bbd4501a6a4571e5f90ef97": {
|
| 1395 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1396 |
+
"model_module_version": "1.5.0",
|
| 1397 |
+
"model_name": "FloatProgressModel",
|
| 1398 |
+
"state": {
|
| 1399 |
+
"_dom_classes": [],
|
| 1400 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1401 |
+
"_model_module_version": "1.5.0",
|
| 1402 |
+
"_model_name": "FloatProgressModel",
|
| 1403 |
+
"_view_count": null,
|
| 1404 |
+
"_view_module": "@jupyter-widgets/controls",
|
| 1405 |
+
"_view_module_version": "1.5.0",
|
| 1406 |
+
"_view_name": "ProgressView",
|
| 1407 |
+
"bar_style": "success",
|
| 1408 |
+
"description": "",
|
| 1409 |
+
"description_tooltip": null,
|
| 1410 |
+
"layout": "IPY_MODEL_58bd7fa138dd49fdba81c7aaaae7ee18",
|
| 1411 |
+
"max": 2608,
|
| 1412 |
+
"min": 0,
|
| 1413 |
+
"orientation": "horizontal",
|
| 1414 |
+
"style": "IPY_MODEL_930be0d638704282bb2d152017e426b4",
|
| 1415 |
+
"value": 2608
|
| 1416 |
+
}
|
| 1417 |
+
},
|
| 1418 |
+
"d3a8e790b1cf4b7b81cd14ced76c8b21": {
|
| 1419 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1420 |
+
"model_module_version": "1.5.0",
|
| 1421 |
+
"model_name": "HBoxModel",
|
| 1422 |
+
"state": {
|
| 1423 |
+
"_dom_classes": [],
|
| 1424 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1425 |
+
"_model_module_version": "1.5.0",
|
| 1426 |
+
"_model_name": "HBoxModel",
|
| 1427 |
+
"_view_count": null,
|
| 1428 |
+
"_view_module": "@jupyter-widgets/controls",
|
| 1429 |
+
"_view_module_version": "1.5.0",
|
| 1430 |
+
"_view_name": "HBoxView",
|
| 1431 |
+
"box_style": "",
|
| 1432 |
+
"children": [
|
| 1433 |
+
"IPY_MODEL_ffb88d550f134522bef235e4562e7703",
|
| 1434 |
+
"IPY_MODEL_ceb341ce3bbd4501a6a4571e5f90ef97",
|
| 1435 |
+
"IPY_MODEL_8afbb9695a364f87a5d8cb9179d0d797"
|
| 1436 |
+
],
|
| 1437 |
+
"layout": "IPY_MODEL_e003619d59ca4e82bcffc06e674496de"
|
| 1438 |
+
}
|
| 1439 |
+
},
|
| 1440 |
+
"d87645ce5d2c443cab2d67adae2a59f3": {
|
| 1441 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1442 |
+
"model_module_version": "1.5.0",
|
| 1443 |
+
"model_name": "HTMLModel",
|
| 1444 |
+
"state": {
|
| 1445 |
+
"_dom_classes": [],
|
| 1446 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1447 |
+
"_model_module_version": "1.5.0",
|
| 1448 |
+
"_model_name": "HTMLModel",
|
| 1449 |
+
"_view_count": null,
|
| 1450 |
+
"_view_module": "@jupyter-widgets/controls",
|
| 1451 |
+
"_view_module_version": "1.5.0",
|
| 1452 |
+
"_view_name": "HTMLView",
|
| 1453 |
+
"description": "",
|
| 1454 |
+
"description_tooltip": null,
|
| 1455 |
+
"layout": "IPY_MODEL_fe58601fb3d14dddb4c6172693b89707",
|
| 1456 |
+
"placeholder": "",
|
| 1457 |
+
"style": "IPY_MODEL_fb15837db0f64e0fbf057a1d8af5f8e7",
|
| 1458 |
+
"value": " 652/652 [00:03<00:00, 217.00 examples/s]"
|
| 1459 |
+
}
|
| 1460 |
+
},
|
| 1461 |
+
"da60736bf83a40dba607d1790b18e1ec": {
|
| 1462 |
+
"model_module": "@jupyter-widgets/base",
|
| 1463 |
+
"model_module_version": "1.2.0",
|
| 1464 |
+
"model_name": "LayoutModel",
|
| 1465 |
+
"state": {
|
| 1466 |
+
"_model_module": "@jupyter-widgets/base",
|
| 1467 |
+
"_model_module_version": "1.2.0",
|
| 1468 |
+
"_model_name": "LayoutModel",
|
| 1469 |
+
"_view_count": null,
|
| 1470 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1471 |
+
"_view_module_version": "1.2.0",
|
| 1472 |
+
"_view_name": "LayoutView",
|
| 1473 |
+
"align_content": null,
|
| 1474 |
+
"align_items": null,
|
| 1475 |
+
"align_self": null,
|
| 1476 |
+
"border": null,
|
| 1477 |
+
"bottom": null,
|
| 1478 |
+
"display": null,
|
| 1479 |
+
"flex": null,
|
| 1480 |
+
"flex_flow": null,
|
| 1481 |
+
"grid_area": null,
|
| 1482 |
+
"grid_auto_columns": null,
|
| 1483 |
+
"grid_auto_flow": null,
|
| 1484 |
+
"grid_auto_rows": null,
|
| 1485 |
+
"grid_column": null,
|
| 1486 |
+
"grid_gap": null,
|
| 1487 |
+
"grid_row": null,
|
| 1488 |
+
"grid_template_areas": null,
|
| 1489 |
+
"grid_template_columns": null,
|
| 1490 |
+
"grid_template_rows": null,
|
| 1491 |
+
"height": null,
|
| 1492 |
+
"justify_content": null,
|
| 1493 |
+
"justify_items": null,
|
| 1494 |
+
"left": null,
|
| 1495 |
+
"margin": null,
|
| 1496 |
+
"max_height": null,
|
| 1497 |
+
"max_width": null,
|
| 1498 |
+
"min_height": null,
|
| 1499 |
+
"min_width": null,
|
| 1500 |
+
"object_fit": null,
|
| 1501 |
+
"object_position": null,
|
| 1502 |
+
"order": null,
|
| 1503 |
+
"overflow": null,
|
| 1504 |
+
"overflow_x": null,
|
| 1505 |
+
"overflow_y": null,
|
| 1506 |
+
"padding": null,
|
| 1507 |
+
"right": null,
|
| 1508 |
+
"top": null,
|
| 1509 |
+
"visibility": null,
|
| 1510 |
+
"width": null
|
| 1511 |
+
}
|
| 1512 |
+
},
|
| 1513 |
+
"e003619d59ca4e82bcffc06e674496de": {
|
| 1514 |
+
"model_module": "@jupyter-widgets/base",
|
| 1515 |
+
"model_module_version": "1.2.0",
|
| 1516 |
+
"model_name": "LayoutModel",
|
| 1517 |
+
"state": {
|
| 1518 |
+
"_model_module": "@jupyter-widgets/base",
|
| 1519 |
+
"_model_module_version": "1.2.0",
|
| 1520 |
+
"_model_name": "LayoutModel",
|
| 1521 |
+
"_view_count": null,
|
| 1522 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1523 |
+
"_view_module_version": "1.2.0",
|
| 1524 |
+
"_view_name": "LayoutView",
|
| 1525 |
+
"align_content": null,
|
| 1526 |
+
"align_items": null,
|
| 1527 |
+
"align_self": null,
|
| 1528 |
+
"border": null,
|
| 1529 |
+
"bottom": null,
|
| 1530 |
+
"display": null,
|
| 1531 |
+
"flex": null,
|
| 1532 |
+
"flex_flow": null,
|
| 1533 |
+
"grid_area": null,
|
| 1534 |
+
"grid_auto_columns": null,
|
| 1535 |
+
"grid_auto_flow": null,
|
| 1536 |
+
"grid_auto_rows": null,
|
| 1537 |
+
"grid_column": null,
|
| 1538 |
+
"grid_gap": null,
|
| 1539 |
+
"grid_row": null,
|
| 1540 |
+
"grid_template_areas": null,
|
| 1541 |
+
"grid_template_columns": null,
|
| 1542 |
+
"grid_template_rows": null,
|
| 1543 |
+
"height": null,
|
| 1544 |
+
"justify_content": null,
|
| 1545 |
+
"justify_items": null,
|
| 1546 |
+
"left": null,
|
| 1547 |
+
"margin": null,
|
| 1548 |
+
"max_height": null,
|
| 1549 |
+
"max_width": null,
|
| 1550 |
+
"min_height": null,
|
| 1551 |
+
"min_width": null,
|
| 1552 |
+
"object_fit": null,
|
| 1553 |
+
"object_position": null,
|
| 1554 |
+
"order": null,
|
| 1555 |
+
"overflow": null,
|
| 1556 |
+
"overflow_x": null,
|
| 1557 |
+
"overflow_y": null,
|
| 1558 |
+
"padding": null,
|
| 1559 |
+
"right": null,
|
| 1560 |
+
"top": null,
|
| 1561 |
+
"visibility": null,
|
| 1562 |
+
"width": null
|
| 1563 |
+
}
|
| 1564 |
+
},
|
| 1565 |
+
"ef1da96b7eb9459cbe3137fa21d954a9": {
|
| 1566 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1567 |
+
"model_module_version": "1.5.0",
|
| 1568 |
+
"model_name": "DescriptionStyleModel",
|
| 1569 |
+
"state": {
|
| 1570 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1571 |
+
"_model_module_version": "1.5.0",
|
| 1572 |
+
"_model_name": "DescriptionStyleModel",
|
| 1573 |
+
"_view_count": null,
|
| 1574 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1575 |
+
"_view_module_version": "1.2.0",
|
| 1576 |
+
"_view_name": "StyleView",
|
| 1577 |
+
"description_width": ""
|
| 1578 |
+
}
|
| 1579 |
+
},
|
| 1580 |
+
"f606ffa8c38a4875bc02a8013e66eb9f": {
|
| 1581 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1582 |
+
"model_module_version": "1.5.0",
|
| 1583 |
+
"model_name": "DescriptionStyleModel",
|
| 1584 |
+
"state": {
|
| 1585 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1586 |
+
"_model_module_version": "1.5.0",
|
| 1587 |
+
"_model_name": "DescriptionStyleModel",
|
| 1588 |
+
"_view_count": null,
|
| 1589 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1590 |
+
"_view_module_version": "1.2.0",
|
| 1591 |
+
"_view_name": "StyleView",
|
| 1592 |
+
"description_width": ""
|
| 1593 |
+
}
|
| 1594 |
+
},
|
| 1595 |
+
"fb15837db0f64e0fbf057a1d8af5f8e7": {
|
| 1596 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1597 |
+
"model_module_version": "1.5.0",
|
| 1598 |
+
"model_name": "DescriptionStyleModel",
|
| 1599 |
+
"state": {
|
| 1600 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1601 |
+
"_model_module_version": "1.5.0",
|
| 1602 |
+
"_model_name": "DescriptionStyleModel",
|
| 1603 |
+
"_view_count": null,
|
| 1604 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1605 |
+
"_view_module_version": "1.2.0",
|
| 1606 |
+
"_view_name": "StyleView",
|
| 1607 |
+
"description_width": ""
|
| 1608 |
+
}
|
| 1609 |
+
},
|
| 1610 |
+
"fe58601fb3d14dddb4c6172693b89707": {
|
| 1611 |
+
"model_module": "@jupyter-widgets/base",
|
| 1612 |
+
"model_module_version": "1.2.0",
|
| 1613 |
+
"model_name": "LayoutModel",
|
| 1614 |
+
"state": {
|
| 1615 |
+
"_model_module": "@jupyter-widgets/base",
|
| 1616 |
+
"_model_module_version": "1.2.0",
|
| 1617 |
+
"_model_name": "LayoutModel",
|
| 1618 |
+
"_view_count": null,
|
| 1619 |
+
"_view_module": "@jupyter-widgets/base",
|
| 1620 |
+
"_view_module_version": "1.2.0",
|
| 1621 |
+
"_view_name": "LayoutView",
|
| 1622 |
+
"align_content": null,
|
| 1623 |
+
"align_items": null,
|
| 1624 |
+
"align_self": null,
|
| 1625 |
+
"border": null,
|
| 1626 |
+
"bottom": null,
|
| 1627 |
+
"display": null,
|
| 1628 |
+
"flex": null,
|
| 1629 |
+
"flex_flow": null,
|
| 1630 |
+
"grid_area": null,
|
| 1631 |
+
"grid_auto_columns": null,
|
| 1632 |
+
"grid_auto_flow": null,
|
| 1633 |
+
"grid_auto_rows": null,
|
| 1634 |
+
"grid_column": null,
|
| 1635 |
+
"grid_gap": null,
|
| 1636 |
+
"grid_row": null,
|
| 1637 |
+
"grid_template_areas": null,
|
| 1638 |
+
"grid_template_columns": null,
|
| 1639 |
+
"grid_template_rows": null,
|
| 1640 |
+
"height": null,
|
| 1641 |
+
"justify_content": null,
|
| 1642 |
+
"justify_items": null,
|
| 1643 |
+
"left": null,
|
| 1644 |
+
"margin": null,
|
| 1645 |
+
"max_height": null,
|
| 1646 |
+
"max_width": null,
|
| 1647 |
+
"min_height": null,
|
| 1648 |
+
"min_width": null,
|
| 1649 |
+
"object_fit": null,
|
| 1650 |
+
"object_position": null,
|
| 1651 |
+
"order": null,
|
| 1652 |
+
"overflow": null,
|
| 1653 |
+
"overflow_x": null,
|
| 1654 |
+
"overflow_y": null,
|
| 1655 |
+
"padding": null,
|
| 1656 |
+
"right": null,
|
| 1657 |
+
"top": null,
|
| 1658 |
+
"visibility": null,
|
| 1659 |
+
"width": null
|
| 1660 |
+
}
|
| 1661 |
+
},
|
| 1662 |
+
"ffb88d550f134522bef235e4562e7703": {
|
| 1663 |
+
"model_module": "@jupyter-widgets/controls",
|
| 1664 |
+
"model_module_version": "1.5.0",
|
| 1665 |
+
"model_name": "HTMLModel",
|
| 1666 |
+
"state": {
|
| 1667 |
+
"_dom_classes": [],
|
| 1668 |
+
"_model_module": "@jupyter-widgets/controls",
|
| 1669 |
+
"_model_module_version": "1.5.0",
|
| 1670 |
+
"_model_name": "HTMLModel",
|
| 1671 |
+
"_view_count": null,
|
| 1672 |
+
"_view_module": "@jupyter-widgets/controls",
|
| 1673 |
+
"_view_module_version": "1.5.0",
|
| 1674 |
+
"_view_name": "HTMLView",
|
| 1675 |
+
"description": "",
|
| 1676 |
+
"description_tooltip": null,
|
| 1677 |
+
"layout": "IPY_MODEL_c07a874cdc4a48b8bf3b1d8e8a89b6eb",
|
| 1678 |
+
"placeholder": "",
|
| 1679 |
+
"style": "IPY_MODEL_0b6b96bd67fb4b1e86f85c64a03bed6e",
|
| 1680 |
+
"value": "Saving the dataset (3/3 shards): 100%"
|
| 1681 |
+
}
|
| 1682 |
+
}
|
| 1683 |
+
}
|
| 1684 |
+
}
|
| 1685 |
+
},
|
| 1686 |
+
"nbformat": 4,
|
| 1687 |
+
"nbformat_minor": 0
|
| 1688 |
+
}
|
models/best_model.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:57faf4c4ab9e05100d57faeafd4e1483b457fd584328b0441fed29a09c24d0f7
|
| 3 |
+
size 10457402
|
models/int8_model.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:99f9bf7ac84040490ab68bd59c0644df806bbc5d6a76e0ad7ee7d9cf1c0cde49
|
| 3 |
+
size 2741589
|
models/onnx_model.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2c0d45fb6d6b17aa74902ba8daa9cb12c0ea4232d5c41cc4f7436e51d01c50ce
|
| 3 |
+
size 10184809
|
requirements.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi==0.104.1
|
| 2 |
+
uvicorn==0.24.0.post1
|
| 3 |
+
python-multipart==0.0.6
|
| 4 |
+
onnxruntime==1.16.3
|
| 5 |
+
Pillow==10.1.0
|
| 6 |
+
numpy==1.26.2
|
static/logo.png
ADDED
|
Git LFS Details
|
static/script.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// 1. ZDJĘCIA Z DATASETU
|
| 2 |
+
const hardcodedMeals = [
|
| 3 |
+
{ name: "Stek z warzywami", image: "/test_images/stek_z_warzywami.jpg", macros: { kcal: 525, p: 48, f: 35, c: 6 } },
|
| 4 |
+
{ name: "Mini pizza salami", image: "/test_images/mini_pizza_salami.jpg", macros: { kcal: 132, p: 6, f: 6, c: 15 } },
|
| 5 |
+
{ name: "Jajecznica z brokułem", image: "/test_images/jajecznica_z_brokulem.jpg", macros: { kcal: 296, p: 19, f: 21, c: 7 } },
|
| 6 |
+
{ name: "Mix sałat", image: "/test_images/miska_salaty.jpg", macros: { kcal: 20, p: 1, f: 0, c: 4 } },
|
| 7 |
+
{ name: "Bekon", image: "/test_images/bekon.jpg", macros: { kcal: 470, p: 32, f: 36, c: 1 } },
|
| 8 |
+
{ name: "Owsianka z owocami", image: "/test_images/owsianka_z_owocami.jpg", macros: { kcal: 155, p: 5, f: 3, c: 29 } }
|
| 9 |
+
];
|
| 10 |
+
|
| 11 |
+
// 2. ZDJĘCIA SPOZA DATASETU
|
| 12 |
+
const externalMeals = [
|
| 13 |
+
{ name: "Burger drwala", image: "/test_images/burger_drwala.png", macros: { kcal: 915, p: 39, f: 52, c: 70 } },
|
| 14 |
+
{ name: "Kotelty drobiowe z ziemniakami i sałatą", image: "/test_images/kotelty_z_ziemniakami.jpeg", macros: { kcal: 590, p: 61, f: 11, c: 63 } },
|
| 15 |
+
{ name: "Spaghetti bolognese", image: "/test_images/spaghetti-bolognese.jpg", macros: { kcal: 405, p: 21, f: 17, c: 43 } },
|
| 16 |
+
{ name: "SUPER bowl", image: "/test_images/super_bowl.png", macros: { kcal: 716, p: 33, f: 42, c: 60 } }
|
| 17 |
+
];
|
| 18 |
+
|
| 19 |
+
// 3. POSIŁKI UŻYTKOWNIKÓW
|
| 20 |
+
let userMeals = JSON.parse(localStorage.getItem('savedUserMeals')) || [];
|
| 21 |
+
|
| 22 |
+
let currentFile = null;
|
| 23 |
+
let currentTruth = null;
|
| 24 |
+
let activeTab = null;
|
| 25 |
+
|
| 26 |
+
// Słownik do przywracania oryginalnych nazw przycisków
|
| 27 |
+
const btnOriginalText = {
|
| 28 |
+
test: "🗂️ Dataset",
|
| 29 |
+
external: "🌍 Spoza Datasetu",
|
| 30 |
+
user: "👤 Użytkownik"
|
| 31 |
+
};
|
| 32 |
+
|
| 33 |
+
window.onload = () => {};
|
| 34 |
+
|
| 35 |
+
function openSidebar(tab) {
|
| 36 |
+
const sidebar = document.getElementById('sidebar');
|
| 37 |
+
const btns = {
|
| 38 |
+
test: document.getElementById('btnTest'),
|
| 39 |
+
external: document.getElementById('btnExternal'),
|
| 40 |
+
user: document.getElementById('btnUser')
|
| 41 |
+
};
|
| 42 |
+
|
| 43 |
+
// Resetujemy wszystkie przyciski do stanu domyślnego
|
| 44 |
+
for (let key in btns) {
|
| 45 |
+
btns[key].classList.remove('open');
|
| 46 |
+
btns[key].classList.remove('shifted'); // Usuwamy przesunięcie
|
| 47 |
+
btns[key].style.backgroundColor = "#333";
|
| 48 |
+
btns[key].style.color = "white";
|
| 49 |
+
btns[key].innerText = btnOriginalText[key];
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
// Jeśli kliknięto aktywny panel -> zamknij i przerwij (wszystko wraca na prawo)
|
| 53 |
+
if (activeTab === tab && sidebar.classList.contains('open')) {
|
| 54 |
+
sidebar.classList.remove('open');
|
| 55 |
+
activeTab = null;
|
| 56 |
+
return;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
// Otwarcie nowego panelu
|
| 60 |
+
sidebar.classList.add('open');
|
| 61 |
+
activeTab = tab;
|
| 62 |
+
|
| 63 |
+
// Przesuwamy WSZYSTKIE przyciski na lewo (do krawędzi panelu)
|
| 64 |
+
for (let key in btns) {
|
| 65 |
+
btns[key].classList.add('shifted');
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
// Stylizacja TYLKO aktywnego przycisku i zmiana tekstu na emotkę
|
| 69 |
+
btns[tab].classList.add('open');
|
| 70 |
+
btns[tab].style.backgroundColor = "#00ff88";
|
| 71 |
+
btns[tab].style.color = "#121212";
|
| 72 |
+
btns[tab].innerText = "▶︎▶︎▶︎"; // Emotka zastępująca ">>> Zamknij"
|
| 73 |
+
|
| 74 |
+
// Wybór odpowiedniej zawartości do wyświetlenia
|
| 75 |
+
if (tab === 'test') {
|
| 76 |
+
renderList(hardcodedMeals, 'test');
|
| 77 |
+
} else if (tab === 'external') {
|
| 78 |
+
renderList(externalMeals, 'external');
|
| 79 |
+
} else {
|
| 80 |
+
renderList(userMeals, 'user');
|
| 81 |
+
}
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
function renderList(mealsArray, type) {
|
| 85 |
+
const list = document.getElementById('mealsList');
|
| 86 |
+
const form = document.getElementById('addMealForm');
|
| 87 |
+
const title = document.getElementById('sidebarTitle');
|
| 88 |
+
const desc = document.getElementById('sidebarDesc');
|
| 89 |
+
|
| 90 |
+
list.innerHTML = "";
|
| 91 |
+
|
| 92 |
+
if (type === 'test') {
|
| 93 |
+
title.innerText = "Baza Datasetu";
|
| 94 |
+
desc.innerText = "Oryginalne posiłki wycięte ze zbioru testowego.";
|
| 95 |
+
form.style.display = 'none';
|
| 96 |
+
if(mealsArray.length === 0) list.innerHTML = "<p style='color:#555;'>Brak zdjęć w skrypcie.</p>";
|
| 97 |
+
} else if (type === 'external') {
|
| 98 |
+
title.innerText = "Spoza Datasetu";
|
| 99 |
+
desc.innerText = "Testy na zdjęciach spoza zbioru.";
|
| 100 |
+
form.style.display = 'none';
|
| 101 |
+
if(mealsArray.length === 0) list.innerHTML = "<p style='color:#555;'>Brak zewnętrznych zdjęć.</p>";
|
| 102 |
+
} else {
|
| 103 |
+
title.innerText = "Posiłki Użytkownika";
|
| 104 |
+
desc.innerText = "Zapisywane lokalnie w przeglądarce.";
|
| 105 |
+
form.style.display = 'block';
|
| 106 |
+
if(mealsArray.length === 0) list.innerHTML = "<p style='color:#555; text-align:center;'>Dodaj pierwszy posiłek poniżej!</p>";
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
mealsArray.forEach((meal, index) => {
|
| 110 |
+
list.innerHTML += `
|
| 111 |
+
<div class="meal-card" onclick="loadMealIntoAnalyzer(${index}, '${type}')">
|
| 112 |
+
<img src="${meal.image}" alt="Zdjęcie">
|
| 113 |
+
<div class="meal-card-title">${meal.name}</div>
|
| 114 |
+
<div class="meal-card-macro">
|
| 115 |
+
🔥 ${meal.macros.kcal} kcal | 🍗 ${meal.macros.p}g | 🥑 ${meal.macros.f}g | 🍞 ${meal.macros.c}g
|
| 116 |
+
</div>
|
| 117 |
+
</div>
|
| 118 |
+
`;
|
| 119 |
+
});
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
function previewNewImage(event) {
|
| 123 |
+
if(event.target.files.length === 0) return;
|
| 124 |
+
currentFile = event.target.files[0];
|
| 125 |
+
currentTruth = null;
|
| 126 |
+
setupPreview(URL.createObjectURL(currentFile), "Tryb: Nieznane zdjęcie (Z dysku)");
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
async function loadMealIntoAnalyzer(index, type) {
|
| 130 |
+
let meal;
|
| 131 |
+
if (type === 'test') meal = hardcodedMeals[index];
|
| 132 |
+
else if (type === 'external') meal = externalMeals[index];
|
| 133 |
+
else meal = userMeals[index];
|
| 134 |
+
|
| 135 |
+
currentTruth = meal.macros;
|
| 136 |
+
|
| 137 |
+
try {
|
| 138 |
+
const res = await fetch(meal.image);
|
| 139 |
+
const blob = await res.blob();
|
| 140 |
+
currentFile = new File([blob], "test_image.jpg", { type: "image/jpeg" });
|
| 141 |
+
setupPreview(meal.image, `Tryb: Ground Truth (${meal.name})`);
|
| 142 |
+
|
| 143 |
+
if(window.innerWidth < 800) openSidebar(activeTab);
|
| 144 |
+
} catch (err) {
|
| 145 |
+
alert("Błąd ładowania! Upewnij się, że zdjęcie jest fizycznie w folderze.");
|
| 146 |
+
}
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
function setupPreview(imageSrc, modeText) {
|
| 150 |
+
const preview = document.getElementById('preview');
|
| 151 |
+
const modeInd = document.getElementById('modeIndicator');
|
| 152 |
+
|
| 153 |
+
preview.src = imageSrc;
|
| 154 |
+
preview.style.display = 'block';
|
| 155 |
+
document.getElementById('analyzeBtn').disabled = false;
|
| 156 |
+
document.getElementById('resultsPanel').style.display = 'none';
|
| 157 |
+
|
| 158 |
+
modeInd.innerText = modeText;
|
| 159 |
+
modeInd.style.color = currentTruth ? "#ffaa00" : "#aaa";
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
async function analyzeImage() {
|
| 163 |
+
if (!currentFile) return;
|
| 164 |
+
|
| 165 |
+
const btn = document.getElementById('analyzeBtn');
|
| 166 |
+
btn.disabled = true;
|
| 167 |
+
btn.innerText = "⏳ ONNX analizuje...";
|
| 168 |
+
|
| 169 |
+
const formData = new FormData();
|
| 170 |
+
formData.append("file", currentFile);
|
| 171 |
+
|
| 172 |
+
try {
|
| 173 |
+
const response = await fetch('/predict-macro', {
|
| 174 |
+
method: 'POST',
|
| 175 |
+
body: formData
|
| 176 |
+
});
|
| 177 |
+
const data = await response.json();
|
| 178 |
+
displayResults(data.predictions);
|
| 179 |
+
} catch (error) {
|
| 180 |
+
alert("Błąd serwera! Upewnij się, że FastAPI działa.");
|
| 181 |
+
console.error(error);
|
| 182 |
+
} finally {
|
| 183 |
+
btn.disabled = false;
|
| 184 |
+
btn.innerText = "Analizuj Makro";
|
| 185 |
+
}
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
function displayResults(preds) {
|
| 189 |
+
document.getElementById('res-kcal').innerText = preds.kcal + " kcal";
|
| 190 |
+
document.getElementById('res-protein').innerText = preds.protein_g + " g";
|
| 191 |
+
document.getElementById('res-fat').innerText = preds.fat_g + " g";
|
| 192 |
+
document.getElementById('res-carb').innerText = preds.carb_g + " g";
|
| 193 |
+
|
| 194 |
+
const truthCols = document.querySelectorAll('.truth-col');
|
| 195 |
+
|
| 196 |
+
if (currentTruth) {
|
| 197 |
+
truthCols.forEach(col => col.style.display = 'table-cell');
|
| 198 |
+
|
| 199 |
+
document.getElementById('truth-kcal').innerText = currentTruth.kcal + " kcal";
|
| 200 |
+
document.getElementById('truth-protein').innerText = currentTruth.p + " g";
|
| 201 |
+
document.getElementById('truth-fat').innerText = currentTruth.f + " g";
|
| 202 |
+
document.getElementById('truth-carb').innerText = currentTruth.c + " g";
|
| 203 |
+
|
| 204 |
+
document.getElementById('diff-kcal').innerText = Math.abs((preds.kcal - currentTruth.kcal).toFixed(1)) + " kcal";
|
| 205 |
+
document.getElementById('diff-protein').innerText = Math.abs((preds.protein_g - currentTruth.p).toFixed(1)) + " g";
|
| 206 |
+
document.getElementById('diff-fat').innerText = Math.abs((preds.fat_g - currentTruth.f).toFixed(1)) + " g";
|
| 207 |
+
document.getElementById('diff-carb').innerText = Math.abs((preds.carb_g - currentTruth.c).toFixed(1)) + " g";
|
| 208 |
+
} else {
|
| 209 |
+
truthCols.forEach(col => col.style.display = 'none');
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
document.getElementById('resultsPanel').style.display = 'block';
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
function addUserMeal() {
|
| 216 |
+
const fileInput = document.getElementById('newMealImage');
|
| 217 |
+
const name = document.getElementById('newMealName').value;
|
| 218 |
+
const kcal = document.getElementById('newMealKcal').value;
|
| 219 |
+
const p = document.getElementById('newMealP').value;
|
| 220 |
+
const f = document.getElementById('newMealF').value;
|
| 221 |
+
const c = document.getElementById('newMealC').value;
|
| 222 |
+
|
| 223 |
+
if(!fileInput.files[0] || !name || !kcal) {
|
| 224 |
+
alert("Wypełnij nazwę, zdjęcie i chociaż kalorie!");
|
| 225 |
+
return;
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
const reader = new FileReader();
|
| 229 |
+
reader.onload = function(e) {
|
| 230 |
+
const newMeal = {
|
| 231 |
+
name: name,
|
| 232 |
+
image: e.target.result,
|
| 233 |
+
macros: { kcal: kcal, p: p||0, f: f||0, c: c||0 }
|
| 234 |
+
};
|
| 235 |
+
|
| 236 |
+
userMeals.push(newMeal);
|
| 237 |
+
localStorage.setItem('savedUserMeals', JSON.stringify(userMeals));
|
| 238 |
+
|
| 239 |
+
document.getElementById('newMealName').value = "";
|
| 240 |
+
fileInput.value = "";
|
| 241 |
+
renderList(userMeals, 'user');
|
| 242 |
+
};
|
| 243 |
+
reader.readAsDataURL(fileInput.files[0]);
|
| 244 |
+
}
|
static/style.css
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
body {
|
| 2 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 3 |
+
background-color: #121212;
|
| 4 |
+
color: #ffffff;
|
| 5 |
+
margin: 0;
|
| 6 |
+
overflow-x: hidden;
|
| 7 |
+
display: flex;
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
.main-panel {
|
| 11 |
+
flex-grow: 1;
|
| 12 |
+
display: flex;
|
| 13 |
+
justify-content: center;
|
| 14 |
+
align-items: center;
|
| 15 |
+
min-height: 100vh;
|
| 16 |
+
padding: 2rem;
|
| 17 |
+
transition: 0.3s;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
.container {
|
| 21 |
+
background-color: #1e1e1e;
|
| 22 |
+
padding: 2rem;
|
| 23 |
+
border-radius: 12px;
|
| 24 |
+
box-shadow: 0 8px 16px rgba(0,0,0,0.5);
|
| 25 |
+
width: 100%;
|
| 26 |
+
max-width: 500px;
|
| 27 |
+
text-align: center;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
h1 { color: #00ff88; margin-top: 0; }
|
| 31 |
+
.mode-indicator { color: #aaa; font-size: 0.9rem; margin-bottom: 20px; }
|
| 32 |
+
|
| 33 |
+
input[type="file"] { display: none; }
|
| 34 |
+
|
| 35 |
+
.custom-file-upload {
|
| 36 |
+
border: 2px dashed #00ff88;
|
| 37 |
+
padding: 1.5rem;
|
| 38 |
+
cursor: pointer;
|
| 39 |
+
border-radius: 8px;
|
| 40 |
+
display: block;
|
| 41 |
+
margin-bottom: 1rem;
|
| 42 |
+
transition: 0.3s;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
.custom-file-upload:hover { background-color: rgba(0, 255, 136, 0.1); }
|
| 46 |
+
|
| 47 |
+
#preview {
|
| 48 |
+
max-width: 100%;
|
| 49 |
+
border-radius: 8px;
|
| 50 |
+
margin-bottom: 1rem;
|
| 51 |
+
display: none;
|
| 52 |
+
max-height: 300px;
|
| 53 |
+
object-fit: cover;
|
| 54 |
+
width: 100%;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
button {
|
| 58 |
+
background-color: #00ff88;
|
| 59 |
+
color: #121212;
|
| 60 |
+
border: none;
|
| 61 |
+
padding: 10px 20px;
|
| 62 |
+
font-size: 1rem;
|
| 63 |
+
font-weight: bold;
|
| 64 |
+
border-radius: 6px;
|
| 65 |
+
cursor: pointer;
|
| 66 |
+
width: 100%;
|
| 67 |
+
transition: 0.3s;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
button:hover { background-color: #00cc6a; }
|
| 71 |
+
button:disabled { background-color: #555; cursor: not-allowed; }
|
| 72 |
+
|
| 73 |
+
.results {
|
| 74 |
+
margin-top: 1.5rem;
|
| 75 |
+
text-align: left;
|
| 76 |
+
display: none;
|
| 77 |
+
background-color: #2a2a2a;
|
| 78 |
+
padding: 1rem;
|
| 79 |
+
border-radius: 8px;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
table {
|
| 83 |
+
width: 100%;
|
| 84 |
+
border-collapse: collapse;
|
| 85 |
+
margin-top: 10px;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
th, td {
|
| 89 |
+
text-align: left;
|
| 90 |
+
padding: 8px;
|
| 91 |
+
border-bottom: 1px solid #444;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
th { color: #888; font-size: 0.9rem; }
|
| 95 |
+
.emoji-col { width: 30px; text-align: center; }
|
| 96 |
+
.val-model { color: #00ff88; font-weight: bold; }
|
| 97 |
+
.val-truth { color: #ffaa00; }
|
| 98 |
+
.val-diff { color: #ff4444; font-size: 0.9rem; }
|
| 99 |
+
|
| 100 |
+
.sidebar {
|
| 101 |
+
position: fixed;
|
| 102 |
+
right: -400px;
|
| 103 |
+
top: 0;
|
| 104 |
+
width: 350px;
|
| 105 |
+
height: 100vh;
|
| 106 |
+
background-color: #1a1a1a;
|
| 107 |
+
border-left: 1px solid #333;
|
| 108 |
+
transition: right 0.3s ease-in-out;
|
| 109 |
+
padding: 1.5rem;
|
| 110 |
+
box-sizing: border-box;
|
| 111 |
+
overflow-y: auto;
|
| 112 |
+
z-index: 100;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
.sidebar.open { right: 0; }
|
| 116 |
+
#sidebarTitle { color: #00ff88; margin-top: 0; }
|
| 117 |
+
#sidebarDesc { font-size: 0.85rem; color: #888; }
|
| 118 |
+
|
| 119 |
+
/* PRZYCISKI ZAKŁADEK (Poziome, bez rotacji) */
|
| 120 |
+
/* PRZYCISKI ZAKŁADEK */
|
| 121 |
+
.toggle-btn {
|
| 122 |
+
position: fixed;
|
| 123 |
+
right: 20px;
|
| 124 |
+
background-color: #333;
|
| 125 |
+
color: white;
|
| 126 |
+
width: 180px;
|
| 127 |
+
height: 45px; /* Sztywna wysokość wszystkich przycisków */
|
| 128 |
+
box-sizing: border-box;
|
| 129 |
+
display: flex; /* Utrzymuje tekst idealnie na środku */
|
| 130 |
+
align-items: center;
|
| 131 |
+
justify-content: center;
|
| 132 |
+
z-index: 101;
|
| 133 |
+
transition: all 0.3s ease-in-out;
|
| 134 |
+
border-radius: 6px;
|
| 135 |
+
box-shadow: -2px 0 5px rgba(0,0,0,0.5);
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
/* Pozycje startowe (obliczone pod 45px wysokości + 10px odstępu) */
|
| 139 |
+
#btnTest { top: 20px; }
|
| 140 |
+
#btnExternal { top: 75px; }
|
| 141 |
+
#btnUser { top: 130px; }
|
| 142 |
+
|
| 143 |
+
/* Nowa klasa: Kiedy JAKIKOLWIEK panel jest otwarty, przesuwamy wszystkie przyciski */
|
| 144 |
+
.toggle-btn.shifted {
|
| 145 |
+
right: 350px;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
/* Kiedy KONKRETNY przycisk jest aktywny - zmienia kolor i łączy się z panelem */
|
| 149 |
+
.toggle-btn.open {
|
| 150 |
+
background-color: #00ff88;
|
| 151 |
+
color: #121212;
|
| 152 |
+
border-radius: 6px 0 0 6px;
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
.meal-card {
|
| 156 |
+
background-color: #2a2a2a;
|
| 157 |
+
border-radius: 8px;
|
| 158 |
+
padding: 10px;
|
| 159 |
+
margin-bottom: 15px;
|
| 160 |
+
cursor: pointer;
|
| 161 |
+
border: 1px solid transparent;
|
| 162 |
+
transition: 0.2s;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
.meal-card:hover { border-color: #00ff88; }
|
| 166 |
+
.meal-card img { width: 100%; height: 120px; object-fit: cover; border-radius: 4px; }
|
| 167 |
+
.meal-card-title { font-weight: bold; margin: 8px 0 4px 0; font-size: 1.1rem; }
|
| 168 |
+
.meal-card-macro { font-size: 0.85rem; color: #aaa; }
|
| 169 |
+
|
| 170 |
+
.add-meal-form {
|
| 171 |
+
background-color: #222;
|
| 172 |
+
padding: 15px;
|
| 173 |
+
border-radius: 8px;
|
| 174 |
+
margin-top: 20px;
|
| 175 |
+
border: 1px dashed #555;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
.add-meal-form input[type="number"], .add-meal-form input[type="text"] {
|
| 179 |
+
width: 100%; padding: 8px; margin-bottom: 8px; background-color: #333;
|
| 180 |
+
border: 1px solid #444; color: white; border-radius: 4px; box-sizing: border-box;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
.form-label { font-size: 0.85rem; color: #aaa; display: block; margin-bottom: 5px; }
|
| 184 |
+
.form-file { display: block; margin-bottom: 10px; font-size: 0.8rem; }
|
| 185 |
+
.form-row { display: flex; gap: 5px; }
|
| 186 |
+
.btn-save { margin-top: 10px; background-color: #444; color: white; }
|
test_images/bekon.jpg
ADDED
|
Git LFS Details
|
test_images/burger_drwala.png
ADDED
|
Git LFS Details
|
test_images/jajecznica_z_brokulem.jpg
ADDED
|
Git LFS Details
|
test_images/kotelty_z_ziemniakami.jpeg
ADDED
|
Git LFS Details
|
test_images/mini_pizza_salami.jpg
ADDED
|
Git LFS Details
|
test_images/miska_salaty.jpg
ADDED
|
Git LFS Details
|
test_images/owsianka_z_owocami.jpg
ADDED
|
Git LFS Details
|
test_images/pizza_slice.jpg
ADDED
|
Git LFS Details
|
test_images/spaghetti-bolognese.jpg
ADDED
|
Git LFS Details
|
test_images/stek_z_warzywami.jpg
ADDED
|
Git LFS Details
|
test_images/super_bowl.png
ADDED
|
Git LFS Details
|