Euromind
  • Javascript
    • Javascript

      Dansk evighedskalender

      7. december, 2020

      Javascript

      API til Statistikbanken

      21. september, 2019

      Javascript

      IntersectionObserver

      9. august, 2019

      Javascript

      Navngivne RegEx-grupper i ECMAScript 2018

      29. juli, 2019

      Javascript

      RegEx: Unicode og Look Backward i ECMAScript 2018

      24. juli, 2019

  • CSS/SCSS
    • CSS/SCSS

      Dansk evighedskalender

      7. december, 2020

      CSS/SCSS

      Variable fonte med dansk tegnsæt i open source

      11. august, 2019

      CSS/SCSS

      Progressbar for dokumentposition

      31. juli, 2019

      CSS/SCSS

      Media Query i 2019

      18. juli, 2019

      CSS/SCSS

      Danske Adressers Web API

      17. juli, 2019

  • C#
    • C#

      Authentication for IOS og Android med Firebase i…

      4. oktober, 2019

      C#

      Andersen, Grundvig, Kierkegaard og ML.NET – del 3

      5. september, 2019

      C#

      Hurtig eksport til Excel

      4. september, 2019

      C#

      Andersen, Grundtvig, Kierkegaard og ML.NET – del 2

      2. september, 2019

      C#

      Andersen, Grundvig, Kierkegaard og ML.NET – del 1

      11. august, 2019

  • Javascript
    • Javascript

      Dansk evighedskalender

      7. december, 2020

      Javascript

      API til Statistikbanken

      21. september, 2019

      Javascript

      IntersectionObserver

      9. august, 2019

      Javascript

      Navngivne RegEx-grupper i ECMAScript 2018

      29. juli, 2019

      Javascript

      RegEx: Unicode og Look Backward i ECMAScript 2018

      24. juli, 2019

  • CSS/SCSS
    • CSS/SCSS

      Dansk evighedskalender

      7. december, 2020

      CSS/SCSS

      Variable fonte med dansk tegnsæt i open source

      11. august, 2019

      CSS/SCSS

      Progressbar for dokumentposition

      31. juli, 2019

      CSS/SCSS

      Media Query i 2019

      18. juli, 2019

      CSS/SCSS

      Danske Adressers Web API

      17. juli, 2019

  • C#
    • C#

      Authentication for IOS og Android med Firebase i…

      4. oktober, 2019

      C#

      Andersen, Grundvig, Kierkegaard og ML.NET – del 3

      5. september, 2019

      C#

      Hurtig eksport til Excel

      4. september, 2019

      C#

      Andersen, Grundtvig, Kierkegaard og ML.NET – del 2

      2. september, 2019

      C#

      Andersen, Grundvig, Kierkegaard og ML.NET – del 1

      11. august, 2019

Euromind
C#

Stylometri i C# – del 4

af Per Lindsø Larsen 9. juli, 2019
skrevet af Per Lindsø Larsen 9. juli, 2019
Stylometri i C# – del 4

Kaosteori indebærer som bekendt at en sommerfugls slag med vingen teoretisk set kan udløse orkan på den anden side af kloden. Sikkert er det i hvert fald, at sommerfugle i Malaysia har påvirket den stylometriske forskning helt andre steder.  

I 1943 fremsatte den engelske statistiker R. A. Fischer en model, der kunne sandsynliggøre – på baggrund af allerede kendte sommerfuglearter i Malaysia – hvor mange nye arter, der ville blive fundet i Malaysia, hvis et givent antal summerfugle-jægere blev sendt afsted med en givent antal sommerfugle-fælder. Den spændende model fik nogle tankebaner til at kortslutte for de to amerikanske statistikere, Efron og Thisted, der undfangede følgende stylometriske tanke:

Hvis vi betragter ordene i en forfatters kendte værker som allerede kendte sommerfugle-arter, så kan det med Fischer’s model beregnes hvor mange nye sommerfugle-arter – læs: nye ord – der kan forventes at blive fundet i en ukendt tekst, såfremt den formodede forfatter virkelig er forfatter til denne tekst. Ord, som forfatteren allerede kender, men endnu ikke har brugt. En snurrig teori, hvis bagvedliggende ræsonnement jeg aldrig har haft kapacitet til at tænke helt til ende.

