blob: e8c0f87d1950e150408778a18746a6064e0a22df [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
19ngramme <- oringramme %>%
20 add_column(NSTOPW = sapply(oringramme$tokens,function(x) length(deleteStopwords(tolower(unlist(strsplit(x," "))),stopwords)))) %>%
21 # select(-matches("CO_TOKEN.*"), -tokens) %>%
22 select(-matches("CO_TOKEN.*")) %>% # keep tokens for interpretability
23 mutate(across(matches(".rank.*"), ~ replace_na(.x, 1000))) %>%
24 mutate(across(c("dice", "lfmd", "llr", "ld", "pmi"), ~ replace_na(.x, min(.x) - 1))) %>%
25 rename_at(syfeatures$innames, ~ syfeatures[syfeatures$innames==.x,]$synames ) %>%
26 mutate(across(everything(), ~ replace_na(.x, 0))) %>%
27 mutate(CO_IDIOM = as.factor(if_else(CO_IDIOM !=1, 0, 1))) # just two classes: 0 no idiom, 1 idiom
28
29covars <- 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")
30syvars <- c(syfeaturenames$synames,"NSTOPW")
31vars <- c(covars,syvars)
32
33fmla <- as.formula(paste("CO_IDIOM ~ ", paste(vars, collapse= "+")))
34fmlaco <- as.formula(paste("CO_IDIOM ~ ", paste(covars, collapse= "+")))
35fmlasy <- as.formula(paste("CO_IDIOM ~ ", paste(syvars, collapse= "+")))
36
37# Simple train/test split
38
39trainRows <- sample(nrow(ngramme), nrow(ngramme)*0.8, replace = FALSE)
40train <- ngramme[trainRows,]
41test <- ngramme[setdiff(1:nrow(ngramme),trainRows),]
42
43rf_classifier = randomForest(fmla, train, ntree=100, mtry=10, importance=TRUE)
44
45# only SY features
46# rf_classifier = randomForest(fmlasy, train, ntree=100, mtry=10, importance=TRUE)
47
48prediction_for_table <- predict(rf_classifier, test %>% select(-CO_IDIOM))
49
50# different cutoff for prediction
51# prediction_for_table <- predict(rf_classifier, test %>% select(-CO_IDIOM), cutoff = c(0.8, 0.2))
52
53confusion <- table(observed=test$CO_IDIOM,predicted=prediction_for_table)
54conf <- confusionMatrix(confusion)
55print(conf)
56varImpPlot(rf_classifier)
57
58# optional resampling with smote
59
60smoted.data <- SMOTE(fmla, subset(train, select = c("CO_IDIOM", vars)), perc.over = 1200, perc.under = 100)
61rf_classifier = randomForest(fmla, smoted.data, ntree=100, mtry=4, importance=TRUE)
62prediction_for_table <- predict(rf_classifier,test %>% select(-CO_IDIOM))
63confusion <- table(observed=test$CO_IDIOM,predicted=prediction_for_table)
64confusionMatrix(confusion)
65
66# Using estimates by random forest on entire dataset
67
68library(randomForest)
69rf_classifier_full = randomForest(fmla, data=ngramme, ntree=100, mtry=2, importance=TRUE, cutoff=c(0.8,0.2))
70rf_classifier_full
71varImpPlot(rf_classifier_full)
72
73# Feature ranking
74
75# rf features as table
76
77# correlated features seem to split their rankings
78
79rfranks<-importance(rf_classifier_full)[,3:4]
80
81# ttest
82
83idioms<-ngramme %>% filter(CO_IDIOM==1)
84nonidioms<-ngramme %>% filter(CO_IDIOM!=1)
85
86ttestPvalues<-sapply(vars,
87 function(sel) t.test(idioms[sel],nonidioms[sel])$p.value)
88
89# information gain
90# multiply by 1000 to avoid undersized bins
91# features are ranked individually not matter their correlation
92igain<-information.gain(fmla, data=ngramme%>%mutate_at(vars, ~ . * 1000),unit="log2")
93
94featureRanks<-cbind(rfranks,igain,ttestPvalues)
95
96#randomForestExplainer::explain_forest(rf_classifier )
97
98# averate estimates and feature ranks over 10 runs
99errrate<-0
100conf<-matrix(0,2,3)
101featureRanks<-matrix(0,4,length(vars))
102for (i in 1:10) {
103 # rfc =randomForest(fmla, data=ngramme, ntree=100, importance=TRUE)
104 rfc =randomForest(fmla, data=ngramme, ntree=100, importance=TRUE, cutoff=c(0.8,0.2))
105 errrate<-errrate+rfc$err.rate[100,1]
106 conf<-conf+rfc$confusion
107 featureRanks<-featureRanks+
108 cbind(importance(rfc)[,3:4],
109 sapply(vars,
110 function(sel) t.test(idioms[sel],nonidioms[sel])$p.value),
111 information.gain(fmla, data=ngramme%>%mutate_at(vars, ~ . * 1000),unit="log2"))
112 print(errrate/i)
113 conf1<-round(
114 rbind(
115 cbind(conf[,1:2]/i,(1-conf[,3]/i)*100),
116 c(100*diag(conf[,1:2])/colSums(conf[,1:2]),NA),
117 c(rowSums(conf[,1:2]/i),NA)),digits=2)
118 colnames(conf1)<-c("0","1","rec")
119 rownames(conf1)<-c("0","1","prec","sum")
120 print(conf1)
121}
122featureRanks<-featureRanks/10
123
124
125
126