Skip to content

Instantly share code, notes, and snippets.

@mjlassila
Created October 15, 2012 07:15
Show Gist options
  • Save mjlassila/3891171 to your computer and use it in GitHub Desktop.
Save mjlassila/3891171 to your computer and use it in GitHub Desktop.
ITIA41 - Viikkoharjoitusten esimerkkiratkaisuja 4--
#### Tehtävä 2 ####
# NLTK:n word_tokenize -metodia tulisi käyttää vain yksittäisiin lauseisiin. Työnkulku
# raakatekstistä pilkotuksi tekstiksi voisi olla esimerkiksi tällainen:
from nltk tokenize import *
# Ladataan tajunnanvirtaa.
text = "Vippaa mulle $5,55 ja laula lujaa. Jollen laula, niin et laula."
tokenized_text = [word for sentence in sent_tokenize(text) for word in word_tokenize(sentence)]
# Ero suoraan word_tokenize-metodilla käsiteltyyn tekstiin saadaan selville esimerkiksi näin:
>>> tokenized_text
['Vippaa', 'mulle', '$', '5,55', 'ja', 'laula', 'lujaa', '.', 'Jollen', 'laula', ',', 'niin', 'et'
, 'laula', '.']
# Huomataan, että välimerkit ovat eroteltuna.
# Pilkotaan teksti suoraan word_tokenize() -metodilla.
>>> hastily_tokenized_text = word_tokenize(text)
>>> set(hastily_tokenized_text).difference(tokenized_text)
set(['lujaa.'])
# Voidaan huomata, että käytettäessä word_tokenize() -metodia kerralla useampaan lauseeseen,
# tokenisaatio ei toimi oikein - välimerkki jää mukaan.
# Tutkitaan vielä, miten wordpunct-tokenisoitu teksti eroaa word-tokenisoituun tekstiin:
>>> wordpunct_tokenized_text = wordpunct_tokenize(text)
set(wordpunct_tokenized_text).difference(tokenized_text)
set(['5', '55'])
# Pilkkuerotteinen hintatieto on katkennut. Wordpunct-tokenisaatio toimii word_tokenisaatioon verrattuna
# aggressiivisemmin; se katkaisee tekstin jokaisen välimerkin kohdalta
# riippumatta välimerkin esiintymisyhteydesä.
#### Tehtävä 3 ####
# Luovuutta käyttäen kaikki olivat saaneet ratkaistua tehtävän jo edellisellä kerralla vaikka tehtävän opastus
# oli tuolloin vajavainen. Eräs vaihtoehtoinen ratkaisu voisi olla näin, tokenisointia käyttäen:
from nltk.tokenize import *
text = open("/home/courses/itima41/kalevala.txt").read()
punctuation = [',','.',';','!']
tokenized_text = [word for sentence in sent_tokenize(text) for word in word_tokenize(sentence)]
lowercase_words_only = [token.lower() for token in tokenized_text if token not in punctuation]
#### Tehtävä 4 ####
# Vertailemalla stemmauksen tuloksia saattoi huomata, että Lancaster on Porteriin
# ja Snowballiin verrattuna huomattavasti aggressiivisempi stemmaaja. Ylistemmauksen riski on siis
# huomattava. Pääsääntöisesti stemmatessa kannattaa käyttää Snowballia, jos vaihtoehtoina ovat kolme
# tehtävässä mainittua stemmaajaa. Snowball on englannin kielen osalta Porter-stemmaajan parannettu versio
# ja lisäksi se tukee lukuisia muita kieliä -- myös suomea.
# Tässä tehtävässä Snowball-stemmaajan tulosteessa näkyneet u-kirjaimet viittaavat tulosteessa
# käytettyyn merkistöön. Merkistöasioita käsitellään yksityiskohtaisesti seitsemänsissä
# viikkoharjoituksissa ja luennoilla
# Eräs tapa ratkaista tehtävä:
from nltk.stem import PorterStemmer, SnowballStemmer, LancasterStemmer
from nltk.tokenize import word_tokenize, sent_tokenize
wikileaks_text = open('/home/courses/itima41/wikileaks-estonia.txt','r').read()
wikileaks_snippet = wikileaks_text[338:]
wikileaks_tokenized = [word for sentence in sent_tokenize(wikileaks_snippet) for word in word_tokenize(sentence)]
# Otetaan käyttöön stemmerit
porter_stemmer = PorterStemmer()
snowball_stemmer = SnowballStemmer('english')
lancaster_stemmer = LancasterStemmer()
# Tehdään stemmaukset
wikileaks_porter = [porter_stemmer.stem(token) for token in wikileaks_tokenized]
wikileaks_snowball = [snowball_stemmer.stem(token) for token in wikileaks_tokenized]
wikileaks_lancaster = [lancaster_stemmer.stem(token) for token in wikileaks_tokenized]
#### Tehtävä 5 ####
# Tehtävään oli jäänyt tulkinnanvaraa, haettiinko sanaesiintymiä vai sanoja.
# Hyväksyin molemmat vaihtoehdot. Kuten moni oli kommentoinut, päätteisiin perustuva adverbin
# tunnistus ei ole yksin riittävä keino tekstissä esiintyvien adverbien erottelemiseksi.
# Päätteisiin perustuva tunnistus on samaan aikaan liian karkea (moni ei-advenbi päättyy
# myös ly-päätteeseen) ja liian suppea (epäsäännöllisiä advenbeja on paljon).
# Eräs tapa ratkaista tehtävä - listaten kunkin sanan vain kerran:
import re
from nltk.book import *
word_occurrences = set(text4)
potential_adverbs = [word for word in word_occurrences if word.endswith('ly')]
# Vaihtoehtoisesti säännöllisillä lausekkeilla
potential_adverbs_with_regexp = [word for word in word_occurrences if re.findall('ly$',word)])
# Verrataan ratkaisujen eroja
set(potential_adverbs).difference(potential_adverbs_with_regexp)
set([])
# ==> Ei eroa.
#### Tehtävä 6 ####
# Tätä tehtävää hankaloitti, jos raakatekstin sijaan ratkaisussa oli jostain syystä päätynyt käyttämään
# lähestymistapaa, jossa teksti pilkottiin aluksi osiksi. Helpoiten tehtävän sai ratkaistua käsittelemällä
# pilkkomatonta tekstiä.
# Eräs tapa:
import re
wikileaks_text = open('/home/courses/itima41/wikileaks-estonia.txt','r').read()
re.findall(r'\b[0-9]{2,4}\-[0-9]{2,4}\b',wikileaks_text)
# Malliratkaisun säännöllisessä lausekkeessa oleva \b -ilmaus tarkoittaa sanarajan sijaintia, l. # välilyöntiä, pistettä, rivinvaihtoa, muuta välimerkkiä. Vrt. \b-ilmaus on merkkijonoille sama
# kuin ilmaukset ^ ja $ riveille.
# Olen antanut puoli pistettä jos säännöllinen lauseke on pääpiirteittäin oikein. Täydet pisteet on saanut,
# jos komentolauseke palauttaa ainoastaan vuosivälejä kuvaavat merkkijonot, ilman ylimääräisiä merkkejä.
#### Tehtävä 7 ####
# Kuten tehtävä 6 , tämäkin tehtävä oli helpointa ratkaista suoraan raakatekstin pohjalta.
# Jos teksti oli ositettu listaksi, joka koostui sanoista ja välimerkeistä, eräs tehtävässä eteenpäin
# vienyt ratkaisu oli luoda tekstistä NLTK Text komennolla:
teksti = nltk.Text(ositettu_teksti)
# jolloin teksti-muuttujassa olevan NLTK Text:n sisältöä saattoi käsitellä metodilla teksti.findall().
# NLTK Text:llä on lisäksi monia muita metodeita, kuten concordance() ja count(), joihin olemme
# tutustuneet jo aiemmin.
# Alla muutama tapa ratkaista tehtävä säännöllisten lausekkeiden avulla:
import re
wikileaks_text = open('/home/courses/itima41/wikileaks-estonia.txt','r').read()
re.findall('[Cc][Yy][Bb][Ee][Rr]\s[A-Za-z0-9]*', wikileaks_text)
re.findall('cyber\s[A-Za-z0-9]*',wikileaks_text, re.IGNORECASE)
re.findall(r'(?i)cyber\s\w*', wikileaks_text)
#### Tehtävä 8 ####
re.split(r'\W', teksti)
re.split('\W+', teksti)
# Joissain ratkaisuissa tehtävää oli tulkittu siten, ettei tekstin tyhjät merkit -- kuten välilyönnit ja
# rivivaihdot -- ole merkkejä. Jos vastaus osoitti muuten, että asia on ymmärrety, annoin vastauksesta
# täydet pisteet.
# Moni huomasi, että \W yksinään tuottaa tyhjiä listan alkioita, jos katkaisukohtana oleva merkki tai
# täsmäävien merkkien yhdistelmä toistuu. Tämän voi välttää käyttämällä + lisämäärettä, jolloin
# täsmääminen tapahtuu vain yhden kerran per merkkien yhdistelmä.
# Suomenkielistä tekstiä käsitellessä pitää muistaa, että säännöllisten lausekkeiden näkökulmasta skandit
# ovat erikoismerkkejä. Tästä syystä esimerkiksi fraasi "Härmän häjyt höyrypäät" pilkkoontuii
# merkkijonoiksi ['H', 'rm', 'n', 'h', 'jyt', 'h', 'yryp', 't'] katkaistaessa fraasi säännöllisellä
# lausekkeella \W+
#### Tehtävä 9 ####
# Tehtävänannossa oli virhe. Tarkoituksena oli, että tässä yhdeksännessä tehtävässä olisi tulostettu ne
# merkkijonot, jotka päättyvät suffiksiin. Tehtävänannon viimeinen lause ("Tulosta vain nämä merkkijonot")
# kuitenkin johti harhaan. Pulmapalstalla korjatussa tehtävänannossa viimeinen lause kuuluu:
# "Tulosta vain nämä merkkijonot (sanan esiintymät)."
# Arvostelussa on hyväksytty sekä alkuperäisen että korjatun tehtävänannon mukaan laaditut ratkaisut.
# Alla malliratkaisu korjatun tehtävänannon mukaisena.
from nltk.tokenize import *
text = open('/home/courses/itima41/wikileaks-estonia.txt').read()
suffixes = ['ing', 'ly', 'ed', 'ious', 'ies', 'ive', 'es','ment','er']
tokenized_text = word_tokenize(text)
for token in tokenized_text:
for suffix in suffixes:
if token.endswith(suffix):
print token
#### Tehtävä 10 ####
# Tehtävän 9 virheellisyys vaikutti myös tämän tehtävän suoritukseen. Tämä on otettu huomioon arvostelussa.
# Puuttunut pohdintaosuus vaikutti pistemäärään.
# Tiedonhaussa stemmaus parantaa haun kattavuutta, mutta heikentää tarkkuutta. Etenkin silloin kun käytetyn
# stemmerin tuottamat sanan juuret ovat erittäin lyhyitä -- kuten esimerkiksi Lancaster-stemmeriä
# käytettäessä -- merkitykseltään tyystin poikkeavat sanat voivat stemmatessa saada saman juuren.
# Hakutuloksissa tämä näkyy niin, että tulosjoukossa voi olla täysin hakulauseeseen liittymättömiä
# dokumentteja.
from nltk.tokenize import *
text = open('/home/courses/itima41/wikileaks-estonia.txt').read()
suffixes = ['ing', 'ly', 'ed', 'ious', 'ies', 'ive', 'es','ment','er']
tokenized_text = word_tokenize(text)
for token in tokenized_text:
for suffix in suffixes:
if token.endswith(suffix):
print (token[:-len(suffix)])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment