2021年12月26日日曜日

早口音読とダジャレ音読を作った

早口音読 と ダジャレ音読 を作りました。 小学校でよく宿題になる音読ですが、 短文を少し読むだけのケースも多い気がしてます。 それだったら面白い音読をたくさんしてもいいのでは、と思いました。 という訳で、早口言葉とダジャレを音読練習しましょう。



使い道はわかりやすいですが、難点があるとすれば、 早口言葉は小〜1小2の子には漢字や言葉がすこし難しいことでしょうか。 小2ならギリギリいけそうかな…。小さな子はダジャレのほうが良さそうです。

ダジャレ成分が高いので、ひさびさに Zenn にもネタ記事を投稿してみました。 紹介する方法では非常にコンパクトなデータ構造を使い、総当たりに近い形で読みを探索することで、音声認識の表記揺れに対応します。 実装上の改善ポイントはいろいろあって、読み辞書の生成はもっときちんと解析すれば、さらにコンパクトにできそうです。

技術的な話 (長音符)

Zenn には書いてない技術的な補足記事も書いてみます。 総当たりで解析しても、それでも解析が難しいところもあります。 それは「あー」「ああ」「あぁ」の違いです。 無理そうなので除外したりしている例をいくつかリストアップすると以下。
土星が驚いた。ドシェー!,どせい が おどろいた。ドシェー!
エイがイェーイ,えい が イェーイ
栄養は体にえーよー,えいよう は からだ に えーよー
英和辞典はええわー,えいわ じてん は ええわー
エースでえーっすか?,エース で えーっすか?
あの歌の歌詞ははずかしー,あの うた の かし は はずかしー
キタねえやつが来たねえ,キタねえ やつ が きたねえ
キタねーやつが来たねー,キタねー やつ が きたねー
交代するなんてなんてこうったい,こうたい する なんて なんて こうったい
高知にいるからこうっちに来い
コート来ておこーっと,コート きて おこーっと
屋根はやーねー,やね は やーねー
Google の音声認識だと、良い候補がなかった時には「よくわからんから一番近い言葉に変えてしまおう」という感じで動きます。 「えーよー」は「えいよう」になります。「ー」は置換される傾向があります。 「おこーっと」は「おこうと」となります。「っ」は消滅する傾向があります。 「やーねー」のような綺麗な文章で存在しない言葉は「やね」に丸められます。 これらの変換に音声認識側でルールはないように見えます。 ちなみに 長音符 「ー」 に文法的ルールはあって、 現代語ではひらがなに長音符は使わないように教育されます。 音声認識にも一定量は反映されていると思います。

上記を踏まえると、ダジャレは丁寧な文法で作る必要があります。 「っ」と「ー」「ぁぃぅぇぉ」が出てきたら、認識チェックは必須です。 「は」と「わ」も注意が必要です。 「だぜー」「いたいよー」「だぜっ」と言った口語特有の表現は、Google の音声認識では、ほぼ長音符なしに変換されます。 なので文末の一文字だけ削除してチェックすると案外ちんと動くことがあります。 ただ「うめー」「だお」のように長音符ありに変換されやすいものもあります。 このへんの違いは何とも言えないんですが、日本語は語尾が小さくなるように話されるので、最後の一文字が長音符なら判定はゆるくて良いのかなと思ってます。

ちなみに「っ」と「ー」「ぁぃぅぇぉ」が同時に二つ出てきたら、まず認識できないと思ってます。 たとえば「イェーイ」ですが、これは人間でも文字起こしが厳しいですよね。 解析側で処理しようとしても「お」が「う」に変わったり、「え」が「い」に変わったして大変です。 他にもダジャレ特有の、微妙に音韻がズレているもの (ex: おっかしいなあ→おっかりーなあ) を一緒と判定する機能は作ってません。 今回は対象がオジサンではなく小さな子なので、綺麗な文法のダジャレだけに限定して良いと思ってます。 今回は実装していませんが、長音符に起因する表記揺れはもう少し対応できるようにしても良いかも知れません。

技術的な話 (連濁)

