初めに
TTSの学習のひとつで、文字列をすべてひらがなにしたい場合があります。その際に簡単に使える sudachiを使って処理をしてみます
以下にサンプルリポジトリを公開しています
開発環境
- uv
- python 3.11
セットアップ
uv pip install sudachipy sudachidict-core
ひらながに変換
今回は、つくよみちゃんコーパス│声優統計コーパス(JVSコーパス準拠)の内容で実行をしてみます
sudachiを使ったファイル読み込みおよび変換コードは以下です
from sudachipy import dictionary, tokenizer def katakana_to_hiragana(text): """カタカナをひらがなに変換する関数""" hiragana = '' for char in text: code = ord(char) # カタカナの範囲内の文字をひらがなに変換 if 0x30A1 <= code <= 0x30FA: hiragana += chr(code - 0x60) else: hiragana += char return hiragana # Sudachiの辞書をロード tokenizer_obj = dictionary.Dictionary().create() mode = tokenizer.Tokenizer.SplitMode.C # 分割モードを指定 # 結果を保存するファイルを開く with open('sudachi-result.txt', 'w', encoding='utf-8') as f_output: # sample.txtを読み込んで処理 with open('sample.txt', 'r', encoding='utf-8') as f_input: for line in f_input: line = line.strip() if not line: continue if ':' in line: identifier, script = line.split(':', 1) readings = [] for token in tokenizer_obj.tokenize(script, mode): yomi = token.reading_form() readings.append(yomi) katakana_text = ''.join(readings) hiragana_text = katakana_to_hiragana(katakana_text) output_line = f"{identifier}:{hiragana_text}\n" f_output.write(output_line) else: f_output.write(line + '\n')
以下のようなフォーマットの sample.txt
がルートパスにあることを想定しています
VOICEACTRESS100_001:また、東寺のように、五大明王と呼ばれる、主要な明王の中央に配されることも多い。 VOICEACTRESS100_002:ニューイングランド風は、牛乳をベースとした、白いクリームスープであり、ボストンクラムチャウダーとも呼ばれる。 VOICEACTRESS100_003:コンピュータゲームのメーカーや、業界団体などに関連する人物のカテゴリ。
こちらを処理をすることで以下のような結果になります
VOICEACTRESS100_001:また、とうじのように、ごだいみょうおうとよばれる、しゅようなみょうおうのちゅうおうにはいされることもおおい。 VOICEACTRESS100_002:にゅーいんぐらんどふうは、ぎゅうにゅうをべーすとした、しろいくりーむすーぷであり、ぼすとんくらむちゃうだーともよばれる。 VOICEACTRESS100_003:こんぴゅーたげーむのめーかーや、ぎょうかいだんたいなどにかんれんするじんぶつのかてごり。
辞書の変更
sudachiの辞書は3つあります。
- core
- small
- full
今回は 一番語彙が多い full
を使ってみます
まずはインストールをします
uv pip install sudachidict_full
モードを指定する際に辞書を指定します
# Sudachiの辞書をロードし、full辞書を使用するように指定 tokenizer_obj = dictionary.Dictionary(dict="full").create() mode = tokenizer.Tokenizer.SplitMode.C # 分割モードを指定
ここで core
と full
での精度の比較を行います。今回は、以下のようなdiffコードを作って実行しました。
import difflib def compare_results(core_file, full_file, diff_output_file): # ファイルを読み込みます with open(core_file, 'r', encoding='utf-8') as f_core: core_lines = f_core.readlines() with open(full_file, 'r', encoding='utf-8') as f_full: full_lines = f_full.readlines() # 結果を保存するファイルを開く with open(diff_output_file, 'w', encoding='utf-8') as f_output: # 行数のチェック max_lines = max(len(core_lines), len(full_lines)) for i in range(max_lines): core_line = core_lines[i].strip() if i < len(core_lines) else '' full_line = full_lines[i].strip() if i < len(full_lines) else '' # 識別子と台本部分を分離 core_identifier, core_script = (core_line.split(':', 1) + [''])[:2] full_identifier, full_script = (full_line.split(':', 1) + [''])[:2] # 台本部分を比較 if core_script != full_script: f_output.write(f"--- 差分が見つかりました(行 {i+1}) ---\n") f_output.write(f"識別子: {core_identifier}\n") f_output.write(f"【Core辞書の結果】\n") f_output.write(core_script + '\n') f_output.write(f"【Full辞書の結果】\n") f_output.write(full_script + '\n') f_output.write(f"【差分】\n") # 差分を表示(文字単位での比較) diff = difflib.ndiff(core_script, full_script) f_output.write(''.join(diff) + '\n\n') else: pass # f_output.write(f"行 {i+1}({core_identifier}): 差分はありません。\n") # 比較するファイルのパス core_file = 'sudachi-result.txt' full_file = 'sudachi-full-result.txt' diff_output_file = 'diff_results.txt' compare_results(core_file, full_file, diff_output_file)
差分は以下です
--- 差分が見つかりました(行 9) --- 識別子: VOICEACTRESS100_009 【Core辞書の結果】 またねじめしは、なかやまおうのおさめる、りゅうきゅうおうこくとのこうえきにもさんかした。 【Full辞書の結果】 またねじめしは、ちゅうざんおうのおさめる、りゅうきゅうおうこくとのこうえきにもさんかした。 【差分】 ま た ね じ め し は 、- な- か- や- ま+ ち+ ゅ+ う+ ざ+ ん お う の お さ め る 、 り ゅ う き ゅ う お う こ く と の こ う え き に も さ ん か し た 。 --- 差分が見つかりました(行 27) --- 識別子: VOICEACTRESS100_027 【Core辞書の結果】 ちょういきにあった、みねやまはんは、ながおかはんに、べいひゃくひょうをおくったことでゆうめい。 【Full辞書の結果】 ちょういきにあった、みねやまはんは、ながおかはんに、こめひゃっぴょうをおくったことでゆうめい。 【差分】 ち ょ う い き に あ っ た 、 み ね や ま は ん は 、 な が お か は ん に 、- べ- い+ こ+ め ひ ゃ- く- ひ+ っ+ ぴ ょ う を お く っ た こ と で ゆ う め い 。