blob: 1310b6be5b5bb9c02e0f234e135f7143f29afed5 [file] [log] [blame]
Marc Kupietzc3bf3502021-02-19 17:18:57 +01001library(caret)
2library(tidyverse)
3library(DMwR)
4library(randomForest)
5library(FSelector)
6# library(randomForestExplainer)
7# may need to: options(expressions = 5e5) to avoid stackoverflow for installing package
8
9setwd(dirname(rstudioapi::getSourceEditorContext()$path))
10stopwords <- readLines(con = "../data/stopwords.txt",encoding="UTF-8")
11oringramme <- read.csv("../data/gold03_anno_ml_synfeat_nstopw.csv", header = TRUE, sep = "\t", dec=".", quote="", encoding="UTF-8",stringsAsFactors=FALSE)
12syfeaturenames <- read.csv("../data/syfeatures.tsv", header = TRUE, sep = "\t", dec=".", quote="", encoding="UTF-8",stringsAsFactors=FALSE)
13# syfeaturenames$navalue<-sapply(syfeaturenames$navalue,as.numeric)
14
15deleteStopwords = function(wl, stopwords = NULL) {
16 wl[!(wl %in% stopwords)]
17}
18
Marc Kupietz631800f2021-02-19 17:27:26 +010019oringramme <- oringramme %>%
20 filter(CO_IDIOM < 2) # just two classes: 0 no idiom, 1 idiom
21
Marc Kupietzc3bf3502021-02-19 17:18:57 +010022ngramme <- oringramme %>%
23 add_column(NSTOPW = sapply(oringramme$tokens,function(x) length(deleteStopwords(tolower(unlist(strsplit(x," "))),stopwords)))) %>%
24 # select(-matches("CO_TOKEN.*"), -tokens) %>%
25 select(-matches("CO_TOKEN.*")) %>% # keep tokens for interpretability
26 mutate(across(matches(".rank.*"), ~ replace_na(.x, 1000))) %>%
27 mutate(across(c("dice", "lfmd", "llr", "ld", "pmi"), ~ replace_na(.x, min(.x) - 1))) %>%
28 rename_at(syfeatures$innames, ~ syfeatures[syfeatures$innames==.x,]$synames ) %>%
29 mutate(across(everything(), ~ replace_na(.x, 0))) %>%
Marc Kupietz631800f2021-02-19 17:27:26 +010030 mutate(CO_IDIOM = as.factor(if_else(CO_IDIOM !=1, "0", "1")))
Marc Kupietzc3bf3502021-02-19 17:18:57 +010031
32covars <- c("CO_LL", "CO_Z", "CO_G", "CO_T", "CO_LOGDICE", "CO_PMI", "CO_MI3", "CO_DEREKO", "CO_SGT", "CO_WIN5_VEC","CO_WIN5_VEC_AUTOSEM")
33syvars <- c(syfeaturenames$synames,"NSTOPW")
34vars <- c(covars,syvars)
35
36fmla <- as.formula(paste("CO_IDIOM ~ ", paste(vars, collapse= "+")))
37fmlaco <- as.formula(paste("CO_IDIOM ~ ", paste(covars, collapse= "+")))
38fmlasy <- as.formula(paste("CO_IDIOM ~ ", paste(syvars, collapse= "+")))
39
40# Simple train/test split
41
42trainRows <- sample(nrow(ngramme), nrow(ngramme)*0.8, replace = FALSE)
43train <- ngramme[trainRows,]
44test <- ngramme[setdiff(1:nrow(ngramme),trainRows),]
45
46rf_classifier = randomForest(fmla, train, ntree=100, mtry=10, importance=TRUE)
47
48# only SY features
49# rf_classifier = randomForest(fmlasy, train, ntree=100, mtry=10, importance=TRUE)
50
51prediction_for_table <- predict(rf_classifier, test %>% select(-CO_IDIOM))
52
53# different cutoff for prediction
54# prediction_for_table <- predict(rf_classifier, test %>% select(-CO_IDIOM), cutoff = c(0.8, 0.2))
55
56confusion <- table(observed=test$CO_IDIOM,predicted=prediction_for_table)
57conf <- confusionMatrix(confusion)
58print(conf)
59varImpPlot(rf_classifier)
60
61# optional resampling with smote
62
63smoted.data <- SMOTE(fmla, subset(train, select = c("CO_IDIOM", vars)), perc.over = 1200, perc.under = 100)
64rf_classifier = randomForest(fmla, smoted.data, ntree=100, mtry=4, importance=TRUE)
65prediction_for_table <- predict(rf_classifier,test %>% select(-CO_IDIOM))
66confusion <- table(observed=test$CO_IDIOM,predicted=prediction_for_table)
67confusionMatrix(confusion)
68
69# Using estimates by random forest on entire dataset
70
71library(randomForest)
72rf_classifier_full = randomForest(fmla, data=ngramme, ntree=100, mtry=2, importance=TRUE, cutoff=c(0.8,0.2))
73rf_classifier_full
74varImpPlot(rf_classifier_full)
75
76# Feature ranking
77
78# rf features as table
79
80# correlated features seem to split their rankings
81
82rfranks<-importance(rf_classifier_full)[,3:4]
83
84# ttest
85
86idioms<-ngramme %>% filter(CO_IDIOM==1)
87nonidioms<-ngramme %>% filter(CO_IDIOM!=1)
88
89ttestPvalues<-sapply(vars,
90 function(sel) t.test(idioms[sel],nonidioms[sel])$p.value)
91
92# information gain
93# multiply by 1000 to avoid undersized bins
94# features are ranked individually not matter their correlation
95igain<-information.gain(fmla, data=ngramme%>%mutate_at(vars, ~ . * 1000),unit="log2")
96
97featureRanks<-cbind(rfranks,igain,ttestPvalues)
98
99#randomForestExplainer::explain_forest(rf_classifier )
100
101# averate estimates and feature ranks over 10 runs
102errrate<-0
103conf<-matrix(0,2,3)
104featureRanks<-matrix(0,4,length(vars))
105for (i in 1:10) {
106 # rfc =randomForest(fmla, data=ngramme, ntree=100, importance=TRUE)
107 rfc =randomForest(fmla, data=ngramme, ntree=100, importance=TRUE, cutoff=c(0.8,0.2))
108 errrate<-errrate+rfc$err.rate[100,1]
109 conf<-conf+rfc$confusion
110 featureRanks<-featureRanks+
111 cbind(importance(rfc)[,3:4],
112 sapply(vars,
113 function(sel) t.test(idioms[sel],nonidioms[sel])$p.value),
114 information.gain(fmla, data=ngramme%>%mutate_at(vars, ~ . * 1000),unit="log2"))
115 print(errrate/i)
116 conf1<-round(
117 rbind(
118 cbind(conf[,1:2]/i,(1-conf[,3]/i)*100),
119 c(100*diag(conf[,1:2])/colSums(conf[,1:2]),NA),
120 c(rowSums(conf[,1:2]/i),NA)),digits=2)
121 colnames(conf1)<-c("0","1","rec")
122 rownames(conf1)<-c("0","1","prec","sum")
123 print(conf1)
124}
125featureRanks<-featureRanks/10
126
127
128
129