phoneme-entropy 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- phoneme_entropy-0.1.0/.github/workflows/ci.yml +44 -0
- phoneme_entropy-0.1.0/.github/workflows/release.yml +86 -0
- phoneme_entropy-0.1.0/.gitignore +45 -0
- phoneme_entropy-0.1.0/CITATION.cff +21 -0
- phoneme_entropy-0.1.0/LICENSE +25 -0
- phoneme_entropy-0.1.0/PKG-INFO +111 -0
- phoneme_entropy-0.1.0/README.md +75 -0
- phoneme_entropy-0.1.0/THIRD_PARTY_LICENSES +37 -0
- phoneme_entropy-0.1.0/examples/quickstart.py +79 -0
- phoneme_entropy-0.1.0/examples/usage_example.ipynb +186 -0
- phoneme_entropy-0.1.0/hf/dataset_card.md +72 -0
- phoneme_entropy-0.1.0/pyproject.toml +78 -0
- phoneme_entropy-0.1.0/src/phoneme_entropy/__init__.py +90 -0
- phoneme_entropy-0.1.0/src/phoneme_entropy/_data/celex_en_sample.csv +1201 -0
- phoneme_entropy-0.1.0/src/phoneme_entropy/data.py +128 -0
- phoneme_entropy-0.1.0/src/phoneme_entropy/dirichlet.py +396 -0
- phoneme_entropy-0.1.0/src/phoneme_entropy/estimators.py +485 -0
- phoneme_entropy-0.1.0/src/phoneme_entropy/maxent.py +87 -0
- phoneme_entropy-0.1.0/src/phoneme_entropy/segmentation.py +277 -0
- phoneme_entropy-0.1.0/tests/conftest.py +15 -0
- phoneme_entropy-0.1.0/tests/test_data.py +20 -0
- phoneme_entropy-0.1.0/tests/test_dirichlet.py +59 -0
- phoneme_entropy-0.1.0/tests/test_estimators.py +46 -0
- phoneme_entropy-0.1.0/tests/test_maxent.py +43 -0
- phoneme_entropy-0.1.0/tests/test_segmentation.py +62 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install (with dev extras)
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
pip install -e ".[dev]"
|
|
28
|
+
|
|
29
|
+
- name: Run tests
|
|
30
|
+
run: pytest -q
|
|
31
|
+
|
|
32
|
+
build:
|
|
33
|
+
# Confirm the sdist/wheel build and pass metadata checks on every push.
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
- uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.12"
|
|
40
|
+
- name: Build & check distribution
|
|
41
|
+
run: |
|
|
42
|
+
python -m pip install --upgrade pip build twine
|
|
43
|
+
python -m build
|
|
44
|
+
twine check dist/*
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Two-stage publishing, both via PyPI Trusted Publishing (OIDC — no stored tokens):
|
|
4
|
+
#
|
|
5
|
+
# * push a tag v* -> build + publish to TestPyPI (release candidate)
|
|
6
|
+
# * publish a GitHub Release -> build + publish to PyPI (promote to real PyPI)
|
|
7
|
+
# * manual dispatch -> build + publish to TestPyPI
|
|
8
|
+
#
|
|
9
|
+
# Typical flow:
|
|
10
|
+
# git tag v0.1.0 && git push origin v0.1.0 # -> lands on TestPyPI, smoke-test it
|
|
11
|
+
# # then, on GitHub, cut a Release for tag v0.1.0 -> lands on PyPI
|
|
12
|
+
#
|
|
13
|
+
# One-time setup (per index) at https://<index>/manage/account/publishing/ :
|
|
14
|
+
# add a pending publisher -> owner: suchirsalhan, repo: phoneme,
|
|
15
|
+
# workflow: release.yml, environment: testpypi (on TestPyPI) / pypi (on PyPI).
|
|
16
|
+
# Also create matching GitHub environments (repo Settings -> Environments):
|
|
17
|
+
# `testpypi` and `pypi`.
|
|
18
|
+
#
|
|
19
|
+
# Prefer API tokens? Remove the environment/permissions blocks, add repo secrets
|
|
20
|
+
# TEST_PYPI_API_TOKEN / PYPI_API_TOKEN, and set `password:` on the publish steps.
|
|
21
|
+
|
|
22
|
+
on:
|
|
23
|
+
push:
|
|
24
|
+
tags: ["v*"]
|
|
25
|
+
release:
|
|
26
|
+
types: [published]
|
|
27
|
+
workflow_dispatch:
|
|
28
|
+
|
|
29
|
+
jobs:
|
|
30
|
+
build:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
- uses: actions/setup-python@v5
|
|
35
|
+
with:
|
|
36
|
+
python-version: "3.12"
|
|
37
|
+
- name: Build sdist + wheel
|
|
38
|
+
run: |
|
|
39
|
+
python -m pip install --upgrade pip build twine
|
|
40
|
+
python -m build
|
|
41
|
+
twine check dist/*
|
|
42
|
+
- name: Upload dist artifact
|
|
43
|
+
uses: actions/upload-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
name: dist
|
|
46
|
+
path: dist/
|
|
47
|
+
|
|
48
|
+
publish-testpypi:
|
|
49
|
+
# Release candidates: tag pushes and manual runs go to TestPyPI.
|
|
50
|
+
needs: build
|
|
51
|
+
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
environment: testpypi
|
|
54
|
+
permissions:
|
|
55
|
+
id-token: write # required for Trusted Publishing (OIDC)
|
|
56
|
+
steps:
|
|
57
|
+
- name: Download dist artifact
|
|
58
|
+
uses: actions/download-artifact@v4
|
|
59
|
+
with:
|
|
60
|
+
name: dist
|
|
61
|
+
path: dist/
|
|
62
|
+
- name: Publish to TestPyPI
|
|
63
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
64
|
+
with:
|
|
65
|
+
repository-url: https://test.pypi.org/legacy/
|
|
66
|
+
# password: ${{ secrets.TEST_PYPI_API_TOKEN }} # token auth alternative
|
|
67
|
+
|
|
68
|
+
publish-pypi:
|
|
69
|
+
# Promotion: publishing a GitHub Release ships to real PyPI.
|
|
70
|
+
needs: build
|
|
71
|
+
if: github.event_name == 'release'
|
|
72
|
+
runs-on: ubuntu-latest
|
|
73
|
+
environment: pypi
|
|
74
|
+
permissions:
|
|
75
|
+
id-token: write # required for Trusted Publishing (OIDC)
|
|
76
|
+
steps:
|
|
77
|
+
- name: Download dist artifact
|
|
78
|
+
uses: actions/download-artifact@v4
|
|
79
|
+
with:
|
|
80
|
+
name: dist
|
|
81
|
+
path: dist/
|
|
82
|
+
- name: Publish to PyPI
|
|
83
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
84
|
+
# repository-url defaults to https://upload.pypi.org/legacy/ (real PyPI)
|
|
85
|
+
# with:
|
|
86
|
+
# password: ${{ secrets.PYPI_API_TOKEN }} # token auth alternative
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# --- Local, developer-only instructions (never commit) ---
|
|
2
|
+
LOCAL_INSTRUCTIONS.md
|
|
3
|
+
|
|
4
|
+
# --- Python ---
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*$py.class
|
|
8
|
+
*.egg-info/
|
|
9
|
+
.eggs/
|
|
10
|
+
build/
|
|
11
|
+
dist/
|
|
12
|
+
wheels/
|
|
13
|
+
*.egg
|
|
14
|
+
.installed.cfg
|
|
15
|
+
|
|
16
|
+
# --- Virtual environments ---
|
|
17
|
+
.venv/
|
|
18
|
+
venv/
|
|
19
|
+
env/
|
|
20
|
+
ENV/
|
|
21
|
+
.python-version
|
|
22
|
+
|
|
23
|
+
# --- Testing / coverage ---
|
|
24
|
+
.pytest_cache/
|
|
25
|
+
.coverage
|
|
26
|
+
.coverage.*
|
|
27
|
+
htmlcov/
|
|
28
|
+
.tox/
|
|
29
|
+
.ruff_cache/
|
|
30
|
+
.mypy_cache/
|
|
31
|
+
|
|
32
|
+
# --- Jupyter ---
|
|
33
|
+
.ipynb_checkpoints/
|
|
34
|
+
|
|
35
|
+
# --- Hugging Face / data caches (do not commit private data) ---
|
|
36
|
+
.cache/
|
|
37
|
+
*.arrow
|
|
38
|
+
hf_cache/
|
|
39
|
+
data_cache/
|
|
40
|
+
|
|
41
|
+
# --- OS / editor ---
|
|
42
|
+
.DS_Store
|
|
43
|
+
.idea/
|
|
44
|
+
.vscode/
|
|
45
|
+
*.swp
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it as below, along with the upstream entropy-estimators project."
|
|
3
|
+
title: "phoneme-entropy: phoneme-level entropy, informativity, and maximum-entropy tools"
|
|
4
|
+
authors:
|
|
5
|
+
- family-names: "Moscoso del Prado Martín"
|
|
6
|
+
given-names: Fermín
|
|
7
|
+
- family-names: Salhan
|
|
8
|
+
given-names: Suchir
|
|
9
|
+
type: software
|
|
10
|
+
license: MIT
|
|
11
|
+
repository-code: "https://github.com/suchirsalhan/phoneme"
|
|
12
|
+
version: "0.1.0"
|
|
13
|
+
references:
|
|
14
|
+
- type: software
|
|
15
|
+
title: "entropy-estimators"
|
|
16
|
+
authors:
|
|
17
|
+
- family-names: "Moscoso del Prado Martín"
|
|
18
|
+
given-names: "Fermín"
|
|
19
|
+
repository-code: "https://github.com/fermosc24/entropy-estimators"
|
|
20
|
+
license: MIT
|
|
21
|
+
year: 2025
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fermín Moscoso del Prado Martín & Suchir Salhan
|
|
4
|
+
|
|
5
|
+
Portions of this library extend and depend on the `entropy-estimators` project
|
|
6
|
+
(https://github.com/fermosc24/entropy-estimators), Copyright (c) 2025 Fermín
|
|
7
|
+
Moscoso del Prado Martín, also distributed under the MIT License.
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: phoneme-entropy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Phoneme-level entropy, informativity, and maximum-entropy tools, extending entropy-estimators.
|
|
5
|
+
Project-URL: Homepage, https://github.com/suchirsalhan/phoneme
|
|
6
|
+
Project-URL: Repository, https://github.com/suchirsalhan/phoneme
|
|
7
|
+
Project-URL: Upstream (entropy-estimators), https://github.com/fermosc24/entropy-estimators
|
|
8
|
+
Author: Fermín Moscoso del Prado Martín
|
|
9
|
+
Author-email: Suchir Salhan <suchirsalhan@gmail.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: dirichlet,entropy,information theory,maximum entropy,phonemes,phonology,psycholinguistics
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Requires-Dist: mpmath>=1.2
|
|
20
|
+
Requires-Dist: numpy>=1.21
|
|
21
|
+
Requires-Dist: pandas>=1.3
|
|
22
|
+
Requires-Dist: scipy>=1.7
|
|
23
|
+
Provides-Extra: data
|
|
24
|
+
Requires-Dist: datasets>=2.14; extra == 'data'
|
|
25
|
+
Requires-Dist: huggingface-hub>=0.16; extra == 'data'
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: jupyter; extra == 'dev'
|
|
28
|
+
Requires-Dist: matplotlib>=3.4; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.1; extra == 'dev'
|
|
31
|
+
Requires-Dist: seaborn>=0.11; extra == 'dev'
|
|
32
|
+
Provides-Extra: plot
|
|
33
|
+
Requires-Dist: matplotlib>=3.4; extra == 'plot'
|
|
34
|
+
Requires-Dist: seaborn>=0.11; extra == 'plot'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# phoneme-entropy
|
|
38
|
+
|
|
39
|
+
Phoneme-level entropy, informativity, and maximum-entropy tools. A standalone
|
|
40
|
+
library that bundles the entropy estimators from
|
|
41
|
+
[`entropy-estimators`](https://github.com/fermosc24/entropy-estimators) (MIT,
|
|
42
|
+
© 2025 fermosc24) and adds phonology-oriented analysis utilities.
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install phoneme-entropy
|
|
48
|
+
# or, from source:
|
|
49
|
+
pip install .
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Optional extras: `pip install "phoneme-entropy[plot]"` (matplotlib/seaborn for
|
|
53
|
+
`plot_ranks`), `pip install "phoneme-entropy[data]"` (Hugging Face `datasets`).
|
|
54
|
+
|
|
55
|
+
## Usage
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from collections import defaultdict
|
|
59
|
+
import numpy as np, pandas as pd
|
|
60
|
+
from phoneme_entropy import (
|
|
61
|
+
Entropy, estimate_alpha_entropy,
|
|
62
|
+
segment_informativity, phoneme_prefix_entropy,
|
|
63
|
+
compute_maxent_from_matrix,
|
|
64
|
+
)
|
|
65
|
+
from phoneme_entropy.data import load_sample
|
|
66
|
+
|
|
67
|
+
sample = load_sample() # bundled CELEX sample (Word = space-separated phonemes)
|
|
68
|
+
|
|
69
|
+
# Per-phoneme next-phoneme surprisal and prefix entropy
|
|
70
|
+
surprisal = segment_informativity(sample["Word"])
|
|
71
|
+
prefix_H = phoneme_prefix_entropy(sample["Word"])
|
|
72
|
+
|
|
73
|
+
# Symmetric-Dirichlet concentration implied by an entropy estimate
|
|
74
|
+
phon = defaultdict(int)
|
|
75
|
+
for w in sample["Word"]:
|
|
76
|
+
for p in w.split(): phon[p] += 1
|
|
77
|
+
alpha, se = estimate_alpha_entropy(list(phon.values()), n_boot=0)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
See [`examples/quickstart.py`](examples/quickstart.py) and
|
|
81
|
+
[`examples/usage_example.ipynb`](examples/usage_example.ipynb) for a full
|
|
82
|
+
walkthrough.
|
|
83
|
+
|
|
84
|
+
### Data
|
|
85
|
+
|
|
86
|
+
A small CELEX-derived sample ships with the package (`load_sample()`). The full
|
|
87
|
+
sample is mirrored as a **gated, permissions-only** Hugging Face dataset
|
|
88
|
+
[`suchirsalhan/celex-en-phoneme-sample`](https://huggingface.co/datasets/suchirsalhan/celex-en-phoneme-sample)
|
|
89
|
+
— access is granted to holders of a valid CELEX/LDC license
|
|
90
|
+
([LDC96L14](https://catalog.ldc.upenn.edu/docs/LDC96L14/celex.readme.html)):
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from phoneme_entropy.data import load_hf_dataset
|
|
94
|
+
ds = load_hf_dataset(split="train") # after your access request is approved
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## API
|
|
98
|
+
|
|
99
|
+
| Import | Purpose |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| `Entropy`, `FreqShrink`, `JS_KullbackLeibler`, `JS_JensenShannon` | Entropy / divergence estimators (MLE, JSE, Chao-Shen, CWJ, NBRS, NSB), vendored. |
|
|
102
|
+
| `estimate_alpha_entropy`, `dirichlet_entropy`, `plot_ranks` | Symmetric-Dirichlet inference and rank/probability curves. |
|
|
103
|
+
| `segment_informativity`, `phoneme_prefix_entropy` | Segmental informativity over phoneme strings. |
|
|
104
|
+
| `compute_maxent_from_matrix` | Maximum-entropy fit to feature expectations. |
|
|
105
|
+
| `phoneme_entropy.data.load_sample`, `load_hf_dataset` | Data loaders. |
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
MIT — see [`LICENSE`](LICENSE). Bundles third-party code; see
|
|
110
|
+
[`THIRD_PARTY_LICENSES`](THIRD_PARTY_LICENSES). Please cite via
|
|
111
|
+
[`CITATION.cff`](CITATION.cff).
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# phoneme-entropy
|
|
2
|
+
|
|
3
|
+
Phoneme-level entropy, informativity, and maximum-entropy tools. A standalone
|
|
4
|
+
library that bundles the entropy estimators from
|
|
5
|
+
[`entropy-estimators`](https://github.com/fermosc24/entropy-estimators) (MIT,
|
|
6
|
+
© 2025 fermosc24) and adds phonology-oriented analysis utilities.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install phoneme-entropy
|
|
12
|
+
# or, from source:
|
|
13
|
+
pip install .
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Optional extras: `pip install "phoneme-entropy[plot]"` (matplotlib/seaborn for
|
|
17
|
+
`plot_ranks`), `pip install "phoneme-entropy[data]"` (Hugging Face `datasets`).
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from collections import defaultdict
|
|
23
|
+
import numpy as np, pandas as pd
|
|
24
|
+
from phoneme_entropy import (
|
|
25
|
+
Entropy, estimate_alpha_entropy,
|
|
26
|
+
segment_informativity, phoneme_prefix_entropy,
|
|
27
|
+
compute_maxent_from_matrix,
|
|
28
|
+
)
|
|
29
|
+
from phoneme_entropy.data import load_sample
|
|
30
|
+
|
|
31
|
+
sample = load_sample() # bundled CELEX sample (Word = space-separated phonemes)
|
|
32
|
+
|
|
33
|
+
# Per-phoneme next-phoneme surprisal and prefix entropy
|
|
34
|
+
surprisal = segment_informativity(sample["Word"])
|
|
35
|
+
prefix_H = phoneme_prefix_entropy(sample["Word"])
|
|
36
|
+
|
|
37
|
+
# Symmetric-Dirichlet concentration implied by an entropy estimate
|
|
38
|
+
phon = defaultdict(int)
|
|
39
|
+
for w in sample["Word"]:
|
|
40
|
+
for p in w.split(): phon[p] += 1
|
|
41
|
+
alpha, se = estimate_alpha_entropy(list(phon.values()), n_boot=0)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
See [`examples/quickstart.py`](examples/quickstart.py) and
|
|
45
|
+
[`examples/usage_example.ipynb`](examples/usage_example.ipynb) for a full
|
|
46
|
+
walkthrough.
|
|
47
|
+
|
|
48
|
+
### Data
|
|
49
|
+
|
|
50
|
+
A small CELEX-derived sample ships with the package (`load_sample()`). The full
|
|
51
|
+
sample is mirrored as a **gated, permissions-only** Hugging Face dataset
|
|
52
|
+
[`suchirsalhan/celex-en-phoneme-sample`](https://huggingface.co/datasets/suchirsalhan/celex-en-phoneme-sample)
|
|
53
|
+
— access is granted to holders of a valid CELEX/LDC license
|
|
54
|
+
([LDC96L14](https://catalog.ldc.upenn.edu/docs/LDC96L14/celex.readme.html)):
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from phoneme_entropy.data import load_hf_dataset
|
|
58
|
+
ds = load_hf_dataset(split="train") # after your access request is approved
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## API
|
|
62
|
+
|
|
63
|
+
| Import | Purpose |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| `Entropy`, `FreqShrink`, `JS_KullbackLeibler`, `JS_JensenShannon` | Entropy / divergence estimators (MLE, JSE, Chao-Shen, CWJ, NBRS, NSB), vendored. |
|
|
66
|
+
| `estimate_alpha_entropy`, `dirichlet_entropy`, `plot_ranks` | Symmetric-Dirichlet inference and rank/probability curves. |
|
|
67
|
+
| `segment_informativity`, `phoneme_prefix_entropy` | Segmental informativity over phoneme strings. |
|
|
68
|
+
| `compute_maxent_from_matrix` | Maximum-entropy fit to feature expectations. |
|
|
69
|
+
| `phoneme_entropy.data.load_sample`, `load_hf_dataset` | Data loaders. |
|
|
70
|
+
|
|
71
|
+
## License
|
|
72
|
+
|
|
73
|
+
MIT — see [`LICENSE`](LICENSE). Bundles third-party code; see
|
|
74
|
+
[`THIRD_PARTY_LICENSES`](THIRD_PARTY_LICENSES). Please cite via
|
|
75
|
+
[`CITATION.cff`](CITATION.cff).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
This distribution bundles third-party code. Their licenses are reproduced below.
|
|
2
|
+
|
|
3
|
+
===============================================================================
|
|
4
|
+
entropy-estimators — https://github.com/fermosc24/entropy-estimators
|
|
5
|
+
Vendored into: src/phoneme_entropy/estimators.py
|
|
6
|
+
===============================================================================
|
|
7
|
+
|
|
8
|
+
MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2025 fermosc24
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
|
|
30
|
+
-------------------------------------------------------------------------------
|
|
31
|
+
The NSB estimator portion of the vendored file is itself derived from:
|
|
32
|
+
* nsb_entropy.py by Sungho Hong (OIST, 2011), updated to Python 3 by
|
|
33
|
+
Charlie Strauss (LANL, 2019), based on Mathematica functions by
|
|
34
|
+
Christian Mendl. See http://nsb-entropy.sourceforge.net and
|
|
35
|
+
Nemenman, Shafee & Bialek, "Entropy and Inference, Revisited",
|
|
36
|
+
arXiv:physics/0108025.
|
|
37
|
+
-------------------------------------------------------------------------------
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""End-to-end quickstart for phoneme-entropy.
|
|
3
|
+
|
|
4
|
+
Reproduces the workflow from the original tutorial notebook using the packaged
|
|
5
|
+
API and the bundled CELEX sample. Run it after installing the package:
|
|
6
|
+
|
|
7
|
+
pip install -e ".[dev]"
|
|
8
|
+
python examples/quickstart.py
|
|
9
|
+
|
|
10
|
+
It prints intermediate results and (if matplotlib is available) draws the
|
|
11
|
+
predicted-vs-observed rank plot and the max-ent fit.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from collections import defaultdict
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
import pandas as pd
|
|
18
|
+
|
|
19
|
+
from phoneme_entropy import (
|
|
20
|
+
compute_maxent_from_matrix,
|
|
21
|
+
estimate_alpha_entropy,
|
|
22
|
+
phoneme_prefix_entropy,
|
|
23
|
+
segment_informativity,
|
|
24
|
+
)
|
|
25
|
+
from phoneme_entropy.data import load_sample
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def main() -> None:
|
|
29
|
+
# 1. Load the bundled CELEX English sample. "Word" holds space-separated
|
|
30
|
+
# phonemes; "Frequency" holds corpus frequencies.
|
|
31
|
+
sample = load_sample()
|
|
32
|
+
print(f"Loaded {len(sample)} words. Columns: {list(sample.columns)}")
|
|
33
|
+
|
|
34
|
+
# 2. Phoneme unigram frequencies.
|
|
35
|
+
phonfreqs = defaultdict(int)
|
|
36
|
+
for word in sample["Word"]:
|
|
37
|
+
for phoneme in word.split():
|
|
38
|
+
phonfreqs[phoneme] += 1
|
|
39
|
+
phonfreqs = pd.DataFrame(phonfreqs.items(), columns=["Phoneme", "Frequency"])
|
|
40
|
+
print(f"Inventory size (V): {len(phonfreqs)}")
|
|
41
|
+
|
|
42
|
+
# 3. Symmetric-Dirichlet concentration implied by the phoneme distribution.
|
|
43
|
+
# n_boot=0 -> deterministic point estimate (no bootstrap standard error).
|
|
44
|
+
alpha, se = estimate_alpha_entropy(phonfreqs["Frequency"], n_boot=0)
|
|
45
|
+
print(f"Estimated Dirichlet alpha: {alpha:.4f}")
|
|
46
|
+
|
|
47
|
+
# 4. Per-phoneme surprisal (next-phoneme informativity) and prefix entropy.
|
|
48
|
+
surprisal = segment_informativity(sample["Word"])
|
|
49
|
+
prefix_entropy = phoneme_prefix_entropy(sample["Word"])
|
|
50
|
+
|
|
51
|
+
# 5. Merge, form frequency-weighted target expectations, fit max-ent.
|
|
52
|
+
merged = phonfreqs.merge(surprisal, on="Phoneme").merge(prefix_entropy, on="Phoneme")
|
|
53
|
+
p = merged["Frequency"] / merged["Frequency"].sum()
|
|
54
|
+
targets = np.array(
|
|
55
|
+
[np.sum(p * merged["Surprisal"]), np.sum(p * merged["Entropy"])]
|
|
56
|
+
)
|
|
57
|
+
F = merged[["Surprisal", "Entropy"]].to_numpy()
|
|
58
|
+
probs, lambdas = compute_maxent_from_matrix(F, targets)
|
|
59
|
+
print(f"Max-ent Lagrange multipliers (lambda): {lambdas}")
|
|
60
|
+
|
|
61
|
+
# 6. Optional plots (only if matplotlib is installed).
|
|
62
|
+
try:
|
|
63
|
+
import matplotlib.pyplot as plt
|
|
64
|
+
|
|
65
|
+
from phoneme_entropy.dirichlet import plot_ranks
|
|
66
|
+
|
|
67
|
+
plot_ranks(phonfreqs["Frequency"], types="Reversed", loglog=False)
|
|
68
|
+
plt.figure()
|
|
69
|
+
plt.scatter(np.log(p), np.log(probs))
|
|
70
|
+
plt.xlabel("(log) observed probability")
|
|
71
|
+
plt.ylabel("(log) predicted probability")
|
|
72
|
+
plt.tight_layout()
|
|
73
|
+
plt.show()
|
|
74
|
+
except ImportError:
|
|
75
|
+
print("matplotlib not installed; skipping plots. Install with '.[plot]'.")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
if __name__ == "__main__":
|
|
79
|
+
main()
|