All Posts By

Hanna Szabó-Fischer

Könyvmolyproblémák: hogyan választ olvasnivalót egy magyar adattudós?

By | Data Science, Machine Learning, Python | No Comments

Itt a tél, az ünnepek után, a hosszú estéken pedig egyre többen találják meg a kikapcsolódást az olvasásban. A könyvmolyok azonban gyakran találkoznak azzal a problémával, hogy nehéz „spoilermentesen” információt szerezni egy-egy kötetről. Annál pedig kevés bosszantóbb dolog van, mint amikor egy háromszáz oldalas könyvben még a századik oldal körül is olyan dolgok történnek, amiket már olvastunk a fülszövegben. Szabó-Fischer Hanna erre keresett megoldást.

„Persze lehet találni jó fülszövegeket is, de én mára gyakorlatilag teljesen száműztem az életemből őket és igyekszem más forrásból beszerezni ezt az információt. A más forrás pedig nem más, mint a moly.hu közössége” – osztotta meg személyes tapasztalatait Szabó-Fischer Hanna adattudós, a budapesti United Consult szakértője. Mint fogalmazott, a könyvrajongók közösségi oldalán, az egyes adatlapokon a felhasználók címkéket tehetnek a könyvekre (például ifjúsági, kortárs, romantikus, fantasy, regény, novella, vers stb.). Ezek alapján viszonylag jól el lehet dönteni, hogy egy adott könyv tetszene vagy sem.

Az adattudós hangsúlyozza ugyanakkor, hogy a világirodalom olyan kiterjedt és sokszínű, hogy ez a magyar adatbázis és platform természetesen nem lehet „mindenható” a nemzetközi irodalom terén.

„Kiegészítésként a goodreads.com is a kedvenceim között van. Itt viszont sajnos nem létezik a címkézés, ami miatt elég zsákbamacska-szerűen válogatok a könyvek között. Megelégelve ezt az állapotot, arra az elhatározásra jutottam, hogy készítek magamnak egy automata címkéző rendszert” – számolt be elhatározásáról Szabó-Fischer Hanna, aki nem mindennapi projektbe kezdett a „könyvmolyproblémák” megoldására.

A projekt lépései

„Ha mi magunk olvasnánk egy fülszöveget, akkor viszonylag könnyen tudnánk besorolni kategóriákba, de ahhoz, hogy egy program értelmezni tudja, jóval több előkészületre van szükség. Először is kell egy adatbázis, amely tartalmaz sok fülszöveget és a hozzá tartozó címkéket. A program később majd ezekből a példákból fog mintázatokat megtanulni, ami alapján egy ismeretlen szöveget bekategorizál. A másik nagyon fontos lépés a fülszövegek előkészítése. A program nem egy szöveget, hanem szavak összességét fogja látni, ezért biztosítanunk kell azt, hogy a számunkra egyértelműen hasonló jelentéssel bíró szavakat (például könyv, könyvek, könyvről, könyvekről) a gép hasonlónak értelmezze” – ismertette az alapproblémákat a United Consult szakértője.


Szabó-Fischer Hanna a nyers fülszövegtől a működő programig az adatgyűjtéssel kezdve, a szövegfeldolgozáson, majd a dokumentummátrix felépítésén és az osztályozáson át – az ábrán látható folyamat segítségével – jutott el. Lássuk ezeket lépésről lépésre, kicsit a szakmai részletekbe is elmélyedve.

Adatgyűjtés

„Ahhoz, hogy osztályozót építsek szükségem volt egy viszonylag nagy tanulóhalmazra, melyet a moly.hu adatbázisát használva készítettem el. Ezer angol nyelvű könyv címét, fülszövegét és a felhasználók által rájuk aggatott címkéket töltöttem le. A scrapeléshez, azaz a tömeges adatletöltéshez a pythonban megírt BeautifulSoup nevű csomagot használtam” – ismertette a szakértő.

Szövegfeldolgozás

Szabó-Fischer Hanna tapasztalatai szerint a szövegfeldolgozás sokkal hatékonyabban működik angol szövegekre, ráadásul a Goodreads-en is többnyire angol nyelven vannak feltöltve a könyvek, így kézenfekvő volt, hogy angolra optimalizálja a programot.

A szövegfeldolgozáshoz az nltk csomag volt a segítségére, a munkát pedig a fülszövegek megtisztításával kezdte.

Forrás: Towards Data Science

 