人間には簡単に認識できても、妙に音声認識率が悪い言葉もあります。 例えば「勉強好き」の「ず」のように濁音になるケースの処理が難しいです。 こういうのは「連濁」と呼ばれるらしいです。 ちなみに「べんきょうすき」と言わないと認識してくれません。 理由を考えると「づき」「ずき」のように、同じ発音にひらがなが複数あるため、発音が一緒の熟語が出てきてしまうからだと思います。 読み解析側ではサポートしてますが、音声認識側の精度によって読み方を指定しないと苦しいダジャレがいくつかあります。 STT はこういった細かい部分を全部チェックしないと不安が残る精度なので、バリエーションは増やしにくいです。

音声認識の課題

作ってみて一番気になったのは既存の音声認識の、非言語的フレーズへの弱さの問題です。 たとえば九九の音読も作ろうと試みたのですが、 Google の音声認識は文章的なものの認識率はすごい一方、それ以外の精度は低くてうまく認識しません。 その原因は、認識結果を見る限り、統計的に起きやすい文章と発音に無理やり解釈してまう (ように見える) からです。 現時点では細かな部分は聞き取りミスしやすいものをすべて登録するような荒業以外に解決策がないです。 九九などはそれでも対処できないくらい正解から外れたものばかりなので、頑張っても苦労が増えるだけです。 音声認識の精度がもっと上がるか、文章以外も認識できるモデルが出るまでは待ちですね。

形態素解析の課題

形態素解析辞書についても、普通の形態素解析では見つからない細かな問題が見つかり、なかなか面白かったです。 古語や口語の対応が難しかったり、日常的に使われる特殊な読み、日常的に省略されたり追加される語尾の存在など、色々と気付かされました。 mecab-ipadic-neologd でもそういった言葉は登録されてなかったので、改善はできなそうです。 UniDic は多少の登録がありますが、ほんの少しの改善が限度になりそうです。 あと長音符や連濁をうまく扱えるライブラリがあるといいですね。 先に正規化してから形態素解析すればスコアは結構上がるんじゃないかなとも思ったりします。

個人的には世の中の多くのタスクに N-Best な形態素解析は不要だと思っていて、 そんな気持ちを少し前にブログにも書きました。 その一つの答えになっている仕組みは実現できているんじゃないかと思います。 ちなみに最近流行の BERT でポンも解決策の一つですが、メモリや速度や資本に問題が生じやすいです。 最近流行のスケーリング上げればどうとでもなる世界線なら、なおさらです。 深層学習の構造上、現時点ではメモリや速度の最適化あたりはまだ人手がいる気がしています。 面倒だから基本やりたくないけど、アプリを作ってるとたまに必要になります。

2021年12月24日金曜日

フリゲ紹介: Super Depth

私が人生で最初にプレイしたゲームの名前をひょんなことから思い出せたので、メモしておきます。 名前は Super Depth といって、PC-98 でプレイできたゲームみたいです。

当時プレイしたのは古すぎてパソコンが捨てられる寸前で、小1くらいの時だったのかなあ。 もう少し前かもしれないし、後かも知れません。 PC-98 が捨てられてからは、信長の野望をプレイしていたことをよく覚えています。 キーボードも適当に押して、手探りでプレイしていた記憶があります。 英語とか絶対に何もわかってないはずなので、少しくらいなら何とかなることがわかりますね。

Super Depth は当時もめちゃくちゃ面白かった記憶があって、ゲーム画面をよく覚えていました。 実際 PC-98 世代の人には大人気だったゲームらしいです。 今の世代の人がプレイしても、ミニゲームとしてなら十分楽しめる完成度だと思います。



Super Depath は、Android と Flash に移植されネット上で公開されていて、自由にプレイできます。 Linux 上でプレイしようと思ったのですが、Anbox 経由で Android 版をプレイするのは少し面倒です。 Flash の SWF をダウンロードして、 Flash Player projector でプレイするのが一番楽そうです。

もはや何年越しかわからないくらい久々にプレイしてみても、よくできているなあと感じます。 最近のシューティングは派手なのが多いけど、Super Depth はシンプルなのに奥が深いのが良いですね。



昔プレイした時よりすこし弾速が早い気がする。ジャネーの法則?

2021年12月11日土曜日

九九タイピングを作った

九九タイピング を作りました。

かけ算は早く計算することを目的とした作業なので、 ほとんどの子は 手書きde暗算 や タイプde暗算 のほうが練習に良いです。 ただ集中力がなくて続かない子はそれなりにいます。 また、タイピングも ABC → あいうえお は全員がすぐクリアできますが、 次の 漢字 や フォニックス あたりで苦労する子は多いです。 そんな時に使います。



フォニックスあたりで苦労する要因は以下と勝手に思ってます。
  • 単純に練習量が足りない
  • 題材が少なく飽きやすい
  • ホームポジションがいい加減
  • 小さな子ほど集中力が低く飽きっぽい

あまり良い解決策はないので、ネタを追加するのが一番じゃないかな。 4つとも改善するには九九は良いかもと思って作りました。 フォニックスより文字数が増えるのが難点ですが、 決まったフレーズを早く入力してホームポジションを意識してもらいながら、 飽きやすい1-2年生に多少なりとも題材を増やすことができます。

ネタ用という感じですが、ときにはネタも必要なので、まあいいかな。 九九を丸ごとタイプすると 5key/sec でも段ごとに 20〜25秒くらいは掛かります。 1key/sec が出ない子が遊ぶことが多いと思うので、100〜200秒は掛かることを想定したほうが良さそうです。 そのような子にとって 200秒は厳しい気がしたので、答えだけ入力するようにしてみました。 これなら 5key/sec で 5〜15秒くらいになります。 あいうえおよりほんの少しハードルが高いくらいの難易度になり、 1key/sec が出ない子でも 25〜150秒で終わる計算になるので良い調整になります。

英語で読み上げたら面白かったので、あえて英語の読み上げにしました。

2021年12月1日水曜日

Lubuntu + WineHQ で快適なフリゲ生活

WineHQ が進化してほとんどのゲームが動くようになりました。 インストールがすごく簡単になって色々変わったので、WineHQ 6.0.2 + Lubuntu 20.04 の綺麗なワンパスを残しておきます。 現時点ではほぼ完ぺきな設定になっていると思います。

WineHQ のインストール

まずは公式の説明通りに WineHQ をインストールします。
sudo dpkg --add-architecture i386
wget -nc https://dl.winehq.org/wine-builds/winehq.key
sudo apt-key add winehq.key
sudo add-apt-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ focal main'  # 20.04
sudo apt install --install-recommends winehq-stable
最近の WineHQ は、実のところこれだけでほとんどのゲームは動きます。 Mono, Gecko などのわかりやすいパッケージは、アプリ起動時に足りなければ自動でインストールもしてくれます。 ただそこから多少の設定は必要ですし、最初の設定をミスると動きません。 まずは速攻で以下のおまじないを掛けることが大切です。 おまじないは ~/.bash_profile に設定しておけば、ファイラーからゲームをクリック実行できます。
export MESA_GL_VERSION_OVERRIDE=4.5
もう一つ大事なことは、WineHQ の動作モードです。 WineHQ は 32bit / 64bit の 2つのモードで動きますが、 32bit だと一部のゲームが動かなくなってしまうので、64bit で動かすべきです。 警告がたくさん出ますが、64bit モードで動かせば、32bit にも自動対応してくれます。 なおデフォルトは 64bit なので特に気にする必要はありません。

MESA 関連の設定

先程の設定は公式フォーラムでも紹介されていたテクニックです。 しかし環境変数を export してしまうと OpenGL や MESA を利用したアプリケーション全体が動かなくなる可能性があります。 たとえば Google Chrome などが動かなくなる問題があります。 問題となる場合は、env + alias コマンドを代用して、Wine だけ MESA 4.5 で動くようにしましょう。 先ほどの設定の代わりに、~/.bashrc に以下を設定します。
alias winehq="env MESA_GL_VERSION_OVERRIDE=4.5 wine"
この設定だけだとファイラーからクリック実行できないので関連付けの設定もします。 /usr/share/applications/wine.desktop の Exec フィールドを以下のようにしましょう。
# before
Exec=wine start /unix %f
# after
Exec=env MESA_GL_VERSION_OVERRIDE=4.5 wine start /unix %f
これでファイラーからの安全なクリック実行もできるようになりました。

Winetricks の設定

さて、先ほどゲームは動くと書きましたが、実際には文字が汚くて読みにくいので、以下のパッケージをダウンロードします。
sudo apt install winetricks
winetricks fakejapanese_ipamona  # MSゴシック 代替
昔は、さらに quartz, directmusic, gmdls などの動画・音声周りのインストールが必要でしたが、 今はインストールすると逆に不整合が起きて動かなくなってしまうようです。 特に MP3 周りが危険みたいで、「未実装です。」のエラーが出るようになってしまいます。 外部依存性のあるパッケージだけ追加が必要で、それ以外は設定がいらないように分けられているのは、わかりやすくて良いですね。

MIDI のインストール

さらに MIDI をインストールします。 私は最近ようやく GUI なしで動かせるようになりましたので、その設定を書いておきます。 サウンドフォントは /usr/share/sounds や /usr/share/midi にインストールされます。
# サウンドフォント
sudo apt install freepats
sudo apt install fluid-soundfont-gs fluid-soundfont-gm

# 音声出力
sudo apt install fluidsynth
sudo apt install timidity timidity-daemon 
sudo apt install alsa-utils

# 再生設定1
echo "timidity -iAD -B2,8 -Os1l -s 44100 -x 'soundfont /usr/share/sounds/sf2/FluidR3_GS.sf2 order=1' > / dev/null 2>&1 &" >> ~/.bash_profile
# 再生設定2
echo "fluidsynth -l -s -i -aalsa -o audio.alsa.device=default /usr/share/sounds/sf2/TimGM6mb.sf2 > /dev/null 2>&1 &" >> ~/.bash_profile
source ~/.bash_profile
いろいろサウンドフォントを試してみましたが、fluidsynth の中に入っている TimGM6mb.sf2 が一番綺麗です。 音声出力と再生設定は timidity と fluidsynth のどちらかだけで OK。 そのため、最小構成でインストールするなら fluidsynth と alsa-utils だけで良さそうです。 ~/.bash_profile に MIDI を設定しておけば、デスクトップからダブルクリックでフリゲを起動できます。

再生設定の & は書き忘れるとデスクトップにログインできなくなるので、編集するときはそこだけ要注意してください。 /etc/init.d に登録したり手動起動のほうが安全かも知れません。 インストールに関しては、以上。

最近の動作状況

OS のメモリ使用量の影響もあると思いますが、全体的に Windows よりサクサク動きます。 今や「Wine だと遅いのでは」といった心配は無用で、とても快適です。 ついでなので、以下のページのリスト (日々更新しているのでもう少しチェックしてる) と、有名作品を 10こくらい動作確認してみました。
ゲームの最初をプレイしてみて、動かなかった作品は一つもありませんでした。 ASTLIBRA なんかも普通に動きます。すごい。 ちなみに今回の検証で一番ハマったのは、Wine そのものではなく、Alacritty から起動するとなぜか Wine が動かなかったところ。 今もよくわからないですが、まあ MESA 関連かなあ。

ゲームごとの解決策まとめ

ここまでの説明でほとんどのゲームは動きますが、動かないものもあります。 動かないアプリを動かすための Tips をいくつか載せておきます。
# Win' Wind' Windy
# Trial Windy
# error: 0024:err:gstreamer:mpeg_splitter_init_gst Failed to create mpegaudioparse; are 32-bit GStreamer "good" plugins installed?
sudo apt install gstreamer1.0-plugins-good:i386

また非常にハマりやすい (というかハマった) ポイントを挙げておくと、 巷のゲームの zip ファイルを unzip -O cp932 hoge.zip で展開して遊ぼうとすると、 RPG ツクール 2000 系のゲームではディレクトリの権限がおかしくなることがあります。 RTP をインストールしているはずなのに「ファイルが開けません」と出てきたら、だいたいコレです。 そんな時は以下のコマンドで権限を正しいものに戻しておきましょう。
# RPG_RT.exe があるディレクトリで以下を実行
chmod 755 */

氷水火山SOKOBAN は winetricks を使わないと動きません。 今のところ気になるのはこれくらい。 dsound などを入れれば動きますが、入れてしまうとメイジの転生録などの MP3 を使うゲームが動かなくなります。 MP3 が再生できないと困るアプリのほうが多いので、dsound は入れないほうが良いと思います。 現状では MP3 絡みのところを以下のようなスクリプトを作っておいて切り替えるのが良さそうです。
#!/bin/bash

