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

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

چگونه پشتهٔ واج‌شناسی ما در کنار هم قرار می‌گیرد

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

واژهٔ انگلیسی “read” را در نظر بگیرید. نوشته‌شده، به شما نمی‌گوید چگونه آن را بگویید. “I read the book yesterday” و “I read the book every day” همان پنج حرف را برای دو صدای متفاوت به کار می‌برند — یکی با “red” هم‌قافیه است، دیگری با “reed”. یک صفحه‌خوان، یک دستیار صوتی یا یک جعبهٔ جست‌وجو که تنها به املا نگاه می‌کند نمی‌تواند این را درست از کار دربیاورد. باید دربارهٔ تلفظ استدلال کند، نه فقط متن.

آن مسئلهٔ استدلال — تبدیل واژه‌های نوشته‌شده به صداهایی که بازنمایی می‌کنند — چیزی است که پشتهٔ واج‌شناسی ما حل می‌کند. این نوشته نقشه‌ای است از اینکه اجزای آن چگونه کنار هم می‌نشینند، از نشانه‌گذاری خام تا موتورهای تلفظِ زبان‌ویژه و جست‌وجوی مبتنی بر صدا.

چند اصطلاح، به‌روشنی تعریف‌شده

چند واژه که در سراسر این نوشته می‌آیند:

  • گرافم (Grapheme): یک نماد نوشتاری — یک حرف، یا ترکیبی از حروف مانند “ch”.
  • واج (Phoneme): یک واحد متمایز صدا در یک زبان، مانند صدای “k” در “cat”.
  • IPA (الفبای آوانگاریِ بین‌المللی): یک الفبای استاندارد برای نوشتن دقیق صداها، مستقل از املای هر زبانی. “Cat” در IPA به‌صورت kæt نوشته می‌شود.
  • G2P (گرافم به واج): مسئلهٔ عمومیِ تبدیل املا به صدا.
  • واج‌گونه (Allophone): تحقق متغیر همان واج بسته به بستر — “t” در “top” و “t” در “stop” در انگلیسی همان واج‌اند اما کمی متفاوت تلفظ می‌شوند.
  • هجابندی (Syllabification): تقسیم یک واژه به هجاها، مثلاً “extraordinário” به ex-tra-or-di-ná-ri-o.
  • هم‌نگاشت (Homograph): دو واژه با املای یکسان اما معنای متفاوت؛ یک هم‌نگاشتِ ناهم‌آوا (یا heterophone) هم‌نگاشتی است که بسته به معنای موردنظر متفاوت تلفظ می‌شود، مانند “read”/“read” بالا.
  • صرف‌شناسی (Morphology): ساختار درونی واژه‌ها — پیشوندها، ریشه‌ها، پسوندها، صرف‌ها.
  • برچسب‌زنی اجزای کلام (POS tagging): برچسب‌زدن هر واژهٔ یک جمله به‌عنوان اسم، فعل، صفت و مانند این‌ها.

مسئلهٔ بنیادین

املا یک رمزگذاریِ اتلاف‌دار از صداست. سه چیز جداگانه معکوس‌کردن آن را دشوار می‌کند:

۱. ابهام. همان حروف بسته به معنا، دستور یا صرفاً بی‌قاعدگی می‌توانند به صداهای متفاوت نگاشت شوند (“read” بالا؛ انگلیسی پر از این‌هاست). ۲. گویش. همان واژه، در همان زبان، بسته به اینکه گوینده اهل کجاست متفاوت تلفظ می‌شود. پرتغالی اروپایی و برزیلی املا را مشترک دارند اما واکه‌ها را نه. ۳. پوشش. بیشتر زبان‌های جهان اصلاً هیچ فرهنگ تلفظِ حرفه‌ای گلچین‌شده‌ای ندارند. سامانهٔ G2P‌ای که تنها از طریق یک جدول جست‌وجو کار می‌کند سامانه‌ای است که تنها برای مشتی زبان کار می‌کند.

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

چرا پشته لایه‌بندی شده

پشته مسئله را به لایه‌هایی تقسیم می‌کند که نیازی به دانستن دربارهٔ هم ندارند:

  • نشانه‌گذاری — تبدیل میان الفباهای آوایی و رسم‌الخط‌ها. این هیچ ربطی به واج‌شناسیِ هیچ زبان خاصی ندارد؛ ترجمهٔ نماد است.
  • واج‌شناسی — نگاشت املا به IPA برای یک زبان معین، با استفاده از یک اسپکِ نظام صوتیِ آن زبان.
  • رسیدگی به استثنائات زبان‌ویژه — واژه‌های بی‌قاعده، عجایب گویشی، هم‌نگاشت‌ها و ساختار صرفی‌ای که یک موتور عمومی نمی‌تواند تنها از قواعد املایی استنتاج کند.

نگه‌داشتن این‌ها جدا یک تصمیم طراحی است، نه یک تصادف، و سودی مستقیم دارد: افزودن یک زبان تازه یعنی نوشتنِ یک اسپک (داده‌ای که نظام صوتی آن را توصیف می‌کند)، نه یک برنامهٔ تازه. موتوری که اسپک را مصرف می‌کند، جست‌وجوی شبکه، توکن‌ساز، سنجه‌های فاصله — هیچ‌کدام دوباره نوشته نمی‌شوند. لایهٔ نشانه‌گذاریِ زیرین توسط هر زبانی مشترک است، حتی زبان‌هایی که موتور واج‌شناسی هرگز نامشان را نشنیده.

لایهٔ نشانه‌گذاری: scriptconv

scriptconv یک هستهٔ بدون‌وابستگی برای نشانه‌گذاری آوایی و مدیریت رسم‌الخط است: تشخیص رسم‌الخط بر پایهٔ ISO-15924، تبدیل‌های IPA به و از ARPABET، X-SAMPA، Lexique، Kirshenbaum، Cotovía و نشانه‌گذاری RFE، حرف‌نویسی Buckwalter برای عربی، تجزیهٔ Hangul به جامو، و مدیریت کانا. هیچ‌کدام از این‌ها نیازی به دانستن اینکه یک واژه متعلق به کدام زبان است ندارند — یک رشتهٔ واجی در IPA بدون توجه به زبان مبدأ به همان شکل به ARPABET تبدیل می‌شود:

>>> import scriptconv as s
>>> s.ipa_to_arpa("kæt")
'K AE T'
>>> s.ipa_to_xsampa("kæt")
'k{t'

هر لایه‌ی بالای این یکی می‌تواند فرض کند تبدیل نشانه‌گذاری از پیش حل شده.

موتور: orthography2ipa

orthography2ipa موتور میان‌زبانی است. یک اسپک زبانی — توصیفی اعلانی از قواعد گرافم‌به‌واجِ آن زبان — و یک تکه متن می‌گیرد و IPA تولید می‌کند. در زمان نگارش این نوشته، اسپک‌هایی که ۸۰۷ زبان را می‌پوشانند عرضه می‌کند (available_codes() روی بستهٔ نصب‌شده فهرستی به این طول برمی‌گرداند؛ رقم دقیق را هدفی متحرک در نظر بگیرید، چون اسپک‌ها با گذر زمان افزوده می‌شوند).

>>> import orthography2ipa as o
>>> len(o.available_codes())
820

خودِ موتور هیچ کد زبان‌ویژه‌ای درونش پخته نشده. یک زبان تازه یک فایل اسپک تازه است، بررسی‌شده در برابر همان اسکیمای هر اسپک دیگر.

شبکه: نامزدهای رتبه‌بندی‌شده، نه یک حدس

با توجه به مسئلهٔ ابهام بالا، تعهد به یک خروجی واحد برای هر واژه اغلب اشتباه است. در عوض orthography2ipa یک شبکه — مجموعه‌ای از تلفظ‌های نامزدِ رتبه‌بندی‌شده — تولید می‌کند و اجازه می‌دهد لایه‌های بالاتر آن را با استفاده از بستری که خودِ موتور ندارد (معنا، اجزای کلام، یک مدخل واژگانی) محدود کنند.

دوباره “read” را در نظر بگیرید:

>>> from orthography2ipa import G2P
>>> g = G2P("en")
>>> g.transcribe("read")
'ɹiːd'
>>> g.candidates("read")
[IPAPath('ɹiːd', score=0.0), IPAPath('ɹɛd', score=1.0)]

