Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
1
UMETNA INTELIGENCA Sklop 1: Novejši pristopi k predikciji v strojnem učenju laboratorijske vaje Stran predmeta: http://ucilnica.fri.uni-lj.si/course/view.php?id=81 Asistent: Zoran Bosnid, [email protected]
Vsebina vaj:
1) Uvod v okolje R: a) ureditev delovnega okolja in knjižnic b) uporabniški vmesnik, iskanje pomoči, c) osnovne operacije, razredi struktur (vector, matrix, factor, data.frame) d) generiranje naključnih števil, umetnih podatkovnih množic
2) Nadzorovano učenje v okolju R: a) branje podatkovne baze iz tekstovne datoteke b) predobdelava podatkov za učenje (manjkajoče vrednosti) c) klasifikacijski modeli, napovedovanje, d) regresijski modeli, napovedovanje e) ocenjevanje učenja (klasifikacijska točnost, rel. srednje kv. napaka) f) vizualizacija, izdelava grafov g) (ocenjevanje atributov: inf. prispevek, Gini, Relief)
3) Razlaga v klasifikaciji in regresiji a) Razlaga posameznih napovedi b) Razlaga posameznega atributa za celoten model c) Vizualizacija razlage
4) Individualno delo za seminarsko nalogo Seminarska naloga:
Za seminarsko nalogo bo vsak kandidat: 1) izbral ustrezen (umeten) problem in zgeneriral umetno podatkovno bazo za učenje predikcij, 2) izbral dva obstoječa algoritma za predikcijo: eden, ki bo po pričakovanju dokaj dobro rešil umetni problem, in eden,
ki bo po pričakovanju bolj slabo rešil umetni problem, 3) izbral eno realno bazo podatkov za učenje predikcij (npr. iz UCI repozitorija), 4) pognal oba algoritma za učenje predikcij na obeh problemih (umetnem in realnem) na učni množici in prikazal
uspešnost algoritmov na testni množici, 5) za obe domeni bo izbral 3 testne primere in bo vizualiziral razlago predikcij za te 3 testne primere za oba algoritma
(3X2X2 = 12 razlag primerov), 6) za obe domeni bo vizualiziral tudi razlago modela (2X2 = 4 razlage modelov), 7) svoje ugotovitve bo predstavil v pisnem poročilu, ki ga mora oddati najkasneje en dan pred začetkom predavanj iz
naslednjega sklopa. Seminarske naloge bodo ocenjene in ocena seminarske bo hkrati kandidatova ocena pri tem sklopu.
POROČILO: Pisno poročilo seminarske naloge je potrebno oddati v papirnati obliki - pod vrata kabineta prof. Kononenka in v elektronski obliki (oddaja preko strani na učilnici), najkasneje do četrtka, 18.3. do 12h.
2
1. Uvod v okolje R
http://www.r-project.org/ nastavitev delovnega okolja: workspace, delovna mapa
namestitev potrebnih paketov: tree, rpart, nnet, e1071, RWeka, randomForest
odpiranje vhodne datoteke, nalaganje datoteke s programsko kodo, komentiranje z znakom #
1.1. Ukazi
?funkcija odpre stran s pomočjo za funkcijo funkcija ??funkcija ali help.search(funkcija)
preišče vsebino vseh datotek s pomočjo za niz funkcija
example(funkcija) pokaže primer uporabe funkcije funkcija ls() vrne seznam vseh objektov v delovnem okolju source("datoteka.R") naloži programsko kodo iz vhodne datoteke datoteka.R history(n) prikaže zgodovino ukazov (zadnjih n vrstic)
1.2. Osnovna aritmetika
x <- 3 priredi spremenljivki x vrednost 3 x <- c(1,2,3,4) priredi spremenljivki x vektor s 4 elementi 1, 2, 3, 4 y <- c(x, 0, x) priredi y vektor, ki je združen vektor dveh vektorjev x, ločenih z ničlo 1/x izračuna 1/x in prikaže rezultat na konzoli z <- 2*x + y + 1 izračuna 2*x+y+1 in rezultat shrani v z 1:12 ali seq(1,12) generira zaporedje (vektor) z elementi 1,2,3,4,5,6,7,8,9,10,11,12 rep(3,5) generira vektor, ki vsebuje 5 ponovitev števila 3, torej: 3,3,3,3,3 izbor <- x > 13 izdela logični vektor (TRUE, FALSE), istoležen s komponentami x, ki so večje od 13,
in ga shrani v izbor
1.3. Osnovni in kompleksni tipi spremenljivk
character, numeric, factor – osnovni tipi (znakovni, številčni in diskretni – ta ima vnaprej določen nabor vrednosti), npr.:
#primer spremenljivke tipa factor:
> dnevi <- c("petek", "torek", "petek", "sreda", "torek")
> dnevi.factor <- as.factor(dnevi)
> dnevi.factor
[1] petek torek petek sreda torek
Levels: petek sreda torek
vector – enorazsežni vektor (vse vrednosti so istega tipa), npr. > a <- c("a","b","c",1) #R avtomatsko pretvori zadni element
> a
[1] "a" "b" "c" "1"
matrix – večdimenzionalni vektorji, vsi elementi so enakega osnovnega tipa (character, numeric ali factor),
data.frame – podatkovna zbirka vsak stolpec lahko vsebuje spremenljivke svojega tipa (primerno za različne tipe atributov!)
3
1.4. Funkcije za delo s podatkovnimi tipi
as.vector(argument)
as.matrix(argument)
as.data.frame(argument)
as.numeric(argument)
as.factor(argument)
as.character(argument)
pretvori argument v tip, ki ga določa pretvorbeni klic
m <- matrix(nrow=10, ncol=3)
dim(m), nrow(m), ncol(m) izdelamo matriko z 10 vrsticami in 3 stolpci vrne dimenzijo matrike, število vrstic, število stolpcev
rbind(m1, m2) združi m1 in m2 po vrsticah (imeti morata enako število stolpcev) cbind(m1, m2) združi m1 in m2 po stolpcih (imeti morata enako število vrstic) table(vec1, vec2) navzkrižno tabelira (prikaže frekvence) vrednosti dveh vektorjev data.frame(col1=..., col2=...) izdela podatkovno zbirko s stolpci col1, col2, ... head(data.frame) vrne začetne vrstice podatkovne zbirke names(data.frame) vrne imena stolpcev podatkovne zbirke
1.5. Naslavljanje elementov znotraj podatkovnih struktur
x[c(1,5,2)] naslavljanje z indeksi (izberemo 1., 5. in 2. element) x[x>10] naslavljanje z logičnim pogojem (izberemo elemente, ki so večji od 10) x[-c(1,5,2)] elemente izločamo z negativnimi indeksi (izberemo vse elementa razen 1., 5. in 2.) x[c('tretji','prvi')] naslavljanje vektorja z imeni komponent (poimenujemo jih z names(x) <- ...) t[c(1,5)] <- c(2,3) naslovljenim delom vektorja lahko priredimo vrednosti m[vrstica, stolpec] naslavljanje matrike s številko vrstice in stolpca m[,stolpec] naslavljanje (vseh vrstic in) celega stolpca m[vrstica,] naslavljanje določene vrstice (in celega stolpca) data.frame[,'spol']
data.frame$spol naslavljanje stolpcev podatkovne zbirke po imenu (npr. spol)
which(vektor) vrne indekse, za katere je vrednost logičnega vektorja vektor enaka TRUE
1.6. Pogoste funkcije
log, exp, sin, cos, tan, sqrt,
sum, mean, var, min, max matematične funkcije
length(x) dolžina vektorja x sort, order sort sortira elemente; order vrne vrstni red (rang) elementov sample(x, n, replace=T) generira n števil (s ponavljanjem, če replace=T) z intervala [1,x] rnorm(n, mean = 0, sd = 1) generira n števil, ki so porazdeljena po Gaussovi porazdelitvi
graf gostote verjetnosti: plot(density(rnorm(100))) runif(n, min=0, max=1) generira n števil, ki so porazdeljena po enakomerni porazdelitvi
plot(density(runif(10000)))
Primer 1: Generiranje umetnega problema (diskretni atributi, problem XOR)
# regresijski problem (XOR)
#določimo vrednosti atributov in ciljne vrednosti (R)
a1 <- as.factor(sample(c(0,1), 1001, replace = T))
a2 <- as.factor(sample(c(0,1), 1001, replace = T))
a3 <- as.factor(sample(c(0,1), 1001, replace = T))
R <- ifelse(a1 != a2, 1, 0)
#združimo vse v tempData
tempData <- data.frame(a1 = a1, a2 = a2, a3 = a3, R = R)
# razdelimo na učno (ima 1000 primerov) in testno množico (samo 1 primer)
ucna <- tempData[1:1000,]
primer <- tempData[1001,]
4
Primer 2: Generiranje umetnega problema (zvezni atributi, linearna kombinacija funkcij atributov)
# regresijski problem (linearna kombinacija funkcij posameznih atributov)
#določimo vrednosti atributov in ciljne vrednosti (R)
a1 <- sample(1:100, 1001, replace = T) / 100
a2 <- sample(1:100, 1001, replace = T) / 100
a3 <- sample(1:100, 1001, replace = T) / 100
R <- 1.5 * sin(2* pi * a1) + 0.9 * cos(2 * pi * a2) - a3
#združimo vse v tempData
tempData <- as.data.frame(cbind(a1 = a1, a2 = a2, a3 = a3, R = R))
Ideje za umetne probleme (glej vire)
Moji zapiski...
5
2. Nadzorovano učenje v okolju R
vgrajene podatkovne zbirke: help(package="datasets")
UCI ML repozitorij podatkov: http://archive.ics.uci.edu/ml/ (ali išči z Google-om niz "UCI ML"),
2.1. Branje tekstovnih datotek
Za branje zunanjih datotek uporabimo funkcijo read.table, ki ima naslednjo (osnovno) sintakso (za več glej
?read.table):
read.table(file,
header = FALSE, #ali imamo vrstico z imeni strolpcev
sep = "", #presledek med vrednostmi ("\t" je tabulator)
quote = "\"'", #simbol za navednice
dec = ".", #simbol za decimalno piko
row.names, #imena vrstic
col.names, #imena stolpcev
colClasses = NA, #tipi vhodnih spremenljivk
na.strings = "NA", #manjkajoče spremenljivke
nrows = -1, #največ dovoljeno vrstic za branje (-1 = max)
skip = 0, #koliko vrstic na začetku naj preskoči
comment.char = "#", #vrstice, ki jih ignoriramo
)
Primer: branje datoteke auto-mpg.data iz UCI repozitorija.
Opisi atributov (auto-mpg.names) so naslednji:
1. mpg: continuous 2. cylinders: multi-valued discrete 3. displacement: continuous 4. horsepower: continuous 5. weight: continuous 6. acceleration: continuous 7. model year: multi-valued discrete 8. origin: multi-valued discrete 9. car name: string (unique for each instance)
podatki <- read.table("auto-mpg.data.txt",
colClasses = c('numeric','numeric',rep('numeric',4),"numeric", "numeric", "character"),
col.names=c('mpg','cylinders','dis','horse','weight','accel','year','origin','name'),
na.strings="?")
2.2. Pogoste funkcije za opisovanje in obdelavo podatkovnih zbirk
str(podatki) vrne kratek opis STRukture podatkovne zbirke summary(podatki) izračuna kratke statistike atributov complete.cases(podatki) vrne logični vektor s komponentami, ki predstavljajo, ali ima
primer vse vrednosti znane podatki[complete.cases(podatki),] izbere samo vrstice, ki imajo vse znane vrednosti atributov
6
2.3. Klasifikacijski in regresijski modeli, napovedovanje
Modeliranje in napovedovanje:
napovedni model zgradimo s sintakso: funkcija(formula, ucna.mnozica)
napovedi za testne primere izračunamo s sintakso: predict(model, testna.mnozica)
formula je zapis odvisnosti med spremenljivkami, katero želimo, da model modelira (npr., če želimo iz vseh preostalih atributov napovedovati vrednost atributa z imenom mpg, zapišemo kot formulo mpg ~ . (beri: modeliraj mpg v odvisnosti (znak ~) od vseh (znak .) ostalih atributov)
Učno in testno množico je za klasifikacijo in regresijo potrebno pripraviti drugače, in sicer:
razred, ki ga napovedujemo pri klasifikacijskem problemu, mora biti v podatkovni zbirki tipa factor (torej diskretna spremenljivka)
označba, ki jo napovedujemo pri regresijskem problemu, mora biti v podatkovni zbirki tipa numeric (torej navadna številska spremenljivka)
Klasifikacijski in regresijski modeli:
primeri funkcij klasifikacijskih modelov: rpart (klasifikacijsko drevo), svm, nnet, naiveBayes, IBk (k najbližjih sosedov – iz razreda RWeka),
primeri funkcij regresijskih modelov: rpart (regresijsko drevo), lr (linearna regresija), svm, nnet, randomForest
Primer 1: gradnja klasfifikatorja kNN
#denimo, da imamo podano množico podatkov z imenom dataset, ki ima diskretni razred age
#razdelimo dataset na učno in testno množico
testna.idx <- sample(nrow(dataset), 15) #naključno izberemo 15 testnih primerov
testna <- dataset[testna.idx, ]
ucna <- dataset[-testna.idx, ]
#zgradimo klasifikator
library(RWeka) #potrebno za funkcijo IBk
model.svm <- svm(age ~ ., ucna)]) #age je faktorska spremenljivka
#modelu lahko opcijsko nastavimo tudi število sosedov: control = Weka_control(K = 5)
#napovemo vrednosti testnim primerom
napovedi <- svm(model.svm, testna)
Primer 2: gradnja regresorja randomForest
#zgradimo regresor
library(randomForest) #potrebno za funkcijo randomForest
model.rf <- randomForest(age.cont ~ ., ucna) #age.cont je numerična spremenljivka
#napovemo vrednosti testnim primerom
napovedi <- svm(model.svm, testna)
2.4. Generične funkcije za delo z modeli
Spodaj so naštete funkcije, ki so implementirane za večino napovednih modelov. Te funkcije se odzivajo drugače glede na vrsto modela, ki ga podamo kot argument. Ni nujno, da je za vsak model implementirana vsaka od spodaj naštetih funkcij. print(model) izpiše strukturo ali vsebino modela predict(model, data) napove vrednosti testnim primerom data z uporabo modela model plot(model) grafično prikaže model summary(model) poda jedrnat opis modela formula(model) vrne formulo, s katero je bil zgrajen model deviance(model) vrne razlike med pravimi vrednostmi razredov / označb primerov in
napovedmi modela za iste primere
7
2.5. Ocenjevanje učenja
Klasifikacijska točnost
Je mera za ocenjevanje kakovosti klasifikacijskega modela. Definirana je kot delež primerov, ki so klasificirani pravilno. Denimo, da imamo:
testno množico z imenom testna
razred z imenom razred
napovedi razreda z imenom napovedi
Klasifikacijsko točnost izračunamo z izrazom
length(which(testna$razred == napovedi)) / length(napovedi)
ali lepše, če izdelamo funkcijo klas.tocnost:
klas.tocnost <- function(razredi, napovedi) { #formalni argumenti funkcije
odstotek <- length(which(razredi == napovedi)) / length(napovedi)
return(odstotek)
}
in klasifikacijsko točnost ocenimo s klicem:
klas.tocnost(testna$razred, napovedi)
Relativna srednja kvadratna napaka
Je mera za ocenjevanje kakovosti regresijskega modela. Definirana je kot razmerje med (i) srednjo kvadratno napako razlik med napovedmi in pravimi regresijskimi označbami ter (i) srednjo kvadratno napako referenčnega modela, ki napoveduje povprečno vrednost označb na učni množici.
Relativno srednjo kvadratno napako (rmse) lahko izračunamo s funkcijo:
rmse.napaka <- function(oznacbe, napovedi, oznacbe.ucna)
{
rmse <- sum((oznacbe-napovedi)^2)/ sum((oznacbe-mean(oznacbe.ucna))^2)
return(rmse)
}
2.6. Programski konstrukti
if (pogoj) stavek1 else stavek2 pogojni stavek
while (pogoj) stavki zank
for (var in seznam) stavki zanka
imefun <- function(arg1, arg2, ...) { koda }
deklaracija funkcije
DDoommaaččaa nnaallooggaa:: NNaappiiššii ffuunnkkcciijjee zzaa oossttaallee mmeerree zzaa oocceennjjeevvaannjjee kkaakkoovvoossttii uuččeennjjaa iinn jjiihh uuppoorraabbii vv ddoommaaččii
nnaallooggii ((sseennzziittiivvnnoosstt,, ssppeecciiffiiččnnoosstt,, pprreecciizznnoosstt,, pprriikklliicc iittdd..))!!
8
3. Razlaga napovedi in atributov
3.1. Literatura
ŠTRUMBELJ, Erik, KONONENKO, Igor, ROBNIK ŠIKONJA, Marko. Explaining instance classifications with
interactions of subsets of feature values. Data knowl. eng.. , Oct. 2009, vol. 68, no. 10, str. 886-904
ŠTRUMBELJ, Erik, KONONENKO, Igor. An Eficient Explanation of Individual Classifications using Game Theory, Journal of Machine Learning Research, 11(1):1—18, 2010. (in press)
3.2. Primeri in pomen razlage posameznih primerov
9
3.3. Razlaga posameznih napovedi v okolju R
Za razlago napovedi posameznih primerov uporabljamo funkcijo explainInstance, ki ima naslednjo sintakso:
explainInstance <- function(my.model, my.data, my.instance, m=200)
# my.model | regresijski model naučen na podatkih
# my.data | učni podatki
# my.instance | primer, ki ga želimo razložiti
# m | število vzorcev (privzeta vrednost je 200)
Za podatke mora veljati naslednje:
my.data ima N stolpcev, prvih N-1 so atributi, zadnji je regresijska spremenljivka
atributi so bodisi numerični med 0 in 1 ali faktor s poljubno mnogo vrednostmi
podani model ima pripadajočo funkcijo predict() Primer: razlaga napovedi poasmeznega primera (koraki)
1.) Zgradimo model na učni množici
vzorec <- sample(nrow(x), 3) #izberemo 3 naključne primere
ucna <- x[-vzorec,]
testna <- x[vzorec,]
model.r <- randomForest(mpg ~ ., data=ucna)
2.) Preverimo, ali funkcija predict vrača regresijske vrednosti (ali verjetnosti razredov pri klasifikaciji). Npr.:
> predict(model.r, testna)
371 197 172
29.02856 29.84869 24.42335
=> OK! Če to ne drži, je potrebno spremeniti kodo funkcije explainInstance, da bo delovala pravilno. 3.) Razložimo posamezno napoved izbranega primera:
> explainInstance(model.r, ucna, testna[1,], 200)
$explanation ####prispevki atributov####
[1] 0.0000000 1.0462405 1.8190076 1.0564856 1.1901503 -0.2540223 3.1870371
$instance
mpg cylinders dis horse weight accel year origin
371 0.31 0.4 0.112 0.85 0.2575 0.162 0.82 0.1
$prediction
371
0.29
3.4. Primeri in pomen razlage celega modela (vseh atributov)
10
3.5. Razlaga celega modela v okolju R
Razlagi celega modela pristopamo z izračunom razlage vsakega atributa posebej. Ker so te razlage med seboj neodvisne, jih na koncu predstavimo kot razlago celega modela. Za razlago posameznega modela uporabljamo funkciji explainDiscreteAtr in explainContAtr glede na to, ali je atribut diskreten (faktor) ali zvezen (numeričen). Funkciji imata naslednjo sintakso:
explainDiscreteAtr <- function(my.model, ucna.mnozica, st.atributa, samples=200)
# my.model | regresijski model, naučen na podatkih
# ucna.mnozica | učni podatki
# st.atributa | zaporedna številka atributa, za katerega bomo računali prispevek
# samples | število vzorcev (privzeta vrednost je 200)
explainContAtr <- function(my.model, ucna.mnozica, st.atributa, res=50, samples=250)
# my.model | regresijski model, naučen na podatkih
# ucna.mnozica | učni podatki
# st.atributa | zaporedna številka atributa, za katerega bomo računali prispevek
# res | ločljivost, s katero vzorčimo vrednosti prispevkov
# samples | število vzorcev (privzeta vrednost je 200)
Primer: razlaga napovedi posameznega primera (koraki)
1.) Zgradimo model na učni množici
regression.model.tree <- tree(R ~ ., data = ucna)
2.) Izračunamo razlago dveh zveznih atributov
# razlaga atributov 1 in 2
razlaga.tree.1 <- explainContAtr(regression.model.tree, ucna, 1)
razlaga.tree.2 <- explainContAtr(regression.model.tree, ucna, 2)
3.) Vizualiziramo na istem grafu
#risanje grafa
par(mfrow=c(1,2))
plot(razlaga.tree.1$x, razlaga.tree.1$prispevki, ylim = c(-1.5,1.5), xlab = "vrednost 1.
atributa", ylab = "prispevek (z modro standardni odklon); odlocitveno drevo", pch = 15)
points(razlaga.tree.1$x, razlaga.tree.1$deviacije, col = "blue", pch = 15)
plot(razlaga.tree.2$x, razlaga.tree.2$prispevki, ylim = c(-1.5,1.5), xlab = "vrednost 2.
atributa", ylab = "prispevek (z modro standardni odklon); odlocitveno drevo", pch = 16)
points(razlaga.tree.1$x, razlaga.tree.1$deviacije, col = "blue", pch = 16)
Moji zapiski...
11
4. Vizualizacija in grafika v okolju R
4.1. Primeri vizualizacij s spleta
Primeri grafov na : http://www.stat.auckland.ac.nz/~paul/RGraphics/rgraphics.html
4.2. Funkcije za vizualizacijo podatkov
Primarne funkcije (ustvarijo novo grafično okno)
UKAZ PRIMER POMEN plot(x, y) plot(x$horse, x$accel) nariše graf točk vektorja x proti y coplot(a ~ b | c +d ) coplot( x$horse ~ x$accel | x$year) serija grafov a=f(b), pogojevanih z
vrednosmi spremenljivk c in d pairs(dataset) pairs(quake) (knjižnica rpart) serija grafov parov vseh atributov hist(vector)
hist(t$year, prob=T)
lines(density(t$year)) histogram vektorja
Pomožne grafične funkcije (naknadno dorisujejo v obstoječe grafično okno)
points(x,y) v graf doriše množico točk (x,y) lines(x,y) točke, podane z (x,y) poveže z daljicami text(x, y, besedilo) na koordinate x in y napiše besedilo abline(a, b) doda premico s presečiščem a in strmino b polygon(x,y) izriše poligon z oglišči v točkah (x,y) axis(side) označi osi na strani side grafa (vrednosti pomenijo: 1-spodaj, 2, levo, 3-
zgoraj, 4-desno) rect(xleft, ybottom, xright,
ytop, density = NULL,
angle = 45)
izriše pravokotnih na koordinatah s senčenjem, ki ga opredeljujeta density in angle
4.3. Argumenti funkcij in nastavitve splošnih grafičnih parametrov
Naslednje argumente lahko podamo pri večini grafičnih funkcij iz točke 4.2.
type= način izrisovanja podatkov. Kot vrednost lahko podamo "p" (points), "l"
(lines), "b" (both=points+lines). xlab=, ylab= oznaka vodoravne in navpične osi main= naziv grafa sub= podnaslov grafa pch= znak, ki se uporablja za izris točke na grafu (point character). Lahko
direktno podamo znak (npr. "+") ali pa številsko vrednost 0-25 za izris posebnih znakov (glej dokumentacijo)
lty= vrsta črte (line type) lwd= debelina črte (line width) col= barva cex= faktor povečave znakov (character expansion)
Nastavitve privzetih grafičnih parametrov lahko tudi pregledujemo in spremenimo njihove vrednosti z ukazom
par(). Ta ukaz prikaže vrednosti vseh parametrov. Privzete vrednosti lahko (trajno) spremenimo z ukazom: stari.par <- par(name=setting) # pri tem se v stari.par starijo predhodne vrednosti
Primer: stari <- par(mfrow=c(3,2)) # izrisuje grafe v mreži oblike 3x2
12
Primer: primer vizualizacije (spletni vir)
groups <- c("cows", "sheep", "horses", "elephants", "giraffes")
males <- sample(1:10, 5)
females <- sample(1:10, 5)
par(mar=c(0.5, 5, 0.5, 1))
plot.new()
plot.window(xlim=c(-10, 10), ylim=c(-1.5, 5.5))
ticks <- seq(-10, 10, 5)
y <- 1:5
h <- 0.2
lines(rep(0, 2), c(-1.5, 5.5), col="grey")
segments(-10, y, 10, y, lty="dotted")
rect(-males, y-h, 0, y+h, col="dark grey")
rect(0, y-h, females, y+h, col="light grey")
mtext(groups, at=y, adj=1, side=2, las=2)
par(cex.axis=0.5, mex=0.5)
axis(1, at=ticks, labels=abs(ticks), pos=0)
tw <- 1.5*strwidth("females")
rect(-tw, -1-h, 0, -1+h, col="dark grey")
rect(0, -1-h, tw, -1+h, col="light grey")
text(0, -1, "males", pos=2)
text(0, -1, "females", pos=4)
box("inner", col="grey")
Moji zapiski...