-
Notifications
You must be signed in to change notification settings - Fork 2
Accuracy check YML #277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Accuracy check YML #277
Changes from all commits
e1f90af
fe9785a
d76e10d
25c23eb
93bbb72
6d562cf
2929f06
a4d1611
69c19fa
a5838d9
3f9fa39
a8409f1
5c4e528
7b96923
392ea50
6c3b056
2554a45
aab38cc
978481f
7748c55
c561374
4ff9e1d
9dc92bb
df7b5a7
7ff4e1b
5c93127
b0924af
73f3046
20e4039
4e6a9bc
4eb3771
040794f
d75a28d
510e764
aeeb3c6
dab3fdb
2fe1f5a
209921c
b235670
5440df4
2d0c1f2
af020d2
e446579
291328f
1a06885
7cecae3
1107f98
4f33d75
879d51d
20abecc
3e9d660
05ba1c9
2c7a190
f11b513
3ce3762
b2f4f87
d6a520a
d9a3acd
8eca1e5
c23bbc1
edc9beb
f252ee0
1bb0596
d1575b5
ce2b1fd
8e5b953
8ab7f8a
4666afe
c3dc14d
c8d8ad2
98629a8
fd27de8
e6ccaf0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -229,7 +229,7 @@ jobs: | |
| token: ${{ secrets.CODECOV_TOKEN }} | ||
| slug: embedded-dev-research/ITLabAI | ||
|
|
||
| evaluate-model: | ||
| evaluate-model-alexnet: | ||
| runs-on: ubuntu-latest | ||
| needs: [build-linux] | ||
| permissions: | ||
|
|
@@ -319,3 +319,217 @@ jobs: | |
| git commit -m "[CI] Update accuracy: $(cat accuracy_value.txt)" | ||
| git push origin master | ||
| fi | ||
|
|
||
| download-dataset: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Cache ImageNet-Paste dataset | ||
| id: cache-imagenet | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: docs/ImageNet | ||
| key: imagenet-paste-v1 | ||
| restore-keys: | | ||
| imagenet-paste-v1- | ||
| imagenet-paste- | ||
|
|
||
| - name: Setup Python | ||
| uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: '3.10' | ||
|
|
||
| - name: Install Python dependencies from requirements.txt | ||
| run: | | ||
| cd app/Converters | ||
| pip install -r requirements.txt | ||
| cd ../.. | ||
|
|
||
| - name: Download ImageNet-Paste dataset | ||
| if: steps.cache-imagenet.outputs.cache-hit != 'true' | ||
| env: | ||
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | ||
| run: | | ||
| mkdir -p docs/ImageNet/test | ||
| cd app/Converters | ||
| python download_imagenet.py | ||
| cd ../.. | ||
| - name: Save ImageNet-Paste dataset | ||
| uses: actions/cache/save@v4 | ||
| with: | ||
| path: docs/ImageNet | ||
| key: imagenet-paste-v1 | ||
|
|
||
| evaluate-models-onnx: | ||
| runs-on: ubuntu-latest | ||
| needs: [build-linux, download-dataset] | ||
| permissions: | ||
| contents: write | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| model: [googlenet, densenet, resnet, yolo] | ||
| include: | ||
| - model: googlenet | ||
| parser: parser_onnx.py | ||
| model_file: GoogLeNet.onnx | ||
| model_path: docs/models/GoogLeNet.onnx | ||
| model_url: '' | ||
| extra_args: "--onednn 10000" | ||
| - model: densenet | ||
| parser: parser_onnx.py | ||
| model_file: densenet121_Opset16.onnx | ||
| model_url: https://github.com/onnx/models/raw/refs/heads/main/Computer_Vision/densenet121_Opset16_timm/densenet121_Opset16.onnx?download= | ||
| extra_args: "--onednn 10000" | ||
| - model: resnet | ||
| parser: parser_onnx.py | ||
| model_file: resnest101e_Opset16.onnx | ||
| model_url: https://github.com/onnx/models/raw/refs/heads/main/Computer_Vision/resnest101e_Opset16_timm/resnest101e_Opset16.onnx?download= | ||
| extra_args: "--onednn 10000" | ||
| - model: yolo | ||
| parser: parser_onnx.py | ||
| model_file: yolo11x-cls.pt | ||
| model_url: https://github.com/ultralytics/assets/releases/download/v8.4.0/yolo11x-cls.pt | ||
| extra_args: "--onednn 10000" | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Download binary and libs | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: mnist-RELEASE | ||
| path: build/ | ||
|
|
||
| - name: Set binary path | ||
| id: set_eval_binary | ||
| run: | | ||
| echo "EVAL_BINARY=build/bin/ACC" >> $GITHUB_OUTPUT | ||
|
|
||
| - name: Install system dependencies | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y libgtk-3-0 libtbb12 libjpeg-dev libpng-dev libtiff-dev libopenjp2-7 libdnnl3 | ||
| sudo ldconfig | ||
|
|
||
| - name: Download model (if URL provided) | ||
| if: matrix.model_url != '' | ||
| run: | | ||
| mkdir -p docs/models | ||
| wget -O docs/models/${{ matrix.model_file }} ${{ matrix.model_url }} | ||
|
|
||
| - name: Setup Python | ||
| uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: '3.10' | ||
|
|
||
| - name: Install Python dependencies from requirements.txt | ||
| run: | | ||
| cd app/Converters | ||
| pip install -r requirements.txt | ||
| cd ../.. | ||
|
|
||
| - name: Cache model JSON files | ||
| id: cache-model-json | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: docs/jsons | ||
| key: model-json-${{ matrix.model }}-${{ hashFiles('app/Converters/parser_onnx.py', 'app/Converters/requirements.txt') }} | ||
| restore-keys: | | ||
| model-json-${{ matrix.model }}- | ||
| model-json- | ||
|
|
||
| - name: Generate model JSON | ||
| if: steps.cache-model-json.outputs.cache-hit != 'true' | ||
| run: | | ||
| mkdir -p docs/jsons | ||
| cd app/Converters | ||
| python ${{ matrix.parser }} ${{ matrix.model }} | ||
| cd ../.. | ||
|
|
||
| - name: Restore ImageNet-Paste dataset | ||
| id: cache-imagenet | ||
| uses: actions/cache/restore@v4 | ||
| with: | ||
| path: docs/ImageNet | ||
| key: imagenet-paste-v1 | ||
| restore-keys: | | ||
| imagenet-paste-v1- | ||
| imagenet-paste- | ||
|
|
||
| - name: Prepare environment | ||
| run: | | ||
| chmod +x "${{ steps.set_eval_binary.outputs.EVAL_BINARY }}" | ||
| echo "LD_LIBRARY_PATH=$PWD/build/bin/all_libs:/usr/lib/x86_64-linux-gnu" >> $GITHUB_ENV | ||
|
|
||
| - name: Run evaluation | ||
| run: | | ||
| DATASET_PATH="docs/ImageNet/test" | ||
| MODEL="${{ matrix.model }}" | ||
| EXTRA_ARGS="${{ matrix.extra_args }}" | ||
|
|
||
| "${{ steps.set_eval_binary.outputs.EVAL_BINARY }}" \ | ||
| --model $MODEL \ | ||
| $EXTRA_ARGS > accuracy_$MODEL.txt 2>&1 | ||
|
|
||
| if [ $? -ne 0 ]; then | ||
| echo "Ошибка при оценке модели $MODEL" | ||
| cat accuracy_$MODEL.txt | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "Результат оценки:" | ||
| cat accuracy_$MODEL.txt | ||
|
|
||
| - name: Extract accuracy value | ||
| run: | | ||
| ACCURACY=$(grep -oE '[0-9]+\.?[0-9]*%' accuracy_${{ matrix.model }}.txt | head -1 || echo "0%") | ||
| echo "$ACCURACY" > accuracy_value_${{ matrix.model }}.txt | ||
| echo "Accuracy for ${{ matrix.model }}: $ACCURACY" | ||
|
|
||
| - name: Upload accuracy artifacts | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: accuracy-${{ matrix.model }} | ||
| path: | | ||
| accuracy_${{ matrix.model }}.txt | ||
| accuracy_value_${{ matrix.model }}.txt | ||
|
|
||
| - name: Update README for model (master only) | ||
| if: github.ref == 'refs/heads/master' | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our main branch is called
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| run: | | ||
| TOP1_ACC=$(grep -oE 'Top-1 Accuracy: [0-9]+\.?[0-9]*%' accuracy_${{ matrix.model }}.txt | grep -oE '[0-9]+\.?[0-9]*') | ||
| TOP5_ACC=$(grep -oE 'Top-5 Accuracy: [0-9]+\.?[0-9]*%' accuracy_${{ matrix.model }}.txt | grep -oE '[0-9]+\.?[0-9]*') | ||
| DATE=$(date '+%Y-%m-%d') | ||
|
|
||
| if [ -z "$TOP1_ACC" ] || [ -z "$TOP5_ACC" ]; then | ||
| echo "Ошибка: Не удалось извлечь точность из файла accuracy_${{ matrix.model }}.txt" | ||
| cat accuracy_${{ matrix.model }}.txt | ||
| exit 1 | ||
| fi | ||
|
|
||
| UPDATE_TEXT="<!--ACCURACY_${{ matrix.model }}_PLACEHOLDER-->Accuracy: Top-1: ${TOP1_ACC}% | Top-5: ${TOP5_ACC}% (updated: ${DATE})<!--END_ACCURACY_${{ matrix.model }}-->" | ||
|
|
||
| if grep -q "<!--ACCURACY_${{ matrix.model }}_PLACEHOLDER-->" README.md; then | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we update README in that regard? Since we have more model and only one placeholder as of now
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| sed -i "s|<!--ACCURACY_${{ matrix.model }}_PLACEHOLDER-->.*<!--END_ACCURACY_${{ matrix.model }}-->|${UPDATE_TEXT}|" README.md | ||
| else | ||
| echo "Ошибка: Плейсхолдер <!--ACCURACY_${{ matrix.model }}_PLACEHOLDER--> не найден в README.md" | ||
| echo "Содержимое README.md:" | ||
| cat README.md | ||
| exit 1 | ||
| fi | ||
|
Comment on lines
+517
to
+522
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is better to report an error if we didn't find something
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
|
|
||
| - name: Commit and push changes (main only) | ||
| if: github.ref == 'refs/heads/main' | ||
| run: | | ||
| git config --global user.name "GitHub Actions" | ||
| git config --global user.email "actions@github.com" | ||
| git add README.md | ||
| if git diff-index --quiet HEAD --; then | ||
| echo "No changes to commit" | ||
| else | ||
| git commit -m "[CI] Update accuracy for ${{ matrix.model }}: $(cat accuracy_value_${{ matrix.model }}.txt)" | ||
| git push origin master | ||
| fi | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| import os | ||
| from datasets import load_dataset | ||
| from huggingface_hub import login | ||
| from PIL import Image | ||
| from collections import defaultdict | ||
|
|
||
| hf_token = os.environ.get('HF_TOKEN') | ||
| if hf_token: | ||
| print("Авторизация на Hugging Face Hub...") | ||
| login(token=hf_token) | ||
| else: | ||
| print("Внимание: HF_TOKEN не найден, могут быть ограничения rate limiting") | ||
|
|
||
| base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | ||
| output_dir = os.path.join(base_dir, 'docs', 'ImageNet', 'test') | ||
| os.makedirs(output_dir, exist_ok=True) | ||
|
|
||
| print("Загрузка датасета helenqu/ImageNet-Paste...") | ||
| ds = load_dataset( | ||
| "helenqu/ImageNet-Paste", | ||
| split="validation", | ||
| token=hf_token | ||
| ) | ||
|
|
||
| print(f"Датасет загружен. Всего записей: {len(ds)}") | ||
|
|
||
| print(f"Ключи первой записи: {ds[0].keys()}") | ||
| if 'label' in ds[0]: | ||
| print(f"Пример метки: {ds[0]['label']}") | ||
| print(f"Тип метки: {type(ds[0]['label'])}") | ||
|
|
||
| print("\nСоздание папок для классов 00000-00999 в test/...") | ||
| for i in range(1000): | ||
| class_folder = os.path.join(output_dir, f"{i:05d}") | ||
| os.makedirs(class_folder, exist_ok=True) | ||
| print("Папки созданы!") | ||
|
|
||
| counters = defaultdict(int) | ||
|
|
||
| total_images = len(ds) | ||
| images_per_class = 50 | ||
| max_images = 1000 * images_per_class | ||
|
|
||
| print(f"\nНачинаем сохранение {min(total_images, max_images)} изображений...") | ||
| print(f"По {images_per_class} изображений в каждой из 1000 папок") | ||
| print(f"Путь: {output_dir}/00000/ ... /00999/") | ||
|
|
||
| saved_count = 0 | ||
| skipped_count = 0 | ||
|
|
||
| for i, item in enumerate(ds): | ||
| if saved_count >= max_images: | ||
| print(f"\nДостигнут лимит в {max_images} изображений") | ||
| break | ||
|
|
||
| try: | ||
| image = item['image'] | ||
| if 'label' in item: | ||
| class_id = item['label'] | ||
| elif 'labels' in item: | ||
| class_id = item['labels'] | ||
| else: | ||
| skipped_count += 1 | ||
| if skipped_count % 100 == 0: | ||
| print(f"Пропущено {skipped_count} изображений: нет метки класса") | ||
| continue | ||
|
|
||
| if not isinstance(class_id, (int, float)) or class_id < 0 or class_id >= 1000: | ||
| skipped_count += 1 | ||
| if skipped_count % 100 == 0: | ||
| print(f"Пропущено {skipped_count} изображений: некорректный class_id {class_id}") | ||
| continue | ||
|
|
||
| class_id_int = int(class_id) | ||
|
|
||
| if counters[class_id_int] >= images_per_class: | ||
| continue | ||
|
|
||
| class_folder = os.path.join(output_dir, f"{class_id_int:05d}") | ||
| filename = f"image_{counters[class_id_int]}.jpg" | ||
| output_path = os.path.join(class_folder, filename) | ||
|
|
||
| image.save(output_path, 'JPEG') | ||
| counters[class_id_int] += 1 | ||
| saved_count += 1 | ||
|
|
||
| except Exception as e: | ||
| print(f"Ошибка при сохранении изображения {i}: {e}") | ||
| continue | ||
|
|
||
| print(f"\n{'=' * 50}") | ||
| print(f"ГОТОВО!") | ||
| print(f"{'=' * 50}") | ||
| print(f"Всего сохранено: {saved_count} изображений") | ||
| print(f"Пропущено: {skipped_count} изображений") | ||
| print(f"Распределение по первым 10 классам:") | ||
| for class_id in range(10): | ||
| print(f" Класс {class_id:05d}: {counters[class_id]} изображений") | ||
|
|
||
| classes_with_50 = sum(1 for c in range(1000) if counters[c] == 50) | ||
| print(f"\nКлассов с ровно 50 изображениями: {classes_with_50}/1000") | ||
|
|
||
| if classes_with_50 < 1000: | ||
| print("\nКлассы с недостаточным количеством:") | ||
| for class_id in range(1000): | ||
| if counters[class_id] < 50 and counters[class_id] > 0: | ||
| print(f" Класс {class_id:05d}: только {counters[class_id]} изображений") | ||
|
|
||
| print(f"\nПуть к данным: {output_dir}") | ||
| print(f"Пример: {output_dir}/00042/image_0.jpg") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SIGTERM catching mechanism also can be removed already