بدون بستر بیشتر، موتور بهترین حدسش (زمان حال، هزینهٔ کمتر) را برمی‌گرداند اما جایگزین (زمان گذشته) را با هزینه‌اش پیوست‌شده روی شبکه نگه می‌دارد. مؤلفه‌ای پایین‌دستی که می‌داند جمله در زمان گذشته است می‌تواند نامزد دوم را به‌جای اول انتخاب کند. همین ایده، در مقیاسی بزرگ‌تر، توسط bifonia (پایین‌تر) برای هم‌نگاشت‌های ناهم‌آوای پرتغالی به کار می‌رود: یک شبکهٔ عمومی نامزدها را فراهم می‌کند، یک لایهٔ محدودتر و آگاه‌تر از میان آن‌ها انتخاب می‌کند.

گویش‌ها شهروند درجه‌یک‌اند

دو گویندهٔ یک زبان می‌توانند همان جمله را متفاوت تلفظ کنند، و پشتهٔ واج‌شناسی‌ای که با “پرتغالی” مانند یک نظام صوتیِ واحد ثابت رفتار کند، هر گویش را جز یکی اشتباه می‌گیرد. orthography2ipa مدیریت گویش را مستقیماً نمایان می‌کند — available_profiles() روی بستهٔ نصب‌شده نمایه‌های گویشی و لِکتی مانند lisbon، porto، estremenho، galician و دیگران را فهرست می‌کند — و tugaphone، فرانت‌اند پرتغالیِ ساخته‌شده روی آن، همان جمله را در سراسر گونه‌های لوزوفون واج‌سازی می‌کند. این یک جمله است که از میان هر پنج گویش پشتیبانی‌شده عبور کرده:

گویشخروجی
pt-PT (پرتغال)ˈbõ ˈdiɐ ˈkomu eˈʃta vɔˈse
pt-BR (برزیل)ˈbõ ˈdʒiɐ ˈkɔ̃mʊ eˈsta voˈse
pt-AO (آنگولا)ˈbõ ˈdiɐ ˈkomʊ eˈsta vɔˈse
pt-MZ (موزامبیک)ˈbõ ˈdiɐ ˈkomu eˈsta vɔˈse
pt-TL (تیمور شرقی)ˈbõ ˈdiə ˈkoɔmʊ eˈsta vɔˈse

(“Bom dia, como está você؟” — “صبح بخیر، حالتان چطور است؟”) اسکلت همخوانی در هر پنج مورد قابل‌تشخیص می‌ماند، اما دو نشانگرِ شناخته‌شده بلافاصله آن‌ها را از هم جدا می‌کنند. در “dia”، پرتغالی برزیلی d پیش از i را به تبدیل می‌کند، همان صدای آغاز “jam” در انگلیسی — بقیه یک d ساده را نگه می‌دارند. در “está”، پرتغالی اروپایی s پایانِ یک هجا را به‌صورت ʃ تلفظ می‌کند، همان “sh” در “shoe”، در حالی که هر گونهٔ دیگر s را نگه می‌دارد. یک فرهنگ تلفظِ ساخته‌شده از قواعد یک گویش، هر دوی این‌ها را برای شنوندهٔ هر گویش دیگری اشتباه می‌گیرد.

euskaphone همین کار را برای گویش‌های باسکی انجام می‌دهد، مستقیماً ساخته‌شده روی شبکهٔ orthography2ipa به‌جای یک موتور جداگانه:

>>> from euskaphone import EuskaPhonemizer
>>> EuskaPhonemizer().phonemize_sentence("Kaixo, zer moduz zaude?")
'kai̯ʃo s̻er modus̻ s̻au̯de'

فرانت‌اندهای زبان‌ویژه

