همهٔ مقاله‌ها

· Casimiro Ferreira· 9 دقیقه مطالعه

گرافم به IPA برای ۸۰۷ زبان

  • G2P
  • IPA
  • Phonetics
  • NLP
  • TTS
  • ASR
  • Linguistics
  • FOSS

orthography2ipa یک بسته‌ی Python مبتنی بر داده‌ی خالص است — JSON اعلانی، منطقی نازک و قابل‌افزونه، بدون هیچ وزن آموزش‌دیده — که املا را به IPA نگاشت می‌کند و مدل می‌کند که این واج‌ها چگونه در بستر خود نمود پیدا می‌کنند. این بسته ۸۹۶ مشخصه‌ی زبانی را عرضه می‌کند که ۸۰۷ زبان را دربر می‌گیرند (به‌علاوه‌ی ۸۹ گره‌ی رده‌بندی‌محضِ شاخه) در سراسر بیش از ۲۰ خانواده‌ی زبانی. آن را نصب کنید، داده‌ها را بخوانید، از داده‌ها fork بگیرید. هیچ چیز در یک checkpoint پنهان نشده است.

این بسته لایه‌ی واج‌شناسی زیرِ همه‌ی چیزهای پایین‌دستی است: شبکه‌ی نامزدی که تولید می‌کند توسط فرانت‌اند TTS عربی arbtok، پشته‌های پرتغالی TugaPhone و silabificador (نگاه کنید به NLP کلاسیک برای هجاها و واج‌های پرتغالیواج‌ساز بارانکنیو، واج‌ساز میراندایی، و بنیان واجی برای TTS که روی یک سیب‌زمینی اجرا می‌شود مصرف می‌شود.

دو نقشه، نه یکی

تمایز حیاتی این است: یک نقشه‌ی گرافم به شما می‌گوید که یک املا می‌تواند کدام واج‌ها را بازنمایی کند. یک نقشه‌ی واج‌گونه به شما می‌گوید که یک واج چگونه در بستر نمود می‌یابد. درهم‌آمیختن این دو رایج‌ترین حالت شکست در سامانه‌های G2P است.

import orthography2ipa
en = orthography2ipa.get("en-GB")

en.graphemes["th"]   # ['θ', 'ð']   — one spelling, two possible phonemes
en.allophones["t"]   # ['t', 'tʰ', 'ʔ', 'ɾ']  — one phoneme, four realisations

⟨th⟩ در انگلیسی واقعاً میان /θ/ و /ð/ مبهم است — این یک واقعیت املا به واج است. /t/ در انگلیسی بسته به جایگاهش به‌صورت یک انسدادی ساده، یک انسدادی دمیده، یک انسدادی چاکنایی یا یک زنشی نمود می‌یابد — این یک واقعیت واج به نمود است. جدا نگه داشتن این دو به این معناست که می‌توانید برای رونویسی مسیر متن ← نامزدهای واج و برای مدل‌سازی تلفظ مسیر واج ← نمود سطحی را طی کنید بدون اینکه یکی دیگری را خراب کند. برای TTS این همان تفاوت میان یک لهجه‌ی باورپذیر و یک لهجه‌ی رباتیک است؛ برای ASR این همان تفاوت میان یک واژگانی است که با آنچه مردم واقعاً می‌گویند مطابقت دارد و واژگانی که با فرهنگ لغت مطابقت دارد.

هر زبان چه چیزی را حمل می‌کند

هر زبان یک دیتاکلاس منجمد LanguageSpec است و چیزی به‌مراتب بیش از یک فهرست واج را حمل می‌کند: گرافم‌ها (شامل دو‌نگاشت‌ها و سه‌نگاشت‌ها)، یک نقشه‌ی واج‌گونه، گرافم‌های جایگاهی برای بازنویسی‌های وابسته به بستر (آغاز واژه، میان‌واکه‌ای، پیش از /i/)، تبار وزن‌دار با چند نیا، قواعد سَندی میان‌واژه‌ای، یک فهرست آهنگ (تون) اختیاری، و منشأ — یک QualityTier که مسیر stub → skeleton → research → production را طی می‌کند، یک ScriptType (الفبا، ابجد، ابوگیدا، …)، و منابع کتاب‌شناختی با ارجاع دقیق به شماره‌ی صفحه.

قاعده‌ی گنجاندن سخت‌گیرانه است و ارزش دارد که آشکارا بیان شود: تنها نگاشت‌هایی که در املای رسمی و دستور زبان مستند ریشه دارند وارد می‌شوند. قواعد دلبخواهی بر پایه‌ی زیررشته کنار گذاشته می‌شوند. ⟨lh⟩ پرتغالی، ⟨sch⟩ آلمانی و ⟨th⟩ انگلیسی وارد می‌شوند چون واحدهای املایی استانداردند. اکتشافی‌های راحت اما ساختگی وارد نمی‌شوند. هنگامی که یک مشخصه گرافم‌ها را اعلام می‌کند اما نقشه‌ی واج‌گونه‌ی صریحی ندارد، یک نقشه‌ی همانیِ پایه استخراج می‌شود — هر واج دست‌کم نمود سطحی خودش است — تا هیچ چیز بی‌صدا ناپدید نشود.

گونه‌های منطقه‌ای به‌جای یک پرچم روی یک والد، مشخصه‌ی خاص خود را دریافت می‌کنند. پرتغالی برزیلی و اروپایی به‌صورت نظام‌مند از هم واگرا می‌شوند، پس آن‌ها اشیای LanguageSpec مجزا هستند که از طریق تبار به‌هم پیوند خورده‌اند:

pt_br = orthography2ipa.get("pt-BR")
pt_br.graphemes["t"]   # ['t', 't͡ʃ']  — palatalisation before /i/

درخت‌های گویشی قابل نگهداری می‌مانند چون فایل‌های JSON از وراثت graphemes_base / allophones_base پشتیبانی می‌کنند: یک گونه تنها آنچه را که با والدش تفاوت دارد اعلام می‌کند. تبار وزن‌دار و چند-نیاست — والد، زیرلایه، فرالایه، هم‌لایه — که راه صادقانه‌ی مدل‌سازی زبان‌هایی است که فرآورده‌ی تماس‌اند نه فرزندان خالص.

عمیق روی زمین، نه فقط پهناور

عدد ۸۰۷ پهنا است؛ عمق جایی است که کار در آن نهفته است. مشخصه‌ها لِکت به لِکت پیش می‌روند تا هر جا که ادبیات گویش‌شناسی پیش می‌رود، و هر یک به‌جای اینکه از روی یک جدول واج تطبیق‌یابی شده باشد، با ارجاع دقیق به شماره‌ی صفحه به آن ادبیات استناد داده شده است.

پوشش ایبری روشن‌ترین نمونه است: بیش از ۱۰۰ مشخصه برای زبان‌های شبه‌جزیره. هر زبان رومنسِ اسپانیا — کاستیلی، کاتالان/والنسیایی، گالیسیایی (هم هنجار RAG و هم هنجار بازپیوندگرا)، آستوریایی، آراگونی و گونه‌های دره‌ای‌اش (Ansotano، Chistabín، Benasqués…)، اکسترمادورایی — در کنار باسکی، کریول‌های ایبرو-رومنس، و لایه‌های تاریخی‌ای که بیشتر منابع کاملاً از آن‌ها می‌گذرند: عربی اندلسی و موزارابی. سمت عربی ۳۴ لِکت گویشی را حمل می‌کند (از نجدی و حجازی گرفته تا شامی، مغربی و گونه‌های شبه‌جزیره‌ای)، و سمت لوزوفون ۴۶ لِکت پرتغالی و زبان‌های پرتغال را، تا رده‌ی Rionorese، Guadramilese و زیرگویش‌های میراندایی.

تا جایی که می‌دانیم، چند تا از این‌ها نخستین واج‌شناسی ماشین‌خوانِ منتشرشده برای آن گونه‌اند — به این معنا که یک مشخصه‌ی گرافم/واج‌گونهٔ ساخت‌یافته و اعتبارسنجی‌شده با اسکیما است که یک برنامه می‌تواند از آن پرس‌وجو کند، در برابر یک فهرست واجی که تنها به نثر در ادبیات گویش‌شناسی توصیف شده — Rionorese و Guadramilese از جمله‌ی آن‌ها. کار پایین‌دستی نخستین فرهنگ‌های IPA را برای بارانکنیو و میراندایی عرضه می‌کند.

یک شبکه‌ی نامزد، نه یک حدس واحد

املا یک مسئله‌ی قطعه‌بندی تمیز نیست، پس معماری پرچم‌دار یک شبکه‌ی نامزد است. PhonetokTokenizer توکن‌سازی گرافمِ maximal-munch انجام می‌دهد — حریصانه بلندترین واحد املایی منطبق را ترجیح می‌دهد — و روی جدول گرافم مشخصه، به‌جای یک خروجی شکننده، یک شبکه‌ی به‌ازای هر جایگاه از نامزدهای IPA رتبه‌بندی‌شده تولید می‌کند:

from orthography2ipa.phonetok import PhonetokTokenizer
tok = PhonetokTokenizer(orthography2ipa.get("en-GB"))

tok.ipa_best("through")                 # 'θɹɔː'
for path in tok.ipa_beam("through", beam_width=8):
    print(path.ipa, path.score)         # θɹɔː 0.0, ðɹɔː 1.0, θɹoʊ 1.0, …

این شبکه همان قراردادی است که کل خانواده‌ی پایین‌دستی روی آن بنا می‌شود. یک موتور ویژه‌ی زبان شبکه‌ی مشترک را مصرف می‌کند و تنها آن واج‌شناسی‌ای را می‌افزاید که یک جدول ایستا نمی‌تواند بیان کند، و همه‌ی مصرف‌کنندگان را روی همان هسته‌ی مستدل نگه می‌دارد:

  • arbtok واج‌شناسی TTS عربی را روی این شبکه بنا می‌کند، و همگون‌سازی حروف شمسی، حذف همزه‌ی وصل، مشدد‌سازی و مدیریت لیگاتور را می‌افزاید — و یک آمیزش شبکه-رَوی (rawi-lattice fusion) نوآورانه که واکه‌های کوتاهِ گمشده‌ی متن گویشیِ بدون اعراب را با امتیازدهی به توزیع به‌ازای هر نویسه‌ی یک هم‌رأیه زیر مجوزدهی لِکتِ درخواست‌شده بازیابی می‌کند، به‌جای اعتماد به یک مولد آزاد.
  • TugaPhone، mwl_phonemizer (میراندایی) و g2p_barranquenho همگی همان lattice-core را برای گونه‌های لوزوفون خود مصرف می‌کنند.

سنجش فاصله میان زبان‌ها

از آنجا که داده‌ها ساختارمندند نه پخته‌شده در وزن‌ها، می‌توانید زبان‌ها را به‌طور مستقیم مقایسه کنید. سنجه‌های فاصله ابعاد فهرست واج، گرافم، واج‌گونه و تبار را دربر می‌گیرند، به‌علاوه‌ی یک خانواده‌ی جداگانه‌ی فاصله‌ی خط:

from orthography2ipa.distance import phonological_distance
d = phonological_distance(orthography2ipa.get("pt-BR"), orthography2ipa.get("pt-PT"))

d.combined                    # 0.0515 — near-identical
d.inventory.feature_mean      # phoneme-inventory distance
d.grapheme.mean_ipa_distance  # grapheme-mapping divergence
d.allophone_sim               # allophone-overlap similarity

بردارهای ویژگی نیز نمایان‌اند، پس یک جفت تقریباً یکسان مانند دو استاندارد پرتغالی روی 0.0515 می‌نشیند در حالی که جفت‌های واقعاً دور به‌روشنی از هم جدا می‌شوند. این برای تصمیم‌گیری‌های یادگیری انتقالی، راه‌اندازی کم‌منبع و گویش‌سنجی به یک اندازه سودمند است.

چگونه می‌دانیم که داده‌ها خوب‌اند

«گلد» قابل‌اتکا برای G2P به‌سختی وجود دارد — بیشتر مجموعه‌داده‌های عمومی خروجی خودِ یک واج‌ساز است که به‌عنوان مرجع بازاستفاده شده، پس نرخ خطای پایین در برابر آن‌ها یعنی «با آن ابزار موافق است»، نه «درست است». ما در این مورد صریحیم و به‌جای گزارش یک عدد چاپلوسانه‌ی واحد، روش‌شناسی راستی‌آزمایی‌ای پیرامون آن ساختیم.

برای گونه‌هایی که بیشترین اهمیت را برایمان دارند، گلد تألیف می‌شود، نه استخراج: یک مجموعه‌جمله‌ی موتور-پین‌شده به‌ازای هر لِکت، که در جفت‌های کور داوری می‌شود، در برابر ادبیات با ارجاع دقیق به صفحه حکمیت می‌شود، و از طریق رده‌های تصحیح به یک حلقه‌ی بازخورد موتور بازتا می‌خورد — اختلاف میان خروجی موتور و صورت تصحیح‌شده سرنخی درباره‌ی یک باگ واقعی در مشخصه است. در سراسر گلد TTS موتور-پین‌شده و شواهد منبع-اولیه، چند هزار ردیف راستی‌آزمایی‌شده وجود دارد. چارچوب عمداً درباره‌ی منشأ صادق است: مصنوعی و حکمیت‌شده با ادبیات جایی که تنها همان موجود است، و گلد انسانی راستین جایی که وجود دارد — مجموعه‌ی میراندایی mirandese_g2p از گویشور بومی، شواهد منبع-اولیه‌ی با ارجاع دقیق به صفحه، و مشارکت‌های بومی. ادعاهای دقت تنها در برابر گلد انسانی مطرح می‌شوند؛ یک امتیاز کامل در برابر پیش‌نویسِ خودِ موتور هیچ معنایی نخواهد داشت.

اعداد، که جهت‌نما خوانده می‌شوند و همیشه به منبعشان استناد داده شده‌اند (docs/scoreboard.md، docs/benchmarks.md و اسناد بنچمارک مخازن پایین‌دستی):

  • گویش‌های عربی، ورودی خام بدون اعراب — حالت دشوار و واقع‌گرایانه برای استقرار. روی گلد TTS ورودی‌خام arbtok (۳۳ لِکت)، آمیزش شبکه-رَوی زیر مجوزدهی گویشی به PER میانگین 0.189 می‌رسد و از همان هم‌رأیه که به‌عنوان مولد آزاد اجرا شده (0.193) پیشی می‌گیرد، با حاشیه‌ای متمرکز بر لِکت‌هایی که بیشترین واگرایی را از MSA دارند. روی بیشتر لِکت‌ها arbtok روی ورودی خام از espeak-ng پیشی می‌گیرد؛ روی خود MSA، espeak — که برای MSA تنظیم شده — همچنان می‌برد (espeak 0.176 در برابر arbtok 0.245).
  • گویش‌های عربی، ورودی با اعراب — با حضور علائم، PER مربوط به arbtok در 0.01–0.08 به‌ازای هر لِکت می‌نشیند، به‌خوبی زیرِ صدای تک-MSA espeak (مثلاً نجدی 0.009 در برابر espeak 0.221؛ مصری 0.027 در برابر espeak 0.287). espeak هیچ صدای گویشی ندارد، پس این صادقانه سیب-به-پرتقال است — اما همین شکاف نکته‌ی اصلی است.
  • پرتغالی، در برابر گلد انسانیِ متخصص — پرتغالی اروپاییِ لیسبون روی PER 0.029 (۸۸٪ تطابق دقیق) روی منابع اولیه‌ی با ارجاع دقیق به صفحه می‌نشیند، و گلد میراندایی گویشور بومی روی 0.146.

هر یک از این‌ها یک ویژگی وضعیت-کنونیِ داده‌هاست، که به یک بازه‌ی اطمینان بوت‌استرپ ارجاع متقابل داده شده، نه یک جام قهرمانی جدول امتیازات. جایی که بازه پهن یا نمونه کوچک است، تابلوی امتیاز همین را می‌گوید.

رابط خط فرمان (CLI)

هر آنچه در بالا آمد بدون نوشتن Python دسترس‌پذیر است. اسکریپت کنسولی orthography2ipa دستورهای list، info، transcribe و distance را عرضه می‌کند و هر زیردستور --json را برای لوله‌کشی به درون یک خط‌لوله می‌پذیرد.

orthography2ipa list --family Romance
orthography2ipa info pt-BR --graphemes
orthography2ipa transcribe en-GB "through" --beam 8
orthography2ipa distance es-ES it-IT --json

چرا داده‌ی خالص اهمیت دارد

کل مجموعه‌ی مشخصه‌ها با اسکیما اعتبارسنجی می‌شود — دیتاکلاس‌های منجمد به‌سبک pydantic که با یک مجموعه‌آزمون یکپارچگی جاروب شده‌اند، و SCHEMA.md که شکل آن‌ها را مستند می‌کند. جایی که یک جدول ایستا واقعاً نمی‌تواند قواعد را بیان کند، منطق ویژه‌ی زبان پیرامون داده‌ها متصل می‌شود: هجابندها از طریق یک گروه entry-point ثبت می‌شوند، و موتورهای سنگین‌تر در پایین‌دست بر همان شبکه‌ی مشترک بنا می‌شوند.

هیچ مدل مبهمی نیست که تصمیم بگیرد زبان‌های کاربران شما چگونه به گوش برسند. نگاشت‌ها قابل ممیزی‌اند، منابع تا سطح صفحه ذکر شده‌اند، و افزودن یک زبان به‌معنای نوشتن یک فایل JSON اعتبارسنجی‌شده است — از docs/adding_a_language.md و راهنمای شروع به کار آغاز کنید. برای هر کسی که TTS، ASR یا NLP واجی می‌سازد و از برون‌سپاری واج‌شناسی خود به یک جعبه‌ی سیاه سر باز می‌زند — و می‌خواهد آن را روی سخت‌افزار خودش اجرا کند — همین نکته‌ی اصلی است. این بسته با مجوز Apache 2.0 عرضه می‌شود، و از آنِ شماست که آن را بازرسی، گسترش و روی زیرساخت خودتان میزبانی کنید.