„A tokenizálással szavakra bontottam a fülszöveget, majd minden szót kisbetűssé alakítottam, hiszen a szövegfelismerő rendszerek számára például a „Könyv” és a „könyv” sem ugyanaz. Ezután kiszűrtem a “stop szavakat”. Ezek olyan szavak, amik sokszor megjelennek a szövegekben, de önmagunkban nem hordoznak értéket. Ilyenek például a személyes névmások, létigék, segédigék vagy éppen a kötőszavak” – sorolta a lépéseket a szakértő.

Forrás: python nltk packedge


Fontos feladat volt a szavakat és mondatokat elválasztó, tagoló írásjelek értelmezése, kezelése is. A központozásnál és az egyedüli karaktereknél először a különböző szimbólumokat szűrte ki, majd a feldolgozás során egyedüli karakterként megmaradt elemek következtek.

„A lemmatization és a stemming két hasonló eljárás, összefoglaló néven szótövezésnek hívjuk. A lemmatization során minden szó leredukálódik a „gyökér szinonimájára”. A „playing” vagy a „played” például egyszerűen „play” lesz. Fontos kiemelni, hogy a lemmatization során az algoritmus figyel arra, hogy a redukált szó is szótári szó maradjon. A stemming hasonló logikával működik, azzal a különbséggel, hogy itt az algoritmus meghatározott szabályok alapján vágja vagy cseréli le a szóvégeket, így előfordulhat, hogy nem szótári szavakat kapunk eredményül” – ismertette a szövegfeldolgozás fontos mozzanatát az adattudós. Hozzátette: a számok konvertálásánál az arab számokat egyszerűen csak szöveggé kellett átalakítani.

Forrás: Towards Data Science

Dokumentummátrix-építés

Miután előállt a megtisztított adathalmaz, az adattudós elkészítette a szavakból az úgynevezett document-term mátrixot.

„Ez egy olyan mátrix melynek a sorai a dokumentumok – az én esetemben a fülszövegek –, az oszlopai pedig a szavak, amik előfordultak a fülszövegekben. Arra több megoldás is létezik, hogy az adott fülszövegek és szavak metszeteit miként érdemes feltölteni értékkel. A legegyszerűbb verzió, amikor 0 kerül abba az oszlopba, amely szó nem szerepelt a dokumentumban és 1-es oda, amely szerepelt. Ennél egy fokkal szofisztikáltabb módszer, amikor nem feltétlenül 1-es kerül a metszetbe, hanem a szó gyakorisága, az adott dokumentumban” – ismertette a szakértő.

Szabó-Fischer Hanna ugyanakkor nem az előbbieket, hanem egy harmadik féle módszer alkalmazott: úgynevezett tf-idf (Term Frequency — Inverse Document Frequency) mátrixot épített. Itt az egyes cellákba 0-1 közötti értékek kerültek, amelyek önmagukban reprezentálják az egyes szavak fontosságát (gyakoriságát) az adott dokumentumban és a corpusban (szókészletben) is.

Következőféleképpen számolható:

  • t – term (szó)
  • d – document (szavak összessége, itt: 1 db fülszöveg)
  • N – corpus nagysága (az összes előforduló szó száma)

tf(t,d) = t gyakorisága d-ben / összes szó száma d-ben
df(t) = t gyakorisága az összes dokumentumban

tf-idf(t,d) = tf(t,d) * log(N/(df(t)+1))

Forrás:Towards Data Science

Osztályozás

Elkészült a dokumentummátrix, kezdődhetett az osztályozás. A United Consult senior munkatársa a tanulóhalmazból leválasztotta a címkéket, majd felmérte, hogy mekkora volumennel van dolga.

„Nagyjából nyolcszáz különböző címke gyűlt össze az ezer darab könyvhöz. Ezeket gyakoriság szerint sorba állítottam és a legnépszerűbb ötvenből kiválasztottam azt a tizenötöt, ami számomra a leginkább fontos. Minden könyvről eltároltam, hogy a tizenöt címke közül melyik igaz rá, majd a címkékre egyesével építettem osztályozókat. Ehhez az sklearn csomagot használtam. Három féle algoritmussal próbálkoztam (KNeighbors, Naive-Bayes és SVM), és ezek közül az accuracy alapján döntöttem a Naive-Bayes mellett” – avatott be a szakmai részletekbe. Az eredményekről szólva hozzátette: a legtöbb címkére 70-90% közötti pontossággal működtek az osztályozók a teszthalmazon.

Eredmények