Det blev så igen William Shakespeare, der måtte holde for i  stylometriens tjeneste. Efron og Thisted afprøvede deres teori på et anonymt digt, der er blevet tillagt Shakespeare. Modellen forventede, at der – hvis Shakespeare var forfatteren – ville blive fundet syv nye ord, som Shakespeare ikke tidligere havde brugt. Næsten rigtigt. Der blev fundet ni nye ord. Shakespeare brugte i alt 31.534 ord i sit forfatterskab og forskerne beregnede sig til, at han på den baggrund har kendt ca. 35.000 ord. Altså ca. 3.500 ord, som Shakespeare ikke nåede at få fyret af, inden han døde. – Og vi andre mangler bare ord!

Argumentets slagkraft blæser – som sommerfugle –  i vinden og en senere forsker antydede da også, at ”perhaps the Efron-Thisted Test diverge too far from reality to yield meaningful results”.

Under alle omstændigheder, så henleder Efron-Thisted opmærksomheden på, at stylometri ikke blot handler om, hvad der står i teksten, men også hvad der ikke står – eller sjældent står. Tages H.C. Andersens “Mit Livs Eventyr” som eksempel, så er mere end hvert 15. ord i bogen et såkaldt hapax legomenon – et ord, som kun optræder én gang i. teksten. Tælles alene bogens forskellige ord – dem er der godt 20.000 af – så er 57% af dem hapax legomena. Det er der ikke noget overraskende i. Sædvanligvis ligger det mellem 40% og 60%. Yderligere godt 15% er hapax dislegomena – ord, der optræder to gange i hele bogen.


