# ๐Ÿฝ๏ธ ์Œ์‹ ์ด๋ฏธ์ง€ ๋ถ„๋ฅ˜ ํ”„๋กœ์ ํŠธ ๊ฐ€์ด๋“œ ## ๐Ÿ“‚ ํŒŒ์ผ ๊ตฌ์„ฑ | ํŒŒ์ผ | ์—ญํ•  | ํ•„์ˆ˜? | |------|------|-------| | `app.py` | Gradio ์›น ๋ฐ๋ชจ | โœ… Space ํ•„์ˆ˜ | | `README.md` | Space ์„ค์ • (YAML) | โœ… Space ํ•„์ˆ˜ | | `requirements.txt` | ์˜์กด์„ฑ | โœ… Space ํ•„์ˆ˜ | | `configuration_myresnet.py` | MyResNet Config | ์˜ต์…˜ B์—์„œ๋งŒ ํ•„์š” | | `modeling_myresnet.py` | MyResNet ๋ชจ๋ธ | ์˜ต์…˜ B์—์„œ๋งŒ ํ•„์š” | | `train_food.py` | Food-101 ํ•™์Šต ์Šคํฌ๋ฆฝํŠธ | ๋กœ์ปฌ ํ•™์Šต์šฉ | ## ๐ŸŽฏ ๋‘ ๊ฐ€์ง€ ์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค ### ์‹œ๋‚˜๋ฆฌ์˜ค 1: ํ•™์Šต ์—†์ด ๋ฐ”๋กœ ๋ฐ๋ชจ ์‹คํ–‰ (์ถ”์ฒœ) โญ `app.py`๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ **ํ—ˆ๊น…ํŽ˜์ด์Šค ํ—ˆ๋ธŒ์˜ ๊ณต๊ฐœ ๋ชจ๋ธ `nateraw/food`**๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋ธ์€ ์ด๋ฏธ Food-101์—์„œ ํ•™์Šต๋˜์–ด ์•ฝ 90% ์ •ํ™•๋„๋ฅผ ๋ณด์—ฌ์š”. **Space ์—…๋กœ๋“œ ํŒŒ์ผ (3๊ฐœ๋ฉด ์ถฉ๋ถ„):** 1. `app.py` 2. `README.md` 3. `requirements.txt` ์ฆ‰, ์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” `configuration_myresnet.py`, `modeling_myresnet.py`๋ฅผ Space์— ์˜ฌ๋ฆด ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค! ### ์‹œ๋‚˜๋ฆฌ์˜ค 2: ์ž์ฒด ํ•™์Šตํ•œ MyResNet ์‚ฌ์šฉ ์ง์ ‘ ResNet์„ ํ•™์Šต์‹œ์ผœ์„œ ๊ทธ ๋ชจ๋ธ๋กœ ๋ฐ๋ชจ๋ฅผ ๋Œ๋ฆฌ๊ณ  ์‹ถ๋‹ค๋ฉด: **Step 1: ๋กœ์ปฌ์—์„œ ํ•™์Šต** ```bash pip install torch torchvision transformers datasets accelerate python train_food.py ``` โ†’ `./my-resnet18-food101/` ํด๋”์— ํ•™์Šต๋œ ๋ชจ๋ธ ์ €์žฅ๋จ **Step 2: ๋ชจ๋ธ ํ—ˆ๋ธŒ์— ์—…๋กœ๋“œ** ```bash huggingface-cli login python -c " from modeling_myresnet import MyResNetForImageClassification from configuration_myresnet import MyResNetConfig MyResNetConfig.register_for_auto_class() MyResNetForImageClassification.register_for_auto_class('AutoModelForImageClassification') model = MyResNetForImageClassification.from_pretrained('./my-resnet18-food101') model.push_to_hub('your-username/my-resnet18-food101') " ``` **Step 3: Space `app.py`์—์„œ ์˜ต์…˜ ์ „ํ™˜** ```python # ์˜ต์…˜ A ๋ถ€๋ถ„์„ ์ฃผ์„ ์ฒ˜๋ฆฌ # from transformers import AutoImageProcessor, AutoModelForImageClassification # ... # ์˜ต์…˜ B ์ฃผ์„ ํ•ด์ œ from configuration_myresnet import MyResNetConfig from modeling_myresnet import MyResNetForImageClassification MODEL_ID = "your-username/my-resnet18-food101" model = MyResNetForImageClassification.from_pretrained(MODEL_ID) model.eval() device = "cuda" if torch.cuda.is_available() else "cpu" model = model.to(device) id2label = model.config.id2label ``` **Step 4: ์ „์ฒ˜๋ฆฌ ํ•จ์ˆ˜๋„ ์ˆ˜๋™ ๋ฒ„์ „์œผ๋กœ ๋ณ€๊ฒฝ** ```python from torchvision.transforms import Compose, Resize, ToTensor, Normalize _transform = Compose([ Resize((224, 224)), ToTensor(), Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ]) def preprocess(image): return _transform(image.convert("RGB")).unsqueeze(0).to(device) ``` ## ๐Ÿœ Food-101์˜ 101๊ฐœ ํด๋ž˜์Šค ``` apple_pie, baby_back_ribs, baklava, beef_carpaccio, beef_tartare, beet_salad, beignets, bibimbap, bread_pudding, breakfast_burrito, bruschetta, caesar_salad, cannoli, caprese_salad, carrot_cake, ceviche, cheesecake, cheese_plate, chicken_curry, chicken_quesadilla, chicken_wings, chocolate_cake, chocolate_mousse, churros, clam_chowder, club_sandwich, crab_cakes, creme_brulee, croque_madame, cup_cakes, deviled_eggs, donuts, dumplings, edamame, eggs_benedict, escargots, falafel, filet_mignon, fish_and_chips, foie_gras, french_fries, french_onion_soup, french_toast, fried_calamari, fried_rice, frozen_yogurt, garlic_bread, gnocchi, greek_salad, grilled_cheese_sandwich, grilled_salmon, guacamole, gyoza, hamburger, hot_and_sour_soup, hot_dog, huevos_rancheros, hummus, ice_cream, lasagna, lobster_bisque, lobster_roll_sandwich, macaroni_and_cheese, macarons, miso_soup, mussels, nachos, omelette, onion_rings, oysters, pad_thai, paella, pancakes, panna_cotta, peking_duck, pho, pizza, pork_chop, poutine, prime_rib, pulled_pork_sandwich, ramen, ravioli, red_velvet_cake, risotto, samosa, sashimi, scallops, seaweed_salad, shrimp_and_grits, spaghetti_bolognese, spaghetti_carbonara, spring_rolls, steak, strawberry_shortcake, sushi, tacos, takoyaki, tiramisu, tuna_tartare, waffles ``` **์žฌ๋ฏธ์žˆ๋Š” ์‚ฌ์‹ค**: ๐Ÿฅ˜ **bibimbap (๋น„๋น”๋ฐฅ)**, ๐Ÿฃ **sushi**, ๐ŸฅŸ **gyoza (๋งŒ๋‘)**, ๐Ÿœ **ramen**, ๐ŸŒฎ **tacos** ๋“ฑ ํ•œ์‹/์ผ์‹/์ค‘์‹/๋ฉ•์‹œ์นธ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ตญ๊ฐ€ ์š”๋ฆฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์–ด์š”! ## ๐Ÿ’ก ํ•™์Šต ์‹œ๊ฐ„/์ •ํ™•๋„ ์ฐธ๊ณ  | ๋ฐฉ์‹ | ์‹œ๊ฐ„ (GPU 1์žฅ) | ์ •ํ™•๋„ | |------|---------------|--------| | Scratch ํ•™์Šต (30 epochs) | ์•ฝ 6-10์‹œ๊ฐ„ | ์•ฝ 60-70% | | Pretrained + Fine-tuning (10 epochs) | ์•ฝ 2-4์‹œ๊ฐ„ | ์•ฝ 80-85% | | ๊ณต๊ฐœ ๋ชจ๋ธ `nateraw/food` ์‚ฌ์šฉ | 0 | ~90% | **์ดˆ๋ณด์ž ์ถ”์ฒœ**: ์‹œ๋‚˜๋ฆฌ์˜ค 1 (๊ณต๊ฐœ ๋ชจ๋ธ ์‚ฌ์šฉ)๋กœ ๋จผ์ € Space๋ฅผ ๋„์›Œ๋ณด๊ณ , ๋‚˜์ค‘์— ๊ด€์‹ฌ ์žˆ์œผ๋ฉด ์‹œ๋‚˜๋ฆฌ์˜ค 2๋กœ ์ง์ ‘ ํ•™์Šตํ•ด๋ณด์„ธ์š”! ## ๐Ÿ› ์ž์ฃผ ๊ฒช๋Š” ๋ฌธ์ œ ### 1. ํ•™์Šต ์‹œ OutOfMemory ```python per_device_train_batch_size=64 # 32 ๋˜๋Š” 16์œผ๋กœ ์ค„์ด๊ธฐ gradient_accumulation_steps=2 # ์ด๊ฑธ ๋Œ€์‹  ์ถ”๊ฐ€ ``` ### 2. Food-101 ๋‹ค์šด๋กœ๋“œ๊ฐ€ ๋А๋ฆผ - Food-101์€ ์•ฝ 5GB์ž…๋‹ˆ๋‹ค - ์ฒซ ๋‹ค์šด๋กœ๋“œ ํ›„์—๋Š” `~/.cache/huggingface/datasets/`์— ์บ์‹œ๋จ - ๋‹ค์šด๋กœ๋“œ๋Š” ํ•œ ๋ฒˆ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค ### 3. "KeyError: '0'" ์—๋Ÿฌ - CIFAR ๋ฒ„์ „๊ณผ ๋™์ผํ•œ ๋ฌธ์ œ. `id2label[str(i)]` โ†’ `id2label[i]`๋กœ ์ˆ˜์ • - ์ด ํ”„๋กœ์ ํŠธ์˜ `app.py`๋Š” ์ด๋ฏธ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋˜์–ด ์žˆ์Œ