Az adatgyűjtés után megvolt a szövegfeldolgozás, elkészült a dokumentummátrix, majd lezajlott az osztályozás is. Már csak a program hiányzott, mely a nyers fülszövegekből címkéket generál. Szabó-Fischer Hanna az alábbi ábrán látható lépések segítségével ezt is megírta:

„Végigfuttattam a Goodreads-en lévő várólistámon, és megállapítottam, hogy tendál az egyhangúság felé. Illene szélesíteni a látókörömet” – összegezte az eredményeket az adattudós.

Néhány példa a program alkalmazására:

„Az eredményekből látszik, hogy vannak bizonyos címkék – kortárs, romantikus, fantasy, ifjúsági –, amiket nagyon jól felismer a program, de azokra, amelyek ritkábban szerepeltek a tanuló halmazban – például humoros, női/férfi főszereplő, váltott szemszög, sci-fi, disztópia –, nem tanult rá olyan jól, és az új fülszövegekre nem alkalmazza ezeket a címkéket” – konstatálta Szabó-Fischer Hanna.

Az okokról szólva megosztotta, hogy az alap tanulóhalmazt a moly.hu-ra angolul feltöltött könyvek jelentették, ebben a körben pedig magasan felül reprezentáltak az ifjúsági és kortárs szerzők könyvei, és talán a szórakoztató irodalom is a szépirodalommal szemben, hiszen ezt az adatbázist a felhasználók készítik, és a fiatalabb korosztályban sokkal valószínűbb, hogy valaki angolul olvas, mint az idősebbek között. Mindezek miatt a háborúkkal, gyásszal, történelmi regényekkel kapcsolatos címkék is kevésbé jelentek meg a tanuló halmazban.

„Javítani a felismert címkék sokszínűségén leginkább a tanulóhalmaz számbeli növelésével és a repertoár szélesítésével lehetne” – zárta a szakértő, aki mindezek ellenére jó szívvel ajánlja az előbbiekben ismertetett módszert arra, hogy bárki spoiler nélkül találjon az ízlésének megfelelő könyvet.

További eredmények:

A kód

Szabó-Fischer Hanna a kódot is megosztotta, hátha valakinek kedve támad továbbgondolni az ötletet. Íme…


# SCRAPE
from bs4 import BeautifulSoup
import requests

# go through links to retrieve blurbs and tags
url = 'https://moly.hu' + link["href"]
r = requests.get(url)

# collect html
soup = BeautifulSoup(r.text, 'html.parser')
cimkek = soup.find_all('a', class_='hover_link')
fulszovegek = soup.find_all('div', class_="text")

# TEXT-MINING
def preprocessing(fulszoveg):
    fulszoveg = lower_case_convert(fulszoveg)
    fulszoveg = tokenizing_own(fulszoveg)
    fulszoveg = stop_words_eliminator(fulszoveg)
    fulszoveg = punctuation_eliminator(fulszoveg)
    fulszoveg = apostrophe_eliminator(fulszoveg)
    fulszoveg = single_char_eliminator(fulszoveg)
    fulszoveg = converting_numbers(fulszoveg)
    fulszoveg = tokenizing_own(fulszoveg)
    fulszoveg = stop_words_eliminator(fulszoveg)
    fulszoveg = lemming_own(fulszoveg)
    fulszoveg = stemming_own(fulszoveg)
    return fulszoveg

# TF-IDF
import collections
# making a dictionary which collects all the words, and collect the doc IDs for every word
DF = {}
for i in range(len(fulszovegek)):
    tokens = fulszovegek[i]

    for word in tokens:
        try:
            DF[word].add(i)
        except:
             DF[word] = {i}

# instead of collecting the doc IDs, we need just the counts for every word
for i in DF:
    DF[i] = len(DF[i])
# all the words (keys in DF)
total_vocab = [x for x in DF]

# calcuating TF-IDF
tf_idf = {}
for i in range(len(fulszovegek)):
    tokens = fulszovegek[i]
    counter = collections.Counter(tokens)
    words_count = len(tokens)
    for token in np.unique(tokens):
        tf = counter[token]/words_count
        df = doc_freq(token)
        idf = np.log((len(fulszovegek)+1)/(df+1))
        tf_idf[doc, token] = tf*idf

    doc += 1

# CLASSIFICATION
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import GridSearchCV

# train/test split
data_train=data.sample(frac=0.8,random_state=200)
data_test=data.drop(data_train.index)

# set X
X_train = data_train.drop([cimkek], axis=1)
X_test = data_test.drop([cimkek], axis=1)

