<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Alignment on M1KE BL0G</title><link>https://www.m1ke.org/tags/alignment/</link><description>Recent content in Alignment on M1KE BL0G</description><generator>Hugo -- gohugo.io</generator><language>ja-jp</language><copyright>mike</copyright><lastBuildDate>Mon, 12 Oct 2026 14:00:00 +0900</lastBuildDate><atom:link href="https://www.m1ke.org/tags/alignment/index.xml" rel="self" type="application/rss+xml"/><item><title>mpalignerの仕組み</title><link>https://www.m1ke.org/p/mpaligner%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF/</link><pubDate>Mon, 12 Oct 2026 14:00:00 +0900</pubDate><guid>https://www.m1ke.org/p/mpaligner%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF/</guid><description>&lt;img src="https://www.m1ke.org/p/mpaligner%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF/word-alignment.png" alt="Featured image of post mpalignerの仕組み" /&gt;&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.m1ke.org/p/unidic%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF/" &gt;UniDicの仕組み&lt;/a&gt;・&lt;a class="link" href="https://www.m1ke.org/p/g2p%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%82%92%E4%BD%9C%E3%82%8B%E6%99%82%E3%81%AB%E8%AA%BF%E6%9F%BB%E3%81%97%E3%81%9F%E5%85%88%E8%A1%8C%E6%96%87%E7%8C%AE%E3%81%AA%E3%81%A9%E3%81%AE%E3%83%A1%E3%83%A2/" &gt;G2Pライブラリを作る時に調査した先行文献などのメモ&lt;/a&gt;の文脈で出てきた、mpalignerというアライメントツールについて整理する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="アライメントとは"&gt;アライメントとは&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;アライメント（Alignment）とは、2つの系列（例えば、文字の並びと音素の並び）のどの部分同士が対応しているかを明らかにすること&lt;/li&gt;
&lt;li&gt;G2P（Grapheme-to-Phoneme）の文脈では、ある単語の表記（文字列）と読み（音素列）を、文字単位・音素単位でどう対応させるかという問題にあたる&lt;/li&gt;
&lt;li&gt;単純には、文字列と音素列の文字数が同じなら、先頭から1文字ずつ対応させる1対1アライメントが考えられるが、実際には文字数と音素数が一致しないことが多く、これだけでは不十分&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mpaligner"&gt;mpaligner&lt;/h2&gt;
&lt;h3 id="mpalignerとは"&gt;mpalignerとは&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Keigo Kubo（久保圭吾）が開発した、多対多アライメントツール&lt;/li&gt;
&lt;li&gt;MPは「Many-to-many（多対多）」の略で、生成モデルに基づいて、文字列（表記）と音素列（発音）のアライメントを学習する&lt;/li&gt;
&lt;li&gt;日本語の未知語（辞書に登録されていない単語）に対する発音の自動付与を主な用途としている&lt;/li&gt;
&lt;li&gt;一部だけ手動でアライメントを指定した半教師あり学習や、怪しい（Doubtful）対応の検出・結合といった機能も持つ&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="m2m-alignerとの関係"&gt;m2m-alignerとの関係&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;アルゴリズムの系譜としては、Jiampojamarn, Kondrak, Sherif (2007, NAACL)が英語のL2P（Letter-to-Phoneme）変換のために開発したm2m-aligner（こちらもMany-to-Many Alignerの略）と同じ、多対多アライメントという枠組みに属する&lt;/li&gt;
&lt;li&gt;どちらも、Ristad &amp;amp; Yianilos (1998)のStochastic Transducerに基づくEM（Expectation-Maximization）アルゴリズムで、文字列と音素列の対応を教師データなしで学習する、という考え方を共有している&lt;/li&gt;
&lt;li&gt;mpalignerは、この枠組みを日本語の未知語の読み推定というタスクに向けて実装したツールにあたる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="多対多アライメントの仕組み"&gt;多対多アライメントの仕組み&lt;/h2&gt;
&lt;h3 id="1対1アライメントの限界"&gt;1対1アライメントの限界&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;単純なアライメントでは、1つの文字が1つの音素に対応すると仮定するが、実際の言語ではこの仮定が成り立たないことが多い&lt;/li&gt;
&lt;li&gt;英語の例: 「x」は2つの音素（/k/と/s/）に対応し、「ch」という2文字は1つの音素（/tʃ/）に対応する&lt;/li&gt;
&lt;li&gt;このように、文字数と音素数が一致しない場合、1対1のアライメントでは正しく表現できない&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="多対多アライメントmany-to-many-alignment"&gt;多対多アライメント（Many-to-Many Alignment）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;多対多アライメントは、Stochastic Transducerに基づくEMアルゴリズムで、複数文字と複数音素の対応を教師なしで学習する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="アルゴリズムの流れ"&gt;アルゴリズムの流れ&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;候補アライメントの生成: &lt;code&gt;--maxX&lt;/code&gt;・&lt;code&gt;--maxY&lt;/code&gt;というパラメータ（m2m-alignerではデフォルトはどちらも2）で、文字側・音素側それぞれ最大いくつの文字・音素をまとめた「チャンク」まで対応を許すかを決め、1つの単語の中で考えられる全てのチャンク同士の対応パターンを、格子（ラティス）として表現する&lt;/li&gt;
&lt;li&gt;E-step: 現在のモデル（チャンク対ごとの対応確率）のもとで、ラティス上の各チャンク対がどの程度の確率で使われているかという期待カウントを計算する&lt;/li&gt;
&lt;li&gt;M-step: 計算した期待カウントを、チャンク対ごとに正規化し直すことで、次のイテレーションのモデルパラメータ（チャンク対の対応確率）を再推定する&lt;/li&gt;
&lt;li&gt;E-step・M-stepをパラメータが収束するまで繰り返すことで、「x→k,s」「ch→tʃ」のような、複数文字と複数音素の対応を、人手でラベル付けしなくても自動的に発見できる&lt;/li&gt;
&lt;li&gt;学習が終わったら、各単語ごとに、学習済みのモデルを使って最も確率の高い1つのアライメントを、&lt;a class="link" href="https://www.m1ke.org/p/%E3%83%93%E3%82%BF%E3%83%93%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0/" &gt;ビタビアルゴリズム&lt;/a&gt;で選び出す&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--delX&lt;/code&gt;・&lt;code&gt;--delY&lt;/code&gt;というオプションで、文字側・音素側どちらかに対応するものがない（削除・挿入にあたる）ケースも扱える&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="応用と実例"&gt;応用と実例&lt;/h2&gt;
&lt;h3 id="slearpとの連携"&gt;Slearpとの連携&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Slearp（Kubo他）は、mpalignerが出力したアライメント済みのデータを学習データとして受け取り、G2Pモデルを学習・推定する識別学習（Discriminative Learning）のツールキット&lt;/li&gt;
&lt;li&gt;CRF・Structured AROW・Structured NAROW・Structured SMCWなど、複数の構造学習手法をサポートしている&lt;/li&gt;
&lt;li&gt;つまり、mpalignerが「文字列と音素列の対応（アライメント）を見つける」役割、Slearpが「そのアライメント済みデータから、新しい単語の読みを予測するモデルを学習する」役割という、分業関係になっている&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="未知語の読み推定の実例"&gt;未知語の読み推定の実例&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;mpaligner・Slearpを組み合わせることで、辞書に登録されていない外国語の単語（カタカナ語の元になる単語）の読みを推定できる&lt;/li&gt;
&lt;li&gt;例えば、&amp;ldquo;caligari&amp;quot;という未知の英単語を1文字ずつに分割して入力すると、「カ｜リ｜ガ｜リ｜」という読みが出力される、という実例がある&lt;/li&gt;
&lt;li&gt;MeCabの辞書に外国語の単語を全て登録すると辞書サイズが膨大になってしまうため、このように学習済みモデルで未知語の読みをその場で推定する方式が使われる&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="実際に動かしてみた"&gt;実際に動かしてみた&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;keigo-k/mpaligner&lt;/code&gt;をクローンしてビルドした。最近のGCCはデフォルトで&lt;code&gt;-fno-common&lt;/code&gt;が有効なため、そのままでは古いCのグローバル変数の書き方（&lt;code&gt;HASH_func.c&lt;/code&gt;・&lt;code&gt;mpAlign.c&lt;/code&gt;・&lt;code&gt;mpaligner.c&lt;/code&gt;で同じ変数名を共有）がリンクエラーになる。&lt;code&gt;make CFLAGS=&amp;quot;-O2 -fcommon&amp;quot;&lt;/code&gt;でビルドし直すことで解決した&lt;/li&gt;
&lt;li&gt;「蕎麦・煙草・今日・大和・明日・一人・人気・日本・東京・大阪・夜桜・花見・空気・元気・天気」など、20組の表記・読みペアを用意し、EM学習を実行した&lt;/li&gt;
&lt;li&gt;デフォルト設定では、2文字の単語全体が1つのチャンクとして扱われてしまい、漢字単位の対応が見えなかった。&lt;code&gt;-rx 1&lt;/code&gt;（表記側のチャンク長を1文字に制限）を指定すると、漢字ごとの対応が見えるようになった&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;実行結果の一部は以下の通り（&lt;code&gt;:&lt;/code&gt;は同じチャンク内でまとめられた文字、&lt;code&gt;|&lt;/code&gt;はチャンクの境切り）。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;表記&lt;/th&gt;
&lt;th&gt;読み&lt;/th&gt;
&lt;th&gt;対応&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;蕎麦&lt;/td&gt;
&lt;td&gt;そば&lt;/td&gt;
&lt;td&gt;蕎→そ、麦→ば&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;煙草&lt;/td&gt;
&lt;td&gt;たばこ&lt;/td&gt;
&lt;td&gt;煙→た、草→ばこ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;大和&lt;/td&gt;
&lt;td&gt;やまと&lt;/td&gt;
&lt;td&gt;大→や、和→まと&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;明日&lt;/td&gt;
&lt;td&gt;あす&lt;/td&gt;
&lt;td&gt;明→あ、日→す&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;明日&lt;/td&gt;
&lt;td&gt;あした&lt;/td&gt;
&lt;td&gt;明→あ、日→した&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;東京&lt;/td&gt;
&lt;td&gt;とうきょう&lt;/td&gt;
&lt;td&gt;東→と、京→うきょう&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;大阪&lt;/td&gt;
&lt;td&gt;おおさか&lt;/td&gt;
&lt;td&gt;大→お、阪→おさか&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;空気&lt;/td&gt;
&lt;td&gt;くうき&lt;/td&gt;
&lt;td&gt;空→くう、気→き&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;元気&lt;/td&gt;
&lt;td&gt;げんき&lt;/td&gt;
&lt;td&gt;元→げ、気→んき&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;興味深いのは「明日」の結果。「あす」と読む場合は日→す、「あした」と読む場合は日→したと、同じ漢字の組でも、読みに応じて異なる対応が学習されている&lt;/li&gt;
&lt;li&gt;「気」も、「元気（げんき）」「天気（てんき）」「人気（にんき）」では気→んきと対応するが、「空気（くうき）」では気→きと対応しており、前の文字（空）が「くう」という2モーラを引き受けているため、「気」が受け持つ部分が変わっている&lt;/li&gt;
&lt;li&gt;「東京（とうきょう）」では、京が「うきょう」という3モーラ分を一気に引き受けており、1つの漢字が複数の音に対応する多対多アライメントが、まさにこういう形で現れることを実際のデータで確認できた&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="日本語での応用例-単漢字の読み補完"&gt;日本語での応用例: 単漢字の読み補完&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.m1ke.org/p/unidic%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF/" &gt;UniDicの仕組み&lt;/a&gt;で触れたような辞書では、複合語の読みは登録されているが、個々の漢字単独の読みが登録されていない場合がある&lt;/li&gt;
&lt;li&gt;mpalignerを使うと、複合語（表記列）とその読み（発音列）のペアを多対多でアライメントすることで、個々の漢字がどの読みに対応するかを、教師データなしで推定できる&lt;/li&gt;
&lt;li&gt;例えば、「桜」という漢字単体の読みが辞書に登録されていなくても、「夜桜（よざくら）」のような既知の複合語の表記・読みペアをアライメントすることで、「夜」に「よ」、「桜」に「さくら」という対応を推定できる&lt;/li&gt;
&lt;li&gt;この手法は、辞書に直接登録されていない単漢字の読みを、既存の複合語データから補完するために使える&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;アライメントとは、文字列と音素列のような2つの系列同士の対応関係を明らかにすること&lt;/li&gt;
&lt;li&gt;mpalignerは、日本語の未知語の発音推定を主な用途とした多対多アライメントツールで、英語L2P用のm2m-alignerと同じEMアルゴリズムの枠組みに属する&lt;/li&gt;
&lt;li&gt;チャンク対の候補をラティスとして表現し、E-stepで期待カウントを計算、M-stepで確率を再推定するEMの繰り返しで学習し、最終的なアライメントはビタビアルゴリズムで抽出する&lt;/li&gt;
&lt;li&gt;Slearpと組み合わせることで、mpalignerが見つけたアライメントから、新しい未知語の読みを予測するモデルを学習できる&lt;/li&gt;
&lt;li&gt;日本語では、複合語の表記・読みペアをアライメントすることで、辞書に登録されていない単漢字の読みを補完するといった応用もできる&lt;/li&gt;
&lt;li&gt;実際に動かしてみると、同じ漢字の組でも読みによって異なる対応が学習されたり（明日→あす／あした）、1つの漢字が複数モーラ分の読みを引き受けたり（東京の京→うきょう）する様子を確認できた&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/keigo-k/mpaligner" target="_blank" rel="noopener"
&gt;keigo-k/mpaligner - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/keigo-k/slearp" target="_blank" rel="noopener"
&gt;keigo-k/slearp - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Kubo, K., Kawanami, H., Saruwatari, H., &amp;amp; Shikano, K. (2013). &amp;ldquo;Many-to-many Alignment Algorithm for Automatic Pronunciation Annotation on Japanese Unknown Words&amp;rdquo; IPSJ Journal, Vol. 54, No. 2&lt;/li&gt;
&lt;li&gt;Kubo, K., Kawanami, H., Saruwatari, H., &amp;amp; Shikano, K. (2012). &amp;ldquo;Evaluation of Many-to-Many Alignment Algorithm by Automatic Pronunciation Annotation Using Web Text Mining&amp;rdquo; INTERSPEECH&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/yukinoi/items/1ad8250102b06006ee6c" target="_blank" rel="noopener"
&gt;Slearp + mpaligner による発音推定 - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Jiampojamarn, S., Kondrak, G., &amp;amp; Sherif, T. (2007). &amp;ldquo;Applying Many-to-Many Alignments and Hidden Markov Models to Letter-to-Phoneme Conversion&amp;rdquo; (&lt;a class="link" href="https://aclanthology.org/N07-1047/" target="_blank" rel="noopener"
&gt;ACL Anthology N07-1047&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Ristad, E. S., &amp;amp; Yianilos, P. N. (1998). &amp;ldquo;Learning string-edit distance&amp;rdquo; IEEE Transactions on Pattern Analysis and Machine Intelligence&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/letter-to-phoneme/m2m-aligner" target="_blank" rel="noopener"
&gt;letter-to-phoneme/m2m-aligner - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.m1ke.org/p/unidic%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF/" &gt;UniDicの仕組み&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.m1ke.org/p/g2p%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%82%92%E4%BD%9C%E3%82%8B%E6%99%82%E3%81%AB%E8%AA%BF%E6%9F%BB%E3%81%97%E3%81%9F%E5%85%88%E8%A1%8C%E6%96%87%E7%8C%AE%E3%81%AA%E3%81%A9%E3%81%AE%E3%83%A1%E3%83%A2/" &gt;G2Pライブラリを作る時に調査した先行文献などのメモ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.m1ke.org/p/%E3%83%93%E3%82%BF%E3%83%93%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0/" &gt;ビタビアルゴリズム&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>