pyannote-metrics 4.0.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.
Files changed (54) hide show
  1. pyannote_metrics-4.0.0/.github/workflows/doc.yml +33 -0
  2. pyannote_metrics-4.0.0/.github/workflows/release.yml +125 -0
  3. pyannote_metrics-4.0.0/.github/workflows/test.yml +36 -0
  4. pyannote_metrics-4.0.0/.gitignore +58 -0
  5. pyannote_metrics-4.0.0/.python-version +1 -0
  6. pyannote_metrics-4.0.0/ISSUE_TEMPLATE.md +40 -0
  7. pyannote_metrics-4.0.0/LICENSE +21 -0
  8. pyannote_metrics-4.0.0/PKG-INFO +61 -0
  9. pyannote_metrics-4.0.0/README.md +33 -0
  10. pyannote_metrics-4.0.0/doc/Makefile +20 -0
  11. pyannote_metrics-4.0.0/doc/pyannote-metrics.pdf +0 -0
  12. pyannote_metrics-4.0.0/doc/source/api.rst +8 -0
  13. pyannote_metrics-4.0.0/doc/source/basics.rst +186 -0
  14. pyannote_metrics-4.0.0/doc/source/changelog.rst +306 -0
  15. pyannote_metrics-4.0.0/doc/source/cli.rst +59 -0
  16. pyannote_metrics-4.0.0/doc/source/conf.py +208 -0
  17. pyannote_metrics-4.0.0/doc/source/images/diagnostic.png +0 -0
  18. pyannote_metrics-4.0.0/doc/source/images/pipeline.png +0 -0
  19. pyannote_metrics-4.0.0/doc/source/images/segmentation.png +0 -0
  20. pyannote_metrics-4.0.0/doc/source/index.rst +65 -0
  21. pyannote_metrics-4.0.0/doc/source/pyplots/tutorial.py +29 -0
  22. pyannote_metrics-4.0.0/doc/source/reference.rst +184 -0
  23. pyannote_metrics-4.0.0/doc/source/tutorial.rst +44 -0
  24. pyannote_metrics-4.0.0/notebooks/.ipynb_checkpoints/Better purity metric-checkpoint.ipynb +6 -0
  25. pyannote_metrics-4.0.0/notebooks/.ipynb_checkpoints/Untitled-checkpoint.ipynb +132 -0
  26. pyannote_metrics-4.0.0/notebooks/Better purity metric.ipynb +436 -0
  27. pyannote_metrics-4.0.0/notebooks/Untitled.ipynb +133 -0
  28. pyannote_metrics-4.0.0/notebooks/index.ipynb +36 -0
  29. pyannote_metrics-4.0.0/notebooks/pyannote.metrics.diarization.ipynb +336 -0
  30. pyannote_metrics-4.0.0/notebooks/pyannote.metrics.identification.ipynb +253 -0
  31. pyannote_metrics-4.0.0/pyproject.toml +59 -0
  32. pyannote_metrics-4.0.0/setup.py +84 -0
  33. pyannote_metrics-4.0.0/src/pyannote/metrics/__init__.py +34 -0
  34. pyannote_metrics-4.0.0/src/pyannote/metrics/base.py +419 -0
  35. pyannote_metrics-4.0.0/src/pyannote/metrics/binary_classification.py +239 -0
  36. pyannote_metrics-4.0.0/src/pyannote/metrics/cli.py +713 -0
  37. pyannote_metrics-4.0.0/src/pyannote/metrics/detection.py +608 -0
  38. pyannote_metrics-4.0.0/src/pyannote/metrics/diarization.py +648 -0
  39. pyannote_metrics-4.0.0/src/pyannote/metrics/errors/__init__.py +29 -0
  40. pyannote_metrics-4.0.0/src/pyannote/metrics/errors/identification.py +332 -0
  41. pyannote_metrics-4.0.0/src/pyannote/metrics/errors/segmentation.py +109 -0
  42. pyannote_metrics-4.0.0/src/pyannote/metrics/identification.py +274 -0
  43. pyannote_metrics-4.0.0/src/pyannote/metrics/matcher.py +192 -0
  44. pyannote_metrics-4.0.0/src/pyannote/metrics/plot/__init__.py +27 -0
  45. pyannote_metrics-4.0.0/src/pyannote/metrics/plot/binary_classification.py +205 -0
  46. pyannote_metrics-4.0.0/src/pyannote/metrics/py.typed +0 -0
  47. pyannote_metrics-4.0.0/src/pyannote/metrics/segmentation.py +404 -0
  48. pyannote_metrics-4.0.0/src/pyannote/metrics/spotting.py +334 -0
  49. pyannote_metrics-4.0.0/src/pyannote/metrics/types.py +8 -0
  50. pyannote_metrics-4.0.0/src/pyannote/metrics/utils.py +225 -0
  51. pyannote_metrics-4.0.0/tests/test_detection.py +147 -0
  52. pyannote_metrics-4.0.0/tests/test_diarization.py +115 -0
  53. pyannote_metrics-4.0.0/tests/test_identification.py +73 -0
  54. pyannote_metrics-4.0.0/uv.lock +1750 -0