dir=$(cd $(dirname $0); pwd)
cd "$dir"
env WINEPREFIX=~/.wine-dsound wine RPG_RT.exe

Linux でフリゲの時代はもう来ていますね。

2021年11月15日月曜日

学年別の熟語辞書を作った

学年別の熟語辞書 を作りました。 というか形態素 N-gram からの良い熟語生成を思い付いてしまったので、 以前作った ngram-idioms を一から作り直しました。



以前の生成方法

ngram-idioms では、 形態素 Ngram を前後のつながりを見ながら形態素を複数つなげて熟語らしいものを作り、 テンプレートマッチングでノイズを除去していました。 しかしこの方法は面倒だし、形態素 N-gram の gram 数の影響を受けて、 頻出熟語しか抽出できない問題があります。 今までのような教育用途だと問題ない精度で抽出できるのですが、手作業のノイズ除去が必要だし、 数は少なくなるし賢い生成方法ではないです。

改良案

どこまで真面目に作るかの問題があるのですが、シンプルに作るなら以下の方法で良さそうです。 手作業のメンテが不要なのが良い。
  1. 日本語ウェブコーパス 2010 の 1〜7gram から熟語っぽいものを生成
  2. SudachiDict で熟語判定
  3. SudachiDict と inappropriate-words-ja で地名と人名と禁止語を削除
  4. 品詞判定で不要語を削除
  5. 漢字レベルに合わせて形態素を分類

ポイントは形態素解析辞書の生起コストに違和感があるので、形態素 N-gram のカウントを使うところ。 形態素解析辞書は Neologd でも良いですのが、より信用できる SudachiDict にしました。 以下の記事は熟語生成にもとても参考になります。 なんだ今なら簡単に作れるじゃないかーと思いました。 まあ以前作ったときは SudachiDict の固有名詞フィルターがどれくらい使えるかわからなかったので仕方ない。 やっぱ色々素振りして遊んでないと駄目ですね。

難しいところ=熟語 or 複合名詞

熟語かどうかの判定はとても難しいです。 そのよくわからないところを形態素の 2〜7gram を見て語彙生成した後、SudachiDict にぶん投げて解決しています。 7gram にもなると早口言葉みたいなのがたくさん出てきます。

SudachiDict なら A〜B単位がまさに熟語となります。C単位は微妙なところ。 C単位は「正多角形」のような熟語がほんの少しある一方、「八戸市内」のような熟語か?というものが大量に混ざってきます。 熟語かどうかはすごく判断が難しくて、考え始めるとキリがないです。 そもそも「歴史」も「草木」も熟語じゃなくて複合名詞では?と言われれば「確かにそうかも」となるように、本質的に難しいです。 私は雑なので頑張らず、SudachiDict に丸投げし、B単位までにしました。

SudachiDict は本当によくできた辞書なので、全体的にいい感じに生成されているように見えます。 データを見てもわかるのは、三字熟語まではまあまあ人間的にもわかりやすいですが、 四字熟語以上は熟語なのかしっかり考えないとわからないもの (C単位) のほうが多くなってきます。 ゲームで使えるのは三字熟語まででしょうね。 また基本語彙を押さえておけば三字以上の熟語の大半の意味はわかることも確認できました。

ちなみに昔の実装も面白いので ngram-idioms は残してあります。 ngram-idioms では手動のフィルターを結構作ったので、差分の比較に便利です。 たとえば SudachiDictでは「花王」「山門」「太一」「東横」などを普通名詞にしていますね。 この中では「花王」は固有名詞が正しい気がします。 ただ企業名のフィルターはかなり難しいので、まあ無視で良いかな…。

このへんを頑張ろうとするなら、Mecab をフィルターにすれば、頻度を考慮するので名前として除外されます。 最初は Mecab を併用して頑張ってノイズ除去していましたが、 ビルドに時間が掛かりますし、SudachiDict の進化に期待して最近は特に除去していません。

かなり良いものができたので、以前作ったアプリで関係のあるものは全部更新しておきました。 まずは統計の歪みが完璧に消えて完成度が高くなったと思います。 また難易度調整もしやすくなり、ドリル系のアプリもかなり使いやすくなりました。 なるべく基本語彙から学んでいくことで学習効果も高くなったはず。

