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 も要らない。テキストを入れれば、そこに何度も現れているフレーズが出てくる — 既知語でも新語でも造語でも関係ない。
最初の一歩
from japhrase import PhraseExtractor
text = """ChatGPTの登場により生成AIが注目を集めている。
生成AIはテキストだけでなく画像生成にも使われる。
大規模言語モデルは生成AIの中核技術である。
生成AIの倫理的課題について議論が活発化している。
企業における生成AIの導入事例が増加している。
生成AIの品質向上が求められている。
生成AIと人間の協調が進んでいる。
生成AIの応用範囲は広がり続けている。
生成AIによるコスト削減が期待されている。
生成AIの安全性が議論されている。""" * 3
pe = PhraseExtractor(verbose=0)
df = pe.extract(text)
print(df[["seqchar", "freq"]].head())
seqchar freq
0 生成AI 30.0
2 ChatGPTの登場により生成AI 3.0
12 生成AIはテキストだけでなく画像生 3.0
20 大規模言語モデルは生成AIの中核技 3.0
25 生成AIの倫理的課題について議論が 3.0
テキストを渡すだけ。引数もファイルも不要。「生成AI」が30回出現 — 辞書なしで見つかった。
デモ(2行で全機能体験)
import japhrase
japhrase.run_demo()
内蔵の例文で、フレーズ抽出・語彙多様性・テキスト複雑度・分布比較・コロケーション分析・汚染検出・品質チェックが順に実行される。何も用意しなくていい。
個別のデモもある:
from japhrase import PhraseExtractor
PhraseExtractor.demo()
仕組み — N-gram + PMI + 分岐エントロピー
N-gram(頻度で拾う)
テキストを「連続する N 文字」に分解し、出現頻度を数える。
from japhrase import PhraseExtractor
text = "ChatGPTの登場により生成AIが注目を集めている。生成AIはテキスト生成にも使われる。大規模言語モデルは生成AIの中核技術である。生成AIの導入事例が増加している。生成AIの品質向上が求められている。生成AIの安全性が議論されている。" * 5
pe = PhraseExtractor(verbose=0)
df = pe.extract(text)
print(df[["seqchar", "freq"]].head())
「生成AI」は見つかる。しかし「ている」「である」のような、どこにでも現れる無意味なフレーズも一緒に出てくる。
PMI(意味のある結合だけ残す)
PMI(自己相互情報量)は「偶然一緒に現れる確率」と「実際の共起頻度」の比を測る。
from japhrase import PhraseExtractor
text = "ChatGPTの登場により生成AIが注目を集めている。生成AIはテキスト生成にも使われる。大規模言語モデルは生成AIの中核技術である。生成AIの導入事例が増加している。生成AIの品質向上が求められている。生成AIの安全性が議論されている。" * 5
pe = PhraseExtractor(use_pmi=True, verbose=0)
df = pe.extract(text)
print(df[["seqchar", "freq"]].head())
「生成」と「AI」がこれほど一緒に出現するのは偶然ではない — PMI が高い。「である」は PMI が低い。
分岐エントロピー(切れ目を見つける)
「あるフレーズの次にどんな文字が来るか」の多様性を測り、急に上がる位置をフレーズの境界とする。
from japhrase import PhraseExtractor
text = "ChatGPTの登場により生成AIが注目を集めている。生成AIはテキスト生成にも使われる。大規模言語モデルは生成AIの中核技術である。生成AIの導入事例が増加している。生成AIの品質向上が求められている。生成AIの安全性が議論されている。" * 5
pe = PhraseExtractor(use_pmi=True, use_branching_entropy=True, verbose=0)
df = pe.extract(text)
print(df[["seqchar", "freq"]].head())
N-gram が広く拾い → PMI が意味のある結合だけ残し → 分岐エントロピーが切れ目を正確にする。この3層が japhrase のコア。
プリセット
テキスト種別ごとに最適化済みのパラメータセット。
from japhrase import PhraseExtractor
pe = PhraseExtractor.preset('sns') # SNS/Twitter
pe = PhraseExtractor.preset('news') # ニュース
pe = PhraseExtractor.preset('novel') # 小説
pe = PhraseExtractor.preset('report') # 論文/レポート
パラメータの自動最適化
プリセットで足りないとき、あなたのテキストに合わせて自動チューニングできる。
from japhrase import PhraseExtractor
text = "生成AIが注目を集めている。生成AIはテキスト生成にも使われる。大規模言語モデルは生成AIの中核技術である。" * 10
pe = PhraseExtractor(verbose=0)
# フラグ1個でチューニング付き抽出
df = pe.extract(text, auto_tune=True)
# チューニング結果を確認
pe.show_params()
# 保存・復元
pe.save_params("my_params.json")
pe2 = PhraseExtractor.load_params("my_params.json")
auto_tune=True を付けるだけ。Optunaがあればベイズ最適化、なければヒューリスティック推定。最適化されたパラメータは JSON に保存・復元できる。
分析機能
フレーズ抽出エンジンの上に積み上げた統計分析。すべて pip install japhrase だけで使える。
語彙の豊かさを測る
from japhrase import StylometryAnalyzer
stylo = StylometryAnalyzer()
rich = stylo.analyze_advanced_diversity("朝靄の中を歩いていると、足元で小さな花が揺れた。名前は知らない。淡い紫色の花弁が露を含んで光っている。")
poor = stylo.analyze_advanced_diversity("男は歩いた。男は止まった。男はまた歩いた。男は見た。男は聞いた。")
print(f"豊かな文: Hapax比={rich['hapax_ratio']:.2f}")
print(f"単調な文: Hapax比={poor['hapax_ratio']:.2f}")
| 指標 | 何を測るか |
|---|---|
| Hapax比 | 一度しか使わなかった語の割合(高い = 多様) |
| MATTR | テキスト長に依存しない語彙多様性 |
| Simpson's D | 同じ語に2回当たる確率の逆数(1に近い = 多様) |
| Brunet's W / Honoré's R | 長文でも崩壊しない多様性指標 |
2つのテキストの語彙分布を比較
from japhrase import DistributionComparator
from collections import Counter
comp = DistributionComparator()
result = comp.compare(
Counter({"騎士": 10, "剣": 8, "王城": 5}),
Counter({"研究": 12, "実験": 9, "データ": 7}),
)
print(f"JS距離: {result.jsd:.4f} (0=同一, 1=完全に別)")
語の結びつきの強さを測る
from japhrase import CollocationScorer
text = "生成AIが注目されている。生成AIの技術が進んでいる。" * 50
scorer = CollocationScorer()
cs = scorer.score_phrase("生成AI", 45, text)
print(f"PMI={cs.pmi:.1f} t-score={cs.t_score:.1f} Log-Dice={cs.log_dice:.1f}")
| 指標 | 何に強いか |
|---|---|
| PMI | レアだが意味のある結合(低頻度に敏感) |
| t-score | 高頻度で安定した結合 |
| Log-Dice | コーパスサイズに依存しない(最も安定) |
テキストの複雑度を測る
from japhrase import ComplexityAnalyzer
cx = ComplexityAnalyzer()
r1 = cx.analyze("朝靄の中を歩いていると、足元で小さな花が揺れた。名前は知らない。淡い紫色の花弁が露を含んで光っている。")
r2 = cx.analyze("男は歩いた。" * 20)
print(f"多様な文章: 圧縮率={r1['compression_ratio']:.3f}")
print(f"繰り返し: 圧縮率={r2['compression_ratio']:.3f}")
圧縮率が低い = 同じパターンの繰り返しが多い。
テキストの汚染を検出
文字化け・コピペ重複・括弧の閉じ忘れ等を8軸で検出する。
from japhrase.contamination import scan
profile = scan("正常な文章。\n’文字化け。\n「閉じない台詞")
print(f"汚染スコア: {profile.overall}/100")
print(profile.explain())
一括チェック:
from japhrase.contamination import batch_scan
result = batch_scan({
"1章": "正常なテキスト。問題のない文章が続きます。特に異常はありません。",
"2章": "’文字化け。「閉じない括弧。重複文。重複文。重複文。重複文。重複文。",
"3章": "正常なテキスト。こちらも問題ありません。普通の文章です。",
})
for key, p in result.profiles.items():
print(f"{key}: スコア={p.overall}/100")
テキスト類似度
from japhrase import SimilarityAnalyzer
texts = [
"生成AIが注目を集めている。大規模言語モデルの進化が著しい。",
"生成AIの技術が注目されている。言語モデルが急速に進化している。",
"今日は天気がよい。散歩に出かけた。公園で花を見た。",
]
analyzer = SimilarityAnalyzer(method='jaccard')
matrix = analyzer.compare_texts(texts)
print(matrix)
時系列で語彙の変化を追跡
from japhrase import TemporalAnalyzer
ch1 = "騎士が剣を抜いた。王城の門が開いた。騎士は走った。剣が光った。" * 10
ch2 = "研究室でデータを確認した。実験の結果を記録した。論文を読んだ。" * 10
ch3 = "騎士は剣を収めた。王城に平和が戻った。研究が進んだ。" * 10
ta = TemporalAnalyzer()
result = ta.analyze_series([ch1, ch2, ch3], labels=["1章", "2章", "3章"])
print(f"語彙飽和度: {result['vocab_saturation']:.2f}")
その他
| 機能 | 説明 |
|---|---|
| TextVariantDetector | 表記ゆれ検出(サーバー/サーバ、出来る/できる) |
| WritingHabitDetector | 書き癖検出(高頻度×低PMI = 無意識の繰り返し) |
| CooccurrenceAnalyzer | 共起語分析(キーワード周辺の特異語) |
| Summarizer | 統計的要約(LLM不要・ハルシネーションなし) |
| japhrase.applied | 公開前品質ゲート・話数間推移・キャラ文体指紋 |
ファイルから読み込み
from japhrase import PhraseExtractor
df = PhraseExtractor.from_file("input.txt") # エンコーディング自動検出
df = PhraseExtractor.from_file("data.csv", column="text") # CSV(列指定)
パラメータ一覧
from japhrase import PhraseExtractor
pe = PhraseExtractor(
min_count=6, # 最小出現回数
max_length=16, # フレーズの最大文字数
min_length=4, # フレーズの最小文字数
threshold_originality=0.5, # 類似フレーズ除去の閾値
use_pmi=True, # PMI で意味的結合を評価
use_branching_entropy=True, # 分岐エントロピーで境界検出
knowns=["既知語1"], # 優先的に抽出したい語
verbose=1, # 進捗表示(0:非表示)
)
CLI
japhrase --help # コマンド一覧
japhrase extract --help # フレーズ抽出
japhrase check --help # 文書品質チェック
japhrase detect-habits --help # 書き癖検出
help() で調べる
from japhrase import PhraseExtractor
help(PhraseExtractor.extract)
from japhrase.contamination import scan
help(scan)
テスト
pytest
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, temporal analysis, contamination detection, and adaptive parameter tuning. Pure math, no external AI, 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.12.tar.gz.
File metadata
- Download URL: japhrase-0.3.12.tar.gz
- Upload date:
- Size: 332.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5087db4a75e2f06e97d0c9a35e6894eaa58f7e0f1bf8495ef29fa699e88d478
|
|
| MD5 |
4eea1b5577f916d294b1dbeceab3eefe
|
|
| BLAKE2b-256 |
0ed19700256f32ba1bf468c6edf517dfc1bf0bfdda86cf3f54aa786ef3ed8906
|
File details
Details for the file japhrase-0.3.12-py3-none-any.whl.
File metadata
- Download URL: japhrase-0.3.12-py3-none-any.whl
- Upload date:
- Size: 293.8 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 |
d75cd617ef6d8402813339e3bd6ca333be7d47667e3a0aa109bf2aa058d0ea84
|
|
| MD5 |
1cfcd28e25218014e4d5c9ca1e29dbe4
|
|
| BLAKE2b-256 |
1e7d22d104acc93688538d96e1ac3568df091927f1b77bf8175200abbd70c2fb
|