The purpose of writing graded lab reports is to help students to stay on track and to provide summative feedback. Each lab report is just 1% of the total course mark. Please do not cheat - it is not worth it!
Solve the practical questions, knit your document into a PDF and submit to NTULearn before the deadline. The deadline is very tight because the task is simple. We are sure that everyone is capable to do it by themselves and we want to discourage taking someone else’s report and writing it with your own words.
23 Sep 2026, midnight
We will work with a dataset of RMS Titanic passengers. The response
variable is Survived indicating whether a passenger died or
survived the sinking. We will renamed Survived to
Y and change it to a factor variable with possible values
survived and died.
Here, we load libraries, data and set the random seed. Replace the number “1729” with the numeric part of your matric no.
library(tidyverse) # for manipulation with data
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.2.1 ✔ readr 2.2.0
## ✔ forcats 1.0.1 ✔ stringr 1.6.0
## ✔ ggplot2 4.0.3 ✔ tibble 3.3.1
## ✔ lubridate 1.9.5 ✔ tidyr 1.3.2
## ✔ purrr 1.2.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(caret) # for machine learning
## Loading required package: lattice
##
## Attaching package: 'caret'
##
## The following object is masked from 'package:purrr':
##
## lift
library(kernlab) # for SVM training
##
## Attaching package: 'kernlab'
##
## The following object is masked from 'package:purrr':
##
## cross
##
## The following object is masked from 'package:ggplot2':
##
## alpha
library(titanic) # for the data
X <- titanic_train %>%
select(Survived, Pclass, Sex, Age, SibSp, Parch, Fare, Embarked) %>%
mutate(
Survived = if_else(Survived == 1, "survived", "died"),
Survived = factor(Survived, levels = c("died", "survived"))
# survived is positive class
) %>%
rename(Y = Survived) %>%
drop_na()
head(X)
set.seed(1729) # replace the number '1729' with your matric no
Plot the data as a scatterplot on the axes Age, log(Fare) coloured
according to the response variable Y. Then split the data
into 70% training and 30% test sets and report dimensions of the
training and the test sets.
X %>%
ggplot(aes(x = Age, y = Fare, group = Y, colour = Y)) +
geom_point() + scale_y_log10() +
theme_minimal()
## Warning in scale_y_log10(): log-10 transformation introduced infinite values.
ind <- which(runif(nrow(X)) < 0.7)
train_data <- X %>% slice(ind)
test_data <- X %>% slice(-ind)
cat("Training data dimensions =", dim(train_data), "\n")
## Training data dimensions = 522 8
cat("Test data dimensions =", dim(test_data), "\n")
## Test data dimensions = 192 8
Train a polynomial SVM to predict if a Titanic passenger survived the sinking. Tune the values of the hyperparameters by 5-fold cross-validation. Try degrees \(d=1,2,3\) and choose a reasonable grid for the other hyperparameters. Report the optimal combination of the hyperparameter values and the resulting test accuracy.
svm_poly_grid <- expand.grid(C = c(0.25, 0.5, 1, 2, 4),
scale = c(0.5, 1, 2, 4),
degree = c(1, 2, 3))
mod_svm_poly <- train(
Y ~ . , train_data, method = 'svmPoly',
tuneGrid = svm_poly_grid,
trControl = trainControl(method = "cv", number = 5)
)
The best combination of hyperparemeter values is
mod_svm_poly$bestTune
The resulting test accuracy is
### Helper function
test_accuracy <- function(caret_model,
dataset = test_data,
response_var = "Y") {
cm <- caret_model %>%
predict(dataset, type = "raw") %>%
confusionMatrix(dataset[[response_var]])
cm$overall['Accuracy']
}
mod_svm_poly %>% test_accuracy() %>%
round(3) %>%
cat("Polynomial SVM accuracy =", . ,"\n")
## Polynomial SVM accuracy = 0.792
Train an SVM with a radial basis kernel. Use the following grid for hyperparameter tuning:
svm_gauss_grid <- expand.grid(sigma = 2^(-2:2),
C = 2^(-2:2))
Report the optimal combination of the hyperparameter values and the resulting test accuracy.
mod_svm_radial <- train(Y ~ . , data = train_data, method = "svmRadial",
tuneGrid = svm_gauss_grid,
trControl = trainControl("cv", number = 5))
cat("Best hyperparameters for Gauss kernel are\n")
mod_svm_radial$bestTune
mod_svm_radial %>% test_accuracy() %>%
round(3) %>%
cat("Guass Kernel SVM accuracy =", . ,"\n")
## Best hyperparameters for Gauss kernel are
## Guass Kernel SVM accuracy = 0.792
Is SVM a parametric or a non-parametric model? Can we use SVM for statistical inference? Explain your answer.
Answer SVM is generally considered a non-parametric model because it does not assume a fixed functional form for the relationship between predictors and the response. Instead, it uses the training data to determine decision boundaries (through support vectors and kernel functions). Unlike parametric models such as logistic regression, SVMs do not provide interpretable coefficients or standard errors. Therefore, SVMs are powerful for prediction but not suitable for statistical inference — we cannot, for example, quantify how much gender or passenger class increases or decreases the probability of survival.
I used ChatGPT 5.0 to improve clarity of my answer to Question 4.
Type your name to confirm: Fedor Duzhin