Pure-math text intelligence engine for Japanese — vocabulary richness, contamination detection, writing habit analysis, character voice fingerprinting
Project description
japhrase
辞書もLLMも使わずに、テキストからフレーズを見つける。
pip install japhrase
何をするツールか
日本語テキストの中から、繰り返し出現するフレーズを統計だけで検出する。MeCab も辞書ファイルも外部 AI も要らない。テキストを入れれば、そこに何度も現れているフレーズが出てくる——それが既知語であろうと、辞書に載っていない新語・造語・専門用語であろうと関係ない。
N-gram による頻度抽出
テキストを「連続する N 文字」の断片(N-gram)に分解し、出現頻度を数える。
たとえば生成 AI に関する記事を入力すると:
from japhrase import PhraseExtracter
extractor = PhraseExtracter(min_count=2, max_length=10, min_length=2)
df = extractor.extract(sentences)
seqchar freq
ている 12 ← 意味のないフレーズも拾ってしまう
生成AI 10
大規模言語モデル 4
である 4 ← これも意味がない
「生成AI」「大規模言語モデル」は見つかった。しかし「ている」「である」のような、どんなテキストにも現れる意味のないフレーズも一緒に出てくる。N-gram の頻度だけでは、意味のある結合と偶然の並びを区別できない。
PMI による洗練
ここで PMI(自己相互情報量)を使う。PMI は「2つの要素が偶然一緒に現れる確率」と「実際に一緒に現れた頻度」の比を測る。
extractor = PhraseExtracter(min_count=2, use_pmi=True)
df = extractor.extract(sentences)
seqchar freq pmi
生成AI 10 10.0 ← PMI が高い = 意味のある結合
大規模言語モデル 4 10.0 ← 偶然ではない
である 4 7.2 ← PMI が低い = ありふれた並び
PMI が高いフレーズは、構成要素が偶然隣り合っただけでは説明できないほど頻繁に共起している。「生成」と「AI」がこれほど一緒に出現するのは、それが1つの意味単位だからだ。一方「である」はどんな文脈にも現れるので PMI が低くなる。
PMI を有効にすることで、意味的に結合したフレーズだけを上位に浮かび上がらせることができる。
分岐エントロピーによる境界検出
さらに分岐エントロピーを加えると、フレーズの自然な切れ目を特定できる。「あるフレーズの次にどんな文字が来るか」の多様性を測り、多様性が急に上がる位置をフレーズの境界とみなす。
extractor = PhraseExtracter(min_count=3, use_pmi=True, use_branching_entropy=True)
df = extractor.extract(sentences)
N-gram が「繰り返されているもの」を広く拾い、PMI が「意味のある結合」だけを残し、分岐エントロピーが「切れ目」を正確にする。この3層が japhrase のコアである。
プリセット
テキスト種別ごとに最適化されたパラメータセット(Optuna による実験的最適化済み)。
extractor = PhraseExtracter.preset('sns') # SNS/Twitter(短文・高頻度)
extractor = PhraseExtracter.preset('news') # ニュース(専門用語重視)
extractor = PhraseExtracter.preset('novel') # 小説(繰り返し表現・長め)
extractor = PhraseExtracter.preset('report') # 論文/レポート(定型・学術用語)
ファイルからの読み込み
df = PhraseExtracter.from_file("input.txt")
# エンコーディング自動検出(UTF-8 / Shift-JIS / EUC-JP)
コアの上に積み上げた分析機能
フレーズ抽出エンジンを土台として、以下の統計分析機能を提供する。
テキスト類似度
複数テキスト間の類似度を計算し、コピペ検出や重複分析を行う。
from japhrase import SimilarityAnalyzer
analyzer = SimilarityAnalyzer(method='jaccard')
matrix = analyzer.compare_files(["doc1.txt", "doc2.txt", "doc3.txt"])
pairs = analyzer.find_similar_pairs(matrix, threshold=0.7)
# → [('doc1.txt', 'doc2.txt', 0.82)] ← 82% 類似
Jaccard(N-gram の重なり)、Levenshtein(編集距離)、コサイン(TF-IDF)の3手法。method='auto' で自動選択。
分布比較(2テキスト間の語彙の違い)
2つのテキストの語彙分布がどれだけ違うかを定量化する。「テキスト A にだけ多い語」「テキスト B にだけ多い語」をキーネススコア付きで抽出できる。
from japhrase import DistributionComparator
from collections import Counter
comp = DistributionComparator()
freq_a = Counter({'騎士': 10, '剣': 8, '王城': 5})
freq_b = Counter({'研究': 12, '実験': 9, 'データ': 7})
result = comp.compare(freq_a, freq_b)
JS距離: 1.0000 (0 = 同一の語彙、1 = 完全に別の語彙)
Aにだけ多い語: 騎士, 剣, 王城 ← 「テキストAらしさ」
Bにだけ多い語: 研究, 実験, データ ← 「テキストBらしさ」
JS距離(Jensen-Shannon Divergence)は対称的で有界(0〜1)。対数尤度比(G²)はカイ二乗より疎データに強い。Effect Size(Log Ratio)は「有意かどうか」ではなく「どれだけ違うか」を測る。
コロケーション分析(語の結びつきの強さ)
フレーズを構成する語同士の結びつきを6つの異なる角度から測る。
from japhrase import CollocationScorer
scorer = CollocationScorer()
cs = scorer.score_phrase('生成AI', 45, text)
「生成AI」:
PMI = 3.6 ← 意味的に結合している(偶然ではない)
t-score = 6.1 ← 高頻度で安定した結合
Log-Dice = 13.9 ← コーパスサイズに依存しない結合度
| 指標 | 何に強いか |
|---|---|
| PMI | レアだが意味のある結合を発見する(低頻度に敏感) |
| t-score | 高頻度で安定した結合を発見する(PMI の逆) |
| Log-Dice | コーパスの大きさに影響されない(最も安定) |
| MI³ | PMI の低頻度バイアスを数学的に補正する |
| Delta-P | 方向性がある結合を測る(A→B と B→A は非対称) |
共起語分析
特定のキーワードの周辺に、統計的に特異な頻度で出現する語を抽出する。
from japhrase import CooccurrenceAnalyzer
analyzer = CooccurrenceAnalyzer(window_size=50)
df = analyzer.analyze(text, "機械学習", top_n=10)
# → 機械学習の周辺50字以内に特異的に出現する語のランキング
キャラクター分析(あるキャラの周辺に頻出する語彙)、製品の評判分析(「画面」の周辺に「綺麗」があるか)等に使える。
時系列分析(複数テキスト間の推移)
複数のテキストを時系列として並べ、語彙がどう変化しているかを追跡する。
from japhrase import TemporalAnalyzer
ta = TemporalAnalyzer()
result = ta.analyze_series([ch1, ch2, ch3, ch4, ch5], labels=["1章","2章","3章","4章","5章"])
語彙飽和度: 0.62 (後半で新語が減っている = 語彙が枯れ始めている)
MATTRトレンド: -0.008 (語彙の多様性が徐々に低下)
バースト検出: 特定の語が突然増えた区間を自動で見つける。伏線の使用状況やテーマの変化を追跡できる。
語彙多様性(計量言語学)
テキストの語彙がどれだけ豊かかを、7つの統計指標で定量化する。
from japhrase import StylometryAnalyzer
stylo = StylometryAnalyzer()
adv = stylo.analyze_advanced_diversity(text)
豊かな文章 → Hapax比 0.97 / Simpson 0.9996 → 「語彙が非常に豊か」
単調な文章 → Hapax比 0.26 / Simpson 0.9676 → 「標準的」
| 指標 | 何を測るか | 読み方 |
|---|---|---|
| Hapax比 | 一度しか使わなかった語の割合 | 高い = 同じ語に頼っていない |
| MATTR | テキスト長に依存しない語彙多様性 | 高い = 長文でも語彙が豊か |
| Simpson's D | 同じ語に2回当たる確率の逆数 | 1に近い = 多様 |
| Brunet's W / Honoré's R | 長文で崩壊しない多様性指標 | 長編小説の比較に使える |
| Heaps' Law (β) | 読み進めるほど新語がどれだけ出るか | 高い = 最後まで新語が出続ける |
テキスト複雑度・情報密度
テキストの「難しさ」「密度」「冗長さ」を複数の角度から測る。
from japhrase import ComplexityAnalyzer
cx = ComplexityAnalyzer()
result = cx.analyze(text)
豊かな文章 → 圧縮率 0.71 / 情報率 0.98 ← 各文が新しい情報を提供
繰り返し → 圧縮率 0.36 / 情報率 0.43 ← 同じことの言い直し
| 指標 | 何を測るか | 読み方 |
|---|---|---|
| 圧縮率 | zlib で圧縮したサイズ比 | 低い = 同じパターンの繰り返しが多い |
| 情報率 | 各文が提供する新情報の割合 | 低い = 前の文と同じことを言っている |
| 語彙密度 | 内容語 / 全語の比率 | 低い = 機能語(助詞等)が多く冗長 |
| パープレキシティ | N-gram の予測困難度 | 高い = 多様で予測しにくい文章 |
テキスト品質
| 機能 | 説明 | 使い方 |
|---|---|---|
| TextVariantDetector | 表記ゆれ検出 | サーバー/サーバ、出来る/できる を発見 |
| WritingHabitDetector | 書き癖検出 | 高頻度×低PMI = 無意識の繰り返しを発見 |
| Summarizer | 統計的要約 | LLM不要・ハルシネーションなしでテキスト圧縮 |
汚染検出
テキストの破損(文字化け・コピペ重複・句読点の揺れ等)を8軸で検出する。
from japhrase.contamination import scan, quick_check
quick_check(text) # → True(汚染あり)/ False(クリーン)
profile = scan(text)
print(profile.explain())
⚠️ 汚染スコア: 16/100
■ エンコーディング (55/100, 1件)
L2: mojibakeパターン: '’'
💡 文字化け箇所を正しい文字に置換してください。
■ 構造 (39/100, 1件)
L3: 開き括弧「が閉じていない
💡 括弧の対応を確認してください。
複数テキストの一括チェックやテキスト間比較もできる:
from japhrase.contamination import batch_scan, compare
batch_scan({"1章": t1, "2章": t2, "3章": t3}).contaminated_keys # → ['2章']
compare(text_a, text_b).report() # → 比較レポート
その他
- 執筆ワークフロー: 公開前品質ゲート、話数間推移、キャラ文体指紋、A〜E健康診断(
japhrase.applied) - NMF文書ベクトル化 / ストリーミング処理 / パラメータ自動最適化 / 自動インサイト生成
- 出力形式: CSV、JSON、Excel、HTML レポート
インストール
pip install japhrase # コア(numpy, pandas, scipy)
pip install japhrase[similarity] # + sklearn, Levenshtein
pip install japhrase[viz] # + matplotlib, seaborn
pip install japhrase[all] # 全部入り
Python 3.8+
使い方を調べる
CLI
japhrase --help # コマンド一覧
japhrase extract --help # フレーズ抽出の引数とオプション
japhrase stats --help # 統計出力の形式指定
japhrase check --help # 文書品質チェック
japhrase detect-habits --help # 書き癖検出
Python
全クラス・全関数に docstring がある。help() で引数・戻り値・使用例が出る。
# フレーズ抽出
from japhrase import PhraseExtracter
help(PhraseExtracter) # クラス全体
help(PhraseExtracter.extract) # 個別メソッド
help(PhraseExtracter.preset) # プリセットの使い方
# 統計エンジン
from japhrase import DistributionComparator, CollocationScorer
from japhrase import StylometryAnalyzer, ComplexityAnalyzer, TemporalAnalyzer
help(DistributionComparator) # 2テキスト間の分布比較
help(CollocationScorer) # 語の結びつきの強さ(6指標)
help(StylometryAnalyzer) # 語彙多様性(7指標)
help(ComplexityAnalyzer) # テキスト複雑度
help(TemporalAnalyzer) # 時系列分析
# 汚染検出
from japhrase.contamination import scan, quick_check, compare, batch_scan
help(scan) # 8軸汚染スキャン
help(quick_check) # True/False だけ返す最小API
# 執筆ワークフロー
from japhrase.applied import PreflightChecker, EPDashboard, PartHealthReport
help(PreflightChecker) # 公開前品質ゲート
help(EPDashboard) # 話数間推移ダッシュボード
help(PartHealthReport) # A〜E 健康診断
デモ(例文入り・結果付き)
全機能を内蔵例文で実行し、分析結果と次のステップを表示する。Python を起動して2行:
import japhrase
japhrase.run_demo()
出力(抜粋):
╔══════════════════════════════════════════════════════════╗
║ japhrase デモンストレーション ║
║ 全 7 機能を順に実行します ║
╚══════════════════════════════════════════════════════════╝
============================================================
フレーズ抽出 — PhraseExtracter
============================================================
テキストから、辞書を使わずに頻出フレーズを統計で見つけます。
【入力テキスト(10文 × 5 = 50文)】
ChatGPTの登場により生成AIが注目を集めている。
生成AIはテキストだけでなく画像生成にも使われる。
大規模言語モデルは生成AIの中核技術である。
...(他 7 文)× 5回繰り返し
【結果】
「大規模言語モデル」 — 10回出現
次のステップ:
help(PhraseExtracter) # 全パラメータの説明
============================================================
語彙多様性 — StylometryAnalyzer
============================================================
【豊かな文章】
Hapax比: 0.976 / Simpson: 0.9996 / MATTR: 1.000
→ 語彙が非常に豊か(高度に多様)
【単調な文章】
Hapax比: 0.263 / Simpson: 0.9676 / MATTR: 0.721
→ 標準的な語彙多様性
============================================================
汚染検出 — scan()
============================================================
【入力(汚染あり)】
正常な文章。
’ここに文字化け。
「閉じない台詞
【結果】
汚染スコア: 18/100 ⚠️ 汚染あり
エンコーディング: 55/100 (1件)
L2: mojibakeパターン: '’'
💡 文字化け箇所を正しい文字に置換してください。
...(他4機能のデモも同様に実行されます)
各クラス個別にデモもできる:
from japhrase import PhraseExtracter, StylometryAnalyzer, ComplexityAnalyzer
from japhrase import DistributionComparator, CollocationScorer
PhraseExtracter.demo() # フレーズ抽出のデモ
StylometryAnalyzer.demo() # 語彙多様性のデモ
ComplexityAnalyzer.demo() # テキスト複雑度のデモ
DistributionComparator.demo() # 分布比較のデモ
CollocationScorer.demo() # コロケーション分析のデモ
サンプルスクリプト
python examples/quickstart.py # 全機能の動作確認(コピペで動く)
使用ガイド
ファイルから抽出
from japhrase import PhraseExtracter
df = PhraseExtracter.from_file("input.txt") # テキスト
df = PhraseExtracter.from_file("data.csv", column="text") # CSV(列指定)
df = PhraseExtracter.from_file("input.txt", min_count=10, max_length=20) # パラメータ指定
パラメータ
extractor = PhraseExtracter(
min_count=6, # 最小出現回数(小さいと計算時間が増える)
max_length=16, # フレーズの最大文字数
min_length=4, # フレーズの最小文字数
threshold_originality=0.5, # 類似フレーズ除去の閾値(0.0〜1.0)
use_pmi=True, # PMI で意味的結合を評価
use_branching_entropy=True, # 分岐エントロピーで境界を検出
knowns=["既知語1"], # 優先的に抽出したい既知語
verbose=1, # 進捗表示(0:非表示, 1:表示)
)
結果のエクスポート
extractor.export_csv(df, "output.csv") # CSV(Excel対応BOM付きUTF-8)
extractor.export_json(df, "output.json") # JSON
extractor.export_excel(df, "output.xlsx") # Excel(要 pip install japhrase[excel])
対応ファイル形式
テキスト(.txt)、CSV(.csv)、TSV(.tsv)。エンコーディングは自動検出(UTF-8 / Shift-JIS / EUC-JP)。
トラブルシューティング
# メモリ不足 → バッチサイズを小さくする
extractor = PhraseExtracter(size_sentence=1000)
# 処理が遅い → min_count を上げる / max_length を下げる
extractor = PhraseExtracter(min_count=20, max_length=10)
# 結果が多すぎる → 類似度閾値を上げる
extractor = PhraseExtracter(threshold_originality=0.8)
テスト
pytest # 290件以上
pytest --cov=japhrase # カバレッジ付き
English Summary
japhrase finds phrases in Japanese text without a dictionary or LLM. It scans for recurring N-gram patterns, then uses PMI (pointwise mutual information) to separate meaningful collocations from noise — "生成AI" ranks high because its components co-occur far more than chance predicts, while "である" ranks low. Branching entropy further refines phrase boundaries. On top of this core: text similarity, distribution comparison (JSD, G², keyness), collocation scoring (6 metrics), vocabulary richness (7 metrics), text complexity, and more. Pure math, no external AI, 290+ tests, numpy/scipy only.
ライセンス
MIT License — Takeshi SHIMIZU
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file japhrase-0.3.6.tar.gz.
File metadata
- Download URL: japhrase-0.3.6.tar.gz
- Upload date:
- Size: 806.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b7bf9092794c3945b157e4f41b865be9e2b03d9ee5a231c03eeb09cc400a7d5
|
|
| MD5 |
38c066fc6834ec62ba6509375a1a3ae7
|
|
| BLAKE2b-256 |
00174ff4b4e39300365ff013e59121f00269a749143cb80e128dafc1d69d96a0
|
File details
Details for the file japhrase-0.3.6-py3-none-any.whl.
File metadata
- Download URL: japhrase-0.3.6-py3-none-any.whl
- Upload date:
- Size: 289.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a47754785095cee034aecbf0e27c74ad4edc15ec97b98f8d6f44790e52d58908
|
|
| MD5 |
8c642289b89afebe23b1f237dce48836
|
|
| BLAKE2b-256 |
80ab08dd8e240db29d867622951c0e5b6d73452a0d2b478a2428980d75d8db14
|