@@ -0,0 +1,33 @@
1
+ name: Documentation
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+
7
+ jobs:
8
+ build-and-deploy:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ with:
14
+ persist-credentials: false
15
+ fetch-depth: 0
16
+ - name: Install uv
17
+ uses: astral-sh/setup-uv@v5
18
+ with:
19
+ enable-cache: true
20
+ cache-dependency-glob: uv.lock
21
+
22
+ - name: Install the project
23
+ run: uv sync --extra doc
24
+
25
+ - name: Build documentation
26
+ run: |
27
+ make --directory=doc html
28
+ touch ./doc/build/html/.nojekyll
29
+ - name: Deploy
30
+ uses: peaceiris/actions-gh-pages@v3
31
+ with:
32
+ github_token: ${{ secrets.GITHUB_TOKEN }}
33
+ publish_dir: ./doc/build/html
@@ -0,0 +1,125 @@
1
+ name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI
2
+
3
+ on: push
4
+
5
+ jobs:
6
+ build:
7
+ name: Build distribution 📦
8
+ runs-on: ubuntu-latest
9
+
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ with:
13
+ persist-credentials: false
14
+ fetch-depth: 0
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v5
17
+ with:
18
+ enable-cache: true
19
+ cache-dependency-glob: uv.lock
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version-file: ".python-version"
24
+ - name: Build
25
+ run: uv build
26
+ - name: Store the distribution packages
27
+ uses: actions/upload-artifact@v4
28
+ with:
29
+ name: python-package-distributions
30
+ path: dist/
31
+
32
+ publish-to-pypi:
33
+ name: >-
34
+ Publish Python 🐍 distribution 📦 to PyPI
35
+ if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
36
+ needs:
37
+ - build
38
+ runs-on: ubuntu-latest
39
+ environment:
40
+ name: pypi
41
+ permissions:
42
+ id-token: write
43
+ steps:
44
+ - name: Download all the dists
45
+ uses: actions/download-artifact@v4
46
+ with:
47
+ name: python-package-distributions
48
+ path: dist/
49
+ - name: Install uv
50
+ uses: astral-sh/setup-uv@v5
51
+ with:
52
+ enable-cache: true
53
+ cache-dependency-glob: uv.lock
54
+ - name: Publish distribution 📦 to PyPI
55
+ run: uv publish --trusted-publishing always --publish-url https://upload.pypi.org/legacy/
56
+
57
+
58
+ github-release:
59
+ name: >-
60
+ Sign the Python 🐍 distribution 📦 with Sigstore
61
+ and upload them to GitHub Release
62
+ needs:
63
+ - publish-to-pypi
64
+ runs-on: ubuntu-latest
65
+
66
+ permissions:
67
+ contents: write # IMPORTANT: mandatory for making GitHub Releases
68
+ id-token: write # IMPORTANT: mandatory for sigstore
69
+
70
+ steps:
71
+ - name: Download all the dists
72
+ uses: actions/download-artifact@v4
73
+ with:
74
+ name: python-package-distributions
75
+ path: dist/
76
+ - name: Sign the dists with Sigstore
77
+ uses: sigstore/gh-action-sigstore-python@v3.0.0
78
+ with:
79
+ inputs: >-
80
+ ./dist/*.tar.gz
81
+ ./dist/*.whl
82
+ - name: Create GitHub Release
83
+ env:
84
+ GITHUB_TOKEN: ${{ github.token }}
85
+ run: >-
86
+ gh release create
87
+ "$GITHUB_REF_NAME"
88
+ --repo "$GITHUB_REPOSITORY"
89
+ --notes ""
90
+ - name: Upload artifact signatures to GitHub Release
91
+ env:
92
+ GITHUB_TOKEN: ${{ github.token }}
93
+ # Upload to GitHub Release using the `gh` CLI.
94
+ # `dist/` contains the built packages, and the
95
+ # sigstore-produced signatures and certificates.
96
+ run: >-
97
+ gh release upload
98
+ "$GITHUB_REF_NAME" dist/**
99
+ --repo "$GITHUB_REPOSITORY"
100
+
101
+ # publish-to-testpypi:
102
+ # name: Publish Python 🐍 distribution 📦 to TestPyPI
103
+ # needs:
104
+ # - build
105
+ # runs-on: ubuntu-latest
106
+ #
107
+ # environment:
108
+ # name: testpypi
109
+ #
110
+ # permissions:
111
+ # id-token: write # IMPORTANT: mandatory for trusted publishing
112
+ #
113
+ # steps:
114
+ # - name: Download all the dists
115
+ # uses: actions/download-artifact@v4
116
+ # with:
117
+ # name: python-package-distributions
118
+ # path: dist/
119
+ # - name: Install uv
120
+ # uses: astral-sh/setup-uv@v5
121
+ # with:
122
+ # enable-cache: true
123
+ # cache-dependency-glob: uv.lock
124
+ # - name: Publish distribution 📦 to PyPI
125
+ # run: uv publish --trusted-publishing always --publish-url https://test.pypi.org/legacy/
@@ -0,0 +1,36 @@
1
+ name: Test
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - develop
7
+ push:
8
+ branches:
9
+ - develop
10
+ - master
11
+ - release/*
12
+
13
+
14
+ jobs:
15
+ test:
16
+ name: Test
17
+ runs-on: ubuntu-latest
18
+ strategy:
19
+ matrix:
20
+ python-version:
21
+ - "3.10"
22
+ - "3.11"
23
+ - "3.12"
24
+ env:
25
+ UV_PYTHON: ${{ matrix.python-version }}
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+
29
+ - name: Install uv
30
+ uses: astral-sh/setup-uv@v5
31
+
32
+ - name: Install the project
33
+ run: uv sync --extra test
34
+
35
+ - name: Run tests
36
+ run: uv run pytest tests
@@ -0,0 +1,58 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+
5
+ # C extensions
6
+ *.so
7
+
8
+ # Distribution / packaging
9
+ MANIFEST
10
+ .Python
11
+ env/
12
+ bin/
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ *.egg-info/
23
+ .installed.cfg
24
+ *.egg
25
+
26
+ # Installer logs
27
+ pip-log.txt
28
+ pip-delete-this-directory.txt
29
+
30
+ # Unit test / coverage reports
31
+ htmlcov/
32
+ .tox/
33
+ .coverage
34
+ .cache
35
+ nosetests.xml
36
+ coverage.xml
37
+
38
+ # Translations
39
+ *.mo
40
+
41
+ # Mr Developer
42
+ .mr.developer.cfg
43
+ .project
44
+ .pydevproject
45
+
46
+ # Rope
47
+ .ropeproject
48
+
49
+ # Django stuff:
50
+ *.log
51
+ *.pot
52
+
53
+ # Sphinx documentation
54
+ docs/_build/
55
+
56
+ doc/.ipynb_checkpoints
57
+
58
+ .mypy_cache/
@@ -0,0 +1 @@
1
+ 3.10
@@ -0,0 +1,40 @@
1
+
2
+ #### Description
3
+ <!-- Example: DiarizationPurity does not return the expected value -->
4
+
5
+ #### Steps/Code to Reproduce
6
+ <!--
7
+ Example:
8
+
9
+ ```
10
+ from pyannote.core import Annotation, Segment
11
+ reference = Annotation()
12
+ reference[Segment(0, 10)] = 'A'
13
+ reference[Segment(12, 20)] = 'B'
14
+ reference[Segment(24, 27)] = 'A'
15
+ reference[Segment(30, 40)] = 'C'
16
+ hypothesis = Annotation()
17
+ hypothesis[Segment(2, 13)] = 'a'
18
+ hypothesis[Segment(13, 14)] = 'd'
19
+ hypothesis[Segment(14, 20)] = 'b'
20
+ hypothesis[Segment(22, 38)] = 'c'
21
+ hypothesis[Segment(38, 40)] = 'd'
22
+
23
+ from pyannote.metrics.diarization import DiarizationPurity
24
+ purity = DiarizationPurity()
25
+ print "Purity = {0:.3f}".format(purity(reference, hypothesis))
26
+ ```
27
+ If the code is too long, feel free to put it in a public gist and link
28
+ it in the issue: https://gist.github.com
29
+ -->
30
+
31
+ #### Expected Results
32
+ <!-- Example: Output should be "Purity = 0.667". Please paste or describe the expected results.-->
33
+
34
+ #### Actual Results
35
+ <!-- Please paste or specifically describe the actual output or traceback. -->
36
+
37
+ #### Versions
38
+ <!-- Please paste the output of `pip freeze | grep pyannote` below -->
39
+
40
+ <!-- Thanks for contributing! -->
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 CNRS (Hervé BREDIN - http://herve.niderb.fr)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,61 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyannote-metrics
3
+ Version: 4.0.0
4
+ Summary: A toolkit for reproducible evaluation, diagnostic, and error analysis of speaker diarization systems
5
+ Author-email: Hervé BREDIN <herve@pyannote.ai>
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: numpy>=2.2.2
9
+ Requires-Dist: pandas>=2.2.3
10
+ Requires-Dist: pyannote-core>=6.0.0
11
+ Requires-Dist: pyannote-database>=6.0.0
12
+ Requires-Dist: scikit-learn>=1.6.1
13
+ Requires-Dist: scipy>=1.15.1
14
+ Provides-Extra: cli
15
+ Requires-Dist: docopt>=0.6.2; extra == 'cli'
16
+ Requires-Dist: sympy>=1.13.3; extra == 'cli'
17
+ Requires-Dist: tabulate>=0.9.0; extra == 'cli'
18
+ Provides-Extra: doc
19
+ Requires-Dist: ipython>=8.32.0; extra == 'doc'
20
+ Requires-Dist: matplotlib>=3.10.0; extra == 'doc'
21
+ Requires-Dist: sphinx-rtd-theme>=3.0.2; extra == 'doc'
22
+ Requires-Dist: sphinx>=8.1.3; extra == 'doc'
23
+ Provides-Extra: plot
24
+ Requires-Dist: matplotlib>=3.10.0; extra == 'plot'
25
+ Provides-Extra: test
26
+ Requires-Dist: pytest>=8.3.4; extra == 'test'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # pyannote.metrics
30
+
31
+ > a toolkit for reproducible evaluation, diagnostic, and error analysis of speaker diarization systems
32
+
33
+ An overview of `pyannote.metrics` is available as an [InterSpeech 2017 paper](docs/pyannote-metrics.pdf): it is recommended to read it first, to quickly get an idea whether this tool is for you.
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ $ pip install pyannote.metrics
39
+ ```
40
+
41
+ ## Documentation
42
+
43
+ The documentation is available at [http://pyannote.github.io/pyannote-metrics](http://pyannote.github.io/pyannote-metrics).
44
+
45
+ Sample notebooks are available [here](http://nbviewer.ipython.org/github/pyannote/pyannote-metrics/blob/master/notebooks/index.ipynb).
46
+
47
+ ## Citation
48
+
49
+ If you use `pyannote.metrics` in your research, please use the following citation:
50
+
51
+ ```bibtex
52
+ @inproceedings{pyannote.metrics,
53
+ author = {Herv\'e Bredin},
54
+ title = {{pyannote.metrics: a toolkit for reproducible evaluation, diagnostic, and error analysis of speaker diarization systems}},
55
+ booktitle = {{Interspeech 2017, 18th Annual Conference of the International Speech Communication Association}},
56
+ year = {2017},
57
+ month = {August},
58
+ address = {Stockholm, Sweden},
59
+ url = {http://pyannote.github.io/pyannote-metrics},
60
+ }
61
+ ```
@@ -0,0 +1,33 @@
1
+ # pyannote.metrics
2
+
3
+ > a toolkit for reproducible evaluation, diagnostic, and error analysis of speaker diarization systems
4
+
5
+ An overview of `pyannote.metrics` is available as an [InterSpeech 2017 paper](docs/pyannote-metrics.pdf): it is recommended to read it first, to quickly get an idea whether this tool is for you.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ $ pip install pyannote.metrics
11
+ ```
12
+
13
+ ## Documentation
14
+
15
+ The documentation is available at [http://pyannote.github.io/pyannote-metrics](http://pyannote.github.io/pyannote-metrics).
16
+
17
+ Sample notebooks are available [here](http://nbviewer.ipython.org/github/pyannote/pyannote-metrics/blob/master/notebooks/index.ipynb).
18
+
19
+ ## Citation
20
+
21
+ If you use `pyannote.metrics` in your research, please use the following citation:
22
+
23
+ ```bibtex
24
+ @inproceedings{pyannote.metrics,
25
+ author = {Herv\'e Bredin},
26
+ title = {{pyannote.metrics: a toolkit for reproducible evaluation, diagnostic, and error analysis of speaker diarization systems}},
27
+ booktitle = {{Interspeech 2017, 18th Annual Conference of the International Speech Communication Association}},
28
+ year = {2017},
29
+ month = {August},
30
+ address = {Stockholm, Sweden},
31
+ url = {http://pyannote.github.io/pyannote-metrics},
32
+ }
33
+ ```
@@ -0,0 +1,20 @@
1
+ # Minimal makefile for Sphinx documentation
2
+ #
3
+
4
+ # You can set these variables from the command line.
5
+ SPHINXOPTS =
6
+ SPHINXBUILD = sphinx-build
7
+ SPHINXPROJ = pyannotemetrics
8
+ SOURCEDIR = source
9
+ BUILDDIR = build
10
+
11
+ # Put it first so that "make" without argument is like "make help".
12
+ help:
13
+ uv run --extra doc $(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14
+
15
+ .PHONY: help Makefile
16
+
17
+ # Catch-all target: route all unknown targets to Sphinx using the new
18
+ # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19
+ %: Makefile
20
+ uv run --extra doc $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@@ -0,0 +1,8 @@
1
+ Getting started
2
+ ===============
3
+
4
+ .. toctree::
5
+ :maxdepth: 2
6
+
7
+ tutorial
8
+ basics
@@ -0,0 +1,186 @@
1
+ Principles
2
+ ==========
3
+
4
+ `pyannote.metrics` provides a set of classes to compare the output of speaker diarization (hereafter called `hypothesis`) systems to manual annotations (`reference`). Let us first instantiate a sample `reference` and `hypothesis`.
5
+
6
+ .. ipython::
7
+
8
+ In [10]: from pyannote.core import Segment, Timeline, Annotation
9
+
10
+
11
+ In [11]: reference = Annotation(uri='file1')
12
+ ....: reference[Segment(0, 10)] = 'A'
13
+ ....: reference[Segment(12, 20)] = 'B'
14
+ ....: reference[Segment(24, 27)] = 'A'
15
+ ....: reference[Segment(30, 40)] = 'C'
16
+
17
+ In [12]: hypothesis = Annotation(uri='file1')
18
+ ....: hypothesis[Segment(2, 13)] = 'a'
19
+ ....: hypothesis[Segment(13, 14)] = 'd'
20
+ ....: hypothesis[Segment(14, 20)] = 'b'
21
+ ....: hypothesis[Segment(22, 38)] = 'c'
22
+ ....: hypothesis[Segment(38, 40)] = 'd'
23
+
24
+
25
+ .. plot:: pyplots/tutorial.py
26
+
27
+ This basically tells us that, according to the manual annotation, speaker `A` speaks in timeranges [0s, 10s] and [24s, 27s].
28
+
29
+
30
+ .. note::
31
+
32
+ Overlapping segments are supported. See :mod:`pyannote.core` documentation for more details.
33
+
34
+ `pyannote.metrics` follows an object-oriented paradigm.
35
+ Most evaluation metrics (e.g. :class:`DiarizationErrorRate` below) inherit from :class:`BaseMetric`.
36
+ As such, they share a common set of methods.
37
+
38
+ For instance, once instantiated, they can be called directly to compute the value of the evaluation metric.
39
+
40
+ .. ipython::
41
+ :okwarning:
42
+
43
+ In [10]: from pyannote.metrics.diarization import DiarizationErrorRate
44
+
45
+ In [1]: metric = DiarizationErrorRate()
46
+
47
+ In [1]: metric(reference, hypothesis)
48
+
49
+
50
+ Accumulation & reporting
51
+ ------------------------
52
+
53
+ The same metric instance can be used to evaluate multiple files.
54
+
55
+ .. ipython::
56
+ :okwarning:
57
+
58
+ In [11]: other_reference = Annotation(uri='file2')
59
+ ....: other_reference[Segment(0, 5)] = 'A'
60
+ ....: other_reference[Segment(6, 10)] = 'B'
61
+ ....: other_reference[Segment(12, 13)] = 'B'
62
+ ....: other_reference[Segment(15, 20)] = 'A'
63
+
64
+ In [12]: other_hypothesis = Annotation(uri='file2')
65
+ ....: other_hypothesis[Segment(1, 6)] = 'a'
66
+ ....: other_hypothesis[Segment(6, 7)] = 'b'
67
+ ....: other_hypothesis[Segment(7, 10)] = 'c'
68
+ ....: other_hypothesis[Segment(11, 19)] = 'b'
69
+ ....: other_hypothesis[Segment(19, 20)] = 'a'
70
+
71
+ In [12]: metric = DiarizationErrorRate()
72
+
73
+ In [12]: metric(reference, hypothesis)
74
+
75
+ In [12]: metric(other_reference, other_hypothesis)
76
+
77
+
78
+ You do not need to keep track of the result of each call yourself: this is done automatically.
79
+ For instance, once you have evaluated all files, you can use the overriden :func:`~pyannote.metrics.base.BaseMetric.__abs__` operator to get the accumulated value:
80
+
81
+ .. ipython::
82
+
83
+ In [12]: abs(metric)
84
+
85
+ :func:`~pyannote.metrics.base.BaseMetric.report` provides a convenient summary of the result:
86
+
87
+ .. ipython::
88
+
89
+ In [12]: report = metric.report(display=True)
90
+
91
+
92
+ The internal accumulator can be reset using the :func:`~pyannote.metrics.base.BaseMetric.report` method:
93
+
94
+ .. ipython::
95
+
96
+ In [12]: metric.reset()
97
+
98
+
99
+ Evaluation map
100
+ --------------
101
+
102
+ Though audio files can always be processed entirely (from beginning to end), there are cases where reference annotations are only available for some regions of the audio files.
103
+ All metrics support the provision of an evaluation map that indicate which part of the audio file should be evaluated.
104
+
105
+ .. ipython::
106
+
107
+ In [2]: uem = Timeline([Segment(0, 10), Segment(15, 20)])
108
+
109
+ In [2]: metric(reference, hypothesis, uem=uem)
110
+
111
+
112
+ Components
113
+ ----------
114
+
115
+ Most metrics are computed as the combination of several components.
116
+ For instance, the diarization error rate is the combination of false alarm (non-speech regions classified as speech), missed detection (speech regions classified as non-speech) and confusion between speakers.
117
+
118
+ Using ``detailed=True`` will return the value of each component:
119
+
120
+ .. ipython::
121
+ :okwarning:
122
+
123
+ In [13]: metric(reference, hypothesis, detailed=True)
124
+
125
+ The accumulated value of each component can also be obtained using the overriden :func:`~pyannote.metrics.base.BaseMetric.__getitem__` operator:
126
+
127
+ .. ipython::
128
+ :okwarning:
129
+
130
+ In [13]: metric(other_reference, other_hypothesis)
131
+
132
+ In [13]: metric['confusion']
133
+
134
+ In [13]: metric[:]
135
+
136
+
137
+ Define your own metric
138
+ ----------------------
139
+
140
+ It is possible (and encouraged) to develop and contribute new evaluation metrics.
141
+
142
+ All you have to do is inherit from :class:`BaseMetric` and implement a few methods:
143
+ ``metric_name``, ``metric_components``, ``compute_components``, and ``compute_metric``:
144
+
145
+ .. code-block:: python
146
+
147
+ def is_male(speaker_name):
148
+ # black magic that returns True if speaker is a man, False otherwise
149
+ pass
150
+
151
+ class MyMetric(BaseMetric):
152
+ # This dummy metric computes the ratio between male and female speakers.
153
+ # It does not actually use the reference annotation...
154
+
155
+ @classmethod
156
+ def metric_name(cls):
157
+ # Return human-readable name of the metric
158
+
159
+ return 'male / female ratio'
160
+
161
+ @classmethod:
162
+ def metric_components(cls):
163
+ # Return component names from which the metric is computed
164
+
165
+ return ['male', 'female']
166
+
167
+ def compute_components(self, reference, hypothesis, **kwargs):
168
+ # Actually compute the value of each component
169
+
170
+ components = {'male': 0., 'female': 0.}
171
+
172
+ for segment, _, speaker_name in hypothesis.itertracks(yield_label=True):
173
+ if is_male(speaker_name):
174
+ components['male'] += segment.duration
175
+ else:
176
+ components['female'] += segment.duration
177
+
178
+ return components
179
+
180
+ def compute_metric(self, components):
181
+ # Actually compute the metric based on the component values
182
+
183
+ return components['male'] / components['female']
184
+
185
+
186
+ See :class:`pyannote.metrics.base.BaseMetric` for more details.