# classifier for every tag
tag_list = cimkek
for tag in tag_list:
    y_train = data_train[tag]
    y_test = data_test[tag]

    parameters = {'alpha': [0.1, 0.5, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 2, 2.3, 2.6, 3, 4, 5, 6]}
    naiveB = GridSearchCV(MultinomialNB(), parameters)
    best_est = naiveB.best_estimator_
    best_est.fit(X_train, y_train)
    y_pred = best_est.predict(X_test)
    print('score', best_est.score(X_test, y_test))

# PRODUCT
processed_text = preprocessing(fulszoveg)
data = instert_into_tfidf(processed_text)
result = auto_tag(data)

 


							
						

Gyereknapi vizualizáció: miért nem együtt ünnepel a magyar és az osztrák gyerek?

By | Data Visualization | One Comment

Már nagyon várják a hétvégét a magyar lányok és fiúk, hiszen itt a gyermeknap. Az osztrák vagy éppen thaiföldi lurkók nem ilyen lelkesek, ami nem csoda, nekik ugyanis még hosszú hónapokat kell várniuk e jeles alkalomra. Utánajártunk és látványos, interaktív grafikán ábrázoltuk, hogy a világ különböző tájain mikor ünneplik a gyermeknapot.

 

A nemzetközi gyermeknap hagyománya Törökországból ered, ahol először 1920-ban, majd 1925-ben tartották meg ezt az ünnepet április 23-án. AZ ENSZ 1954-ben hirdette meg az egyetemes gyermeknapot, melynek célja az volt, hogy minden ország megemlékezzen a toleranciáról és az empátiáról a gyermekeink testvériségén keresztül. Az ünnep jó alkalom a gyermekjóléti törekvések fókuszba állítására is.

Magyarországon már a 20. század első évtizedében is rendeztek gyermeknapot, de rendszeressé csak az ‘20-as években vált. 1931 és 1947 között – amikor a háború engedte – gyermekhetet tartottak májusban vagy júniusban. 1948-től kezdve ez a rendezvény is kommunista párt befolyása alá került. 1953-ig június első vasárnapján ünnepelték, majd ‘54-től kezdve ünnepeljük május utolsó vasárnapján a nemzetközi gyermeknapot hazánkban. A világban az év egészen különböző napjain tartják a gyermeknapot, de sok helyen a nemzetközi gyermeknap dátuma egyezményesen június 1-je lett.

A leggyakoribb a nyári ünneplés – ami tehát a június elsejei nemzetközi napnak köszönhető –, de akad tavaszi és őszi időpont is bőven. Téli időpontot leginkább a forró éghajlatú országokban találhatunk.

babygirl

Ők az anyukák kedvencei – látványos vizualizációk a trendi keresztnevekről

By | Big Data, Big Data News, Data Visualization | No Comments

Ezen a hétvégén lesz május első vasárnapja, amit Magyarországon 1925 óta az anyák napjaként ünneplünk. Az édesanyák első ajándéka újszülött gyermekeik számára a gondosan megválasztott keresztnév, mely életük végéig elkíséri őket. Anyák napja alkalmából a névadási trendeket vizsgáltuk az 1950-es évektől napjainkig.

 

Utánanéztünk, hogy a közel hét évtized alatt az édesanyák körében melyek voltak azok a leggyakoribb keresztnevek, amiket újszülött gyermekeiknek választottak, és hogy miként alakultak a névadási trendek Magyarországon.

Érdekes megfigyelni, hogy míg a fiúknál minden korszak között vannak átfedések, addig a lányoknál sokkal nagyobb a fluktuáció, és a top 15-ös listában többször is teljesen kicserélődnek a nevek. A látványos adatvizualizációkat figyelve – miként a való életben is – a szemünk láttára tűnnek el a Máriák és az Erzsébetek, és nem sokkal szerencsésebbek az Istvánok és a Józsefek sem. Az elemzésből kiderült, hogy míg a fiúknál már 2001 óta uralkodnak a Bencék, a lányoknál csak tíz évvel később kerültek az első helyre a Hannák.

Ráadásként pedig egy igazi kuriózum: a következő vizualizáción láthatod, hogy melyek a legnépszerűbb női és férfi keresztnevek Európa országaiban.

Európai trendek

Forrás: Belügyminisztérium Nyilvántartások Vezetéséért Felelős Helyettes Államtitkárság, Magyar Keresztnevek Tára
Vizualizáció: Flourish