Package: kamilib
KaMI-lib (Kraken Model Inspector)HTR / OCR models evaluation agnostic Python package, originally based on
theKrakentranscription system.🔌 InstallationUser installationUse pip to install package:$pipinstallkamilibDeveloper installationCreate a local branch of the kami-lib project$gitclonehttps://gitlab.inria.fr/dh-projects/kami/kami-lib.gitCreate a virtual environment$virtualenv-ppython3.7kami_venvthen$sourcekami_venv/bin/activateInstall dependencies with the requirements file$pipinstall-rrequirements.txtRun the tests$python-munittesttests/*.py-v🏃 TutorialAn “end-to-end pipeline” example that uses Kamilib (written in French)
is available at:Tools build with KaMI-libA turn-key graphical interface :KaMI-app🔑 QuickstartKaMI-lib can be used for different use cases with the classKami().First, import the KaMI-lib package :fromkami.KamiimportKamiThe following sections describe two use cases :How to compare outputs from any automatic transcription system,How to use KaMI-lib with a transcription prediction produced with a
Kraken model.SummaryCompare a reference and a prediction, independently from the Kraken engineEvaluate the prediction of a model generated with the Kraken engineUse text preprocessing to get different scoresMetrics optionsOthers1. Compare a reference and a prediction, independently from the Kraken engineKaMI-lib allows you to compare two strings or two text files by
accessing them with their path.# Define your string to compare.reference_string="Les 13 ans de Maxime ? étaient, Déjà terriblement, savants ! - La Curée, 1871. En avant, pour la lecture."prediction_string="Les 14a de Maxime ! étaient, djàteriblement, savants - La Curée, 1871. En avant? pour la leTTture."# Or specify the path to your text files.# reference_path = "reference.txt"# prediction_path = "prediction.txt"# Create a Kami() object and simply insert your data (string or raw text files)k=Kami([reference_string,prediction_string])you can retrieve the results as dict with the.boardattribute:print(k.scores.board)which returns a dictionary containing your metrics (see also Focus on
metrics section further):{'levensthein_distance_char':14,'levensthein_distance_words':8,'hamming_distance':'Ø','wer':0.4,'cer':0.13333333333333333,'wacc':0.6,'wer_hunt':0.325,'mer':0.1320754716981132,'cil':0.17745383867832842,'cip':0.8225461613216716,'hits':92,'substitutions':5,'deletions':8,'insertions':1}You can also access a specific metric, as follows:print(k.scores.wer)2. Evaluate the prediction of a model generated with the Kraken engineTheKami()object uses a ground truth (XML ALTO or XML PAGE format
only, no text format), a transcription model and an image to evaluate
prediction made by the Kraken engine.Here is a simple example demonstrating how to use this method with a
ground truth in ALTO XML:# Define ground truth path (XML ALTO here)alto_gt="./datatest/lectaurep_set/image_gt_page1/FRAN_0187_16402_L-0_alto.xml"# Define transcription model pathmodel="./datatest/lectaurep_set/models/mixte_mrs_15.mlmodel"# Define imageimage="./datatest/lectaurep_set/image_gt_page1/FRAN_0187_16402_L-0.png"# Create a Kami() object and simply insert your datak=Kami(alto_gt,model=model,image=image)To retrieve the results as dict (.boardattribute), as use case 1.:print(k.scores.board)which returns a dictionary containing your metrics (for more details on
metrics see section …):{'levensthein_distance_char':408,'levensthein_distance_words':255,'hamming_distance':'Ø','wer':0.3128834355828221,'cer':0.09150033639829558,'wacc':0.6871165644171779,'wer_hunt':0.29938650306748466,'mer':0.08970976253298153,'cil':0.1395071670835435,'cip':0.8604928329164565,'hits':4140,'substitutions':238,'deletions':81,'insertions':89}Depending on the size of the ground truth file, the prediction process
may take more or less time.Kraken parameters can be modified. You can specify the number of CPU
workers for inference (default 7) with theworkersparameter and you
can set the principal text direction with thetext_directionparameter (“horizontal-lr”, “horizontal-rl”, “vertical-lr “,
“vertical-rl”. By default Kami uses “horizontal-lr”.).k=Kami(alto_gt,model=model,image=image,workers=7,text_direction="horizontal-lr")3. Use text preprocessing to get different scoresKaMI-lib provides the possibility to apply textual transformations on
the ground truth and the prediction before evaluating them. By doing so,
scores can change according to the performance of the model used. This
functionality allows a better made by the transcription model. For
example, if removing all diacritics improves the scores, it probably
means that the model is not good enough at transcribing them. By default
no preprocessing is applied.To preprocess the ground truth and the prediction, you can useapply_transformsparameter fromKami()class.Theapply_transformsparameter receives a character code
corresponding to the transformations to be performed :Character codeApplied transformationDremove digitsUuppercaseLlowercasePremove punctuationXremove diacriticsYou can combine these options as follows:k=Kami([ground_truth,prediction],apply_transforms="XP"# Combine here : remove diacritics + remove punctuation)It results in a dictionary of more complex scores (use built-inpprintmodule to create a human readable dict.), as follows:importpprint# Get all scorespprint.pprint(k.scores.board){'Length_prediction':2507,'Length_prediction_transformed':2405,'Length_reference':2536,'Length_reference_transformed':2426,'Total_char_removed_from_prediction':102,'Total_char_removed_from_reference':110,'Total_diacritics_removed_from_prediction':84,'Total_diacritics_removed_from_reference':98,'all_transforms':{'cer':5.81,'cil':8.38,'cip':91.61,'deletions':48,'hamming_distance':'Ø','hits':2312,'insertions':27,'levensthein_distance_char':141,'levensthein_distance_words':73,'mer':5.74,'substitutions':66,'wacc':82.28,'wer':17.71},'default':{'cer':6.62,'cil':9.55,'cip':90.44,'deletions':59,'hamming_distance':'Ø','hits':2398,'insertions':30,'levensthein_distance_char':168,'levensthein_distance_words':90,'mer':6.54,'substitutions':79,'wacc':79.54,'wer':20.45},'remove_diacritics':{'cer':6.08,'cil':8.78,'cip':91.21,'deletions':49,'hamming_distance':'Ø','hits':2379,'insertions':31,'levensthein_distance_char':152,'levensthein_distance_words':77,'mer':6.0,'substitutions':72,'wacc':82.05,'wer':17.94},'remove_punctuation':{'cer':6.37,'cil':9.25,'cip':90.74,'deletions':57,'hamming_distance':'Ø','hits':2330,'insertions':25,'levensthein_distance_char':157,'levensthein_distance_words':86,'mer':6.31,'substitutions':75,'wacc':79.71,'wer':20.28}}The‘default’key indicates the scores without any
transformations;The‘all_transforms’key indicates the scores with all
transformations applied (here remove diacritics + remove
punctuation).If you have used text preprocessing, for example:The‘remove_punctuation’key indicates the scores with removed
punctuations only;The‘remove_diacritics’key indicates the scores with removed
diacritics only.4. Metrics optionsKaMI provides the possibility to weight differently the operations made
between the ground truth and the prediction (as insertions,
substitutions or deletions). By default this operations have a weight of
1. You can change these weigthts with the parameters in theKami()class:insertion_costsubstitution_costdeletion_costKeep in mind that these weights are the basis for Levensthein distance
computations and performance metrics like WER and CER, which can greatly
influence final scores.Example:k=Kami([ground_truth,prediction],insertion_cost=1,substitution_cost=0.5,deletion_cost=1)Kami()class also provides score display settings :truncate(bool) : Option to truncate result. Defaults toFalse.percent(bool) :Trueif the user want to show result in
percent elseFalse. Defaults toFalse.round_digits(str) : Set the number of digits after floating
point in string form. Defaults to‘.01’.Example :k=Kami([ground_truth,prediction],apply_transforms="DUP",verbosity=False,truncate=True,percent=True,round_digits='0.01')5. OthersFor debugging you can pass theverbosity(defaults toFalse)
parameter in theKami()class, this displays execution logs.🎯 Focus on metricsOperations between stringsHits: number of identical characters between the reference and
the prediction.Substitutions: number of substitutions (a character replaced by
another) necessary to make the prediction match the reference.Deletions: number of deletions (a character is removed) necessary
to make the prediction match the reference.Insertions: number of insertions (a character is added) necessary
to make the prediction match the reference.for each of these operations, except hits, a cost of 1 is assigned by
default.DistancesLevensthein Distance (Char.): Levenshtein distance (sum of
operations between character strings) at character level.Levensthein Distance (Words): Levenshtein distance (sum of
operations between character strings) at word level.Hamming Distance: A score if the strings’ lengths match but their
content is different;Øif the strings’ lengths don’t
match.Transcription performance (HTR/OCR)The performance metrics are calculated with the Levenshtein distances
mentioned above.WER: Word Error Rate, proportion of words bearing at least one recognition error.
It is generally between[0, 1.0], the closer it is to0the better the recognition.
However, a bad recognition can lead to aWER> 1.0.CER: Character Error Rate, proportion of characters erroneously transcribed.
Generally more accurate than WER. It is generally between[0, 1.0], the closer it is to0the better the recognition. However, a bad recognition can lead to aCER> 1.0.Wacc: Word Accuracy, proportion of words bearing no recognition error.WER Hunt: reproduce the Word Error Rate experiment by Hunt (1990).
Same principle as WER computation with a weighting ofO.5on insertions and deletions.
This metric shows the importance of customizing the weighting of operations made between strings as it depends heavily on the system
and type of data used in an HTR/OCR project. In KaMI-lib, it is possible to modify the weigthts assigned to operations.Experimental Metrics (metrics borrowed from Speech Recognition - ASR)Match Error RateCharacter Information LostCharacter Information Preserve❓ Do you have questions, bug report, features request or feedback ?Please use the issue templates:🐞 Bug report:here🎆 Features request:hereif aforementioned cases does not apply, feel free to open an issue.✒️ How to cite@misc{Kami-lib,
    author = "Lucas Terriel (Inria - ALMAnaCH) and Alix Chagué (Inria - ALMAnaCH)",
    title ={Kami-lib - Kraken model inspector},
    howpublished ={\url{https://github.com/KaMI-tools-project/KaMi-lib}},
    year ={2021-2022}}🐙  License and contactDistributed underMITlicense. The dependencies used in
the project are also distributed under compatible license.Mail authors and contact: Alix Chagué (alix.chague@inria.fr) and Lucas
Terriel (lucas.terriel@inria.fr)Special thanks: Hugo Scheithauer (hugo.scheithauer@inria.fr)KaMI-libis developed and maintained by authors (2021-2022, first
version named Kraken-Benchmark in 2020) with contributions ofALMAnaCHatInriaParis.