学年別の基本語彙一覧を作った

なんとなく知りたかったので、学年別の基本語彙一覧を作りました。 ようするに graded-enja-corpus や mGSL の日本語版です。



作り方

どこまで真面目に作るかの問題があるのですが、シンプルに作るなら以下の方法で良さそうです。 手作業のメンテが不要なのが良い。
  1. 日本語ウェブコーパス 2010 の 1gram を正規化して語彙に変換
  2. 機械的に多少ノイズ除去
  3. SudachiDict と inappropriate-words-ja で地名と人名と禁止語を削除
  4. 品詞判定で不要語を削除
  5. 表層形から原形に直した上で頻度順にソート
  6. 漢字レベルに合わせて形態素を分類

地名や人名のフィルターに SudachiDict を使ってますが、Neologd でも良いかも知れません。 もっとも Neologd は 2gram 以上でないと意味がないので、SudachiDictで 良いんじゃないかな。 処理自体は 2gram にも対応できますが、してません。 2gram を処理すると複合語をさらに抽出できる可能性がありますが、作りたかったのは「語彙一覧」ではなく「基本語彙一覧」です。 別にいらないかなと。 技術的には IPADic では UniDic を使ったほうが厳密ではないか、など色々細かい話はあるけど、まあ無視できるレベルでしょう。 IPADic の粒度のほうが実用上は便利です。

語彙と基本語彙

「語彙」という言葉には曖昧性があり、慣用句を含むこともありますが、 「基本語彙」と書いた時には形態素の原形を指している気がします。 「基本語彙」がわかっていれば「語彙」も、慣用句などの特殊ケースを除いて意味がわかるはずです。 今回作った一覧表は、先生が学年ごとにどれくらい「基本語彙」を覚えるべきか確認したり、 生徒が学年別にサラッと眺めて「基本語彙」を覚えてもらうために作りました。

扱いの難しいもの=接頭辞、接尾辞

この辞書には、固有名詞や複合名詞の他にも、単体では意味の通じない接頭辞や接尾辞は含まれません。 具体例を挙げると「一ヶ月」は複合語、「ヶ月」が接尾辞なので含まれません。 そこをどこまで真面目に含めるかという話はあるのですが、 (1) 接頭辞や接尾時は明らかに実用上ノイズのほうが多く、(2) 後からデータを活用しにくくなるので、削除することにしました。 接尾時や接頭辞は基本語彙じゃないの?と言われると、ぐぬぬ…ですが、別に辞書を作ったほうが平和と思ったので、勘弁。

接頭辞や接尾辞も考慮した辞書を作るには、2gram で複合名詞化すればいいです。 ただ基本語彙ではないように思うので、今回はやってません。 ひらがなはどこまでやっても微妙な出力ですが、こればかりは仕方なさそう。

2021年11月14日日曜日

漢字判定のいろいろな正規表現

漢字判定の正規表現は奥が深いです。 [一-龠] の記述がネット上にたくさんあるのですが、 「々ヵヶ」といった頻出語をサポートしてないことに気付きました。 みんな苦労しているみたい。 たまに必要になるので、自分なりの考えをメモしておきます。

結論はこちら。
[\u4E00-\u9FFF]        # CJK 統合漢字の基本多言語面
[\u4E00-\u9FFF𠮟]      # 常用漢字 (これもありかも)
[\u4E00-\u9FFF々]      # 実用上ここまではサポートしたい
[\u4E00-\u9FFF々ヵヶ]  # +頻出語
[\u4E00-\u9FFF々ヵヶヽヾゝゞ〃仝]  # +くり返し記号など
/[\u3400-\u9FFF\uF900-\uFAFF\u{20000}-\u{37FFF}]/u    # Unicode 15.1 漢字すべて
/[\u3400-\u9FFF\uF900-\uFAFF\u{20000}-\u{37FFF}々]/u  # Unicode 15.1 漢字すべて

漢字の指定