Omfanget af hapax legomena er helt tilbage til 1920’erne blevet anset som en variabel, der kan yde et bidrag til identifikation af forfattere. Sammenlignet med Mit Livs Eventyr ses det, at hyppigheden af hapax legomena er lavere hos Kierkegaard (49%), men sammenligningen er ikke helt fair, da tekstlængderne er forskellige. Det er som med kedelige familie-festtaler: jo længere de bliver, desto større risiko er der for at forfatteren begynder at gentage sig selv og “ødelægge” det ene hapax legomenon efter det andet. For at gøre konkurrence mere sportslig, vil jeg derfor i det følgende hugge værkerne op i lige store tekstblokke, der således på et ensartet grundlag kan sammenlignes. Det ser også mulighed for at se, hvor stabile variablerne er gennem hele værket.

        [Serializable]
        public class ShortSummary
        {

            public int Cluster { get; set; }
            public int Textlength { get; set; }
            public int WordsCount { get; set; }
            public int StopWordsCount { get; set; }
            public int DifferentWordsCount { get; set; }
            public double Herdan { get; set; }
            public double Guiraud { get; set; }
            public double Uber { get; set; }
            public int LongWordsCount { get; set; }
            public int HapaxLegomena { get; set; }
            public int HapaxDisLegomena { get; set; }
            public int HapaxTrisLegomena { get; set; }


            public ShortSummary(TextInfo info, string text, int decimals = 3)
            {
                var words = GetWords(text, false);
                var sentences = GetSentences(text);
                var wordfreq = GetWordFrequencyList(words, decimals);

                Cluster = 0;
                Textlength = text.Length;
                WordsCount = words.Count;
                StopWordsCount = WordsCount - GetWords(text, true).Count;
                DifferentWordsCount = words.Distinct().Count();
                HapaxLegomena = wordfreq.Count(x => x.Antal == 1);
                HapaxDisLegomena = wordfreq.Count(x => x.Antal == 2);
                HapaxTrisLegomena = wordfreq.Count(x => x.Antal == 3);
                LongWordsCount = words.Count(x => x.Length > 6);
                Herdan = CalculateHerdan(WordsCount, DifferentWordsCount, decimals);
                Guiraud = CalculateGuiraud(WordsCount, DifferentWordsCount, decimals);
                Uber = CalculateUber(WordsCount, DifferentWordsCount, decimals);
            }
        }


        public static List<ShortSummary> SummarizeWordClusters(TextInfo info, int ClusterSize, int decimals = 3)
        {
            var summary = new List<ShortSummary>();
            var preProcessedText =
                Stylo.PreProcessText(Path.Combine(@"..\..\Tekster\", info.Filename), Encoding.UTF8, true);
            var clusters = Stylo.getWordClusters(preProcessedText, ClusterSize, false);
            int counter = 1;
            foreach (var cluster in clusters)
            {
                var s = new Stylo.ShortSummary(info, cluster, decimals);
                s.Cluster = counter;
                counter++;
                summary.Add(s);
            }
            return summary;
        }

Ud over hapax legomena – og brødrene dis og tris – hentes nogle supplerende mål for den leksikale rigdom i teksterne: Herdan, Uber og Guiraud Index.

        public static double CalculateHerdan(int wordsCount, int differentWordsCount, int decimals = 6)
        {
                return Math.Round(Math.Log(differentWordsCount) / Math.Log(wordsCount), decimals);
            
        }

        public static double CalculateUber(int wordsCount, int differentWordsCount, int decimals = 2)
        {
          return Math.Round(Math.Pow(Math.Log(wordsCount), 2)
                / (Math.Log(wordsCount) - Math.Log(differentWordsCount)),decimals);
        }

        public static double CalculateGuiraud(int wordsCount, int differentWordsCount, int decimals = 2)
        {
                return Math.Round(differentWordsCount / Math.Sqrt(wordsCount), decimals);
        }

Sammen med tidligere beskrevne funktioner kan nu genereres de nødvendige Excel-tabeller for lige store ord-klynger fra de tre bøger. I eksemplet vælges 25 ordklynger af 3000 ord. Det er det antal, som den korteste af teksterne “Verdens Krønike” tillader.

            List<TextInfo> source = new List<TextInfo>()
            {
                new TextInfo(){Title = "Enten-Eller",Filename = "enteneller.txt" },
                new TextInfo(){Title = "Mit Livs Eventyr",Filename = "hca.txt" },
                new TextInfo(){Title = "Verdens Krønike",Filename = "gv5.txt" }
            };

            int clusterSize = 4000;
            int clusterCount = 20;
            //Opret Excel-fil
            var excel = new Export.Excel("wordclusters.xlsx");
            //Tilføj Excel-ark til filen 
            var sheet = excel.AddSheet("Ordfrekvensliste", true);
            string xAxisTitle = $"Klynge ({clusterSize} ord)";
            string YAxisTitle = "Antal";
            var hapaxchart = sheet.AddChart("Hapax Legomena", eChartType.LineMarkers, 
                             XLabel: xAxisTitle, YLabel: YAxisTitle);
            var differentwordschart = sheet.AddChart("Antal forskellige ord", 
                 eChartType.LineMarkers,XLabel:xAxisTitle, YLabel:YAxisTitle);
            var herdanchart = sheet.AddChart("Herdan Index", eChartType.LineMarkers, 
                              XLabel: xAxisTitle, YLabel: YAxisTitle);
            var longwordschart = sheet.AddChart("Antal lange ord", eChartType.LineMarkers, 
                              XLabel: xAxisTitle, YLabel: YAxisTitle);
            foreach (var book in source)
            {
               var summaries = Stylo.SummarizeWordClusters(book, clusterSize, 3);
                sheet.AddTable($"{book.Title}", summaries.Take(clusterCount));
                sheet.AddSeries(differentwordschart, "Cluster", "DifferentWordsCount");
                sheet.AddSeries(hapaxchart, "Cluster", "HapaxLegomena");
                sheet.AddSeries(herdanchart, "Cluster", "Herdan");
                sheet.AddSeries(longwordschart, "Cluster", "LongWordsCount");
            }
            //Gem fil og åben automatisk i Excel
            excel.Save(true);

Af de tre er Søren Kierkegaard’s bog også den, der har det laveste LIX-tal. Overraskende, måske. Det ville han ikke bryde sig om at vide, den gamle sjover.

Stylometri i C# del 1, del2 og del 3.

Stylometri
0 Kommentarer
4
FacebookTwitterPinterestEmail
forrige post
Barebone AMP i Codepen
næste post
Forbind Visual Studio til IOS devices på 10 minutter

Relaterede indlæg

Authentication for IOS og Android med Firebase i...

4. oktober, 2019

Andersen, Grundvig, Kierkegaard og ML.NET – del 3

5. september, 2019

Hurtig eksport til Excel

4. september, 2019

Andersen, Grundtvig, Kierkegaard og ML.NET – del 2

2. september, 2019

Andersen, Grundvig, Kierkegaard og ML.NET – del 1

11. august, 2019

Forbind Visual Studio til IOS devices på 10...

12. juli, 2019

Serialisering og deserialisering i C#

5. juli, 2019

Stylometri i C# – del 3

2. juli, 2019

Stylometri i C# – del 2

7. juni, 2019

Stylometri i C# – del 1

5. juni, 2019

Efterlad en kommentar Afbryd svar

Gem mit navn, email, og website i denne browser til senere kommentarer.

Seneste indlæg

  • Dansk evighedskalender

    7. december, 2020
  • Automatisk køreafstand i Excel

    17. august, 2020
  • Headless browser på 10 minutter

    25. juli, 2020

Kategorier

  • C#
  • CSS/SCSS
  • Excel
  • HTML
  • Javascript
  • Mobile
  • Webdesign
  • Xamarin

Om mig

Om mig

Per Lindsø Larsen

Freelance fullstack developer bo9sat i Aarhus.

Du kan hyre mig til korterevarende projekter eller konkrete opgaveløsninger.

Pæn rabat til non-profit organisationer og foreninger.

Når jeg ikke koder, deltager jeg løbende i diverse spændende forskningsprojekter om alt andet end kodning.

Keep in touch

Facebook Twitter Email Github

Tags

Adresser AMP AMP Story Android API Billedformater Billedoptimering Brand C# Codepen Cordova CPR Crome DevTools CSS Debug Ecmascript Excel Fonte Gmail Gulp HTML Ikoner IOS Javascript JsFiddle Machine Learning Mail Mediaquery ML.NET Mobile RegEx SCSS SMTP Stylometri Visual Studio Webdesign Xamarin

Nyhedsbrev

Timeld nyhedsbrev for info om nye blog-indlæg, tips m.v.

  • Facebook
  • Twitter
  • Email
  • Github

@2019 - Euromind.com - Code-To-Go. All Right Reserved.
lindsoe@gmail.com - mobil: 42797273


Tilbage til top
Euromind
  • Javascript
    • Javascript

      Dansk evighedskalender

      7. december, 2020

      Javascript

      API til Statistikbanken

      21. september, 2019

      Javascript

      IntersectionObserver

      9. august, 2019

      Javascript

      Navngivne RegEx-grupper i ECMAScript 2018

      29. juli, 2019

      Javascript

      RegEx: Unicode og Look Backward i ECMAScript 2018

      24. juli, 2019

  • CSS/SCSS
    • CSS/SCSS

      Dansk evighedskalender

      7. december, 2020

      CSS/SCSS

      Variable fonte med dansk tegnsæt i open source

      11. august, 2019

      CSS/SCSS

      Progressbar for dokumentposition

      31. juli, 2019

      CSS/SCSS

      Media Query i 2019

      18. juli, 2019

      CSS/SCSS

      Danske Adressers Web API

      17. juli, 2019

  • C#
    • C#

      Authentication for IOS og Android med Firebase i…

      4. oktober, 2019

      C#

      Andersen, Grundvig, Kierkegaard og ML.NET – del 3

      5. september, 2019

      C#

      Hurtig eksport til Excel

      4. september, 2019

      C#

      Andersen, Grundtvig, Kierkegaard og ML.NET – del 2

      2. september, 2019

      C#

      Andersen, Grundvig, Kierkegaard og ML.NET – del 1

      11. august, 2019

Populære indlæg

  • 1

    Stylometri i C# – del 2

    7. juni, 2019
  • 2

    Send email fra Javascript med Gmail API

    21. juni, 2019
  • 3

    Gmail, Yahoo og Outlook som SMTP-server

    18. april, 2019
  • 4

    Andersen, Grundvig, Kierkegaard og ML.NET – del 1

    11. august, 2019
  • 5

    Registrer Gmail API til brug i javascript

    27. juni, 2019
@2019 - Euromind.com - Code-To-Go. All Right Reserved.
lindsoe@gmail.com - mobil: 42797273

Læs ogsåx

Forbind Visual Studio til IOS devices på 10 minutter

12. juli, 2019

Andersen, Grundvig, Kierkegaard og ML.NET – del 1

11. august, 2019

Stylometri i C# – del 1

5. juni, 2019