بالای موتور مشترک، فرانت‌اندهایی می‌نشینند که چیزی را می‌افزایند که یک اسپک عمومی نمی‌تواند: واژه‌های بی‌قاعده، یک واژگان گلچین‌شده، سندی (تغییرات صوتی در مرزهای واژه)، و بازنویسی‌های گویش‌ویژه.

  • tugaphone — پرتغالی، در سراسر pt-PT، pt-BR، pt-AO، pt-MZ و pt-TL، ترکیب یک واژگان گلچین‌شده با بازگشتِ مبتنی بر قاعده (نشان‌داده‌شده در بالا).

  • euskaphone — باسکی، آگاه به گویش، ساخته‌شده روی همان شبکه (نشان‌داده‌شده در بالا).

  • mwl_phonemizer — میراندایی، زبان آستورلئونیِ Terra de Miranda در پرتغال، با سندیِ بین‌واژه‌ای، واج‌گونگی و تکیه:

    >>> from mwl_phonemizer import phonemize
    >>> phonemize("Falo la lhéngua mirandesa.")
    'ˈfalu lɐ ˈʎɛŋɡwa miɾɐˈndez̺ɐ.'
  • g2p_barranquenho — نخستین G2P باز برای بارانکنیو، زبان تماسی ایبرو-رومنسِ بارانکوس، در مرز پرتغال-اسپانیا. برای اینکه قواعد آن چگونه از قرارداد املاییِ خودِ شهرداری استخراج شد به معرفی نخستین فونمایزر برای بارانکنیو نگاه کنید.

  • arbtok — عربی، ساخته‌شده روی شبکهٔ orthography2ipa، که اعراب‌گذاریِ آگاه به گویش را می‌افزاید و عربی معیار، کلاسیک و شماری از گونه‌های منطقه‌ای را پوشش می‌دهد. رسم‌الخط عربی معمولاً نشانه‌های واکهٔ کوتاه را که یک فونمایزر نیاز دارد حذف می‌کند، پس کار اصلی arbtok بازیابی آن‌ها پیش از سپردن نتیجه به موتور مشترک است. این کتابخانه توسط کسی نگهداری می‌شود که عربی زبان مادری‌اش نیست، پس آن را در حال توسعهٔ فعال در نظر بگیرید تا یک مرجعِ نهایی و بازبینی‌شده توسط بومی — سودمند است، اما جایی است که باید خروجی را پیش از عرضه در هر چیز رو‌به‌کاربر با یک گویشور بومی دوباره بررسی کرد.

هر یک از این فرانت‌اندها یک لایهٔ نازک از منطق زبان‌ویژه روی همان موتور شبکهٔ مشترک و همان لایهٔ نشانه‌گذاریِ مشترکِ زیرین است. هیچ‌کدام تبدیل IPA یا جست‌وجوی شبکه را دوباره پیاده‌سازی نمی‌کنند.

ابزارهای پشتیبانِ پرتغالی

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

  • silabificador واژه‌ها را با قواعد دست‌ساز به هجا تقسیم می‌کند:

    >>> from silabificador import syllabify
    >>> syllabify("extraordinário")
    ['ex', 'tra', 'or', 'di', 'ná', 'ri', 'o']
  • tugalex واژگانِ پشتِ tugaphone است: رونویسی‌های IPA، داده‌ی هجایی و قواعد املایی برای واژه‌های واقعی، پس واژگان رایج و بی‌قاعده هر بار نیازی به استخراج دوباره از املا ندارند.

  • tugatagger چندین باک‌اند برچسب‌زنی POS (spaCy، Stanza، برچسب‌زنی به‌سبک Brill، یک بازگشتِ اکتشافیِ بدون وابستگی) را پشت یک واسط می‌پیچد، پس ابزارهای دیگر می‌توانند بپرسند «این واژه چه جزء کلامی است» بدون تعهد به یک باک‌اند خاص.

  • tugamorph یک تحلیلگر صرفیِ مبتنی بر قاعده است: یک واژه را به پیشوند، ریشه، پسوند، صرف و کلیتیک تقسیم می‌کند، تنها با استفاده از کتابخانهٔ استاندارد Python، و به‌صورت اختیاری با silabificador و tugatagger تیزتر می‌شود.

  • bifonia هم‌نگاشت‌های ناهم‌آوای پرتغالی اروپایی را حل می‌کند — واژه‌هایی مانند “sede” (تشنگی، ˈsedɨ، در برابر ادارهٔ مرکزی، ˈsɛdɨ) که تلفظ درست به معنا بستگی دارد، نه به دستور. برای اینکه چگونه ساخته و ارزیابی شد به درست گفتنش: رفع ابهام هم‌نگاشت‌های ناهم‌آوای پرتغالی برای TTS نگاه کنید. این نمونهٔ عینیِ پشتِ ایدهٔ شبکهٔ بالاست: orthography2ipa می‌تواند هر دو خوانش نامزد “sede” را فراهم کند، اما تنها یک لایهٔ آگاه به معنا مانند bifonia می‌تواند از میان آن‌ها انتخاب کند.

برای شرح بیشتر اینکه silabificador و tugaphone روزبه‌روز چگونه با هم کار می‌کنند، به NLP کلاسیک برای پرتغالی: هجابندی و گرافم به واج نگاه کنید، و برای موتور گسترده‌تر زیرِ همهٔ این‌ها، به گرافم به IPA برای ۸۰۷ زبان.

جست‌وجوی مبتنی بر صدا: phonematcher

همهٔ آنچه بالاست متن را به صدا تبدیل می‌کند. phonematcher با خودِ بازنمایی‌های صوتی کار می‌کند: فاصلهٔ آوایی میان نمادهای IPA را محاسبه می‌کند و جست‌وجوی فازی روی فهرست‌های واژه بر اساس چگونگیِ شنیده‌شدن واژه‌ها انجام می‌دهد، نه چگونگیِ املایشان.

>>> from phonematcher.distance import phonetic_distance
>>> phonetic_distance('b', 'p')   # voiced vs. voiceless bilabial stop — very similar
0.043478260869565216
>>> phonetic_distance('p', 'k')   # bilabial vs. velar stop — less similar
0.34782608695652173
>>> phonetic_distance('a', 'k')   # vowel vs. consonant — maximally different
1.0

آن سنجهٔ فاصله در دو موقعیت عینی سودمند است: جست‌وجوی یک کاتالوگ از واژه‌ها یا نام‌ها بر اساس چگونگی شنیده‌شدن به‌جای املای دقیقشان (سودمند برای واسط‌های صوتیِ تحمل‌کنندهٔ غلط‌املایی و تطبیق وام‌واژه‌ها میان نظام‌های نوشتاری)، و مقایسهٔ اینکه دو لِکت مرتبط از نظر واج‌شناختی چقدر به هم نزدیک‌اند — همان نوع مقایسه‌ای که جدول گویشیِ بالا با چشم انجام می‌دهد، اما محاسبه‌شده به‌جای دیده‌بانی‌شده. phonematcher روی PyPI نیست؛ از منبع نصب می‌شود (pip install -e . در برابر checkout گیت‌هاب، به‌علاوهٔ rapidfuzz).

محدودیت‌های صادقانه

پوشش در سراسر ۸۰۷ اسپک زبانی به‌طور ذاتی ناهموار است: زبان‌هایی با ادبیات واج‌شناختیِ تثبیت‌شده و یک واژگان، خروجی بهتری از زبان‌هایی با یک اسپکِ نازک که عمدتاً از قراردادهای املایی عمومی استنتاج شده به دست می‌آورند. کیفیت به‌طور پیوسته بهترین است جایی که یک واژگان گلچین‌شده وجود دارد — پرتغالی، پشتیبانی‌شده توسط tugalex، قوی‌ترین مورد در این پشته است؛ زبان‌هایی که خالصاً بر قواعد اسپک بدون واژگان تکیه می‌کنند واژگان بی‌قاعده و وام‌گرفته را بد مدیریت می‌کنند.

چند مؤلفه صراحتاً مراجعِ نهایی و بازبینی‌شده توسط بومی نیستند: arbtok توسط یک گویشورِ غیربومیِ عربی نگهداری می‌شود و باید پیش از استفاده در هر چیز رو‌به‌کاربر در برابر داوریِ بومی بررسی شود. فرانت‌اندهای ساخته‌شده روی اسپک‌های نازک همان نازکی را به ارث می‌برند — یک فرانت‌اند تنها به‌خوبیِ اسپک و واژگانِ زیرینش است.

چرا این اهمیت دارد اگر زبان شما هیچ ابزار گفتاری ندارد

بیشتر زبان‌های جهان هیچ صدای TTS تجاری، هیچ مدل STT تجاری، و هیچ فرهنگ تلفظِ حرفه‌ای نگهداری‌شده‌ای ندارند. طراحیِ لایه‌ای بالا یعنی این شکاف نیازی به ساختن یک موتور واج‌شناسی از صفر ندارد: نیاز به نوشتنِ یک اسپک برای نظام صوتیِ زبان هدف دارد و، در جای ممکن، یک واژگان از واژه‌های بی‌قاعده‌اش. موتور شبکه، تبدیل‌های نشانه‌گذاری، و ابزارهای جست‌وجو از پیش آنجایند. اگر زبان، گویش یا محصول شما به پشتیبانی تلفظی نیاز دارد که هنوز وجود ندارد، این همان نوع کاری است که ما انجام می‌دهیم — به خدمات ما نگاه کنید یا با ما تماس بگیرید.