Clouded our vision, the dark side has. But wisdom and style, we will find.
library(caret)
## Loading required package: ggplot2
## Loading required package: lattice
library(pROC)
## Type 'citation("pROC")' for a citation.
##
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
##
## cov, smooth, var
correct_answer: did the response answer the question
response_length: longer and nuanced vs short and direct
sentiment_score: humans tend to display stronger sentiments
response_time: instantaneous?
df_combined <- read.csv("df_combined.csv", header = TRUE)
head(df_combined)
## question answer
## 1 Who is Luke Skywalker's father? Darth Vader.
## 2 What is the name of Han Solo's ship? The Millennium Falcon.
## 3 What color is Yoda's lightsaber? Green.
## 4 Who is the leader of the Rebel Alliance? Mon Mothma.
## 5 What species is Chewbacca? Wookiee.
## 6 What planet does Princess Leia come from? Alderaan.
## response_type correct_answer response_length sentiment_score response_time
## 1 Machine No 12 -0.01 1.41
## 2 Machine No 21 0.00 0.77
## 3 Machine No 9 -0.35 1.85
## 4 Human Yes 22 0.22 2.29
## 5 Human No 15 0.71 2.98
## 6 Machine Yes 13 0.05 1.51
set.seed(666)
train_index <- sample(1:nrow(df_combined), 0.7 * nrow(df_combined))
valid_index <- setdiff(1:nrow(df_combined), train_index)
Include only response_length, sentiment_score, and response_time in the training.
train_df <- df_combined[train_index, -c(1,2)]
valid_df <- df_combined[valid_index, -c(1,2)]
model <- train(response_type ~ ., data = train_df,
method = "glm", family = "binomial",
trControl = trainControl(method = "cv", number = 5))
pred_train <- predict(model, newdata = train_df)
head(pred_train)
## [1] Human Human Machine Human Human Machine
## Levels: Human Machine
pred_prob_train <- predict(model, newdata = train_df, type = "prob")
head(pred_prob_train)
## Human Machine
## 62 0.71165774 0.28834226
## 11 0.97627693 0.02372307
## 28 0.02700434 0.97299566
## 14 0.97588489 0.02411511
## 5 0.63384398 0.36615602
## 12 0.03203892 0.96796108
pred_valid <- predict(model, newdata = valid_df)
head(pred_valid)
## [1] Machine Machine Human Machine Machine Human
## Levels: Human Machine
pred_prob_valid <- predict(model, newdata = valid_df, type = "prob")
head(pred_prob_valid)
## Human Machine
## 2 0.02310238 0.97689762
## 4 0.30120997 0.69879003
## 9 0.91713211 0.08286789
## 17 0.03463946 0.96536054
## 18 0.46585953 0.53414047
## 21 0.53765080 0.46234920
ensure consistency in factor levels
pred_train <- factor(pred_train,
levels = c("Human", "Machine"))
train_df$response_type <- factor(train_df$response_type,
levels = c("Human", "Machine"))
pred_valid <- factor(pred_valid,
levels = c("Human", "Machine"))
valid_df$response_type <- factor(valid_df$response_type,
levels = c("Human", "Machine"))
cm_train <- confusionMatrix(pred_train,
train_df$response_type,
positive = "Human")
cm_train
## Confusion Matrix and Statistics
##
## Reference
## Prediction Human Machine
## Human 16 6
## Machine 5 35
##
## Accuracy : 0.8226
## 95% CI : (0.7047, 0.908)
## No Information Rate : 0.6613
## P-Value [Acc > NIR] : 0.003865
##
## Kappa : 0.6085
##
## Mcnemar's Test P-Value : 1.000000
##
## Sensitivity : 0.7619
## Specificity : 0.8537
## Pos Pred Value : 0.7273
## Neg Pred Value : 0.8750
## Prevalence : 0.3387
## Detection Rate : 0.2581
## Detection Prevalence : 0.3548
## Balanced Accuracy : 0.8078
##
## 'Positive' Class : Human
##
cm_train$byClass["F1"]
## F1
## 0.744186
cm_valid <- confusionMatrix(pred_valid,
valid_df$response_type, positive = "Human")
cm_valid
## Confusion Matrix and Statistics
##
## Reference
## Prediction Human Machine
## Human 9 4
## Machine 3 12
##
## Accuracy : 0.75
## 95% CI : (0.5513, 0.8931)
## No Information Rate : 0.5714
## P-Value [Acc > NIR] : 0.04018
##
## Kappa : 0.4948
##
## Mcnemar's Test P-Value : 1.00000
##
## Sensitivity : 0.7500
## Specificity : 0.7500
## Pos Pred Value : 0.6923
## Neg Pred Value : 0.8000
## Prevalence : 0.4286
## Detection Rate : 0.3214
## Detection Prevalence : 0.4643
## Balanced Accuracy : 0.7500
##
## 'Positive' Class : Human
##
cm_valid$byClass["F1"]
## F1
## 0.72
roc_curve <- roc(response = valid_df$response_type,
predictor = pred_prob_valid[, "Human"],
levels = c("Machine", "Human"))
## Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve for Validation Set")
auc(roc_curve)
## Area under the curve: 0.8125
new_data <- read.csv("new_data.csv", header = TRUE)
new_data
## correct_answer response_length sentiment_score response_time
## 1 Yes 40 0.8 4.5
## 2 Yes 25 0.1 3.0
## 3 No 10 -0.2 0.8
new_pred <- predict(model, newdata = new_data)
new_pred
## [1] Human Machine Machine
## Levels: Human Machine
new_prob <- predict(model, newdata = new_data, type = "prob")
new_prob
## Human Machine
## 1 0.94496213 0.05503787
## 2 0.47860589 0.52139411
## 3 0.02132912 0.97867088
new_data$response_type <- new_pred
new_data$probability_of_human <- round(new_prob[, "Human"], 2)
new_data
## correct_answer response_length sentiment_score response_time response_type
## 1 Yes 40 0.8 4.5 Human
## 2 Yes 25 0.1 3.0 Machine
## 3 No 10 -0.2 0.8 Machine
## probability_of_human
## 1 0.94
## 2 0.48
## 3 0.02
Change the threshold
library(plotly)
thresholds <- c(0.05, 0.50, 0.95)
frame_data <- do.call(rbind, lapply(thresholds, function(threshold) {
temp_df <- new_data
temp_df$Prediction <- ifelse(temp_df$probability_of_human > threshold, "Human", "Machine")
pred_summary <- as.data.frame(table(temp_df$Prediction))
colnames(pred_summary) <- c("Prediction", "Number")
pred_summary$Threshold <- paste("Threshold =", format(threshold, nsmall = 2))
return(pred_summary)
}))
plot <- frame_data %>%
plot_ly(
x = ~Prediction,
y = ~Number,
color = ~Prediction,
text = ~paste("Threshold:", Threshold, "<br>Prediction:",
Prediction, "<br>Number:", Number),
hoverinfo = "text",
type = "bar",
frame = ~Threshold,
colors = c("Human" = "#90ee90", "Machine" = "#556b2f")) %>%
layout(
title = "Predictions Across Thresholds",
xaxis = list(title = "Prediction (Human vs Machine)"),
yaxis = list(
title = "Number of Predictions",
tickmode = "linear",
dtick = 1,
range = c(0, 3)
),
updatemenus = list(
list(
type = "buttons",
showactive = TRUE,
buttons = list(
list(
label = "Play",
method = "animate",
args = list(NULL,
list(frame = list(duration = 500, redraw = TRUE),
transition = list(duration = 0))
)
),
list(
label = "Pause",
method = "animate",
args = list(NULL, list(mode = "immediate", frame = list(duration = 0)))
)
)
)
)
)
plot