漢字の指定方法は、[一-龠] というものがネット上で多く見受けられ、私も利用していました。 最後の漢字が「龠」つまり U+9FA0 である理由は正直よくわからないのですが、たぶん Unicode 1.1 のときの指定を使っているのでしょう。 「龍」というよく使われる単語が、U+9F8D にあるので、それ以上の範囲削減は不可能です。 現在はさらに拡張されていますし、CJK 統合漢字の基本多言語面に基づく、[\u4E00-\u9FFF] が最も厳密な指定だろうと思います。

ちなみに [\u4E00-\u9FFF] の指定は JIS 第 2 水準までを想定した指定ですが、新常用漢字の「𠮟」を処理できないなどの問題があります。 ではどうするかというと、Unicode プロパティの /\p{scx=Han}/u を使う方法もあります。 ただこれでも「々」は判定できませんし、記号が含まれる致命的な問題があります。 同じことは /\p{scx=Hiragana}/u などにも言えて、Unicodeプロパティは意外と扱いに困ります。

ちょっと前に /[\u3400-\u9FFF\uF900-\uFAFF\u{20000}-\u{2FFFF}]/u という漢字判定もよく見かけました。 これもいい感じではあるのですが、今は CJK統合漢字拡張 H 以降に対応できていません。 そのため第3漢字面もサポートしないといけませんが、U+38000〜U+3AB9FF は甲骨文字がアサインされる予定があります。 甲骨文字も漢字と言えば漢字なのですが…漢字としてサポートするべきかは迷うところです。ひとまずサポートしないほうが良さそうかな。 そのギリギリ手前の U+37FFF までにするか、CJK統合漢字拡張 H の最終文字 U+323AF までにするかは難しいところです。 結局どこまでにするのが良いかは Unicode と CJK統合漢字の進化をよく見ながら決定するしかないのだろうと思います。

Unicode 15.1 (最新) の漢字すべてを想定した時に、現状でたぶん一番楽そうなのは、/[\u3400-\u9FFF\uF900-\uFAFF\u{20000}-\u{37FFF}]/u という漢字判定です。 Unicode フラグ u を付けた上で、\u{} で指定するのがポイント。

参考:

漢字に関連する語の指定

/\p{scx=Han}/u は使えそうで使い物にならないことが多いので、漢字や用例、文字コードに対する知識を深めるのは割と重要そうです。 くり返しを意味する「々」は漢字ではないらしいのですが、日常生活でも頻繁に出現します。 そのためたいていはサポートしないと、色々な不都合が生じます。

また「一ヶ所」のような使い方をする「ヵヶ」もたいてい必須語になります。 ただ「ヵヶ」は助数詞可能な名詞として出現し、必ず複合語として使われる漢字なので、サポートしなくていい場合もありそうです。 「ヵヶ」は Unicocde 的にはカタカナの一部として扱われているので、カタカナ語との重複に注意が必要です。 SudachiDict を見ると「ヶラヶラ」「スヵッ」「ヵッォ」などの謎エントリ以外はカタカナとして使っている用例が見当たりません。 単語としての単位ではカタカナからも除外したほうがよく、プログラミング的には漢字として扱って良いのではないかと思います。 余談ながら、カタカナの正規表現では、「ヵヶ」を除外しないでもいい時は [ァ-ヶ] と指定し、除外したい時は [ァ-ヴ] と指定するのが良さそうです。 /\p{scx=Hiragana}/u や /\p{scx=Katakana}/u はこのへんも扱いにくく、非常に使いにくい指定だったりします。 一番致命的なのは「ー」がひらがな/カタカナ判定されたり、記号が含まれるところですけどね。
くり返し記号は他にも「ヽヾゝゞ〃仝々」というものがあります。 先に述べた「々」もこの一部です。 現代語ではほぼ出現しませんが、「いすゞ」のような特殊例があります。 とはいえこちらは基本的には無視して大丈夫でしょう。 他にも「〆〇〻」といった漢字も、稀に出現はします。 ただ指定も面倒臭いので、これらは無視しても大丈夫でしょう。 ほとんどのケースでは、[\u4E00-\u9FFF々]、真面目にやるなら /[\u3400-\u9FFF\uF900-\uFAFF\u{20000}-\u{37FFF}々]/u で大丈夫じゃないでしょうか。
利用用途に応じて範囲を調整しないといけないのが地味に面倒です。