Created
December 25, 2018 11:13
-
-
Save onidzelskyi/53fe2cbf3ec8f1d7afd70e70032e677a to your computer and use it in GitHub Desktop.
Language detect
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" -*- coding: utf-8 -*- | |
# | |
# Sample program for language detection | |
# Link to original paper https://www.kleemans.ch/letter-frequency | |
# | |
# How to run | |
# 1. add environment PYTHONIOENCODING="UTF-8" | |
# 2. python language_detect.py < letter_frequency.csv | |
# | |
""" | |
# Sample text section | |
ITALIAN_BOCCACCIO_TEXT = """Mossi adunque piú cosí egregi come antichi popoli da questa laudevole | |
sentenzia e apertissimamente vera, alcuna volta di deitá, altra di | |
marmorea statua, e sovente di celebre sepultura, e tal fiata di | |
triunfale arco, e quando di laurea corona secondo i meriti precedenti | |
onoravano i valorosi: le pene, per opposito, a' colpevoli date non | |
curo di raccontare. Per li quali onori e purgazioni la assiria, la | |
macedonica, la greca e ultimamente la romana republica aumentate, con | |
l'opere le fini della terra, e con la fama toccaron le stelle. Le | |
vestigie de' quali in cosí alti esempli, non solamente da' successori | |
presenti, e massimamente da' miei fiorentini, sono male seguite, ma in | |
tanto s'è disviato da esse, che ogni premio di virtú possiede | |
l'ambizione; per che, sí come e io e ciascun altro che a ciò con | |
occhio ragionevole vuole guardare, non senza grandissima afflizione | |
d'animo possiamo vedere li malvagi e perversi uomini a' luoghi eccelsi | |
e a' sommi ofici e guiderdoni elevare, e li buoni scacciare, deprimere | |
e abbassare. Alle quali cose qual fine serbi il giudicio di Dio, | |
coloro il veggiano che il timone governano di questa nave: percioché | |
noi, piú bassa turba, siamo trasportati dal fiotto, della fortuna, ma | |
non della colpa partecipi. E, comeché con infinite ingratitudini e | |
dissolute perdonanze apparenti si potessero le predette cose | |
verificare, per meno scoprire li nostri difetti e per pervenire al mio | |
principale intento, una sola mi fia assai avere raccontata (né questa | |
fia poco o picciola), ricordando l'esilio del chiarissimo uomo Dante | |
Alighieri. Il quale, antico cittadino né d'oscuri parenti nato, quanto | |
per vertú e per scienzia e per buone operazioni meritasse, assai il | |
mostrano e mostreranno le cose che da lui fatte appaiono: le quali, se | |
in una republica giusta fossero state operate, niuno dubbio ci è che | |
esse non gli avessero altissimi meriti apparecchiati.""" | |
DUTCH_ETHERLANDS_TEXT = """Zijn vader had vier kinderen, drie zoons en één dochter. Hij moet een | |
verdienstelijk en verstandig man zijn geweest, want hij schijnt aan al | |
zijne kinderen het onderwijs te hebben doen geven, dat de gewone school | |
aanbood. Christophorus had goed leeren lezen, schrijven en rekenen. Ook | |
had hij eenige vorderingen gemaakt in het Latijn en het teekenen. Zelfs | |
bezocht hij de hoogeschool te Pavia, waar hij zich vlijtig oefende | |
in meetkunde, aardrijkskunde, sterrekunde en zeevaartkunde.""" | |
FINNISH_KIVI_TEXT = """Jukolan talo, eteläisessä Hämeessä, seisoo erään mäen pohjaisella | |
rinteellä, liki Toukolan kylää. Sen läheisin ympäristö on kivinen | |
tanner, mutta alempana alkaa pellot, joissa, ennenkuin talo oli häviöön | |
mennyt, aaltoili teräinen vilja. Peltojen alla on niittu, apilaäyräinen, | |
halkileikkaama monipolvisen ojan; ja runsaasti antoi se heiniä, | |
ennenkuin joutui laitumeksi kylän karjalle. Muutoin on talolla avaria | |
metsiä, soita ja erämaita, jotka, tämän tilustan ensimmäisen perustajan | |
oivallisen toiminnan kautta, olivat langenneet sille osaksi jo ison-jaon | |
käydessä entisinä aikoina. Silloinpa Jukolan isäntä, pitäen enemmän | |
huolta jälkeentulevainsa edusta kuin omasta parhaastansa, otti vastaan | |
osaksensa kulon polttaman metsän ja sai sillä keinolla seitsemän vertaa | |
enemmän kuin toiset naapurinsa. Mutta kaikki kulovalkean jäljet olivat | |
jo kadonneet hänen piiristänsä ja tuuhea metsä kasvanut sijaan.--Ja tämä | |
on niiden seitsemän veljen koto, joiden elämänvaiheita tässä nyt käyn | |
kertoilemaan.""" | |
# Define variables | |
# csv separator | |
CSV_SEP = ';' | |
def load_csv(sep=','): | |
"""load language frequencies from standard input. | |
@:param sep - separator for csv file, string. | |
@:return tuple (frequencies as dictionary, letters as list)""" | |
# dictionary of supported languages | |
lang_freq = {} | |
# list of supported languages | |
language_list = [] | |
# list of supported letters | |
letters = [] | |
# TODO: Add an implementation | |
return lang_freq, letters | |
def calc_mse(lang_freq, let_freq): | |
"""Calculate Mean Square Error. | |
@:param language_freq - pre-calculated frequencies for supported languages. | |
@:param letters_freq - calculated frequencies for detected text. | |
@:return dictionary of MSE for for supported languages.""" | |
# MSE dictionary for each language | |
mse = {} | |
# TODO: Add an implementation | |
return mse | |
def calc_letter_frequency(text, all_letters): | |
"""Calculate frequencies for letters in detected text. | |
@:param text - text to be analyzed, string. | |
@:param all_letters - list of letters taken in accounts. | |
@:return dictionary for calculated frequencies for detected text.""" | |
# total count of letters in text | |
letters_count = 0 | |
# dictionary for letter frequency in text | |
letters_freq = {} | |
# TODO: Add an implementation | |
return letters_freq | |
# get text frequencies | |
def detect_language(text, lang_freq, all_letters): | |
"""Calculate probabilities for supported languages of given text. | |
@:param text - text to be analyzed, string. | |
@:param lang_freq - pre-calculated frequencies for supported languages. | |
@:param all_letters - list of letters taken in accounts. | |
@:return detected language for given text as string.""" | |
# language for text | |
predicted_language = '<undetected>' | |
# TODO: Add an implementation | |
# MSE | |
# TODO: Add an implementation | |
# Find out language itself as minimal value of MSE | |
# TODO: Add an implementation | |
return predicted_language | |
# Demo app | |
if __name__ == "__main__": | |
# Load pre-calculated values | |
language_freq, allowed_letters = load_csv(CSV_SEP) | |
# For each sample text detect its language | |
for expected_lang, sample_text in zip(['Finnish', 'Italian', 'Dutch'], | |
[FINNISH_KIVI_TEXT, ITALIAN_BOCCACCIO_TEXT, DUTCH_ETHERLANDS_TEXT]): | |
detected_language = detect_language(sample_text, language_freq, allowed_letters) | |
print('Expected / detected language: {} / {}'.format(expected_lang, detected_language)) |
We can make this file beautiful and searchable if this error is corrected: No commas found in this CSV file in line 0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Letter;French;German;Spanish;Portuguese;Esperanto;Italian;Turkish;Swedish;Polish;Dutch;Danish;Icelandic;Finnish;Czech | |
a;7.636%;6.516%;11.525%;14.634%;12.117%;11.745%;12.920%;9.383%;10.503%;7.486%;6.025%;10.110%;12.217%;8.421% | |
b;0.901%;1.886%;2.215%;1.043%;0.980%;0.927%;2.844%;1.535%;1.740%;1.584%;2.000%;1.043%;0.281%;0.822% | |
c;3.260%;2.732%;4.019%;3.882%;0.776%;4.501%;1.463%;1.486%;3.895%;1.242%;0.565%;0;0.281%;0.740% | |
d;3.669%;5.076%;5.010%;4.992%;3.044%;3.736%;5.206%;4.702%;3.725%;5.933%;5.858%;1.575%;1.043%;3.475% | |
e;14.715%;16.396%;12.181%;12.570%;8.995%;11.792%;9.912%;10.149%;7.352%;17.324%;15.453%;6.418%;7.968%;7.562% | |
f;1.066%;1.656%;0.692%;1.023%;1.037%;1.153%;0.461%;2.027%;0.143%;0.805%;2.406%;3.013%;0.194%;0.084% | |
g;0.866%;3.009%;1.768%;1.303%;1.171%;1.644%;1.253%;2.862%;1.731%;3.403%;4.077%;4.241%;0.392%;0.092% | |
h;0.737%;4.577%;0.703%;0.781%;0.384%;0.636%;1.212%;2.090%;1.015%;2.380%;1.621%;1.871%;1.851%;1.356% | |
i;7.529%;6.550%;6.247%;6.186%;10.012%;10.143%;9.600%;5.817%;8.328%;6.499%;6.000%;7.578%;10.817%;6.073% | |
j;0.613%;0.268%;0.493%;0.397%;3.501%;0.011%;0.034%;0.614%;1.836%;1.461%;0.730%;1.144%;2.042%;1.433% | |
k;0.049%;1.417%;0.011%;0.015%;4.163%;0.009%;5.683%;3.140%;2.753%;2.248%;3.395%;3.314%;4.973%;2.894% | |
l;5.456%;3.437%;4.967%;2.779%;6.104%;6.510%;5.922%;5.275%;2.564%;3.568%;5.229%;4.532%;5.761%;3.802% | |
m;2.968%;2.534%;3.157%;4.738%;2.994%;2.512%;3.752%;3.471%;2.515%;2.213%;3.237%;4.041%;3.202%;2.446% | |
n;7.095%;9.776%;6.712%;4.446%;7.955%;6.883%;7.987%;8.542%;6.237%;10.032%;7.240%;7.711%;8.826%;6.468% | |
o;5.796%;2.594%;8.683%;9.735%;8.779%;9.832%;2.976%;4.482%;6.667%;6.063%;4.636%;2.166%;5.614%;6.695% | |
p;2.521%;0.670%;2.510%;2.523%;2.755%;3.056%;0.886%;1.839%;2.445%;1.370%;1.756%;0.789%;1.842%;1.906% | |
q;1.362%;0.018%;0.877%;1.204%;0;0.505%;0;0.020%;0;0.009%;0.007%;0;0.013%;0.001% | |
r;6.693%;7.003%;6.871%;6.530%;5.914%;6.367%;7.722%;8.431%;5.243%;6.411%;8.956%;8.581%;2.872%;4.799% | |
s;7.948%;7.270%;7.977%;6.805%;6.092%;4.981%;3.014%;6.590%;5.224%;5.733%;5.805%;5.630%;7.862%;5.212% | |
t;7.244%;6.154%;4.632%;4.336%;5.276%;5.623%;3.314%;7.691%;2.475%;6.923%;6.862%;4.953%;8.750%;5.727% | |
u;6.311%;4.166%;2.927%;3.639%;3.183%;3.011%;3.235%;1.919%;2.062%;2.192%;1.979%;4.562%;5.008%;2.160% | |
v;1.838%;0.846%;1.138%;1.575%;1.904%;2.097%;0.959%;2.415%;0.012%;1.854%;2.332%;2.437%;2.250%;5.344% | |
w;0.074%;1.921%;0.017%;0.037%;0;0.033%;0;0.142%;5.813%;1.821%;0.069%;0;0.094%;0.016% | |
x;0.427%;0.034%;0.215%;0.253%;0;0.003%;0;0.159%;0.004%;0.036%;0.028%;0.046%;0.031%;0.027% | |
y;0.128%;0.039%;1.008%;0.006%;0;0.020%;3.336%;0.708%;3.206%;0.035%;0.698%;0.900%;1.745%;1.043% | |
z;0.326%;1.134%;0.467%;0.470%;0.494%;1.181%;1.500%;0.070%;4.852%;1.374%;0.034%;0;0.051%;1.503% | |
ß;0;0.307%;0;0;0;0;0;0;0;0;0;0;0;0 | |
à;0.486%;0;0;0.072%;0;0.635%;0;0;0;0;0;0;0;0 | |
á;0;0;0.502%;0.118%;0;0;0;0;0;0;0;1.799%;0;0.867% | |
â;0.051%;0;0;0.562%;0;0;0;0;0;0;0;0;0;0 | |
ã;0;0;0;0.733%;0;0;0;0;0;0;0;0;0;0 | |
ä;0;0.578%;0;0;0;0;0;1.797%;0;0;0;0;3.577%;0 | |
å;0;0;0;0;0;0;0;1.338%;0;0;1.190%;0;0.003%;0 | |
æ;0;0;0;0;0;0;0;0;0;0;0.872%;0.867%;0;0 | |
ç;0.085%;0;0;0.530%;0;0;1.156%;0;0;0;0;0;0;0 | |
è;0.271%;0;0;0;0;0.263%;0;0;0;0;0;0;0;0 | |
é;1.504%;0;0.433%;0.337%;0;0;0;0;0;0;0;0.647%;0;0.633% | |
ê;0.218%;0;0;0.450%;0;0;0;0;0;0;0;0;0;0 | |
ë;0.008%;0;0;0;0;0;0;0;0;0;0;0;0;0 | |
ì;0;0;0;0;0;0.030%;0;0;0;0;0;0;0;0 | |
í;0;0;0.725%;0.132%;0;0;0;0;0;0;0;1.570%;0;1.643% | |
î;0.045%;0;0;0;0;0;0;0;0;0;0;0;0;0 | |
ï;0.005%;0;0;0;0;0;0;0;0;0;0;0;0;0 | |
ð;0;0;0;0;0;0;0;0;0;0;0;4.393%;0;0 | |
ñ;0;0;0.311%;0;0;0;0;0;0;0;0;0;0;0 | |
ò;0;0;0;0;0;0.002%;0;0;0;0;0;0;0;0 | |
ó;0;0;0.827%;0.296%;0;0;0;0;1.141%;0;0;0.994%;0;0.024% | |
ô;0.023%;0;0;0.635%;0;0;0;0;0;0;0;0;0;0 | |
ö;0;0.443%;0;0;0;0;0.777%;1.305%;0;0;0;0.777%;0.444%;0 | |
ø;0;0;0;0;0;0;0;0;0;0;0.939%;0;0;0 | |
ù;0.058%;0;0;0;0;0.166%;0;0;0;0;0;0;0;0 | |
ú;0;0;0.168%;0.207%;0;0;0;0;0;0;0;0.613%;0;0.045% | |
ü;0;0.995%;0.012%;0.026%;0;0;1.854%;0;0;0;0;0;0;0 | |
ý;0;0;0;0;0;0;0;0;0;0;0;0.228%;0;0.995% | |
þ;0;0;0;0;0;0;0;0;0;0;0;1.455%;0;0 | |
ą;0;0;0;0;0;0;0;0;0.699%;0;0;0;0;0 | |
ć;0;0;0;0;0;0;0;0;0.743%;0;0;0;0;0 | |
ĉ;0;0;0;0;0.657%;0;0;0;0;0;0;0;0;0 | |
č;0;0;0;0;0;0;0;0;0;0;0;0;0;0.462% | |
ď;0;0;0;0;0;0;0;0;0;0;0;0;0;0.015% | |
ę;0;0;0;0;0;0;0;0;1.035%;0;0;0;0;0 | |
ě;0;0;0;0;0;0;0;0;0;0;0;0;0;1.222% | |
ĝ;0;0;0;0;0.691%;0;0;0;0;0;0;0;0;0 | |
ğ;0;0;0;0;0;0;1.125%;0;0;0;0;0;0;0 | |
ĥ;0;0;0;0;0.022%;0;0;0;0;0;0;0;0;0 | |
ı;0;0;0;0;0;0;5.114%;0;0;0;0;0;0;0 | |
ĵ;0;0;0;0;0.055%;0;0;0;0;0;0;0;0;0 | |
ł;0;0;0;0;0;0;0;0;2.109%;0;0;0;0;0 | |
ń;0;0;0;0;0;0;0;0;0.362%;0;0;0;0;0 | |
ň;0;0;0;0;0;0;0;0;0;0;0;0;0;0.007% | |
œ;0.018%;0;0;0;0;0;0;0;0;0;0;0;0;0 | |
ř;0;0;0;0;0;0;0;0;0;0;0;0;0;0.380% | |
ś;0;0;0;0;0;0;0;0;0.814%;0;0;0;0;0 | |
ŝ;0;0;0;0;0.385%;0;0;0;0;0;0;0;0;0 | |
ş;0;0;0;0;0;0;1.780%;0;0;0;0;0;0;0 | |
š;0;0;0;0;0;0;0;0;0;0;0;0;0;0.688% | |
ť;0;0;0;0;0;0;0;0;0;0;0;0;0;0.006% | |
ŭ;0;0;0;0;0.520%;0;0;0;0;0;0;0;0;0 | |
ů;0;0;0;0;0;0;0;0;0;0;0;0;0;0.204% | |
ź;0;0;0;0;0;0;0;0;0.078%;0;0;0;0;0 | |
ż;0;0;0;0;0;0;0;0;0.706%;0;0;0;0;0 | |
ž;0;0;0;0;0;0;0;0;0;0;0;0;0;0.721% | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment