Update app.py
Browse files
app.py
CHANGED
|
@@ -349,14 +349,28 @@ class StandardNEREvaluator:
|
|
| 349 |
for col in df.columns:
|
| 350 |
results_df[col] = df[col].values
|
| 351 |
|
| 352 |
-
# ترتیب
|
| 353 |
metric_cols = [
|
| 354 |
'seqeval_precision', 'seqeval_recall', 'seqeval_f1', 'seqeval_accuracy',
|
| 355 |
'exact_precision', 'exact_recall', 'exact_f1',
|
| 356 |
'tp_count', 'fp_count', 'fn_count'
|
| 357 |
]
|
| 358 |
-
|
| 359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 360 |
|
| 361 |
self.results_df = results_df
|
| 362 |
|
|
@@ -390,11 +404,19 @@ class StandardNEREvaluator:
|
|
| 390 |
• مرجع (انسانی): {reference_col}
|
| 391 |
• پیشبینی (LLM): {predicted_col}
|
| 392 |
|
| 393 |
-
|
| 394 |
• F1 (seqeval): {avg_seqeval_f1:.4f}
|
| 395 |
• F1 (Exact): {avg_exact_f1:.4f}
|
| 396 |
• اختلاف: {abs(avg_seqeval_f1 - avg_exact_f1):.4f}
|
| 397 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 398 |
✅ این ارزیابی مطابق با استانداردهای CoNLL-2003 است"""
|
| 399 |
|
| 400 |
return True, status, results_df
|
|
@@ -620,9 +642,10 @@ def create_interface():
|
|
| 620 |
|
| 621 |
# جدول نتایج
|
| 622 |
results_table = gr.Dataframe(
|
| 623 |
-
label="نتایج تفصیلی (10 سطر اول)",
|
| 624 |
visible=False,
|
| 625 |
-
wrap=True
|
|
|
|
| 626 |
)
|
| 627 |
|
| 628 |
# فایل دانلود
|
|
@@ -655,7 +678,50 @@ def create_interface():
|
|
| 655 |
|
| 656 |
ابزار **Reference_text** را به عنوان جواب صحیح در نظر میگیرد و **anonymized_text** را با آن مقایسه میکند.
|
| 657 |
|
| 658 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 659 |
|
| 660 |
- `company-01`, `COMPANY-01`, `COMPANY_001_REGEX`
|
| 661 |
- `person-02`, `PERSON-02`, `PERSON_002_REGEX`
|
|
@@ -664,15 +730,89 @@ def create_interface():
|
|
| 664 |
- `group-05`, `GROUP-05`
|
| 665 |
- `stock-06`, `STOCK-06`
|
| 666 |
|
| 667 |
-
|
|
|
|
|
|
|
| 668 |
|
| 669 |
- **Precision**: از entities که LLM شناسایی کرده، چند درصد درست بودند؟
|
| 670 |
- **Recall**: از entities مرجع، چند درصد توسط LLM پیدا شدند؟
|
| 671 |
-
- **F1-Score**: میانگین هماهنگ Precision و Recall
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 672 |
|
| 673 |
</div>
|
| 674 |
""")
|
| 675 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 676 |
# فوتر
|
| 677 |
gr.Markdown("""
|
| 678 |
---
|
|
|
|
| 349 |
for col in df.columns:
|
| 350 |
results_df[col] = df[col].values
|
| 351 |
|
| 352 |
+
# ترتیب ستونها: متریکها + سه ستون اصلی + بقیه
|
| 353 |
metric_cols = [
|
| 354 |
'seqeval_precision', 'seqeval_recall', 'seqeval_f1', 'seqeval_accuracy',
|
| 355 |
'exact_precision', 'exact_recall', 'exact_f1',
|
| 356 |
'tp_count', 'fp_count', 'fn_count'
|
| 357 |
]
|
| 358 |
+
|
| 359 |
+
# سه ستون اصلی (اگر موجود باشند)
|
| 360 |
+
main_cols = []
|
| 361 |
+
if 'original_text' in results_df.columns:
|
| 362 |
+
main_cols.append('original_text')
|
| 363 |
+
if 'Reference_text' in results_df.columns:
|
| 364 |
+
main_cols.append('Reference_text')
|
| 365 |
+
if 'anonymized_text' in results_df.columns:
|
| 366 |
+
main_cols.append('anonymized_text')
|
| 367 |
+
|
| 368 |
+
# بقیه ستونها (اگر چیز دیگری هست)
|
| 369 |
+
other_cols = [col for col in results_df.columns
|
| 370 |
+
if col not in metric_cols and col not in main_cols]
|
| 371 |
+
|
| 372 |
+
# ترتیب نهایی: متریکها + ستونهای اصلی + بقیه
|
| 373 |
+
results_df = results_df[metric_cols + main_cols + other_cols]
|
| 374 |
|
| 375 |
self.results_df = results_df
|
| 376 |
|
|
|
|
| 404 |
• مرجع (انسانی): {reference_col}
|
| 405 |
• پیشبینی (LLM): {predicted_col}
|
| 406 |
|
| 407 |
+
📊 **مقایسه روشها:**
|
| 408 |
• F1 (seqeval): {avg_seqeval_f1:.4f}
|
| 409 |
• F1 (Exact): {avg_exact_f1:.4f}
|
| 410 |
• اختلاف: {abs(avg_seqeval_f1 - avg_exact_f1):.4f}
|
| 411 |
|
| 412 |
+
📋 **ستونهای خروجی:**
|
| 413 |
+
• 10 متریک ارزیابی (seqeval & exact match)
|
| 414 |
+
• original_text - متن خام اصلی
|
| 415 |
+
• Reference_text - ناشناسسازی انسانی (مرجع)
|
| 416 |
+
• anonymized_text - ناشناسسازی LLM (پیشبینی)
|
| 417 |
+
|
| 418 |
+
💾 **نکته:** فایل CSV دانلودی شامل همه {len(df)} سطر و تمام ستونها است
|
| 419 |
+
|
| 420 |
✅ این ارزیابی مطابق با استانداردهای CoNLL-2003 است"""
|
| 421 |
|
| 422 |
return True, status, results_df
|
|
|
|
| 642 |
|
| 643 |
# جدول نتایج
|
| 644 |
results_table = gr.Dataframe(
|
| 645 |
+
label="نتایج تفصیلی (10 سطر اول) - شامل متریکها و هر 3 ستون متن",
|
| 646 |
visible=False,
|
| 647 |
+
wrap=True,
|
| 648 |
+
column_widths=["10%", "10%", "10%", "10%", "10%", "10%", "10%", "5%", "5%", "5%", "20%", "20%", "20%"]
|
| 649 |
)
|
| 650 |
|
| 651 |
# فایل دانلود
|
|
|
|
| 678 |
|
| 679 |
ابزار **Reference_text** را به عنوان جواب صحیح در نظر میگیرد و **anonymized_text** را با آن مقایسه میکند.
|
| 680 |
|
| 681 |
+
---
|
| 682 |
+
|
| 683 |
+
## 📊 ستونهای خروجی (جدول و CSV):
|
| 684 |
+
|
| 685 |
+
### بخش 1️⃣: متریکهای seqeval (4 ستون)
|
| 686 |
+
- `seqeval_precision` - دقت با IOB2 tagging
|
| 687 |
+
- `seqeval_recall` - بازخوانی با IOB2 tagging
|
| 688 |
+
- `seqeval_f1` - **F1-Score (مهمترین متریک)**
|
| 689 |
+
- `seqeval_accuracy` - دقت کلی
|
| 690 |
+
|
| 691 |
+
### بخش 2️⃣: متریکهای Exact Match (3 ستون)
|
| 692 |
+
- `exact_precision` - دقت با مقایسه مستقیم
|
| 693 |
+
- `exact_recall` - بازخوانی با مقایسه مستقیم
|
| 694 |
+
- `exact_f1` - F1 برای مقایسه
|
| 695 |
+
|
| 696 |
+
### بخش 3️⃣: آمار خطاها (3 ستون)
|
| 697 |
+
- `tp_count` - تعداد True Positives (درست)
|
| 698 |
+
- `fp_count` - تعداد False Positives (اضافی)
|
| 699 |
+
- `fn_count` - تعداد False Negatives (فراموش شده)
|
| 700 |
+
|
| 701 |
+
### بخش 4️⃣: متنهای اصلی (3 ستون)
|
| 702 |
+
- `original_text` - متن خام
|
| 703 |
+
- `Reference_text` - ناشناسسازی انسانی
|
| 704 |
+
- `anonymized_text` - ناشناسسازی LLM
|
| 705 |
+
|
| 706 |
+
**جمع کل: 13 ستون در فایل خروجی** ✅
|
| 707 |
+
|
| 708 |
+
---
|
| 709 |
+
|
| 710 |
+
## 🎯 مثال خروجی:
|
| 711 |
+
|
| 712 |
+
```csv
|
| 713 |
+
seqeval_f1,tp_count,fp_count,fn_count,original_text,Reference_text,anonymized_text
|
| 714 |
+
0.5000,1,1,1,"شرکت فولاد...","شرکت company-01...","شرکت company-01..."
|
| 715 |
+
```
|
| 716 |
+
|
| 717 |
+
### تفسیر این سطر:
|
| 718 |
+
- F1 = 0.5 (متوسط)
|
| 719 |
+
- 1 entity درست، 1 اضافی، 1 فراموش شده
|
| 720 |
+
- LLM نیمی از entities را درست تشخیص داده
|
| 721 |
+
|
| 722 |
+
---
|
| 723 |
+
|
| 724 |
+
## 2️⃣ فرمتهای پشتیبانی شده:
|
| 725 |
|
| 726 |
- `company-01`, `COMPANY-01`, `COMPANY_001_REGEX`
|
| 727 |
- `person-02`, `PERSON-02`, `PERSON_002_REGEX`
|
|
|
|
| 730 |
- `group-05`, `GROUP-05`
|
| 731 |
- `stock-06`, `STOCK-06`
|
| 732 |
|
| 733 |
+
---
|
| 734 |
+
|
| 735 |
+
## 3️⃣ معیارهای ارزیابی:
|
| 736 |
|
| 737 |
- **Precision**: از entities که LLM شناسایی کرده، چند درصد درست بودند؟
|
| 738 |
- **Recall**: از entities مرجع، چند درصد توسط LLM پیدا شدند؟
|
| 739 |
+
- **F1-Score**: میانگین هماهنگ Precision و Recall ← **مهمترین!**
|
| 740 |
+
|
| 741 |
+
### راهنمای F1-Score:
|
| 742 |
+
- 🟢 F1 ≥ 0.9: عالی
|
| 743 |
+
- 🟡 F1 = 0.7-0.9: خوب
|
| 744 |
+
- 🔴 F1 < 0.7: نیاز به بهبود
|
| 745 |
|
| 746 |
</div>
|
| 747 |
""")
|
| 748 |
|
| 749 |
+
# مثال
|
| 750 |
+
with gr.Accordion("💡 مثال تفسیر نتایج", open=False):
|
| 751 |
+
gr.Markdown("""
|
| 752 |
+
<div class="rtl">
|
| 753 |
+
|
| 754 |
+
## مثال کامل:
|
| 755 |
+
|
| 756 |
+
### ورودی:
|
| 757 |
+
```
|
| 758 |
+
original_text: "شرکت فولاد با person و amount"
|
| 759 |
+
Reference_text: "شرکت company-01 با person-02 و amount-03"
|
| 760 |
+
anonymized_text: "شرکت company-01 با person-99 و amount-03"
|
| 761 |
+
```
|
| 762 |
+
|
| 763 |
+
### تحلیل:
|
| 764 |
+
- ✅ `company-01` درست (TP)
|
| 765 |
+
- ✅ `amount-03` درست (TP)
|
| 766 |
+
- ❌ `person-99` اشتباه (FP + FN)
|
| 767 |
+
- ❌ `person-02` فراموش شد
|
| 768 |
+
|
| 769 |
+
### نتایج:
|
| 770 |
+
```
|
| 771 |
+
seqeval_precision: 0.6667 (2 از 3 درست)
|
| 772 |
+
seqeval_recall: 0.6667 (2 از 3 پیدا شد)
|
| 773 |
+
seqeval_f1: 0.6667
|
| 774 |
+
tp_count: 2
|
| 775 |
+
fp_count: 1
|
| 776 |
+
fn_count: 1
|
| 777 |
+
```
|
| 778 |
+
|
| 779 |
+
### تفسیر:
|
| 780 |
+
- F1 = 0.67 (عملکرد متوسط)
|
| 781 |
+
- مشکل: LLM شناسه person را اشتباه تشخیص داده
|
| 782 |
+
- **راهحل:** بهبود prompt برای تشخیص دقیقتر شناسهها
|
| 783 |
+
|
| 784 |
+
---
|
| 785 |
+
|
| 786 |
+
## نحوه استفاده از CSV خروجی:
|
| 787 |
+
|
| 788 |
+
### 1. در Excel:
|
| 789 |
+
- ستونهای متریک را با conditional formatting رنگ کنید
|
| 790 |
+
- سطرهای با F1 < 0.5 را پررنگ کنید
|
| 791 |
+
- برای بهبود مدل، این سطرها را بررسی کنید
|
| 792 |
+
|
| 793 |
+
### 2. در Python:
|
| 794 |
+
```python
|
| 795 |
+
import pandas as pd
|
| 796 |
+
df = pd.read_csv('evaluation_results.csv')
|
| 797 |
+
|
| 798 |
+
# سطرهای ضعیف
|
| 799 |
+
weak = df[df['seqeval_f1'] < 0.5]
|
| 800 |
+
print(f"سطرهای ضعیف: {len(weak)}")
|
| 801 |
+
|
| 802 |
+
# بررسی خطاها
|
| 803 |
+
print(f"کل FP: {df['fp_count'].sum()}")
|
| 804 |
+
print(f"کل FN: {df['fn_count'].sum()}")
|
| 805 |
+
```
|
| 806 |
+
|
| 807 |
+
### 3. برای تحلیل:
|
| 808 |
+
- سطرهای با `fp_count` زیاد → LLM entities اضافی میسازد
|
| 809 |
+
- سطرهای با `fn_count` زیاد → LLM entities را فراموش میکند
|
| 810 |
+
- سطرهای با `F1 = 1.0` → الگوهای موفق
|
| 811 |
+
|
| 812 |
+
</div>
|
| 813 |
+
""")
|
| 814 |
+
|
| 815 |
+
|
| 816 |
# فوتر
|
| 817 |
gr.Markdown("""
|
| 818 |
---
|