File size: 10,622 Bytes
e899795 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | import os
import re
# Paths to the READMEs
README_PATHS = [
r"..\..\Balochi Tokenizer_HF\README.md",
r"..\..\Final Tokenizers\README.md",
r"..\..\Final Tokenizers-4\README.md",
r"..\README_Git.md"
]
# Paths to the new reports
EXTENDED_REPORT_PATH = "Output/Tokenizer_Comparison_Extended_Report.md"
ABLATION_REPORT_PATH = "Output/Ablation/Vocab_Ablation_Report.md"
def parse_markdown_table(md_text, section_header):
"""Finds a table under a specific header and returns its rows."""
pattern = re.compile(rf"{re.escape(section_header)}\n+.*?\|(.*?)\n\n", re.DOTALL)
m = pattern.search(md_text)
if not m:
return []
table_text = m.group(0)
lines = [line.strip() for line in table_text.split('\n') if line.strip().startswith('|')]
return lines
def extract_master_metrics():
"""Extracts the transposed master metrics table from the new report."""
with open(EXTENDED_REPORT_PATH, "r", encoding="utf-8") as f:
content = f.read()
lines = parse_markdown_table(content, "## 4. Master Metrics Table")
if not lines or len(lines) < 3:
return {}
# Header row
headers = [col.strip() for col in lines[0].split('|')[1:-1]]
tokenizers = headers[1:] # First col is 'Metric'
data = {tok: {} for tok in tokenizers}
for row in lines[2:]:
cols = [col.strip() for col in row.split('|')[1:-1]]
if not cols:
continue
metric_name = cols[0].replace("**", "").strip()
for i, val in enumerate(cols[1:]):
if i < len(tokenizers):
tok = tokenizers[i]
data[tok][metric_name] = val
return data
def extract_ablation_metrics(algo_header, eval_text_header):
"""Extracts ablation metrics for a specific algorithm and text."""
with open(ABLATION_REPORT_PATH, "r", encoding="utf-8") as f:
content = f.read()
# First find the text section
text_split = content.split(eval_text_header)
if len(text_split) < 2: return {}
text_content = text_split[1]
# Then find the algorithm section
lines = parse_markdown_table(text_content, algo_header)
if not lines or len(lines) < 3: return {}
sizes = [col.strip() for col in lines[0].split('|')[1:-1]][1:]
data = {size: {} for size in sizes}
for row in lines[2:]:
cols = [col.strip() for col in row.split('|')[1:-1]]
if not cols: continue
metric_name = cols[0].replace("**", "").strip()
for i, val in enumerate(cols[1:]):
if i < len(sizes):
size = sizes[i]
data[size][metric_name] = val
return data
def extract_diminishing_returns(algo_header):
with open(ABLATION_REPORT_PATH, "r", encoding="utf-8") as f:
content = f.read()
text_split = content.split("## 3. Diminishing Returns Analysis")
if len(text_split) < 2: return {}
lines = parse_markdown_table(text_split[1], algo_header)
if not lines or len(lines) < 3: return {}
data = {}
for row in lines[2:]:
cols = [col.strip() for col in row.split('|')[1:-1]]
if len(cols) >= 4:
size = cols[0]
data[size] = {
"Avg Compression": cols[1],
"Avg Fertility": cols[2],
"Avg Tokens": cols[3]
}
return data
def process_readme(filepath, master_data, labzank_ablation, lib_cap_ablation, dr_data):
with open(filepath, "r", encoding="utf-8") as f:
content = f.read()
# Mapping between README tokenizer names and new report names
tok_map = {
"Balochi BPE": "Balochi_BPE",
"Balochi WordPiece": "Balochi_WordPiece",
"Balochi SentencePiece": "Balochi_SentencePiece",
"NLTK (baseline)": "NLTK",
"BERT Multilingual": "BERT",
"Gemma 2B": "Gemma",
"Balochi_30K (HF)": "Balochi_30K",
"AraBERT_v2": "AraBERT_v2",
"CAMeLBERT_MSA": "CAMeLBERT_MSA",
"ARBERT": "ARBERT",
"AraGPT2": "AraGPT2",
"ParsBERT": "ParsBERT",
"PersianBERT_FA": "PersianBERT_FA",
"PersianBPE": "PersianBPE",
"UrduBERT": "UrduBERT"
}
# 1. Update Master Performance Results
def replace_master_row(m):
row = m.group(0)
cols = row.split('|')
tok_display = cols[1].replace("**", "").strip()
if tok_display in tok_map:
tok_key = tok_map[tok_display]
if tok_key in master_data:
d = master_data[tok_key]
# Format exactly as original
is_bold = "**" in cols[1]
def fmt(val, bold=False):
return f" **{val}** " if bold else f" {val} "
try:
cols[2] = fmt(d.get("Token Count", ""), is_bold)
cols[3] = fmt(d.get("Compression Ratio", ""), is_bold)
cols[4] = fmt(d.get("Fertility", ""), is_bold)
cols[5] = fmt(d.get("UNK Count", ""), False)
cols[6] = fmt(d.get("UNK Rate (%)", ""), "**" in cols[6])
if len(cols) > 7:
cols[7] = fmt(d.get("Continuation Rate", ""), False)
except Exception as e:
print(f"Error on row: {row}")
print(cols)
raise e
return "|".join(cols)
return row
# Find the master table lines and replace
lines = content.split('\n')
in_master_table = False
for i, line in enumerate(lines):
if "### 5.2 Master Performance Results" in line:
in_master_table = True
elif in_master_table and (line.startswith("## ") or line.startswith("### ") and "5.2" not in line):
in_master_table = False
if in_master_table and line.strip().startswith('|') and not line.strip().startswith('|:') and not line.strip().startswith('| Tokenizer'):
lines[i] = replace_master_row(re.match(r'.*', line))
# Rejoin lines
content = '\n'.join(lines)
# 2. Update Ablation Results
def update_ablation_table(content, header, data_source):
in_table = False
lines = content.split('\n')
for i, line in enumerate(lines):
if header in line:
in_table = True
elif in_table and line.startswith("##") and not line.startswith("####"):
in_table = False
if in_table and line.strip().startswith('|') and not line.strip().startswith('|:') and not line.strip().startswith('| Algorithm'):
cols = line.split('|')
algo = cols[1].strip()
size = cols[2].strip()
size_key = size.replace("K", "") + "K"
algo_key = "BPE" if "BPE" in algo else ("WORDPIECE" if "WP" in algo else "SENTENCEPIECE")
if algo_key in data_source and size_key in data_source[algo_key]:
d = data_source[algo_key][size_key]
is_bold = "**" in cols[3]
def fmt(val, bold=False): return f" **{val}** " if bold else f" {val} "
# Token Count | Compression | Fertility | Vocab Util.
# Some tables have Unique Tokens, some don't.
if "Unique Tokens" in content.split(header)[1].split('\n')[2]: # Check header row for this table
if len(cols) > 5:
cols[3] = fmt(d.get("Token Count", ""), is_bold)
# cols[4] = Unique Tokens
cols[5] = fmt(d.get("Compression Ratio", ""), is_bold)
cols[6] = fmt(d.get("Fertility", ""), is_bold)
if len(cols) > 7 and "Vocab Util." in cols[7]:
pass
else:
if len(cols) > 5:
cols[3] = fmt(d.get("Token Count", ""), is_bold)
cols[4] = fmt(d.get("Compression Ratio", ""), is_bold)
cols[5] = fmt(d.get("Fertility", ""), is_bold)
lines[i] = "|".join(cols)
return '\n'.join(lines)
content = update_ablation_table(content, "#### `liberal capitalism.txt` Results", lib_cap_ablation)
# 3. Update Diminishing Returns
# Doing a simpler regex replacement for Diminishing returns numbers
for algo, dr_algo_name in [("SentencePiece", "### SENTENCEPIECE"), ("BPE", "### BPE"), ("WordPiece", "### WORDPIECE")]:
algo_data = dr_data.get(dr_algo_name, {})
for size_key, vals in algo_data.items():
# e.g., | **32,000** | 3.9982 | 1.1748 | 5,244 | — |
pattern = re.compile(rf"\|\s*\**{size_key}\**\s*\|\s*[\d\.]+\s*\|\s*[\d\.]+\s*\|\s*[\d,]+\s*\|")
def repl(m):
s = m.group(0)
parts = s.split('|')
parts[2] = f" {vals['Avg Compression']} "
parts[3] = f" {vals['Avg Fertility']} "
parts[4] = f" {vals['Avg Tokens']} "
return "|".join(parts)
content = pattern.sub(repl, content)
# Save
with open(filepath, "w", encoding="utf-8") as f:
f.write(content)
print(f"Updated {filepath}")
def main():
print("Extracting new data...")
master_data = extract_master_metrics()
lib_cap_ablation = {
"BPE": extract_ablation_metrics("### BPE Algorithm", "## 2. Results — `liberal capitalism.txt`"),
"WORDPIECE": extract_ablation_metrics("### WORDPIECE Algorithm", "## 2. Results — `liberal capitalism.txt`"),
"SENTENCEPIECE": extract_ablation_metrics("### SENTENCEPIECE Algorithm", "## 2. Results — `liberal capitalism.txt`")
}
dr_data = {
"### BPE": extract_diminishing_returns("### BPE"),
"### WORDPIECE": extract_diminishing_returns("### WORDPIECE"),
"### SENTENCEPIECE": extract_diminishing_returns("### SENTENCEPIECE")
}
print("Updating README files...")
for path in README_PATHS:
full_path = os.path.abspath(path)
if os.path.exists(full_path):
process_readme(full_path, master_data, {}, lib_cap_ablation, dr_data)
else:
print(f"Warning: Could not find {full_path}")
if __name__ == "__main__":
main()
|